From: | Carsten Kropf <ckropf2(at)fh-hof(dot)de> |
---|---|
To: | Yeb Havinga <yebhavinga(at)gmail(dot)com> |
Cc: | pgsql-general(at)postgresql(dot)org |
Subject: | Re: Extending SQL in C using VARIABLE length type |
Date: | 2010-02-10 10:51:36 |
Message-ID: | FF69034A-5B01-4178-B1C7-86E9A3642AC8@fh-hof.de |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-general |
Actually, I thought, I did this using the int32 variable called "dimension" which should be exactly this field. Unfortunately, it seems, that something is wrong here. I'll look inside the code of cube to determine the things I'm doing wrong, currently. Thanks so far for your advice.
My in-method is the following:
Datum pointnd_in(PG_FUNCTION_ARGS)
{
PointND * in = NULL;
// access the format string
char * in_string = PG_GETARG_CSTRING(0);
char * save = in_string;
// 1024 bytes should be sufficient for one coordinate
char curr_buffer[1024];
bool corrupted = false;
float8 * coordinates = NULL;
unsigned int dimensions = 0, i = 0;
coordinates = (float8 *) palloc(sizeof(float8));
// allocate the memory
// read bytewise and count the ',' in order to determine the amount of dimensions, after that: parse the point
in_string = find_char(in_string, '(');
// next sign after opening bracket
++in_string;
// read as long, as no closing bracket has been found
for (dimensions = 0; *in_string != ')' && !corrupted; ++dimensions)
{
// clear the memory
memset(curr_buffer, 0, 1024);
for (i = 0; *in_string != ',' && *in_string != 0 && *in_string != ')'; ++in_string, ++i)
{
if ((*in_string < '0' || *in_string > '9') && *in_string != '.')
{
corrupted = true;
break;
}
// copy current sign
curr_buffer[i] = *in_string;
}
// something has happened here (no valid number)
if (corrupted)
{
break;
}
coordinates = (float8 *) repalloc(coordinates, (dimensions + 1) * sizeof(float8));
//sscanf(curr_buffer, "%f", &coordinates[dimensions]);
coordinates[dimensions] = strtod(curr_buffer, NULL);
// if we have a comma here, skip it
if (*in_string == ',')
{
++in_string;
}
if (*in_string == ' ')
{
// skip space
++in_string;
}
}
// something lead to a corruption of the point
if (corrupted)
{
ereport(ERROR, (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), errmsg("invalid representation of a point: %s, has to look like \"(<coord1>,<coord2>,...)\"", save)));
}
else
{
in = (PointND *) palloc(sizeof(float8) * dimensions + VARHDRSZ);
SET_VARSIZE(in, dimensions);
// copy the coordinates to the data area
memcpy((void *) VARDATA(in), (void *) coordinates, (dimensions) * sizeof(float8));
}
PG_RETURN_POINTER(in);
}
So, probably in here, I am doing something terribly wrong and you could correct me at this point. As I already said, I thought that my int32 dimensions variable would represent exactly this vl_len_header field. The remaining stuff is OK then? That means the creation script and information about storage alignment and layout or do you detect addititonal errors?
I know, that this code might not be the best, but I am still in the testing phase of how to achieve sth using Postgres with C.
Thanks so far for your advice
Best regards
Carsten Kropf
Am 10.02.2010 um 11:39 schrieb Yeb Havinga:
>
> Carsten Kropf wrote:
>> The usage of static types with fixed length was actually no problem for me, so I proceeded to variable length types.
>> I created an n-dimensional point structure called "PointND" that contains a field of float8 values of dynamic length. I also put in a int4/int32 field for the length specification, as required by the documentation. So the structure looks like the following:
>> struct PointND
>> {
>> int32 dimensions;
>> float8 coordinates[1];
>> };
> The structure should begin with a int32 vl_len_ header. At creation / palloc time the size must be set with the SET_VARSIZE macro, and the size can be queried with the VARSIZE_ * macros -> doxygen.postgresql.org is your friend here. Take a look at e.g. contrib/cube for examples.
>
> regards,
> Yeb Havinga
>
From | Date | Subject | |
---|---|---|---|
Next Message | Guillaume Lelarge | 2010-02-10 10:54:51 | Re: when a table was last vacuumed |
Previous Message | Yeb Havinga | 2010-02-10 10:39:24 | Re: Extending SQL in C using VARIABLE length type |