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 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 pcpatch_bytea_envelope(PG_FUNCTION_ARGS) { SERIALIZED_PATCH *serpatch = PG_GETARG_SERPATCH_P(0); uint8 *bytes; size_t bytes_size; bytea *wkb; size_t wkb_size; PCSCHEMA *schema = pc_schema_from_pcid(serpatch->pcid, fcinfo); PCPATCH *pa = pc_patch_deserialize(serpatch, schema); if ( ! pa ) PG_RETURN_NULL(); bytes = pc_patch_to_geometry_wkb_envelope(pa, &bytes_size); wkb_size = VARHDRSZ + bytes_size; wkb = palloc(wkb_size); memcpy(VARDATA(wkb), bytes, bytes_size); SET_VARSIZE(wkb, wkb_size); pc_patch_free(pa); pfree(bytes); PG_RETURN_BYTEA_P(wkb); }
Datum pcpatch_unnest(PG_FUNCTION_ARGS) { typedef struct { int nextelem; int numelems; PCPOINTLIST *pointlist; } pcpatch_unnest_fctx; FuncCallContext *funcctx; pcpatch_unnest_fctx *fctx; MemoryContext oldcontext; /* stuff done only on the first call of the function */ if (SRF_IS_FIRSTCALL()) { PCPATCH *patch; SERIALIZED_PATCH *serpatch; /* create a function context for cross-call persistence */ funcctx = SRF_FIRSTCALL_INIT(); /* * switch to memory context appropriate for multiple function calls */ oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); /* * Get the patch value and detoast if needed. We can't do this * earlier because if we have to detoast, we want the detoasted copy * to be in multi_call_memory_ctx, so it will go away when we're done * and not before. (If no detoast happens, we assume the originally * passed array will stick around till then.) */ serpatch = PG_GETARG_SERPATCH_P(0); patch = pc_patch_deserialize(serpatch, pc_schema_from_pcid_uncached(serpatch->pcid)); /* allocate memory for user context */ fctx = (pcpatch_unnest_fctx *) palloc(sizeof(pcpatch_unnest_fctx)); /* initialize state */ fctx->nextelem = 0; fctx->numelems = patch->npoints; fctx->pointlist = pc_pointlist_from_patch(patch); /* save user context, switch back to function context */ funcctx->user_fctx = fctx; MemoryContextSwitchTo(oldcontext); } /* stuff done on every call of the function */ funcctx = SRF_PERCALL_SETUP(); fctx = funcctx->user_fctx; if (fctx->nextelem < fctx->numelems) { Datum elem; PCPOINT *pt = pc_pointlist_get_point(fctx->pointlist, fctx->nextelem); SERIALIZED_POINT *serpt = pc_point_serialize(pt); fctx->nextelem++; elem = PointerGetDatum(serpt); SRF_RETURN_NEXT(funcctx, elem); } else { /* do when there is no more left */ SRF_RETURN_DONE(funcctx); } }
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; }