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_enforce_typmod(PG_FUNCTION_ARGS) { SERIALIZED_PATCH *arg = PG_GETARG_SERPATCH_P(0); uint32 typmod = PG_GETARG_INT32(1); uint32 pcid = pcid_from_typmod(typmod); /* We don't need to have different behavior based on explicitness. */ /* bool isExplicit = PG_GETARG_BOOL(2); */ /* Check if column typmod is consistent with the object */ if ( pcid != arg->pcid ) elog(ERROR, "column pcid (%d) and patch pcid (%d) are not consistent", pcid, arg->pcid); PG_RETURN_POINTER(arg); }
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_numpoints(PG_FUNCTION_ARGS) { SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0); PG_RETURN_INT32(serpa->npoints); }
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); } }