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 pcpoint_in(PG_FUNCTION_ARGS) { char *str = PG_GETARG_CSTRING(0); /* Datum pc_oid = PG_GETARG_OID(1); Not needed. */ int32 typmod = 0; uint32 pcid = 0; PCPOINT *pt; SERIALIZED_POINT *serpt = NULL; if ( (PG_NARGS()>2) && (!PG_ARGISNULL(2)) ) { typmod = PG_GETARG_INT32(2); pcid = pcid_from_typmod(typmod); } /* Empty string. */ if ( str[0] == '\0' ) { ereport(ERROR,(errmsg("pcpoint parse error - empty string"))); } /* Binary or text form? Let's find out. */ if ( str[0] == '0' ) { /* Hex-encoded binary */ pt = pc_point_from_hexwkb(str, strlen(str), fcinfo); pcid_consistent(pt->schema->pcid, pcid); serpt = pc_point_serialize(pt); pc_point_free(pt); } else { ereport(ERROR,(errmsg("parse error - support for text format not yet implemented"))); } if ( serpt ) PG_RETURN_POINTER(serpt); else PG_RETURN_NULL(); }
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); } }