Thread: [GENERAL] User defined Type PostgreSQL in C
I'm developing an extension for postgreSQL in C. I've created two new types, one of var len size (vlen). I do not know how to create the input and output functions for Geo_Polygon type. Anyone have an example? Here's what I've done so far.
typedef struct Geo_Point{ double x; double y;
} Geo_Point;
typedef struct Geo_Polygon{ int32 v_len; int32 n_points; Geo_Point point[FLEXIBLE_ARRAY_MEMBER];
} Geo_Polygon;
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, len; 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;
}
len = sizeof(Geo_Point) * (dimension + 1)+ 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));
result->n_points = dimension;
PG_RETURN_POINTER(result);
}
Datum
geo_polygon_out(PG_FUNCTION_ARGS){ Geo_Polygon *geo_polygon = (Geo_Polygon *) PG_GETARG_POINTER(0); StringInfoData buf; int dim = geo_polygon->n_points;
int i; int ndig = 2;
initStringInfo(&buf);
appendStringInfoChar(&buf, '('); for (i = 0; i < dim; i++){
appendStringInfo(&buf, "%.*g", geo_polygon->point[i].x, "%.*g", geo_polygon->point[i].y); appendStringInfoChar(&buf, ')');
} PG_FREE_IF_COPY(geo_polygon, 0); PG_RETURN_CSTRING(buf.data);}