[GENERAL] Enc: Extending SQL in C using VARIABLE length type in user definedtype - Mailing list pgsql-general

From Fabiana Zioti
Subject [GENERAL] Enc: Extending SQL in C using VARIABLE length type in user definedtype
Date
Msg-id SC1PR80MB0736348FAD52E543C836C656FDCE0@SC1PR80MB0736.lamprd80.prod.outlook.com
Whole thread Raw
List 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

pgsql-general by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: [GENERAL] pg_upgrade --link on Windows
Next
From: Adrian Klaver
Date:
Subject: Re: [GENERAL] pg_upgrade --link on Windows