Пример #1
0
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);
}
Пример #2
0
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);
}
Пример #3
0
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);
}
Пример #4
0
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);
}
Пример #5
0
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);
	}
}
Пример #6
0
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;
}