Enc: Extending SQL in C using VARIABLE length type in user defined type

From: Fabiana Zioti <fabi_zioti(at)hotmail(dot)com>
To: "pgsql-general(at)postgresql(dot)org" <pgsql-general(at)postgresql(dot)org>
Subject: Enc: Extending SQL in C using VARIABLE length type in user defined type
Date: 2017-06-09 14:18:13
Message-ID: SC1PR80MB0736348FAD52E543C836C656FDCE0@SC1PR80MB0736.lamprd80.prod.outlook.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

I am trying around a little bit with creating my own types using shared objects, written in C. 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 "Geo_Polygon" that contains a field of Geo_Point values of dynamic length. Like:

typedef struct Geo_Point{
double x;
double y;
int id;
} Geo_Point;

typedef struct Geo_Polygon{
int32 v_len;
Geo_Point pontos[FLEXIBLE_ARRAY_MEMBER];
} Geo_Polygon;

The Geo_Point works fine.

I don`t know to convert the structure of Geo_polygon to the internal/external representation properly.

PG_FUNCTION_INFO_V1(geo_polygon_in);
PG_FUNCTION_INFO_V1(geo_polygon_out);

PG_FUNCTION_INFO_V1(geo_polygon_in);
Datum
geo_polygon_in(PG_FUNCTION_ARGS){
char *str = PG_GETARG_CSTRING(0);
char *new_position = NULL;
char aux[1024];
int i, dimension;
Geo_Polygon *result;
Geo_Point *point;
double x, y;

point = (Geo_Point *) palloc(sizeof(Geo_Point));

new_position = strchr(str, '(');

for (dimension = 0; *new_position != '\0'; dimension++){

memset(aux, 0, sizeof(aux));
for (i = 0; *new_position != ')'; i++, ++new_position) {
aux[i] = *new_position;
}
aux[i] = *new_position;
++new_position;
if (*new_position == ',') {
++new_position;
}

point = (Geo_Point *) repalloc(point, (dimension + 1) * sizeof(Geo_Point));
if(sscanf(aux, " ( %lf , %lf )", &x, &y )!= 2)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
errmsg("entrada errada para o tipo geo_point: \"%s\"",
str)));

point->x = x;
point->y = y;

}

int len = sizeof(Geo_Point) * dimension + VARHDRSZ;
result = (Geo_Polygon *) palloc0(len);
SET_VARSIZE(result, len);
// copy the coordinates to the data area destino arqu e quantos bytes
memcpy((void *) VARDATA(result),
(void *) VARDATA (point),
(dimension) * sizeof(Geo_Point));

PG_RETURN_POINTER(result);

}

PG_FUNCTION_INFO_V1(geo_polygon_out);

Datum
geo_polygon_out(PG_FUNCTION_ARGS){
Geo_Polygon *geo_polygon = (Geo_Polygon *) PG_GETARG_POINTER(0);
char *result;
int i, tam;

tam = VARSIZE(geo_polygon->point);
for (i = 0; i < tam; i++){
result = psprintf("(%g,%g)", geo_polygon->point[i].x, geo_polygon->point[i].y);
snprintf(result, 100, "(%g,%g)", geo_polygon->point[i].x, geo_polygon->point[i].y);
}

PG_RETURN_CSTRING(result);

}

I would be very glad, if somebody could provide me some help to this.

Obs: I see cube.c and I did not understand.
Thank you in advance

Best regards

Fabiana

Browse pgsql-general by date

  From Date Subject
Next Message Adrian Klaver 2017-06-09 14:24:03 Re: pg_upgrade --link on Windows
Previous Message Bruce Momjian 2017-06-09 14:07:24 Re: pg_upgrade --link on Windows