Datum pcpoint_from_double_array(PG_FUNCTION_ARGS) { uint32 pcid = PG_GETARG_INT32(0); ArrayType *arrptr = PG_GETARG_ARRAYTYPE_P(1); int nelems; float8 *vals; PCPOINT *pt; PCSCHEMA *schema = pc_schema_from_pcid(pcid, fcinfo); SERIALIZED_POINT *serpt; if ( ! schema ) elog(ERROR, "unable to load schema for pcid = %d", pcid); if ( ARR_ELEMTYPE(arrptr) != FLOAT8OID ) elog(ERROR, "array must be of float8[]"); if ( ARR_NDIM(arrptr) != 1 ) elog(ERROR, "float8[] must have only one dimension"); if ( ARR_HASNULL(arrptr) ) elog(ERROR, "float8[] must not have null elements"); nelems = ARR_DIMS(arrptr)[0]; if ( nelems != schema->ndims || ARR_LBOUND(arrptr)[0] > 1 ) elog(ERROR, "array dimensions do not match schema dimensions of pcid = %d", pcid); vals = (float8*) ARR_DATA_PTR(arrptr); pt = pc_point_from_double_array(schema, vals, nelems); serpt = pc_point_serialize(pt); pc_point_free(pt); PG_RETURN_POINTER(serpt); }
Datum pcpatch_uncompress(PG_FUNCTION_ARGS) { SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0); PCSCHEMA *schema = pc_schema_from_pcid(serpa->pcid, fcinfo); PCPATCH *patch = pc_patch_deserialize(serpa, schema); SERIALIZED_PATCH *serpa_out = pc_patch_serialize_uncompressed(patch); pc_patch_free(patch); PG_RETURN_POINTER(serpa_out); }
Datum pcschema_get_ndims(PG_FUNCTION_ARGS) { int ndims; uint32 pcid = PG_GETARG_INT32(0); PCSCHEMA *schema = pc_schema_from_pcid(pcid, fcinfo); if ( ! schema ) elog(ERROR, "unable to load schema for pcid = %d", pcid); ndims = schema->ndims; PG_RETURN_INT32(ndims); }
PCPATCH * pc_patch_from_hexwkb(const char *hexwkb, size_t hexlen, FunctionCallInfoData *fcinfo) { PCPATCH *patch; PCSCHEMA *schema; uint32 pcid; uint8 *wkb = bytes_from_hexbytes(hexwkb, hexlen); size_t wkblen = hexlen/2; pcid = wkb_get_pcid(wkb); schema = pc_schema_from_pcid(pcid, fcinfo); patch = pc_patch_from_wkb(schema, wkb, wkblen); pfree(wkb); return patch; }
Datum pcpoint_out(PG_FUNCTION_ARGS) { PCPOINT *pcpt = NULL; PCSCHEMA *schema = NULL; SERIALIZED_POINT *serpt = NULL; char *hexwkb = NULL; serpt = PG_GETARG_SERPOINT_P(0); schema = pc_schema_from_pcid(serpt->pcid, fcinfo); pcpt = pc_point_deserialize(serpt, schema); hexwkb = pc_point_to_hexwkb(pcpt); pc_point_free(pcpt); PG_RETURN_CSTRING(hexwkb); }
Datum pcpatch_out(PG_FUNCTION_ARGS) { PCPATCH *patch = NULL; SERIALIZED_PATCH *serpatch = NULL; char *hexwkb = NULL; PCSCHEMA *schema = NULL; serpatch = PG_GETARG_SERPATCH_P(0); schema = pc_schema_from_pcid(serpatch->pcid, fcinfo); patch = pc_patch_deserialize(serpatch, schema); hexwkb = pc_patch_to_hexwkb(patch); pc_patch_free(patch); PG_RETURN_CSTRING(hexwkb); }
Datum pcpatch_as_text(PG_FUNCTION_ARGS) { SERIALIZED_PATCH *serpatch = PG_GETARG_SERPATCH_P(0); text *txt; char *str; PCSCHEMA *schema = pc_schema_from_pcid(serpatch->pcid, fcinfo); PCPATCH *patch = pc_patch_deserialize(serpatch, schema); if ( ! patch ) PG_RETURN_NULL(); str = pc_patch_to_string(patch); pc_patch_free(patch); txt = cstring_to_text(str); pfree(str); PG_RETURN_TEXT_P(txt); }
Datum pcpoint_as_text(PG_FUNCTION_ARGS) { SERIALIZED_POINT *serpt = PG_GETARG_SERPOINT_P(0); text *txt; char *str; PCSCHEMA *schema = pc_schema_from_pcid(serpt->pcid, fcinfo); PCPOINT *pt = pc_point_deserialize(serpt, schema); if ( ! pt ) PG_RETURN_NULL(); str = pc_point_to_string(pt); pc_point_free(pt); txt = cstring_to_text(str); pfree(str); PG_RETURN_TEXT_P(txt); }
Datum pcpatch_bytea_envelope(PG_FUNCTION_ARGS) { uint8 *bytes; size_t bytes_size; bytea *wkb; size_t wkb_size; SERIALIZED_PATCH *serpatch = PG_GETHEADER_SERPATCH_P(0); PCSCHEMA *schema = pc_schema_from_pcid(serpatch->pcid, fcinfo); bytes = pc_patch_to_geometry_wkb_envelope(serpatch, schema, &bytes_size); wkb_size = VARHDRSZ + bytes_size; wkb = palloc(wkb_size); memcpy(VARDATA(wkb), bytes, bytes_size); SET_VARSIZE(wkb, wkb_size); pfree(bytes); PG_RETURN_BYTEA_P(wkb); }
PCPATCH * pc_patch_from_hexwkb(const char *hexwkb, size_t hexlen, FunctionCallInfoData *fcinfo) { PCPATCH *patch; PCSCHEMA *schema; uint32 pcid; uint8 *wkb = bytes_from_hexbytes(hexwkb, hexlen); size_t wkblen = hexlen/2; pcid = wkb_get_pcid(wkb); if ( ! pcid ) elog(ERROR, "%s: pcid is zero", __func__); schema = pc_schema_from_pcid(pcid, fcinfo); if ( ! schema ) elog(ERROR, "%s: unable to look up schema entry", __func__); patch = pc_patch_from_wkb(schema, wkb, wkblen); pfree(wkb); return patch; }
Datum pcpoint_get_value(PG_FUNCTION_ARGS) { SERIALIZED_POINT *serpt = PG_GETARG_SERPOINT_P(0); text *dim_name = PG_GETARG_TEXT_P(1); char *dim_str; float8 double_result; PCSCHEMA *schema = pc_schema_from_pcid(serpt->pcid, fcinfo); PCPOINT *pt = pc_point_deserialize(serpt, schema); if ( ! pt ) PG_RETURN_NULL(); dim_str = text_to_cstring(dim_name); if ( ! pc_point_get_double_by_name(pt, dim_str, &double_result) ) { pc_point_free(pt); elog(ERROR, "dimension \"%s\" does not exist in schema", dim_str); } pfree(dim_str); pc_point_free(pt); PG_RETURN_DATUM(DirectFunctionCall1(float8_numeric, Float8GetDatum(double_result))); }
Datum pcpoint_as_bytea(PG_FUNCTION_ARGS) { SERIALIZED_POINT *serpt = PG_GETARG_SERPOINT_P(0); uint8 *bytes; size_t bytes_size; bytea *wkb; size_t wkb_size; PCSCHEMA *schema = pc_schema_from_pcid(serpt->pcid, fcinfo); PCPOINT *pt = pc_point_deserialize(serpt, schema); if ( ! pt ) PG_RETURN_NULL(); bytes = pc_point_to_geometry_wkb(pt, &bytes_size); wkb_size = VARHDRSZ + bytes_size; wkb = palloc(wkb_size); memcpy(VARDATA(wkb), bytes, bytes_size); SET_VARSIZE(wkb, wkb_size); pc_point_free(pt); pfree(bytes); PG_RETURN_BYTEA_P(wkb); }
static PCPATCH * pcpatch_from_point_array(ArrayType *array, FunctionCallInfoData *fcinfo) { int nelems; bits8 *bitmap; int bitmask; size_t offset = 0; int i; uint32 pcid = 0; PCPATCH *pa; PCPOINTLIST *pl; PCSCHEMA *schema = 0; /* How many things in our array? */ nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array)); /* PgSQL supplies a bitmap of which array entries are null */ bitmap = ARR_NULLBITMAP(array); /* Empty array? Null return */ if ( nelems == 0 ) return NULL; /* Make our holder */ pl = pc_pointlist_make(nelems); offset = 0; bitmap = ARR_NULLBITMAP(array); bitmask = 1; for ( i = 0; i < nelems; i++ ) { /* Only work on non-NULL entries in the array */ if ( ! array_get_isnull(bitmap, i) ) { SERIALIZED_POINT *serpt = (SERIALIZED_POINT *)(ARR_DATA_PTR(array)+offset); PCPOINT *pt; if ( ! schema ) { schema = pc_schema_from_pcid(serpt->pcid, fcinfo); } if ( ! pcid ) { pcid = serpt->pcid; } else if ( pcid != serpt->pcid ) { elog(ERROR, "pcpatch_from_point_array: pcid mismatch (%d != %d)", serpt->pcid, pcid); } pt = pc_point_deserialize(serpt, schema); if ( ! pt ) { elog(ERROR, "pcpatch_from_point_array: point deserialization failed"); } pc_pointlist_add_point(pl, pt); offset += INTALIGN(VARSIZE(serpt)); } } if ( pl->npoints == 0 ) return NULL; pa = pc_patch_from_pointlist(pl); pc_pointlist_free(pl); return pa; }
static PCPATCH * pcpatch_from_patch_array(ArrayType *array, FunctionCallInfoData *fcinfo) { int nelems; bits8 *bitmap; int bitmask; size_t offset = 0; int i; uint32 pcid = 0; PCPATCH *pa; PCPATCH **palist; int numpatches = 0; PCSCHEMA *schema = 0; /* How many things in our array? */ nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array)); /* PgSQL supplies a bitmap of which array entries are null */ bitmap = ARR_NULLBITMAP(array); /* Empty array? Null return */ if ( nelems == 0 ) return NULL; /* Make our temporary list of patches */ palist = pcalloc(nelems*sizeof(PCPATCH*)); /* Read the patches out of the array and deserialize */ offset = 0; bitmap = ARR_NULLBITMAP(array); bitmask = 1; for ( i = 0; i < nelems; i++ ) { /* Only work on non-NULL entries in the array */ if ( ! array_get_isnull(bitmap, i) ) { SERIALIZED_PATCH *serpatch = (SERIALIZED_PATCH *)(ARR_DATA_PTR(array)+offset); if ( ! schema ) { schema = pc_schema_from_pcid(serpatch->pcid, fcinfo); } if ( ! pcid ) { pcid = serpatch->pcid; } else if ( pcid != serpatch->pcid ) { elog(ERROR, "pcpatch_from_patch_array: pcid mismatch (%d != %d)", serpatch->pcid, pcid); } pa = pc_patch_deserialize(serpatch, schema); if ( ! pa ) { elog(ERROR, "pcpatch_from_patch_array: patch deserialization failed"); } palist[numpatches++] = pa; offset += INTALIGN(VARSIZE(serpatch)); } } /* Can't do anything w/ NULL */ if ( numpatches == 0 ) return NULL; /* Pass to the lib to build the output patch from the list */ pa = pc_patch_from_patchlist(palist, numpatches); /* Free the temporary patch list */ for ( i = 0; i < numpatches; i++ ) { pc_patch_free(palist[i]); } pcfree(palist); return pa; }