diff --git a/.github/workflows/code_layout.yml b/.github/workflows/code_layout.yml index 32e4100..60f664a 100644 --- a/.github/workflows/code_layout.yml +++ b/.github/workflows/code_layout.yml @@ -16,7 +16,7 @@ jobs: - name: Install clang-format run: sudo apt-get install clang-format - name: Clang-format check - run: clang-format --dry-run --Werror -style=file lib/*.c lib/*.cpp lib/*.hpp lib/*.h lib/cunit/*.c lib/cunit/*.h + run: clang-format --dry-run --Werror -style=file pgsql/*.c pgsql/*.h lib/*.c lib/*.cpp lib/*.hpp lib/*.h lib/cunit/*.c lib/cunit/*.h sql_code_layout: name: SQL linter runs-on: ubuntu-18.04 diff --git a/pgsql/pc_access.c b/pgsql/pc_access.c index 3ddee8c..b174590 100644 --- a/pgsql/pc_access.c +++ b/pgsql/pc_access.c @@ -1,16 +1,17 @@ /*********************************************************************** -* pc_access.c -* -* Accessor/aggregate functions for points and patches in PgSQL. -* -* PgSQL Pointcloud is free and open source software provided -* by the Government of Canada -* Copyright (c) 2013 Natural Resources Canada -* -***********************************************************************/ + * pc_access.c + * + * Accessor/aggregate functions for points and patches in PgSQL. + * + * PgSQL Pointcloud is free and open source software provided + * by the Government of Canada + * Copyright (c) 2013 Natural Resources Canada + * + ***********************************************************************/ -#include "pc_pgsql.h" /* Common PgSQL support for our type */ +#include "pc_pgsql.h" /* Common PgSQL support for our type */ #include "utils/numeric.h" + #include "funcapi.h" #include "lib/stringinfo.h" #include "pc_api_internal.h" /* for pcpatch_summary */ @@ -63,78 +64,79 @@ Datum pcpatch_agg_final_pcpatch(PG_FUNCTION_ARGS); Datum pcpatch_unnest(PG_FUNCTION_ARGS); /** -* Read a named dimension from a PCPOINT -* PC_Get(point pcpoint, dimname text) returns Numeric -*/ + * Read a named dimension from a PCPOINT + * PC_Get(point pcpoint, dimname text) returns Numeric + */ PG_FUNCTION_INFO_V1(pcpoint_get_value); 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; + 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(); + 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))); + 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))); } /** -* Returns all the values of a point as a double precision array -* PC_Get(point pcpoint) returns Float8[] -*/ + * Returns all the values of a point as a double precision array + * PC_Get(point pcpoint) returns Float8[] + */ PG_FUNCTION_INFO_V1(pcpoint_get_values); Datum pcpoint_get_values(PG_FUNCTION_ARGS) { - SERIALIZED_POINT *serpt; - ArrayType *result; - PCSCHEMA *schema; - PCPOINT *pt; - Datum *elems; - int i; - double *vals; + SERIALIZED_POINT *serpt; + ArrayType *result; + PCSCHEMA *schema; + PCPOINT *pt; + Datum *elems; + int i; + double *vals; - serpt = PG_GETARG_SERPOINT_P(0); - schema = pc_schema_from_pcid(serpt->pcid, fcinfo); - pt = pc_point_deserialize(serpt, schema); - if ( ! pt ) PG_RETURN_NULL(); + serpt = PG_GETARG_SERPOINT_P(0); + schema = pc_schema_from_pcid(serpt->pcid, fcinfo); + pt = pc_point_deserialize(serpt, schema); + if (!pt) + PG_RETURN_NULL(); - elems = (Datum * )palloc(schema->ndims * sizeof(Datum) ); - vals = pc_point_to_double_array(pt); - i = schema->ndims; - while (i--) elems[i] = Float8GetDatum(vals[i]); - pcfree(vals); - result = construct_array(elems, schema->ndims, FLOAT8OID, - sizeof(float8), FLOAT8PASSBYVAL, 'd'); + elems = (Datum *)palloc(schema->ndims * sizeof(Datum)); + vals = pc_point_to_double_array(pt); + i = schema->ndims; + while (i--) + elems[i] = Float8GetDatum(vals[i]); + pcfree(vals); + result = construct_array(elems, schema->ndims, FLOAT8OID, sizeof(float8), + FLOAT8PASSBYVAL, 'd'); - pc_point_free(pt); - PG_RETURN_ARRAYTYPE_P(result); + pc_point_free(pt); + PG_RETURN_ARRAYTYPE_P(result); } - -static inline bool -array_get_isnull(const bits8 *nullbitmap, int offset) +static inline bool array_get_isnull(const bits8 *nullbitmap, int offset) { - if (nullbitmap == NULL) - { - return false; /* assume not null */ - } - if (nullbitmap[offset / 8] & (1 << (offset % 8))) - { - return false; /* not null */ - } - return true; + if (nullbitmap == NULL) + { + return false; /* assume not null */ + } + if (nullbitmap[offset / 8] & (1 << (offset % 8))) + { + return false; /* not null */ + } + return true; } static PCPATCH * @@ -144,74 +146,74 @@ pcpatch_from_point_array(ArrayType *array, FunctionCallInfoData *fcinfo) pcpatch_from_point_array(ArrayType *array, FunctionCallInfo fcinfo) #endif { - int nelems; - bits8 *bitmap; - size_t offset = 0; - int i; - uint32 pcid = 0; - PCPATCH *pa; - PCPOINTLIST *pl; - PCSCHEMA *schema = 0; + int nelems; + bits8 *bitmap; + 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)); + /* 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); + /* PgSQL supplies a bitmap of which array entries are null */ + bitmap = ARR_NULLBITMAP(array); - /* Empty array? Null return */ - if ( nelems == 0 ) - return NULL; + /* Empty array? Null return */ + if (nelems == 0) + return NULL; - /* Make our holder */ - pl = pc_pointlist_make(nelems); + /* Make our holder */ + pl = pc_pointlist_make(nelems); - offset = 0; - bitmap = ARR_NULLBITMAP(array); - 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; + offset = 0; + bitmap = ARR_NULLBITMAP(array); + 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 (!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); - } + 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"); - } + pt = pc_point_deserialize(serpt, schema); + if (!pt) + { + elog(ERROR, "pcpatch_from_point_array: point deserialization failed"); + } - pc_pointlist_add_point(pl, pt); + pc_pointlist_add_point(pl, pt); - offset += INTALIGN(VARSIZE(serpt)); - } + offset += INTALIGN(VARSIZE(serpt)); + } + } - } + if (pl->npoints == 0) + return NULL; - if ( pl->npoints == 0 ) - return NULL; - - pa = pc_patch_from_pointlist(pl); - pc_pointlist_free(pl); - return pa; + pa = pc_patch_from_pointlist(pl); + pc_pointlist_free(pl); + return pa; } - static PCPATCH * #if PGSQL_VERSION < 120 pcpatch_from_patch_array(ArrayType *array, FunctionCallInfoData *fcinfo) @@ -219,972 +221,1001 @@ pcpatch_from_patch_array(ArrayType *array, FunctionCallInfoData *fcinfo) pcpatch_from_patch_array(ArrayType *array, FunctionCallInfo fcinfo) #endif { - int nelems; - bits8 *bitmap; - size_t offset = 0; - int i; - uint32 pcid = 0; - PCPATCH *pa; - PCPATCH **palist; - int numpatches = 0; - PCSCHEMA *schema = 0; + int nelems; + bits8 *bitmap; + 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)); + /* 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); + /* PgSQL supplies a bitmap of which array entries are null */ + bitmap = ARR_NULLBITMAP(array); - /* Empty array? Null return */ - if ( nelems == 0 ) - return NULL; + /* Empty array? Null return */ + if (nelems == 0) + return NULL; - /* Make our temporary list of patches */ - palist = pcalloc(nelems*sizeof(PCPATCH*)); + /* 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); - 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); + /* Read the patches out of the array and deserialize */ + offset = 0; + bitmap = ARR_NULLBITMAP(array); + 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 (!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); - } + 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"); - } + pa = pc_patch_deserialize(serpatch, schema); + if (!pa) + { + elog(ERROR, "pcpatch_from_patch_array: patch deserialization failed"); + } - palist[numpatches++] = pa; + palist[numpatches++] = pa; - offset += INTALIGN(VARSIZE(serpatch)); - } + offset += INTALIGN(VARSIZE(serpatch)); + } + } - } + /* Can't do anything w/ NULL */ + if (numpatches == 0) + return NULL; - /* 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); - /* 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); - /* Free the temporary patch list */ - for ( i = 0; i < numpatches; i++ ) - { - pc_patch_free(palist[i]); - } - pcfree(palist); - - return pa; + return pa; } - PG_FUNCTION_INFO_V1(pcpatch_from_pcpatch_array); Datum pcpatch_from_pcpatch_array(PG_FUNCTION_ARGS) { - ArrayType *array; - PCPATCH *pa; - SERIALIZED_PATCH *serpa; + ArrayType *array; + PCPATCH *pa; + SERIALIZED_PATCH *serpa; - if ( PG_ARGISNULL(0) ) - PG_RETURN_NULL(); + if (PG_ARGISNULL(0)) + PG_RETURN_NULL(); - array = DatumGetArrayTypeP(PG_GETARG_DATUM(0)); - pa = pcpatch_from_patch_array(array, fcinfo); - if ( ! pa ) - PG_RETURN_NULL(); + array = DatumGetArrayTypeP(PG_GETARG_DATUM(0)); + pa = pcpatch_from_patch_array(array, fcinfo); + if (!pa) + PG_RETURN_NULL(); - serpa = pc_patch_serialize(pa, NULL); - pc_patch_free(pa); - PG_RETURN_POINTER(serpa); + serpa = pc_patch_serialize(pa, NULL); + pc_patch_free(pa); + PG_RETURN_POINTER(serpa); } PG_FUNCTION_INFO_V1(pcpatch_from_pcpoint_array); Datum pcpatch_from_pcpoint_array(PG_FUNCTION_ARGS) { - ArrayType *array; - PCPATCH *pa; - SERIALIZED_PATCH *serpa; + ArrayType *array; + PCPATCH *pa; + SERIALIZED_PATCH *serpa; - if ( PG_ARGISNULL(0) ) - PG_RETURN_NULL(); + if (PG_ARGISNULL(0)) + PG_RETURN_NULL(); - array = DatumGetArrayTypeP(PG_GETARG_DATUM(0)); - pa = pcpatch_from_point_array(array, fcinfo); - if ( ! pa ) - PG_RETURN_NULL(); + array = DatumGetArrayTypeP(PG_GETARG_DATUM(0)); + pa = pcpatch_from_point_array(array, fcinfo); + if (!pa) + PG_RETURN_NULL(); - serpa = pc_patch_serialize(pa, NULL); - pc_patch_free(pa); - PG_RETURN_POINTER(serpa); + serpa = pc_patch_serialize(pa, NULL); + pc_patch_free(pa); + PG_RETURN_POINTER(serpa); } - PG_FUNCTION_INFO_V1(pcpatch_from_float_array); Datum pcpatch_from_float_array(PG_FUNCTION_ARGS) { - int i, ndims, nelems, npoints; - float8 *vals; - PCPATCH *pa; - PCPOINTLIST *pl; - SERIALIZED_PATCH *serpa; - uint32 pcid = PG_GETARG_INT32(0); - ArrayType *arrptr = PG_GETARG_ARRAYTYPE_P(1); - PCSCHEMA *schema = pc_schema_from_pcid(pcid, fcinfo); + int i, ndims, nelems, npoints; + float8 *vals; + PCPATCH *pa; + PCPOINTLIST *pl; + SERIALIZED_PATCH *serpa; + uint32 pcid = PG_GETARG_INT32(0); + ArrayType *arrptr = PG_GETARG_ARRAYTYPE_P(1); + PCSCHEMA *schema = pc_schema_from_pcid(pcid, fcinfo); - if ( ! schema ) - elog(ERROR, "unable to load schema for pcid = %d", pcid); + 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_ELEMTYPE(arrptr) != FLOAT8OID) + elog(ERROR, "array must be of float8[]"); - if ( ARR_NDIM(arrptr) != 1 ) - elog(ERROR, "float8[] must have one dimension"); + if (ARR_NDIM(arrptr) != 1) + elog(ERROR, "float8[] must have one dimension"); - if ( ARR_HASNULL(arrptr) ) - elog(ERROR, "float8[] must not have null elements"); + if (ARR_HASNULL(arrptr)) + elog(ERROR, "float8[] must not have null elements"); - ndims = schema->ndims; - nelems = ARR_DIMS(arrptr)[0]; + ndims = schema->ndims; + nelems = ARR_DIMS(arrptr)[0]; - if ( nelems % ndims != 0 ) { - elog(ERROR, "array dimensions do not match schema dimensions of pcid = %d", pcid); - } + if (nelems % ndims != 0) + { + elog(ERROR, "array dimensions do not match schema dimensions of pcid = %d", + pcid); + } - npoints = nelems / ndims; + npoints = nelems / ndims; - vals = (float8*) ARR_DATA_PTR(arrptr); - pl = pc_pointlist_make(nelems); + vals = (float8 *)ARR_DATA_PTR(arrptr); + pl = pc_pointlist_make(nelems); - for ( i = 0; i < npoints; ++i ) { + for (i = 0; i < npoints; ++i) + { - PCPOINT* pt = pc_point_from_double_array(schema, vals, i * ndims, ndims); - pc_pointlist_add_point(pl, pt); - } + PCPOINT *pt = pc_point_from_double_array(schema, vals, i * ndims, ndims); + pc_pointlist_add_point(pl, pt); + } - pa = pc_patch_from_pointlist(pl); - pc_pointlist_free(pl); - if ( ! pa ) - PG_RETURN_NULL(); + pa = pc_patch_from_pointlist(pl); + pc_pointlist_free(pl); + if (!pa) + PG_RETURN_NULL(); - serpa = pc_patch_serialize(pa, NULL); + serpa = pc_patch_serialize(pa, NULL); - pc_patch_free(pa); - PG_RETURN_POINTER(serpa); + pc_patch_free(pa); + PG_RETURN_POINTER(serpa); } typedef struct { - ArrayBuildState *s; + ArrayBuildState *s; } abs_trans; PG_FUNCTION_INFO_V1(pointcloud_abs_in); Datum pointcloud_abs_in(PG_FUNCTION_ARGS) { - ereport(ERROR,(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("function pointcloud_abs_in not implemented"))); - PG_RETURN_POINTER(NULL); + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("function pointcloud_abs_in not implemented"))); + PG_RETURN_POINTER(NULL); } PG_FUNCTION_INFO_V1(pointcloud_abs_out); Datum pointcloud_abs_out(PG_FUNCTION_ARGS) { - ereport(ERROR,(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("function pointcloud_abs_out not implemented"))); - PG_RETURN_POINTER(NULL); + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("function pointcloud_abs_out not implemented"))); + PG_RETURN_POINTER(NULL); } - PG_FUNCTION_INFO_V1(pointcloud_agg_transfn); Datum pointcloud_agg_transfn(PG_FUNCTION_ARGS) { - Oid arg1_typeid = get_fn_expr_argtype(fcinfo->flinfo, 1); - MemoryContext aggcontext; - abs_trans *a; - ArrayBuildState *state; - Datum elem; + Oid arg1_typeid = get_fn_expr_argtype(fcinfo->flinfo, 1); + MemoryContext aggcontext; + abs_trans *a; + ArrayBuildState *state; + Datum elem; - if (arg1_typeid == InvalidOid) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("could not determine input data type"))); + if (arg1_typeid == InvalidOid) + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("could not determine input data type"))); - if ( ! AggCheckCallContext(fcinfo, &aggcontext) ) - { - /* cannot be called directly because of dummy-type argument */ - elog(ERROR, "pointcloud_agg_transfn called in non-aggregate context"); - aggcontext = NULL; /* keep compiler quiet */ - } + if (!AggCheckCallContext(fcinfo, &aggcontext)) + { + /* cannot be called directly because of dummy-type argument */ + elog(ERROR, "pointcloud_agg_transfn called in non-aggregate context"); + aggcontext = NULL; /* keep compiler quiet */ + } - if ( PG_ARGISNULL(0) ) - { - a = (abs_trans*) palloc(sizeof(abs_trans)); - a->s = NULL; - } - else - { - a = (abs_trans*) PG_GETARG_POINTER(0); - } - state = a->s; - elem = PG_ARGISNULL(1) ? (Datum) 0 : PG_GETARG_DATUM(1); - state = accumArrayResult(state, - elem, - PG_ARGISNULL(1), - arg1_typeid, - aggcontext); - a->s = state; + if (PG_ARGISNULL(0)) + { + a = (abs_trans *)palloc(sizeof(abs_trans)); + a->s = NULL; + } + else + { + a = (abs_trans *)PG_GETARG_POINTER(0); + } + state = a->s; + elem = PG_ARGISNULL(1) ? (Datum)0 : PG_GETARG_DATUM(1); + state = + accumArrayResult(state, elem, PG_ARGISNULL(1), arg1_typeid, aggcontext); + a->s = state; - PG_RETURN_POINTER(a); + PG_RETURN_POINTER(a); } - - - -static Datum -pointcloud_agg_final(abs_trans *a, MemoryContext mctx, FunctionCallInfo fcinfo) +static Datum pointcloud_agg_final(abs_trans *a, MemoryContext mctx, + FunctionCallInfo fcinfo) { - ArrayBuildState *state; - int dims[1]; - int lbs[1]; - state = a->s; - dims[0] = state->nelems; - lbs[0] = 1; - return makeMdArrayResult(state, 1, dims, lbs, mctx, false); + ArrayBuildState *state; + int dims[1]; + int lbs[1]; + state = a->s; + dims[0] = state->nelems; + lbs[0] = 1; + return makeMdArrayResult(state, 1, dims, lbs, mctx, false); } PG_FUNCTION_INFO_V1(pcpoint_agg_final_array); Datum pcpoint_agg_final_array(PG_FUNCTION_ARGS) { - abs_trans *a; - Datum result = 0; + abs_trans *a; + Datum result = 0; - if (PG_ARGISNULL(0)) - PG_RETURN_NULL(); /* returns null iff no input values */ + if (PG_ARGISNULL(0)) + PG_RETURN_NULL(); /* returns null iff no input values */ - a = (abs_trans*) PG_GETARG_POINTER(0); + a = (abs_trans *)PG_GETARG_POINTER(0); - result = pointcloud_agg_final(a, CurrentMemoryContext, fcinfo); - PG_RETURN_DATUM(result); + result = pointcloud_agg_final(a, CurrentMemoryContext, fcinfo); + PG_RETURN_DATUM(result); } - PG_FUNCTION_INFO_V1(pcpatch_agg_final_array); Datum pcpatch_agg_final_array(PG_FUNCTION_ARGS) { - abs_trans *a; - Datum result = 0; + abs_trans *a; + Datum result = 0; - if (PG_ARGISNULL(0)) - PG_RETURN_NULL(); /* returns null iff no input values */ + if (PG_ARGISNULL(0)) + PG_RETURN_NULL(); /* returns null iff no input values */ - a = (abs_trans*) PG_GETARG_POINTER(0); + a = (abs_trans *)PG_GETARG_POINTER(0); - result = pointcloud_agg_final(a, CurrentMemoryContext, fcinfo); - PG_RETURN_DATUM(result); + result = pointcloud_agg_final(a, CurrentMemoryContext, fcinfo); + PG_RETURN_DATUM(result); } - PG_FUNCTION_INFO_V1(pcpoint_agg_final_pcpatch); Datum pcpoint_agg_final_pcpatch(PG_FUNCTION_ARGS) { - ArrayType *array; - abs_trans *a; - PCPATCH *pa; - SERIALIZED_PATCH *serpa; + ArrayType *array; + abs_trans *a; + PCPATCH *pa; + SERIALIZED_PATCH *serpa; - if (PG_ARGISNULL(0)) - PG_RETURN_NULL(); /* returns null iff no input values */ + if (PG_ARGISNULL(0)) + PG_RETURN_NULL(); /* returns null iff no input values */ - a = (abs_trans*) PG_GETARG_POINTER(0); + a = (abs_trans *)PG_GETARG_POINTER(0); - array = DatumGetArrayTypeP(pointcloud_agg_final(a, CurrentMemoryContext, fcinfo)); - pa = pcpatch_from_point_array(array, fcinfo); - if ( ! pa ) - PG_RETURN_NULL(); + array = + DatumGetArrayTypeP(pointcloud_agg_final(a, CurrentMemoryContext, fcinfo)); + pa = pcpatch_from_point_array(array, fcinfo); + if (!pa) + PG_RETURN_NULL(); - serpa = pc_patch_serialize(pa, NULL); - pc_patch_free(pa); - PG_RETURN_POINTER(serpa); + serpa = pc_patch_serialize(pa, NULL); + pc_patch_free(pa); + PG_RETURN_POINTER(serpa); } - PG_FUNCTION_INFO_V1(pcpatch_agg_final_pcpatch); Datum pcpatch_agg_final_pcpatch(PG_FUNCTION_ARGS) { - ArrayType *array; - abs_trans *a; - PCPATCH *pa; - SERIALIZED_PATCH *serpa; + ArrayType *array; + abs_trans *a; + PCPATCH *pa; + SERIALIZED_PATCH *serpa; - if (PG_ARGISNULL(0)) - PG_RETURN_NULL(); /* returns null iff no input values */ + if (PG_ARGISNULL(0)) + PG_RETURN_NULL(); /* returns null iff no input values */ - a = (abs_trans*) PG_GETARG_POINTER(0); + a = (abs_trans *)PG_GETARG_POINTER(0); - array = DatumGetArrayTypeP(pointcloud_agg_final(a, CurrentMemoryContext, fcinfo)); - pa = pcpatch_from_patch_array(array, fcinfo); - if ( ! pa ) - PG_RETURN_NULL(); + array = + DatumGetArrayTypeP(pointcloud_agg_final(a, CurrentMemoryContext, fcinfo)); + pa = pcpatch_from_patch_array(array, fcinfo); + if (!pa) + PG_RETURN_NULL(); - serpa = pc_patch_serialize(pa, NULL); - pc_patch_free(pa); - PG_RETURN_POINTER(serpa); + serpa = pc_patch_serialize(pa, NULL); + pc_patch_free(pa); + PG_RETURN_POINTER(serpa); } - PG_FUNCTION_INFO_V1(pcpatch_unnest); Datum pcpatch_unnest(PG_FUNCTION_ARGS) { - typedef struct - { - int nextelem; - int numelems; - PCPOINTLIST *pointlist; - } pcpatch_unnest_fctx; + typedef struct + { + int nextelem; + int numelems; + PCPOINTLIST *pointlist; + } pcpatch_unnest_fctx; - FuncCallContext *funcctx; - pcpatch_unnest_fctx *fctx; - MemoryContext oldcontext; + 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; + /* 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(); + /* 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); + /* + * 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)); + /* + * 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)); + /* 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); + /* 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); - } + /* 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; + /* 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); - } + 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); + } } PG_FUNCTION_INFO_V1(pcpatch_uncompress); 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_to_uncompressed(patch); - pc_patch_free(patch); - PG_RETURN_POINTER(serpa_out); + 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_to_uncompressed(patch); + pc_patch_free(patch); + PG_RETURN_POINTER(serpa_out); } PG_FUNCTION_INFO_V1(pcpatch_compress); Datum pcpatch_compress(PG_FUNCTION_ARGS) { - SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0); - text *compr_in_text = PG_GETARG_TEXT_P(1); - char *compr_in = text_to_cstring(compr_in_text); - text *config_in_text = PG_GETARG_TEXT_P(2); - char *config_in = text_to_cstring(config_in_text); - PCSCHEMA *schema = pc_schema_from_pcid(serpa->pcid, fcinfo); - PCPATCH *patch_in = pc_patch_deserialize(serpa, schema); - PCPATCH *pa = patch_in; - SERIALIZED_PATCH *serpa_out; - PCDIMSTATS *stats = NULL; - int i; + SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0); + text *compr_in_text = PG_GETARG_TEXT_P(1); + char *compr_in = text_to_cstring(compr_in_text); + text *config_in_text = PG_GETARG_TEXT_P(2); + char *config_in = text_to_cstring(config_in_text); + PCSCHEMA *schema = pc_schema_from_pcid(serpa->pcid, fcinfo); + PCPATCH *patch_in = pc_patch_deserialize(serpa, schema); + PCPATCH *pa = patch_in; + SERIALIZED_PATCH *serpa_out; + PCDIMSTATS *stats = NULL; + int i; - /* Uncompress first */ - if ( patch_in->type != PC_NONE ) { - pa = pc_patch_uncompress(patch_in); - } + /* Uncompress first */ + if (patch_in->type != PC_NONE) + { + pa = pc_patch_uncompress(patch_in); + } - schema = pc_schema_clone(schema); /* we're going to modify it */ + schema = pc_schema_clone(schema); /* we're going to modify it */ - /* Set compression scheme */ - if ( *compr_in == '\0' || strcasecmp(compr_in, "auto") == 0 ) { - /* keep schema defined compression */ - } - else if ( strcmp(compr_in, "dimensional") == 0 ) {{ - char *ptr = config_in; - PCPATCH_DIMENSIONAL *pdl = pc_patch_dimensional_from_uncompressed((PCPATCH_UNCOMPRESSED*)pa); - schema->compression = PC_DIMENSIONAL; - stats = pc_dimstats_make(schema); - pc_dimstats_update(stats, pdl); - /* make sure to avoid stat updates (not sure if needed) */ - stats->total_points = PCDIMSTATS_MIN_SAMPLE+1; + /* Set compression scheme */ + if (*compr_in == '\0' || strcasecmp(compr_in, "auto") == 0) + { + /* keep schema defined compression */ + } + else if (strcmp(compr_in, "dimensional") == 0) + { + { + char *ptr = config_in; + PCPATCH_DIMENSIONAL *pdl = + pc_patch_dimensional_from_uncompressed((PCPATCH_UNCOMPRESSED *)pa); + schema->compression = PC_DIMENSIONAL; + stats = pc_dimstats_make(schema); + pc_dimstats_update(stats, pdl); + /* make sure to avoid stat updates (not sure if needed) */ + stats->total_points = PCDIMSTATS_MIN_SAMPLE + 1; + /* Fill in per-dimension compression */ + if (*ptr) + for (i = 0; i < stats->ndims; ++i) + { + PCDIMSTAT *stat = &(stats->stats[i]); + /*pcinfo("ptr: %s", ptr);*/ + if (*ptr == ',' || strncmp(ptr, "auto", strlen("auto")) == 0) + { + /* leave auto-determined compression */ + } + else if (strncmp(ptr, "rle", strlen("rle")) == 0) + { + stat->recommended_compression = PC_DIM_RLE; + } + else if (strncmp(ptr, "sigbits", strlen("sigbits")) == 0) + { + stat->recommended_compression = PC_DIM_SIGBITS; + } + else if (strncmp(ptr, "zlib", strlen("zlib")) == 0) + { + stat->recommended_compression = PC_DIM_ZLIB; + } + else + { + elog(ERROR, + "Unrecognized dimensional compression '%s'. Please specify " + "'auto', 'rle', 'sigbits' or 'zlib'", + ptr); + } + while (*ptr && *ptr != ',') + ++ptr; + if (!*ptr) + break; + else + ++ptr; + } - /* Fill in per-dimension compression */ - if ( *ptr ) - for (i=0; indims; ++i) { - PCDIMSTAT *stat = &(stats->stats[i]); - /*pcinfo("ptr: %s", ptr);*/ - if ( *ptr == ',' || strncmp(ptr, "auto", strlen("auto")) == 0 ) { - /* leave auto-determined compression */ - } - else if ( strncmp(ptr, "rle", strlen("rle")) == 0 ) { - stat->recommended_compression = PC_DIM_RLE; - } - else if ( strncmp(ptr, "sigbits", strlen("sigbits")) == 0 ) { - stat->recommended_compression = PC_DIM_SIGBITS; - } - else if ( strncmp(ptr, "zlib", strlen("zlib")) == 0 ) { - stat->recommended_compression = PC_DIM_ZLIB; - } - else { - elog(ERROR, "Unrecognized dimensional compression '%s'. Please specify 'auto', 'rle', 'sigbits' or 'zlib'", ptr); - } - while (*ptr && *ptr != ',') ++ptr; - if ( ! *ptr ) break; - else ++ptr; - } + if (pa != patch_in) + pc_patch_free(pa); + pa = (PCPATCH *)pc_patch_dimensional_compress(pdl, stats); + pc_patch_dimensional_free(pdl); + } + } + else if (strcmp(compr_in, "laz") == 0) + { + schema->compression = PC_LAZPERF; + } + else + { + elog(ERROR, + "Unrecognized compression '%s'. Please specify 'auto','dimensional' " + "or 'laz'", + compr_in); + } - if ( pa != patch_in ) pc_patch_free(pa); - pa = (PCPATCH*)pc_patch_dimensional_compress(pdl, stats); - pc_patch_dimensional_free(pdl); - }} - else if ( strcmp(compr_in, "laz") == 0 ) { - schema->compression = PC_LAZPERF; - } - else { - elog(ERROR, "Unrecognized compression '%s'. Please specify 'auto','dimensional' or 'laz'", compr_in); - } + pa->schema = schema; /* install overridden schema */ + serpa_out = pc_patch_serialize(pa, stats); - pa->schema = schema; /* install overridden schema */ - serpa_out = pc_patch_serialize(pa, stats); + if (pa != patch_in) + pc_patch_free(pa); + pc_patch_free(patch_in); + pc_schema_free(schema); - if ( pa != patch_in ) - pc_patch_free(pa); - pc_patch_free(patch_in); - pc_schema_free(schema); - - PG_RETURN_POINTER(serpa_out); + PG_RETURN_POINTER(serpa_out); } PG_FUNCTION_INFO_V1(pcpatch_numpoints); Datum pcpatch_numpoints(PG_FUNCTION_ARGS) { - SERIALIZED_PATCH *serpa = PG_GETHEADER_SERPATCH_P(0); - PG_RETURN_INT32(serpa->npoints); + SERIALIZED_PATCH *serpa = PG_GETHEADER_SERPATCH_P(0); + PG_RETURN_INT32(serpa->npoints); } PG_FUNCTION_INFO_V1(pcpatch_pointn); Datum pcpatch_pointn(PG_FUNCTION_ARGS) { - SERIALIZED_POINT *serpt; - SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0); - int32 n = PG_GETARG_INT32(1); - PCSCHEMA *schema = pc_schema_from_pcid(serpa->pcid, fcinfo); - PCPATCH *patch = pc_patch_deserialize(serpa, schema); - PCPOINT *pt = NULL; - if(patch) { - pt = pc_patch_pointn(patch,n); - pc_patch_free(patch); - } - if(!pt) PG_RETURN_NULL(); - serpt = pc_point_serialize(pt); - pc_point_free(pt); - PG_RETURN_POINTER(serpt); + SERIALIZED_POINT *serpt; + SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0); + int32 n = PG_GETARG_INT32(1); + PCSCHEMA *schema = pc_schema_from_pcid(serpa->pcid, fcinfo); + PCPATCH *patch = pc_patch_deserialize(serpa, schema); + PCPOINT *pt = NULL; + if (patch) + { + pt = pc_patch_pointn(patch, n); + pc_patch_free(patch); + } + if (!pt) + PG_RETURN_NULL(); + serpt = pc_point_serialize(pt); + pc_point_free(pt); + PG_RETURN_POINTER(serpt); } PG_FUNCTION_INFO_V1(pcpatch_range); Datum pcpatch_range(PG_FUNCTION_ARGS) { - SERIALIZED_PATCH *serpaout; - SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0); - int32 first = PG_GETARG_INT32(1); - int32 count = PG_GETARG_INT32(2); - PCSCHEMA *schema = pc_schema_from_pcid(serpa->pcid, fcinfo); - PCPATCH *patch = pc_patch_deserialize(serpa, schema); - PCPATCH *patchout = NULL; - if ( patch ) - { - patchout = pc_patch_range(patch, first, count); - if ( patchout != patch ) - pc_patch_free(patch); - } - if ( !patchout ) - PG_RETURN_NULL(); - serpaout = pc_patch_serialize(patchout, NULL); - pc_patch_free(patchout); - PG_RETURN_POINTER(serpaout); + SERIALIZED_PATCH *serpaout; + SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0); + int32 first = PG_GETARG_INT32(1); + int32 count = PG_GETARG_INT32(2); + PCSCHEMA *schema = pc_schema_from_pcid(serpa->pcid, fcinfo); + PCPATCH *patch = pc_patch_deserialize(serpa, schema); + PCPATCH *patchout = NULL; + if (patch) + { + patchout = pc_patch_range(patch, first, count); + if (patchout != patch) + pc_patch_free(patch); + } + if (!patchout) + PG_RETURN_NULL(); + serpaout = pc_patch_serialize(patchout, NULL); + pc_patch_free(patchout); + PG_RETURN_POINTER(serpaout); } PG_FUNCTION_INFO_V1(pcpatch_pcid); Datum pcpatch_pcid(PG_FUNCTION_ARGS) { - SERIALIZED_PATCH *serpa = PG_GETHEADER_SERPATCH_P(0); - PG_RETURN_INT32(serpa->pcid); + SERIALIZED_PATCH *serpa = PG_GETHEADER_SERPATCH_P(0); + PG_RETURN_INT32(serpa->pcid); } PG_FUNCTION_INFO_V1(pcpatch_summary); Datum pcpatch_summary(PG_FUNCTION_ARGS) { - const int stats_size_guess = 400; - SERIALIZED_PATCH *serpa; - PCSCHEMA *schema; - PCSTATS *stats; - PCPATCH *patch = NULL; - StringInfoData strdata; - text *ret; - const char *comma = ""; - int i; + const int stats_size_guess = 400; + SERIALIZED_PATCH *serpa; + PCSCHEMA *schema; + PCSTATS *stats; + PCPATCH *patch = NULL; + StringInfoData strdata; + text *ret; + const char *comma = ""; + int i; - serpa = PG_GETHEADERX_SERPATCH_P(0, stats_size_guess); - schema = pc_schema_from_pcid(serpa->pcid, fcinfo); - if ( serpa->compression == PC_DIMENSIONAL ) - { - /* need full data to inspect per-dimension compression */ - /* NOTE: memory usage could be optimized to only fetch slices - * at specific offsets, but doesn't seem worth at this time - * See https://github.com/pgpointcloud/pointcloud/pull/51#issuecomment-83592363 - */ - serpa = PG_GETARG_SERPATCH_P(0); - patch = pc_patch_deserialize(serpa, schema); - } - else if ( stats_size_guess < pc_stats_size(schema) ) - { - /* only need stats here */ - serpa = PG_GETHEADERX_SERPATCH_P(0, pc_stats_size(schema)); - } - stats = pc_patch_stats_deserialize(schema, serpa->data); + serpa = PG_GETHEADERX_SERPATCH_P(0, stats_size_guess); + schema = pc_schema_from_pcid(serpa->pcid, fcinfo); + if (serpa->compression == PC_DIMENSIONAL) + { + /* need full data to inspect per-dimension compression */ + /* NOTE: memory usage could be optimized to only fetch slices + * at specific offsets, but doesn't seem worth at this time + * See + * https://github.com/pgpointcloud/pointcloud/pull/51#issuecomment-83592363 + */ + serpa = PG_GETARG_SERPATCH_P(0); + patch = pc_patch_deserialize(serpa, schema); + } + else if (stats_size_guess < pc_stats_size(schema)) + { + /* only need stats here */ + serpa = PG_GETHEADERX_SERPATCH_P(0, pc_stats_size(schema)); + } + stats = pc_patch_stats_deserialize(schema, serpa->data); - initStringInfo(&strdata); - /* Make space for VARSIZ, see SET_VARSIZE below */ - appendStringInfoSpaces(&strdata, VARHDRSZ); + initStringInfo(&strdata); + /* Make space for VARSIZ, see SET_VARSIZE below */ + appendStringInfoSpaces(&strdata, VARHDRSZ); - appendStringInfo(&strdata, "{" - "\"pcid\":%d, \"npts\":%d, \"srid\":%d, " - "\"compr\":\"%s\",\"dims\":[", - serpa->pcid, serpa->npoints, schema->srid, - pc_compression_name(serpa->compression)); + appendStringInfo(&strdata, + "{" + "\"pcid\":%d, \"npts\":%d, \"srid\":%d, " + "\"compr\":\"%s\",\"dims\":[", + serpa->pcid, serpa->npoints, schema->srid, + pc_compression_name(serpa->compression)); - for (i=0; indims; ++i) - { - PCDIMENSION *dim = schema->dims[i]; - PCBYTES bytes; - double val; - appendStringInfo(&strdata, - "%s{\"pos\":%d,\"name\":\"%s\",\"size\":%d" - ",\"type\":\"%s\"", - comma, dim->position, dim->name, dim->size, - pc_interpretation_string(dim->interpretation)); + for (i = 0; i < schema->ndims; ++i) + { + PCDIMENSION *dim = schema->dims[i]; + PCBYTES bytes; + double val; + appendStringInfo(&strdata, + "%s{\"pos\":%d,\"name\":\"%s\",\"size\":%d" + ",\"type\":\"%s\"", + comma, dim->position, dim->name, dim->size, + pc_interpretation_string(dim->interpretation)); - /* Print per-dimension compression (if dimensional) */ - if ( serpa->compression == PC_DIMENSIONAL ) - { - bytes = ((PCPATCH_DIMENSIONAL*)patch)->bytes[i]; - switch ( bytes.compression ) - { - case PC_DIM_RLE: - appendStringInfoString(&strdata,",\"compr\":\"rle\""); - break; - case PC_DIM_SIGBITS: - appendStringInfoString(&strdata,",\"compr\":\"sigbits\""); - break; - case PC_DIM_ZLIB: - appendStringInfoString(&strdata,",\"compr\":\"zlib\""); - break; - case PC_DIM_NONE: - appendStringInfoString(&strdata,",\"compr\":\"none\""); - break; - default: - appendStringInfo(&strdata,",\"compr\":\"unknown(%d)\"", - bytes.compression); - break; - } - } + /* Print per-dimension compression (if dimensional) */ + if (serpa->compression == PC_DIMENSIONAL) + { + bytes = ((PCPATCH_DIMENSIONAL *)patch)->bytes[i]; + switch (bytes.compression) + { + case PC_DIM_RLE: + appendStringInfoString(&strdata, ",\"compr\":\"rle\""); + break; + case PC_DIM_SIGBITS: + appendStringInfoString(&strdata, ",\"compr\":\"sigbits\""); + break; + case PC_DIM_ZLIB: + appendStringInfoString(&strdata, ",\"compr\":\"zlib\""); + break; + case PC_DIM_NONE: + appendStringInfoString(&strdata, ",\"compr\":\"none\""); + break; + default: + appendStringInfo(&strdata, ",\"compr\":\"unknown(%d)\"", + bytes.compression); + break; + } + } - if ( stats ) - { - pc_point_get_double_by_name(&(stats->min), dim->name, &val); - appendStringInfo(&strdata,",\"stats\":{\"min\":%g", val); - pc_point_get_double_by_name(&(stats->max), dim->name, &val); - appendStringInfo(&strdata,",\"max\":%g", val); - pc_point_get_double_by_name(&(stats->avg), dim->name, &val); - appendStringInfo(&strdata,",\"avg\":%g}", val); - } - appendStringInfoString(&strdata, "}"); - comma = ","; - } + if (stats) + { + pc_point_get_double_by_name(&(stats->min), dim->name, &val); + appendStringInfo(&strdata, ",\"stats\":{\"min\":%g", val); + pc_point_get_double_by_name(&(stats->max), dim->name, &val); + appendStringInfo(&strdata, ",\"max\":%g", val); + pc_point_get_double_by_name(&(stats->avg), dim->name, &val); + appendStringInfo(&strdata, ",\"avg\":%g}", val); + } + appendStringInfoString(&strdata, "}"); + comma = ","; + } - appendStringInfoString(&strdata, "]}"); + appendStringInfoString(&strdata, "]}"); - ret = (text*)strdata.data; - SET_VARSIZE(ret, strdata.len); - PG_RETURN_TEXT_P(ret); + ret = (text *)strdata.data; + SET_VARSIZE(ret, strdata.len); + PG_RETURN_TEXT_P(ret); } PG_FUNCTION_INFO_V1(pcpatch_compression); Datum pcpatch_compression(PG_FUNCTION_ARGS) { - SERIALIZED_PATCH *serpa = PG_GETHEADER_SERPATCH_P(0); - PG_RETURN_INT32(serpa->compression); + SERIALIZED_PATCH *serpa = PG_GETHEADER_SERPATCH_P(0); + PG_RETURN_INT32(serpa->compression); } PG_FUNCTION_INFO_V1(pcpatch_intersects); Datum pcpatch_intersects(PG_FUNCTION_ARGS) { - SERIALIZED_PATCH *serpa1 = PG_GETHEADER_SERPATCH_P(0); - SERIALIZED_PATCH *serpa2 = PG_GETHEADER_SERPATCH_P(1); + SERIALIZED_PATCH *serpa1 = PG_GETHEADER_SERPATCH_P(0); + SERIALIZED_PATCH *serpa2 = PG_GETHEADER_SERPATCH_P(1); - if ( serpa1->pcid != serpa2->pcid ) - elog(ERROR, "%s: pcid mismatch (%d != %d)", __func__, serpa1->pcid, serpa2->pcid); + if (serpa1->pcid != serpa2->pcid) + elog(ERROR, "%s: pcid mismatch (%d != %d)", __func__, serpa1->pcid, + serpa2->pcid); - if ( pc_bounds_intersects(&(serpa1->bounds), &(serpa2->bounds)) ) - { - PG_RETURN_BOOL(true); - } - PG_RETURN_BOOL(false); + if (pc_bounds_intersects(&(serpa1->bounds), &(serpa2->bounds))) + { + PG_RETURN_BOOL(true); + } + PG_RETURN_BOOL(false); } PG_FUNCTION_INFO_V1(pcpatch_size); Datum pcpatch_size(PG_FUNCTION_ARGS) { - SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0); - PG_RETURN_INT32(VARSIZE(serpa)); + SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0); + PG_RETURN_INT32(VARSIZE(serpa)); } PG_FUNCTION_INFO_V1(pcpoint_size); Datum pcpoint_size(PG_FUNCTION_ARGS) { - SERIALIZED_POINT *serpt = PG_GETARG_SERPOINT_P(0); - PG_RETURN_INT32(VARSIZE(serpt)); + SERIALIZED_POINT *serpt = PG_GETARG_SERPOINT_P(0); + PG_RETURN_INT32(VARSIZE(serpt)); } PG_FUNCTION_INFO_V1(pcpoint_pcid); Datum pcpoint_pcid(PG_FUNCTION_ARGS) { - SERIALIZED_POINT *serpt = PG_GETARG_SERPOINT_P(0); - PG_RETURN_INT32(serpt->pcid); + SERIALIZED_POINT *serpt = PG_GETARG_SERPOINT_P(0); + PG_RETURN_INT32(serpt->pcid); } PG_FUNCTION_INFO_V1(pc_version); Datum pc_version(PG_FUNCTION_ARGS) { - text *version_text; - char version[64]; - snprintf(version, 64, "%s", POINTCLOUD_VERSION); - version_text = cstring_to_text(version); - PG_RETURN_TEXT_P(version_text); + text *version_text; + char version[64]; + snprintf(version, 64, "%s", POINTCLOUD_VERSION); + version_text = cstring_to_text(version); + PG_RETURN_TEXT_P(version_text); } PG_FUNCTION_INFO_V1(pc_pgsql_version); Datum pc_pgsql_version(PG_FUNCTION_ARGS) { - text *version_text; - char version[12]; - snprintf(version, 12, "%d", PGSQL_VERSION); - version_text = cstring_to_text(version); - PG_RETURN_TEXT_P(version_text); + text *version_text; + char version[12]; + snprintf(version, 12, "%d", PGSQL_VERSION); + version_text = cstring_to_text(version); + PG_RETURN_TEXT_P(version_text); } PG_FUNCTION_INFO_V1(pc_libxml2_version); Datum pc_libxml2_version(PG_FUNCTION_ARGS) { - text *version_text; - char version[64]; - snprintf(version, 64, "%s", LIBXML2_VERSION); - version_text = cstring_to_text(version); - PG_RETURN_TEXT_P(version_text); + text *version_text; + char version[64]; + snprintf(version, 64, "%s", LIBXML2_VERSION); + version_text = cstring_to_text(version); + PG_RETURN_TEXT_P(version_text); } PG_FUNCTION_INFO_V1(pc_lazperf_enabled); Datum pc_lazperf_enabled(PG_FUNCTION_ARGS) { #ifdef HAVE_LAZPERF - PG_RETURN_BOOL(true); + PG_RETURN_BOOL(true); #else - PG_RETURN_BOOL(false); + PG_RETURN_BOOL(false); #endif } /** -* Read a named dimension statistic from a PCPATCH -* PC_PatchMax(patch pcpatch, dimname text) returns Numeric -* PC_PatchMin(patch pcpatch, dimname text) returns Numeric -* PC_PatchAvg(patch pcpatch, dimname text) returns Numeric -* PC_PatchMax(patch pcpatch) returns PcPoint -* PC_PatchMin(patch pcpatch) returns PcPoint -* PC_PatchAvg(patch pcpatch) returns PcPoint -*/ + * Read a named dimension statistic from a PCPATCH + * PC_PatchMax(patch pcpatch, dimname text) returns Numeric + * PC_PatchMin(patch pcpatch, dimname text) returns Numeric + * PC_PatchAvg(patch pcpatch, dimname text) returns Numeric + * PC_PatchMax(patch pcpatch) returns PcPoint + * PC_PatchMin(patch pcpatch) returns PcPoint + * PC_PatchAvg(patch pcpatch) returns PcPoint + */ PG_FUNCTION_INFO_V1(pcpatch_get_stat); Datum pcpatch_get_stat(PG_FUNCTION_ARGS) { - static int stats_size_guess = 400; - SERIALIZED_PATCH *serpa = PG_GETHEADERX_SERPATCH_P(0, stats_size_guess); - PCSCHEMA *schema = pc_schema_from_pcid(serpa->pcid, fcinfo); - int32 statno = PG_GETARG_INT32(1); - char *dim_str = 0; - PCSTATS *stats; - const PCPOINT *pt; - SERIALIZED_POINT *serpt = NULL; - float8 double_result; - int rv = 1; + static int stats_size_guess = 400; + SERIALIZED_PATCH *serpa = PG_GETHEADERX_SERPATCH_P(0, stats_size_guess); + PCSCHEMA *schema = pc_schema_from_pcid(serpa->pcid, fcinfo); + int32 statno = PG_GETARG_INT32(1); + char *dim_str = 0; + PCSTATS *stats; + const PCPOINT *pt; + SERIALIZED_POINT *serpt = NULL; + float8 double_result; + int rv = 1; + if (PG_NARGS() > 2) + { + /* TODO: only get small slice ? */ + dim_str = text_to_cstring(PG_GETARG_TEXT_P(2)); + } - if ( PG_NARGS() > 2 ) { - /* TODO: only get small slice ? */ - dim_str = text_to_cstring(PG_GETARG_TEXT_P(2)); - } + if (stats_size_guess < pc_stats_size(schema)) + { + serpa = PG_GETHEADERX_SERPATCH_P(0, pc_stats_size(schema)); + } - if ( stats_size_guess < pc_stats_size(schema) ) - { - serpa = PG_GETHEADERX_SERPATCH_P(0, pc_stats_size(schema) ); - } + stats = pc_patch_stats_deserialize(schema, serpa->data); - stats = pc_patch_stats_deserialize(schema, serpa->data); + if (!stats) + PG_RETURN_NULL(); - if ( ! stats ) - PG_RETURN_NULL(); + /* Min */ + if (0 == statno) + pt = &(stats->min); + /* Max */ + else if (1 == statno) + pt = &(stats->max); + /* Avg */ + else if (2 == statno) + pt = &(stats->avg); + /* Unsupported */ + else + elog(ERROR, "stat number \"%d\" is not supported", statno); - /* Min */ - if ( 0 == statno ) - pt = &(stats->min); - /* Max */ - else if ( 1 == statno ) - pt = &(stats->max); - /* Avg */ - else if ( 2 == statno ) - pt = &(stats->avg); - /* Unsupported */ - else - elog(ERROR, "stat number \"%d\" is not supported", statno); - - /* empty dim string means we want the whole point */ - if ( ! dim_str ) - { - serpt = pc_point_serialize(pt); - pc_stats_free(stats); - PG_RETURN_POINTER(serpt); - } - else - { - rv = pc_point_get_double_by_name(pt, dim_str, &double_result); - pc_stats_free(stats); - if ( ! rv ) - { - elog(ERROR, "dimension \"%s\" does not exist in schema", dim_str); - PG_RETURN_NULL(); - } - pfree(dim_str); - PG_RETURN_DATUM(DirectFunctionCall1(float8_numeric, Float8GetDatum(double_result))); - } + /* empty dim string means we want the whole point */ + if (!dim_str) + { + serpt = pc_point_serialize(pt); + pc_stats_free(stats); + PG_RETURN_POINTER(serpt); + } + else + { + rv = pc_point_get_double_by_name(pt, dim_str, &double_result); + pc_stats_free(stats); + if (!rv) + { + elog(ERROR, "dimension \"%s\" does not exist in schema", dim_str); + PG_RETURN_NULL(); + } + pfree(dim_str); + PG_RETURN_DATUM( + DirectFunctionCall1(float8_numeric, Float8GetDatum(double_result))); + } } /** -* PC_FilterLessThan(patch pcpatch, dimname text, value) returns PcPatch -* PC_FilterGreaterThan(patch pcpatch, dimname text, value) returns PcPatch -* PC_FilterEquals(patch pcpatch, dimname text, value) returns PcPatch -* PC_FilterBetween(patch pcpatch, dimname text, value1, value2) returns PcPatch -*/ + * PC_FilterLessThan(patch pcpatch, dimname text, value) returns PcPatch + * PC_FilterGreaterThan(patch pcpatch, dimname text, value) returns PcPatch + * PC_FilterEquals(patch pcpatch, dimname text, value) returns PcPatch + * PC_FilterBetween(patch pcpatch, dimname text, value1, value2) returns PcPatch + */ PG_FUNCTION_INFO_V1(pcpatch_filter); Datum pcpatch_filter(PG_FUNCTION_ARGS) { - SERIALIZED_PATCH *serpatch = PG_GETARG_SERPATCH_P(0); - PCSCHEMA *schema = pc_schema_from_pcid(serpatch->pcid, fcinfo); - char *dim_name = text_to_cstring(PG_GETARG_TEXT_P(1)); - float8 value1 = PG_GETARG_FLOAT8(2); - float8 value2 = PG_GETARG_FLOAT8(3); - int32 mode = PG_GETARG_INT32(4); - PCPATCH *patch; - PCPATCH *patch_filtered = NULL; - SERIALIZED_PATCH *serpatch_filtered; + SERIALIZED_PATCH *serpatch = PG_GETARG_SERPATCH_P(0); + PCSCHEMA *schema = pc_schema_from_pcid(serpatch->pcid, fcinfo); + char *dim_name = text_to_cstring(PG_GETARG_TEXT_P(1)); + float8 value1 = PG_GETARG_FLOAT8(2); + float8 value2 = PG_GETARG_FLOAT8(3); + int32 mode = PG_GETARG_INT32(4); + PCPATCH *patch; + PCPATCH *patch_filtered = NULL; + SERIALIZED_PATCH *serpatch_filtered; - patch = pc_patch_deserialize(serpatch, schema); - if ( ! patch ) - { - elog(ERROR, "failed to deserialize patch"); - PG_RETURN_NULL(); - } + patch = pc_patch_deserialize(serpatch, schema); + if (!patch) + { + elog(ERROR, "failed to deserialize patch"); + PG_RETURN_NULL(); + } - switch ( mode ) - { - case 0: - patch_filtered = pc_patch_filter_lt_by_name(patch, dim_name, value1); - break; - case 1: - patch_filtered = pc_patch_filter_gt_by_name(patch, dim_name, value1); - break; - case 2: - patch_filtered = pc_patch_filter_equal_by_name(patch, dim_name, value1); - break; - case 3: - patch_filtered = pc_patch_filter_between_by_name(patch, dim_name, value1, value2); - break; - default: - elog(ERROR, "unknown mode \"%d\"", mode); - } + switch (mode) + { + case 0: + patch_filtered = pc_patch_filter_lt_by_name(patch, dim_name, value1); + break; + case 1: + patch_filtered = pc_patch_filter_gt_by_name(patch, dim_name, value1); + break; + case 2: + patch_filtered = pc_patch_filter_equal_by_name(patch, dim_name, value1); + break; + case 3: + patch_filtered = + pc_patch_filter_between_by_name(patch, dim_name, value1, value2); + break; + default: + elog(ERROR, "unknown mode \"%d\"", mode); + } - pc_patch_free(patch); - PG_FREE_IF_COPY(serpatch, 0); + pc_patch_free(patch); + PG_FREE_IF_COPY(serpatch, 0); - if ( ! patch_filtered ) - { - elog(ERROR, "dimension \"%s\" does not exist", dim_name); - } - pfree(dim_name); + if (!patch_filtered) + { + elog(ERROR, "dimension \"%s\" does not exist", dim_name); + } + pfree(dim_name); - /* Always treat zero-point patches as SQL NULL */ - if ( patch_filtered->npoints <= 0 ) - { - pc_patch_free(patch_filtered); - PG_RETURN_NULL(); - } + /* Always treat zero-point patches as SQL NULL */ + if (patch_filtered->npoints <= 0) + { + pc_patch_free(patch_filtered); + PG_RETURN_NULL(); + } - serpatch_filtered = pc_patch_serialize(patch_filtered, NULL); - pc_patch_free(patch_filtered); + serpatch_filtered = pc_patch_serialize(patch_filtered, NULL); + pc_patch_free(patch_filtered); - PG_RETURN_POINTER(serpatch_filtered); + PG_RETURN_POINTER(serpatch_filtered); } const char **array_to_cstring_array(ArrayType *array, int *size) { - int i, j, offset = 0; - int nelems = ArrayGetNItems(ARR_NDIM(array), ARR_DIMS(array)); - const char **cstring = nelems ? pcalloc(nelems * sizeof(char*)) : NULL; - bits8 *bitmap = ARR_NULLBITMAP(array); - for(i=j=0; ipcid, fcinfo); + schema = pc_schema_from_pcid(serpatch->pcid, fcinfo); - patch = pc_patch_deserialize(serpatch, schema); - if(patch) patch_sorted = pc_patch_sort(patch,dim_name,ndims); + patch = pc_patch_deserialize(serpatch, schema); + if (patch) + patch_sorted = pc_patch_sort(patch, dim_name, ndims); - pc_cstring_array_free(dim_name,ndims); - if(patch) pc_patch_free(patch); - PG_FREE_IF_COPY(serpatch, 0); + pc_cstring_array_free(dim_name, ndims); + if (patch) + pc_patch_free(patch); + PG_FREE_IF_COPY(serpatch, 0); - if(!patch_sorted) PG_RETURN_NULL(); + if (!patch_sorted) + PG_RETURN_NULL(); - serpatch_sorted = pc_patch_serialize(patch_sorted,NULL); - pc_patch_free(patch_sorted); - PG_RETURN_POINTER(serpatch_sorted); + serpatch_sorted = pc_patch_serialize(patch_sorted, NULL); + pc_patch_free(patch_sorted); + PG_RETURN_POINTER(serpatch_sorted); } /** True/false if the patch is sorted on dimension */ PG_FUNCTION_INFO_V1(pcpatch_is_sorted); Datum pcpatch_is_sorted(PG_FUNCTION_ARGS) { - ArrayType *array = PG_GETARG_ARRAYTYPE_P(1); - bool strict = PG_GETARG_BOOL(2); - PCSCHEMA *schema = NULL; - SERIALIZED_PATCH *serpatch = NULL; - PCPATCH *patch = NULL; - int ndims; - uint32_t res; - const char **dim_name = array_to_cstring_array(array,&ndims); - if(!ndims) - { - pc_cstring_array_free(dim_name,ndims); - PG_RETURN_BOOL(PC_TRUE); - } - serpatch = PG_GETARG_SERPATCH_P(0); - schema = pc_schema_from_pcid(serpatch->pcid, fcinfo); - patch = pc_patch_deserialize(serpatch, schema); + ArrayType *array = PG_GETARG_ARRAYTYPE_P(1); + bool strict = PG_GETARG_BOOL(2); + PCSCHEMA *schema = NULL; + SERIALIZED_PATCH *serpatch = NULL; + PCPATCH *patch = NULL; + int ndims; + uint32_t res; + const char **dim_name = array_to_cstring_array(array, &ndims); + if (!ndims) + { + pc_cstring_array_free(dim_name, ndims); + PG_RETURN_BOOL(PC_TRUE); + } + serpatch = PG_GETARG_SERPATCH_P(0); + schema = pc_schema_from_pcid(serpatch->pcid, fcinfo); + patch = pc_patch_deserialize(serpatch, schema); - res = pc_patch_is_sorted(patch,dim_name,ndims,strict); + res = pc_patch_is_sorted(patch, dim_name, ndims, strict); - pc_cstring_array_free(dim_name,ndims); - pc_patch_free(patch); + pc_cstring_array_free(dim_name, ndims); + pc_patch_free(patch); - if(res == PC_FAILURE-1) - elog(ERROR, "PC_IsSorted failed"); + if (res == PC_FAILURE - 1) + elog(ERROR, "PC_IsSorted failed"); - PG_RETURN_BOOL(res); + PG_RETURN_BOOL(res); } - diff --git a/pgsql/pc_editor.c b/pgsql/pc_editor.c index fec95d8..eb3b773 100644 --- a/pgsql/pc_editor.c +++ b/pgsql/pc_editor.c @@ -1,126 +1,124 @@ /*********************************************************************** -* pc_editor.c -* -* Editor functions for points and patches in PgSQL. -* -* Copyright (c) 2017 Oslandia -* -***********************************************************************/ + * pc_editor.c + * + * Editor functions for points and patches in PgSQL. + * + * Copyright (c) 2017 Oslandia + * + ***********************************************************************/ -#include "pc_pgsql.h" /* Common PgSQL support for our type */ +#include "pc_pgsql.h" /* Common PgSQL support for our type */ Datum pcpatch_setpcid(PG_FUNCTION_ARGS); Datum pcpatch_transform(PG_FUNCTION_ARGS); - -static SERIALIZED_PATCH * -pcpatch_set_schema(SERIALIZED_PATCH *serpa, - PCSCHEMA *oschema, PCSCHEMA *nschema, float8 def) +static SERIALIZED_PATCH *pcpatch_set_schema(SERIALIZED_PATCH *serpa, + PCSCHEMA *oschema, + PCSCHEMA *nschema, float8 def) { - SERIALIZED_PATCH *serpatch; - PCPATCH *paout; + SERIALIZED_PATCH *serpatch; + PCPATCH *paout; - if ( pc_schema_same_dimensions(oschema, nschema) ) - { - // oschema and nschema have the same dimensions at the same - // positions, so we can take a fast path and avoid the - // point-by-point dimension-by-dimension copying + if (pc_schema_same_dimensions(oschema, nschema)) + { + // oschema and nschema have the same dimensions at the same + // positions, so we can take a fast path and avoid the + // point-by-point dimension-by-dimension copying - if ( oschema->compression == nschema->compression ) - { - // no need to deserialize the patch - serpatch = palloc(serpa->size); - if ( ! serpatch ) - return NULL; - memcpy(serpatch, serpa, serpa->size); - serpatch->pcid = nschema->pcid; - return serpatch; - } - else - { - paout = pc_patch_deserialize(serpa, oschema); - if ( ! paout ) - return NULL; - paout->schema = nschema; - } - } else { - PCPATCH *patch; + if (oschema->compression == nschema->compression) + { + // no need to deserialize the patch + serpatch = palloc(serpa->size); + if (!serpatch) + return NULL; + memcpy(serpatch, serpa, serpa->size); + serpatch->pcid = nschema->pcid; + return serpatch; + } + else + { + paout = pc_patch_deserialize(serpa, oschema); + if (!paout) + return NULL; + paout->schema = nschema; + } + } + else + { + PCPATCH *patch; - patch = pc_patch_deserialize(serpa, oschema); - if ( ! patch ) - return NULL; + patch = pc_patch_deserialize(serpa, oschema); + if (!patch) + return NULL; - paout = pc_patch_set_schema(patch, nschema, def); + paout = pc_patch_set_schema(patch, nschema, def); - if ( patch != paout ) - pc_patch_free(patch); + if (patch != paout) + pc_patch_free(patch); - if ( ! paout ) - return NULL; + if (!paout) + return NULL; + } - } + serpatch = pc_patch_serialize(paout, NULL); + pc_patch_free(paout); - serpatch = pc_patch_serialize(paout, NULL); - pc_patch_free(paout); - - return serpatch; + return serpatch; } - PG_FUNCTION_INFO_V1(pcpatch_setpcid); Datum pcpatch_setpcid(PG_FUNCTION_ARGS) { - SERIALIZED_PATCH *serpatch; - SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0); - int32 pcid = PG_GETARG_INT32(1); - float8 def = PG_GETARG_FLOAT8(2); - PCSCHEMA *oschema = pc_schema_from_pcid(serpa->pcid, fcinfo); - PCSCHEMA *nschema = pc_schema_from_pcid(pcid, fcinfo); + SERIALIZED_PATCH *serpatch; + SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0); + int32 pcid = PG_GETARG_INT32(1); + float8 def = PG_GETARG_FLOAT8(2); + PCSCHEMA *oschema = pc_schema_from_pcid(serpa->pcid, fcinfo); + PCSCHEMA *nschema = pc_schema_from_pcid(pcid, fcinfo); - serpatch = pcpatch_set_schema(serpa, oschema, nschema, def); - if ( ! serpatch ) - PG_RETURN_NULL(); - PG_RETURN_POINTER(serpatch); + serpatch = pcpatch_set_schema(serpa, oschema, nschema, def); + if (!serpatch) + PG_RETURN_NULL(); + PG_RETURN_POINTER(serpatch); } - PG_FUNCTION_INFO_V1(pcpatch_transform); Datum pcpatch_transform(PG_FUNCTION_ARGS) { - SERIALIZED_PATCH *serpatch; - SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0); - int32 pcid = PG_GETARG_INT32(1); - float8 def = PG_GETARG_FLOAT8(2); - PCSCHEMA *oschema = pc_schema_from_pcid(serpa->pcid, fcinfo); - PCSCHEMA *nschema = pc_schema_from_pcid(pcid, fcinfo); + SERIALIZED_PATCH *serpatch; + SERIALIZED_PATCH *serpa = PG_GETARG_SERPATCH_P(0); + int32 pcid = PG_GETARG_INT32(1); + float8 def = PG_GETARG_FLOAT8(2); + PCSCHEMA *oschema = pc_schema_from_pcid(serpa->pcid, fcinfo); + PCSCHEMA *nschema = pc_schema_from_pcid(pcid, fcinfo); - // fast path to setpcid if no data transformation is required + // fast path to setpcid if no data transformation is required - if ( pc_schema_same_interpretations(oschema, nschema) ) - { - serpatch = pcpatch_set_schema(serpa, oschema, nschema, def); - if ( ! serpatch ) - PG_RETURN_NULL(); - PG_RETURN_POINTER(serpatch); - } - else - { - PCPATCH *patch, *paout; + if (pc_schema_same_interpretations(oschema, nschema)) + { + serpatch = pcpatch_set_schema(serpa, oschema, nschema, def); + if (!serpatch) + PG_RETURN_NULL(); + PG_RETURN_POINTER(serpatch); + } + else + { + PCPATCH *patch, *paout; - patch = pc_patch_deserialize(serpa, oschema); - if ( ! patch ) - PG_RETURN_NULL(); + patch = pc_patch_deserialize(serpa, oschema); + if (!patch) + PG_RETURN_NULL(); - paout = pc_patch_transform(patch, nschema, def); + paout = pc_patch_transform(patch, nschema, def); - pc_patch_free(patch); + pc_patch_free(patch); - if ( ! paout ) - PG_RETURN_NULL(); + if (!paout) + PG_RETURN_NULL(); - serpatch = pc_patch_serialize(paout, NULL); - pc_patch_free(paout); + serpatch = pc_patch_serialize(paout, NULL); + pc_patch_free(paout); - PG_RETURN_POINTER(serpatch); - } + PG_RETURN_POINTER(serpatch); + } } diff --git a/pgsql/pc_inout.c b/pgsql/pc_inout.c index 05223f1..f9a74fa 100644 --- a/pgsql/pc_inout.c +++ b/pgsql/pc_inout.c @@ -1,15 +1,15 @@ /*********************************************************************** -* pc_inout.c -* -* Input/output functions for points and patches in PgSQL. -* -* PgSQL Pointcloud is free and open source software provided -* by the Government of Canada -* Copyright (c) 2013 Natural Resources Canada -* -***********************************************************************/ + * pc_inout.c + * + * Input/output functions for points and patches in PgSQL. + * + * PgSQL Pointcloud is free and open source software provided + * by the Government of Canada + * Copyright (c) 2013 Natural Resources Canada + * + ***********************************************************************/ -#include "pc_pgsql.h" /* Common PgSQL support for our type */ +#include "pc_pgsql.h" /* Common PgSQL support for our type */ /* In/out functions */ Datum pcpoint_in(PG_FUNCTION_ARGS); @@ -34,437 +34,437 @@ Datum pcpoint_as_bytea(PG_FUNCTION_ARGS); Datum pcpatch_envelope_as_bytea(PG_FUNCTION_ARGS); Datum pcpatch_bounding_diagonal_as_bytea(PG_FUNCTION_ARGS); - -static void -pcid_consistent(const uint32 pcid, const uint32 column_pcid) +static void pcid_consistent(const uint32 pcid, const uint32 column_pcid) { - if ( column_pcid && pcid != column_pcid ) - { - ereport(ERROR, ( - errcode(ERRCODE_DATATYPE_MISMATCH), - errmsg("point/patch pcid (%u) does not match column pcid (%d)", pcid, column_pcid) - )); - } + if (column_pcid && pcid != column_pcid) + { + ereport(ERROR, + (errcode(ERRCODE_DATATYPE_MISMATCH), + errmsg("point/patch pcid (%u) does not match column pcid (%d)", + pcid, column_pcid))); + } } - PG_FUNCTION_INFO_V1(pcpoint_in); 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; + 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); - } + 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"))); - } + /* 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"))); - } + /* 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(); + if (serpt) + PG_RETURN_POINTER(serpt); + else + PG_RETURN_NULL(); } PG_FUNCTION_INFO_V1(pcpoint_out); Datum pcpoint_out(PG_FUNCTION_ARGS) { - PCPOINT *pcpt = NULL; - PCSCHEMA *schema = NULL; - SERIALIZED_POINT *serpt = NULL; - char *hexwkb = NULL; + 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); + 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); } - PG_FUNCTION_INFO_V1(pcpatch_in); Datum pcpatch_in(PG_FUNCTION_ARGS) { - char *str = PG_GETARG_CSTRING(0); - /* Datum geog_oid = PG_GETARG_OID(1); Not needed. */ - uint32 typmod = 0, pcid = 0; - PCPATCH *patch; - SERIALIZED_PATCH *serpatch = NULL; + char *str = PG_GETARG_CSTRING(0); + /* Datum geog_oid = PG_GETARG_OID(1); Not needed. */ + uint32 typmod = 0, pcid = 0; + PCPATCH *patch; + SERIALIZED_PATCH *serpatch = NULL; - if ( (PG_NARGS()>2) && (!PG_ARGISNULL(2)) ) - { - typmod = PG_GETARG_INT32(2); - pcid = pcid_from_typmod(typmod); - } + 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("pcpatch parse error - empty string"))); - } + /* Empty string. */ + if (str[0] == '\0') + { + ereport(ERROR, (errmsg("pcpatch parse error - empty string"))); + } - /* Binary or text form? Let's find out. */ - if ( str[0] == '0' ) - { - /* Hex-encoded binary */ - patch = pc_patch_from_hexwkb(str, strlen(str), fcinfo); - pcid_consistent(patch->schema->pcid, pcid); - serpatch = pc_patch_serialize(patch, NULL); - pc_patch_free(patch); - } - else - { - ereport(ERROR,(errmsg("parse error - support for text format not yet implemented"))); - } + /* Binary or text form? Let's find out. */ + if (str[0] == '0') + { + /* Hex-encoded binary */ + patch = pc_patch_from_hexwkb(str, strlen(str), fcinfo); + pcid_consistent(patch->schema->pcid, pcid); + serpatch = pc_patch_serialize(patch, NULL); + pc_patch_free(patch); + } + else + { + ereport( + ERROR, + (errmsg("parse error - support for text format not yet implemented"))); + } - if ( serpatch ) PG_RETURN_POINTER(serpatch); - else PG_RETURN_NULL(); + if (serpatch) + PG_RETURN_POINTER(serpatch); + else + PG_RETURN_NULL(); } PG_FUNCTION_INFO_V1(pcpatch_out); Datum pcpatch_out(PG_FUNCTION_ARGS) { - PCPATCH *patch = NULL; - SERIALIZED_PATCH *serpatch = NULL; - char *hexwkb = NULL; - PCSCHEMA *schema = NULL; + 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); + 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); } PG_FUNCTION_INFO_V1(pcschema_is_valid); Datum pcschema_is_valid(PG_FUNCTION_ARGS) { - bool valid; - text *xml = PG_GETARG_TEXT_P(0); - char *xmlstr = text_to_cstring(xml); - PCSCHEMA *schema = pc_schema_from_xml(xmlstr); - pfree(xmlstr); + bool valid; + text *xml = PG_GETARG_TEXT_P(0); + char *xmlstr = text_to_cstring(xml); + PCSCHEMA *schema = pc_schema_from_xml(xmlstr); + pfree(xmlstr); - if ( !schema ) - { - PG_RETURN_BOOL(false); - } + if (!schema) + { + PG_RETURN_BOOL(false); + } - valid = pc_schema_is_valid(schema); - pc_schema_free(schema); - PG_RETURN_BOOL(valid); + valid = pc_schema_is_valid(schema); + pc_schema_free(schema); + PG_RETURN_BOOL(valid); } PG_FUNCTION_INFO_V1(pcschema_get_ndims); Datum pcschema_get_ndims(PG_FUNCTION_ARGS) { - int ndims; - uint32 pcid = PG_GETARG_INT32(0); - PCSCHEMA *schema = pc_schema_from_pcid(pcid, fcinfo); + 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); + if (!schema) + elog(ERROR, "unable to load schema for pcid = %d", pcid); - ndims = schema->ndims; - PG_RETURN_INT32(ndims); + ndims = schema->ndims; + PG_RETURN_INT32(ndims); } /** -* pcpoint_from_double_array(integer pcid, float8[] returns PcPoint -*/ + * pcpoint_from_double_array(integer pcid, float8[] returns PcPoint + */ PG_FUNCTION_INFO_V1(pcpoint_from_double_array); 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; + 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 (!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_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_NDIM(arrptr) != 1) + elog(ERROR, "float8[] must have only one dimension"); - if ( ARR_HASNULL(arrptr) ) - elog(ERROR, "float8[] must not have null elements"); + 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); + 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, 0, nelems); + vals = (float8 *)ARR_DATA_PTR(arrptr); + pt = pc_point_from_double_array(schema, vals, 0, nelems); - serpt = pc_point_serialize(pt); - pc_point_free(pt); - PG_RETURN_POINTER(serpt); + serpt = pc_point_serialize(pt); + pc_point_free(pt); + PG_RETURN_POINTER(serpt); } PG_FUNCTION_INFO_V1(pcpoint_as_text); 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(); + 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); + str = pc_point_to_string(pt); + pc_point_free(pt); + txt = cstring_to_text(str); + pfree(str); + PG_RETURN_TEXT_P(txt); } PG_FUNCTION_INFO_V1(pcpatch_as_text); 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(); + 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); + str = pc_patch_to_string(patch); + pc_patch_free(patch); + txt = cstring_to_text(str); + pfree(str); + PG_RETURN_TEXT_P(txt); } PG_FUNCTION_INFO_V1(pcpoint_as_bytea); 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); + 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(); + 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); + 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); + pc_point_free(pt); + pfree(bytes); - PG_RETURN_BYTEA_P(wkb); + PG_RETURN_BYTEA_P(wkb); } PG_FUNCTION_INFO_V1(pcpatch_envelope_as_bytea); Datum pcpatch_envelope_as_bytea(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); + 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); + 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); + pfree(bytes); - PG_RETURN_BYTEA_P(wkb); + PG_RETURN_BYTEA_P(wkb); } PG_FUNCTION_INFO_V1(pcpatch_bounding_diagonal_as_bytea); Datum pcpatch_bounding_diagonal_as_bytea(PG_FUNCTION_ARGS) { - static const size_t stats_size_guess = 400; - SERIALIZED_PATCH *serpatch; - PCSCHEMA *schema; - PCSTATS *stats; - uint8 *bytes; - size_t bytes_size; - bytea *wkb; - size_t wkb_size; + static const size_t stats_size_guess = 400; + SERIALIZED_PATCH *serpatch; + PCSCHEMA *schema; + PCSTATS *stats; + uint8 *bytes; + size_t bytes_size; + bytea *wkb; + size_t wkb_size; - serpatch = PG_GETHEADERX_SERPATCH_P(0, stats_size_guess); - schema = pc_schema_from_pcid(serpatch->pcid, fcinfo); + serpatch = PG_GETHEADERX_SERPATCH_P(0, stats_size_guess); + schema = pc_schema_from_pcid(serpatch->pcid, fcinfo); - if ( schema->zdim || schema->mdim ) - { - if ( stats_size_guess < pc_stats_size(schema) ) - serpatch = PG_GETHEADERX_SERPATCH_P(0, pc_stats_size(schema)); + if (schema->zdim || schema->mdim) + { + if (stats_size_guess < pc_stats_size(schema)) + serpatch = PG_GETHEADERX_SERPATCH_P(0, pc_stats_size(schema)); - stats = pc_patch_stats_deserialize(schema, serpatch->data); - if ( !stats ) - PG_RETURN_NULL(); + stats = pc_patch_stats_deserialize(schema, serpatch->data); + if (!stats) + PG_RETURN_NULL(); - bytes = pc_bounding_diagonal_wkb_from_stats(stats, &bytes_size); + bytes = pc_bounding_diagonal_wkb_from_stats(stats, &bytes_size); - pc_stats_free(stats); - } - else - { - bytes = pc_bounding_diagonal_wkb_from_bounds( - &serpatch->bounds, schema, &bytes_size); - } + pc_stats_free(stats); + } + else + { + bytes = pc_bounding_diagonal_wkb_from_bounds(&serpatch->bounds, schema, + &bytes_size); + } - wkb_size = VARHDRSZ + bytes_size; - wkb = palloc(wkb_size); - memcpy(VARDATA(wkb), bytes, bytes_size); - SET_VARSIZE(wkb, wkb_size); + wkb_size = VARHDRSZ + bytes_size; + wkb = palloc(wkb_size); + memcpy(VARDATA(wkb), bytes, bytes_size); + SET_VARSIZE(wkb, wkb_size); - pcfree(bytes); + pcfree(bytes); - PG_RETURN_BYTEA_P(wkb); + PG_RETURN_BYTEA_P(wkb); } PG_FUNCTION_INFO_V1(pc_typmod_in); Datum pc_typmod_in(PG_FUNCTION_ARGS) { - uint32 typmod = 0; - Datum *elem_values; - int n = 0; - int i = 0; - ArrayType *arr = (ArrayType *) DatumGetPointer(PG_GETARG_DATUM(0)); + uint32 typmod = 0; + Datum *elem_values; + int n = 0; + int i = 0; + ArrayType *arr = (ArrayType *)DatumGetPointer(PG_GETARG_DATUM(0)); - if (ARR_ELEMTYPE(arr) != CSTRINGOID) - ereport(ERROR, - (errcode(ERRCODE_ARRAY_ELEMENT_ERROR), - errmsg("typmod array must be type cstring[]"))); + if (ARR_ELEMTYPE(arr) != CSTRINGOID) + ereport(ERROR, (errcode(ERRCODE_ARRAY_ELEMENT_ERROR), + errmsg("typmod array must be type cstring[]"))); - if (ARR_NDIM(arr) != 1) - ereport(ERROR, - (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), - errmsg("typmod array must be one-dimensional"))); + if (ARR_NDIM(arr) != 1) + ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), + errmsg("typmod array must be one-dimensional"))); - if (ARR_HASNULL(arr)) - ereport(ERROR, - (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), - errmsg("typmod array must not contain nulls"))); + if (ARR_HASNULL(arr)) + ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), + errmsg("typmod array must not contain nulls"))); - if (ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr)) > 1) - ereport(ERROR, - (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), - errmsg("typmod array must have one element"))); + if (ArrayGetNItems(ARR_NDIM(arr), ARR_DIMS(arr)) > 1) + ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), + errmsg("typmod array must have one element"))); - deconstruct_array(arr, - CSTRINGOID, -2, false, 'c', /* hardwire cstring representation details */ - &elem_values, NULL, &n); + deconstruct_array(arr, CSTRINGOID, -2, false, + 'c', /* hardwire cstring representation details */ + &elem_values, NULL, &n); - for (i = 0; i < n; i++) - { - if ( i == 0 ) /* PCID */ - { - char *s = DatumGetCString(elem_values[i]); - typmod = pg_atoi(s, sizeof(int32), '\0'); - } - } + for (i = 0; i < n; i++) + { + if (i == 0) /* PCID */ + { + char *s = DatumGetCString(elem_values[i]); + typmod = pg_atoi(s, sizeof(int32), '\0'); + } + } - PG_RETURN_INT32(typmod); + PG_RETURN_INT32(typmod); } PG_FUNCTION_INFO_V1(pc_typmod_out); Datum pc_typmod_out(PG_FUNCTION_ARGS) { - char *str = (char*)palloc(64); - uint32 typmod = PG_GETARG_INT32(0); - uint32 pcid = pcid_from_typmod(typmod); + char *str = (char *)palloc(64); + uint32 typmod = PG_GETARG_INT32(0); + uint32 pcid = pcid_from_typmod(typmod); - - /* No PCID value? Then no typmod at all. Return empty string. */ - if ( ! pcid ) - { - str[0] = '\0'; - PG_RETURN_CSTRING(str); - } - else - { - sprintf(str, "(%u)", pcid); - PG_RETURN_CSTRING(str); - } + /* No PCID value? Then no typmod at all. Return empty string. */ + if (!pcid) + { + str[0] = '\0'; + PG_RETURN_CSTRING(str); + } + else + { + sprintf(str, "(%u)", pcid); + PG_RETURN_CSTRING(str); + } } - PG_FUNCTION_INFO_V1(pc_typmod_pcid); Datum pc_typmod_pcid(PG_FUNCTION_ARGS) { - uint32 typmod = PG_GETARG_INT32(0); - uint32 pcid = pcid_from_typmod(typmod); - if ( ! pcid ) - PG_RETURN_NULL(); - else - PG_RETURN_INT32(pcid); + uint32 typmod = PG_GETARG_INT32(0); + uint32 pcid = pcid_from_typmod(typmod); + if (!pcid) + PG_RETURN_NULL(); + else + PG_RETURN_INT32(pcid); } - PG_FUNCTION_INFO_V1(pcpatch_enforce_typmod); 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); */ + 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); + /* 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); + PG_RETURN_POINTER(arg); } PG_FUNCTION_INFO_V1(pcpoint_enforce_typmod); Datum pcpoint_enforce_typmod(PG_FUNCTION_ARGS) { - SERIALIZED_POINT *arg = PG_GETARG_SERPOINT_P(0); - int32 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); */ + SERIALIZED_POINT *arg = PG_GETARG_SERPOINT_P(0); + int32 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 point pcid (%d) are not consistent", pcid, arg->pcid); + /* Check if column typmod is consistent with the object */ + if (pcid != arg->pcid) + elog(ERROR, "column pcid (%d) and point pcid (%d) are not consistent", pcid, + arg->pcid); - PG_RETURN_POINTER(arg); + PG_RETURN_POINTER(arg); } diff --git a/pgsql/pc_pgsql.c b/pgsql/pc_pgsql.c index da51f8c..6fd0746 100644 --- a/pgsql/pc_pgsql.c +++ b/pgsql/pc_pgsql.c @@ -1,351 +1,328 @@ /*********************************************************************** -* pc_pgsql.c -* -* Utility functions to bind pc_api.h functions to PgSQL, including -* memory management and serialization/deserializations. -* -* PgSQL Pointcloud is free and open source software provided -* by the Government of Canada -* Copyright (c) 2013 Natural Resources Canada -* -***********************************************************************/ + * pc_pgsql.c + * + * Utility functions to bind pc_api.h functions to PgSQL, including + * memory management and serialization/deserializations. + * + * PgSQL Pointcloud is free and open source software provided + * by the Government of Canada + * Copyright (c) 2013 Natural Resources Canada + * + ***********************************************************************/ -#include #include "pc_pgsql.h" -#include "executor/spi.h" #include "access/hash.h" +#include "executor/spi.h" #include "utils/hsearch.h" +#include PG_MODULE_MAGIC; /********************************************************************************** -* POSTGRESQL MEMORY MANAGEMENT HOOKS -*/ + * POSTGRESQL MEMORY MANAGEMENT HOOKS + */ -static void * -pgsql_alloc(size_t size) +static void *pgsql_alloc(size_t size) { - void * result; - result = palloc(size); + void *result; + result = palloc(size); - if ( ! result ) - { - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("Out of virtual memory"))); - } + if (!result) + { + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Out of virtual memory"))); + } - return result; + return result; } -static void * -pgsql_realloc(void *mem, size_t size) +static void *pgsql_realloc(void *mem, size_t size) { - void * result; - result = repalloc(mem, size); - if ( ! result ) - { - ereport(ERROR, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("Out of virtual memory"))); - } - return result; + void *result; + result = repalloc(mem, size); + if (!result) + { + ereport(ERROR, + (errcode(ERRCODE_OUT_OF_MEMORY), errmsg("Out of virtual memory"))); + } + return result; } -static void -pgsql_free(void *ptr) -{ - pfree(ptr); -} +static void pgsql_free(void *ptr) { pfree(ptr); } -static void -pgsql_msg_handler(int sig, const char *fmt, va_list ap) - __attribute__ (( format (printf, 2, 0) )); +static void pgsql_msg_handler(int sig, const char *fmt, va_list ap) + __attribute__((format(printf, 2, 0))); -static void -pgsql_msg_handler(int sig, const char *fmt, va_list ap) +static void pgsql_msg_handler(int sig, const char *fmt, va_list ap) { #define MSG_MAXLEN 1024 - char msg[MSG_MAXLEN] = {0}; - vsnprintf(msg, MSG_MAXLEN, fmt, ap); - msg[MSG_MAXLEN-1] = '\0'; - ereport(sig, (errmsg_internal("%s", msg))); + char msg[MSG_MAXLEN] = {0}; + vsnprintf(msg, MSG_MAXLEN, fmt, ap); + msg[MSG_MAXLEN - 1] = '\0'; + ereport(sig, (errmsg_internal("%s", msg))); } -static void -pgsql_error(const char *fmt, va_list ap) __attribute__ (( format (printf, 1, 0) )); +static void pgsql_error(const char *fmt, va_list ap) + __attribute__((format(printf, 1, 0))); -static void -pgsql_error(const char *fmt, va_list ap) +static void pgsql_error(const char *fmt, va_list ap) { - pgsql_msg_handler(ERROR, fmt, ap); + pgsql_msg_handler(ERROR, fmt, ap); } -static void -pgsql_warn(const char *fmt, va_list ap) __attribute__ (( format (printf, 1, 0) )); +static void pgsql_warn(const char *fmt, va_list ap) + __attribute__((format(printf, 1, 0))); -static void -pgsql_warn(const char *fmt, va_list ap) +static void pgsql_warn(const char *fmt, va_list ap) { - pgsql_msg_handler(WARNING, fmt, ap); + pgsql_msg_handler(WARNING, fmt, ap); } -static void -pgsql_info(const char *fmt, va_list ap) __attribute__ (( format (printf, 1, 0) )); +static void pgsql_info(const char *fmt, va_list ap) + __attribute__((format(printf, 1, 0))); -static void -pgsql_info(const char *fmt, va_list ap) +static void pgsql_info(const char *fmt, va_list ap) { - pgsql_msg_handler(NOTICE, fmt, ap); + pgsql_msg_handler(NOTICE, fmt, ap); } /********************************************************************************** -* POINTCLOUD START-UP/SHUT-DOWN CALLBACKS -*/ + * POINTCLOUD START-UP/SHUT-DOWN CALLBACKS + */ /** -* On module load we want to hook the message writing and memory allocation -* functions of libpc to the PostgreSQL ones. -* TODO: also hook the libxml2 hooks into PostgreSQL. -*/ + * On module load we want to hook the message writing and memory allocation + * functions of libpc to the PostgreSQL ones. + * TODO: also hook the libxml2 hooks into PostgreSQL. + */ void _PG_init(void); -void -_PG_init(void) +void _PG_init(void) { - elog(LOG, "Pointcloud (%s) module loaded", POINTCLOUD_VERSION); - pc_set_handlers( - pgsql_alloc, pgsql_realloc, - pgsql_free, pgsql_error, - pgsql_info, pgsql_warn - ); - + elog(LOG, "Pointcloud (%s) module loaded", POINTCLOUD_VERSION); + pc_set_handlers(pgsql_alloc, pgsql_realloc, pgsql_free, pgsql_error, + pgsql_info, pgsql_warn); } /* Module unload callback */ void _PG_fini(void); -void -_PG_fini(void) +void _PG_fini(void) { - elog(LOG, "Pointcloud (%s) module unloaded", POINTCLOUD_VERSION); + elog(LOG, "Pointcloud (%s) module unloaded", POINTCLOUD_VERSION); } /* Mask pcid from bottom of typmod */ uint32 pcid_from_typmod(const int32 typmod) { - if ( typmod == -1 ) - return 0; - else - return (typmod & 0x0000FFFF); + if (typmod == -1) + return 0; + else + return (typmod & 0x0000FFFF); } /********************************************************************************** -* PCPOINT WKB Handling -*/ + * PCPOINT WKB Handling + */ PCPOINT * #if PGSQL_VERSION < 120 -pc_point_from_hexwkb(const char *hexwkb, size_t hexlen, FunctionCallInfoData *fcinfo) +pc_point_from_hexwkb(const char *hexwkb, size_t hexlen, + FunctionCallInfoData *fcinfo) #else pc_point_from_hexwkb(const char *hexwkb, size_t hexlen, FunctionCallInfo fcinfo) #endif { - PCPOINT *pt; - PCSCHEMA *schema; - uint32 pcid; - uint8 *wkb = pc_bytes_from_hexbytes(hexwkb, hexlen); - size_t wkblen = hexlen/2; - pcid = pc_wkb_get_pcid(wkb); - schema = pc_schema_from_pcid(pcid, fcinfo); - pt = pc_point_from_wkb(schema, wkb, wkblen); - pfree(wkb); - return pt; + PCPOINT *pt; + PCSCHEMA *schema; + uint32 pcid; + uint8 *wkb = pc_bytes_from_hexbytes(hexwkb, hexlen); + size_t wkblen = hexlen / 2; + pcid = pc_wkb_get_pcid(wkb); + schema = pc_schema_from_pcid(pcid, fcinfo); + pt = pc_point_from_wkb(schema, wkb, wkblen); + pfree(wkb); + return pt; } -char * -pc_point_to_hexwkb(const PCPOINT *pt) +char *pc_point_to_hexwkb(const PCPOINT *pt) { - uint8 *wkb; - size_t wkb_size; - char *hexwkb; + uint8 *wkb; + size_t wkb_size; + char *hexwkb; - wkb = pc_point_to_wkb(pt, &wkb_size); - hexwkb = pc_hexbytes_from_bytes(wkb, wkb_size); - pfree(wkb); - return hexwkb; + wkb = pc_point_to_wkb(pt, &wkb_size); + hexwkb = pc_hexbytes_from_bytes(wkb, wkb_size); + pfree(wkb); + return hexwkb; } - /********************************************************************************** -* PCPATCH WKB Handling -*/ + * PCPATCH WKB Handling + */ PCPATCH * #if PGSQL_VERSION < 120 -pc_patch_from_hexwkb(const char *hexwkb, size_t hexlen, FunctionCallInfoData *fcinfo) +pc_patch_from_hexwkb(const char *hexwkb, size_t hexlen, + FunctionCallInfoData *fcinfo) #else pc_patch_from_hexwkb(const char *hexwkb, size_t hexlen, FunctionCallInfo fcinfo) #endif { - PCPATCH *patch; - PCSCHEMA *schema; - uint32 pcid; - uint8 *wkb = pc_bytes_from_hexbytes(hexwkb, hexlen); - size_t wkblen = hexlen/2; - pcid = pc_wkb_get_pcid(wkb); - if ( ! pcid ) - elog(ERROR, "%s: pcid is zero", __func__); + PCPATCH *patch; + PCSCHEMA *schema; + uint32 pcid; + uint8 *wkb = pc_bytes_from_hexbytes(hexwkb, hexlen); + size_t wkblen = hexlen / 2; + pcid = pc_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__); + 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; + patch = pc_patch_from_wkb(schema, wkb, wkblen); + pfree(wkb); + return patch; } -char * -pc_patch_to_hexwkb(const PCPATCH *patch) +char *pc_patch_to_hexwkb(const PCPATCH *patch) { - uint8 *wkb; - size_t wkb_size; - char *hexwkb; + uint8 *wkb; + size_t wkb_size; + char *hexwkb; - wkb = pc_patch_to_wkb(patch, &wkb_size); - hexwkb = pc_hexbytes_from_bytes(wkb, wkb_size); - pfree(wkb); - return hexwkb; + wkb = pc_patch_to_wkb(patch, &wkb_size); + hexwkb = pc_hexbytes_from_bytes(wkb, wkb_size); + pfree(wkb); + return hexwkb; } - /********************************************************************************** -* PCID <=> PCSCHEMA translation via POINTCLOUD_FORMATS -*/ + * PCID <=> PCSCHEMA translation via POINTCLOUD_FORMATS + */ uint32 pcid_from_datum(Datum d) { - SERIALIZED_POINT *serpart; - if ( ! d ) - return 0; - /* Serializations are int32_t uint32_t == 8 bytes */ - /* Cast to SERIALIZED_POINT for convenience, SERIALIZED_PATCH shares same header */ - serpart = (SERIALIZED_POINT*)PG_DETOAST_DATUM_SLICE(d, 0, 8); - return serpart->pcid; + SERIALIZED_POINT *serpart; + if (!d) + return 0; + /* Serializations are int32_t uint32_t == 8 bytes */ + /* Cast to SERIALIZED_POINT for convenience, SERIALIZED_PATCH shares same + * header */ + serpart = (SERIALIZED_POINT *)PG_DETOAST_DATUM_SLICE(d, 0, 8); + return serpart->pcid; } -PCSCHEMA * -pc_schema_from_pcid_uncached(uint32 pcid) +PCSCHEMA *pc_schema_from_pcid_uncached(uint32 pcid) { - char sql[256]; - char *xml, *xml_spi, *srid_spi; - int err, srid; - size_t size; - PCSCHEMA *schema; + char sql[256]; + char *xml, *xml_spi, *srid_spi; + int err, srid; + size_t size; + PCSCHEMA *schema; - if (SPI_OK_CONNECT != SPI_connect ()) - { - SPI_finish(); - elog(ERROR, "%s: could not connect to SPI manager", __func__); - return NULL; - } + if (SPI_OK_CONNECT != SPI_connect()) + { + SPI_finish(); + elog(ERROR, "%s: could not connect to SPI manager", __func__); + return NULL; + } - sprintf(sql, "select %s, %s from %s where pcid = %d", - POINTCLOUD_FORMATS_XML, POINTCLOUD_FORMATS_SRID, POINTCLOUD_FORMATS, pcid); - err = SPI_exec(sql, 1); + sprintf(sql, "select %s, %s from %s where pcid = %d", POINTCLOUD_FORMATS_XML, + POINTCLOUD_FORMATS_SRID, POINTCLOUD_FORMATS, pcid); + err = SPI_exec(sql, 1); - if ( err < 0 ) - { - SPI_finish(); - elog(ERROR, "%s: error (%d) executing query: %s", __func__, err, sql); - return NULL; - } + if (err < 0) + { + SPI_finish(); + elog(ERROR, "%s: error (%d) executing query: %s", __func__, err, sql); + return NULL; + } - /* No entry in POINTCLOUD_FORMATS */ - if (SPI_processed <= 0) - { - SPI_finish(); - elog(ERROR, "no entry in \"%s\" for pcid = %d", POINTCLOUD_FORMATS, pcid); - return NULL; - } + /* No entry in POINTCLOUD_FORMATS */ + if (SPI_processed <= 0) + { + SPI_finish(); + elog(ERROR, "no entry in \"%s\" for pcid = %d", POINTCLOUD_FORMATS, pcid); + return NULL; + } - /* Result */ - xml_spi = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1); - srid_spi = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 2); + /* Result */ + xml_spi = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 1); + srid_spi = SPI_getvalue(SPI_tuptable->vals[0], SPI_tuptable->tupdesc, 2); - /* NULL result */ - if ( ! ( xml_spi && srid_spi ) ) - { - SPI_finish(); - elog(ERROR, "unable to read row from \"%s\" for pcid = %d", POINTCLOUD_FORMATS, pcid); - return NULL; - } + /* NULL result */ + if (!(xml_spi && srid_spi)) + { + SPI_finish(); + elog(ERROR, "unable to read row from \"%s\" for pcid = %d", + POINTCLOUD_FORMATS, pcid); + return NULL; + } - /* Copy result to upper executor context */ - size = strlen(xml_spi) + 1; - xml = SPI_palloc(size); - memcpy(xml, xml_spi, size); + /* Copy result to upper executor context */ + size = strlen(xml_spi) + 1; + xml = SPI_palloc(size); + memcpy(xml, xml_spi, size); - /* Parse the SRID string into the function stack */ - srid = atoi(srid_spi); + /* Parse the SRID string into the function stack */ + srid = atoi(srid_spi); - /* Disconnect from SPI, losing all our SPI-allocated memory now... */ - SPI_finish(); + /* Disconnect from SPI, losing all our SPI-allocated memory now... */ + SPI_finish(); - /* Build the schema object */ - schema = pc_schema_from_xml(xml); + /* Build the schema object */ + schema = pc_schema_from_xml(xml); - if ( !schema ) - { - ereport(ERROR, - (errcode(ERRCODE_NOT_AN_XML_DOCUMENT), - errmsg("unable to parse XML for pcid = %d in \"%s\"", pcid, POINTCLOUD_FORMATS))); - } + if (!schema) + { + ereport(ERROR, (errcode(ERRCODE_NOT_AN_XML_DOCUMENT), + errmsg("unable to parse XML for pcid = %d in \"%s\"", pcid, + POINTCLOUD_FORMATS))); + } - schema->pcid = pcid; - schema->srid = srid; + schema->pcid = pcid; + schema->srid = srid; - return schema; + return schema; } - /** -* Hold the schema references in a list. -* We'll just search them linearly, because -* usually we'll have only one per statement -*/ + * Hold the schema references in a list. + * We'll just search them linearly, because + * usually we'll have only one per statement + */ #define SchemaCacheSize 16 typedef struct { - int next_slot; - int pcids[SchemaCacheSize]; - PCSCHEMA* schemas[SchemaCacheSize]; + int next_slot; + int pcids[SchemaCacheSize]; + PCSCHEMA *schemas[SchemaCacheSize]; } SchemaCache; - /** -* Get the schema entry from the schema cache if one exists. -* If it doesn't exist, make a new empty one, cache it, and -* return it. -*/ + * Get the schema entry from the schema cache if one exists. + * If it doesn't exist, make a new empty one, cache it, and + * return it. + */ static SchemaCache * #if PGSQL_VERSION < 120 -GetSchemaCache(FunctionCallInfoData* fcinfo) +GetSchemaCache(FunctionCallInfoData *fcinfo) #else GetSchemaCache(FunctionCallInfo fcinfo) #endif { - SchemaCache *cache = fcinfo->flinfo->fn_extra; - if ( ! cache ) - { - cache = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(SchemaCache)); - memset(cache, 0, sizeof(SchemaCache)); - fcinfo->flinfo->fn_extra = cache; - } - return cache; + SchemaCache *cache = fcinfo->flinfo->fn_extra; + if (!cache) + { + cache = MemoryContextAlloc(fcinfo->flinfo->fn_mcxt, sizeof(SchemaCache)); + memset(cache, 0, sizeof(SchemaCache)); + fcinfo->flinfo->fn_extra = cache; + } + return cache; } - PCSCHEMA * #if PGSQL_VERSION < 120 pc_schema_from_pcid(uint32 pcid, FunctionCallInfoData *fcinfo) @@ -353,614 +330,605 @@ pc_schema_from_pcid(uint32 pcid, FunctionCallInfoData *fcinfo) pc_schema_from_pcid(uint32 pcid, FunctionCallInfo fcinfo) #endif { - SchemaCache *schema_cache = GetSchemaCache(fcinfo); - int i; - PCSCHEMA *schema; - MemoryContext oldcontext; + SchemaCache *schema_cache = GetSchemaCache(fcinfo); + int i; + PCSCHEMA *schema; + MemoryContext oldcontext; - /* Unable to find/make a schema cache? Odd. */ - if ( ! schema_cache ) - { - ereport(ERROR, - (errcode(ERRCODE_INTERNAL_ERROR), - errmsg("unable to create/load statement level schema cache"))); - } + /* Unable to find/make a schema cache? Odd. */ + if (!schema_cache) + { + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("unable to create/load statement level schema cache"))); + } - /* Find our PCID if it's in there (usually it will be first) */ - for ( i = 0; i < SchemaCacheSize; i++ ) - { - if ( schema_cache->pcids[i] == pcid ) - { - return schema_cache->schemas[i]; - } - } + /* Find our PCID if it's in there (usually it will be first) */ + for (i = 0; i < SchemaCacheSize; i++) + { + if (schema_cache->pcids[i] == pcid) + { + return schema_cache->schemas[i]; + } + } - elog(DEBUG1, "schema cache miss, use pc_schema_from_pcid_uncached"); + elog(DEBUG1, "schema cache miss, use pc_schema_from_pcid_uncached"); - /* Not in there, load one the old-fashioned way. */ - oldcontext = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt); - schema = pc_schema_from_pcid_uncached(pcid); - MemoryContextSwitchTo(oldcontext); + /* Not in there, load one the old-fashioned way. */ + oldcontext = MemoryContextSwitchTo(fcinfo->flinfo->fn_mcxt); + schema = pc_schema_from_pcid_uncached(pcid); + MemoryContextSwitchTo(oldcontext); - /* Failed to load the XML? Odd. */ - if ( ! schema ) - { - ereport(ERROR, - (errcode(ERRCODE_INTERNAL_ERROR), - errmsg("unable to load schema for pcid %u", pcid))); - } + /* Failed to load the XML? Odd. */ + if (!schema) + { + ereport(ERROR, (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("unable to load schema for pcid %u", pcid))); + } - /* Save the XML in the next unused slot */ - schema_cache->schemas[schema_cache->next_slot] = schema; - schema_cache->pcids[schema_cache->next_slot] = pcid; - schema_cache->next_slot = (schema_cache->next_slot + 1) % SchemaCacheSize; - return schema; + /* Save the XML in the next unused slot */ + schema_cache->schemas[schema_cache->next_slot] = schema; + schema_cache->pcids[schema_cache->next_slot] = pcid; + schema_cache->next_slot = (schema_cache->next_slot + 1) % SchemaCacheSize; + return schema; } - - /********************************************************************************** -* SERIALIZATION/DESERIALIZATION UTILITIES -*/ + * SERIALIZATION/DESERIALIZATION UTILITIES + */ -SERIALIZED_POINT * -pc_point_serialize(const PCPOINT *pcpt) +SERIALIZED_POINT *pc_point_serialize(const PCPOINT *pcpt) { - size_t serpt_size = sizeof(SERIALIZED_POINT) - 1 + pcpt->schema->size; - SERIALIZED_POINT *serpt = palloc(serpt_size); - serpt->pcid = pcpt->schema->pcid; - memcpy(serpt->data, pcpt->data, pcpt->schema->size); - SET_VARSIZE(serpt, serpt_size); - return serpt; + size_t serpt_size = sizeof(SERIALIZED_POINT) - 1 + pcpt->schema->size; + SERIALIZED_POINT *serpt = palloc(serpt_size); + serpt->pcid = pcpt->schema->pcid; + memcpy(serpt->data, pcpt->data, pcpt->schema->size); + SET_VARSIZE(serpt, serpt_size); + return serpt; } -PCPOINT * -pc_point_deserialize(const SERIALIZED_POINT *serpt, const PCSCHEMA *schema) +PCPOINT *pc_point_deserialize(const SERIALIZED_POINT *serpt, + const PCSCHEMA *schema) { - PCPOINT *pcpt; - size_t pgsize = VARSIZE(serpt) + 1 - sizeof(SERIALIZED_POINT); - /* - * Big problem, the size on disk doesn't match what we expect, - * so we cannot reliably interpret the contents. - */ - if ( schema->size != pgsize ) - { - elog(ERROR, "schema size and disk size mismatch, repair the schema"); - return NULL; - } - pcpt = pc_point_from_data(schema, serpt->data); - return pcpt; + PCPOINT *pcpt; + size_t pgsize = VARSIZE(serpt) + 1 - sizeof(SERIALIZED_POINT); + /* + * Big problem, the size on disk doesn't match what we expect, + * so we cannot reliably interpret the contents. + */ + if (schema->size != pgsize) + { + elog(ERROR, "schema size and disk size mismatch, repair the schema"); + return NULL; + } + pcpt = pc_point_from_data(schema, serpt->data); + return pcpt; } - -size_t -pc_patch_serialized_size(const PCPATCH *patch) +size_t pc_patch_serialized_size(const PCPATCH *patch) { - size_t stats_size = pc_stats_size(patch->schema); - size_t common_size = BUFFERALIGN(sizeof(SERIALIZED_PATCH)) - 1; - switch( patch->type ) - { - case PC_NONE: - { - PCPATCH_UNCOMPRESSED *pu = (PCPATCH_UNCOMPRESSED*)patch; - return common_size + stats_size + pu->datasize; - } - case PC_DIMENSIONAL: - { - return common_size + stats_size + pc_patch_dimensional_serialized_size((PCPATCH_DIMENSIONAL*)patch); - } - case PC_LAZPERF: - { - static size_t lazsize_size = 4; - PCPATCH_LAZPERF *pg = (PCPATCH_LAZPERF*)patch; - return common_size + stats_size + lazsize_size + pg->lazperfsize; - } - default: - { - pcerror("%s: unknown compresed %d", __func__, patch->type); - } - } - return -1; + size_t stats_size = pc_stats_size(patch->schema); + size_t common_size = BUFFERALIGN(sizeof(SERIALIZED_PATCH)) - 1; + switch (patch->type) + { + case PC_NONE: + { + PCPATCH_UNCOMPRESSED *pu = (PCPATCH_UNCOMPRESSED *)patch; + return common_size + stats_size + pu->datasize; + } + case PC_DIMENSIONAL: + { + return common_size + stats_size + + pc_patch_dimensional_serialized_size((PCPATCH_DIMENSIONAL *)patch); + } + case PC_LAZPERF: + { + static size_t lazsize_size = 4; + PCPATCH_LAZPERF *pg = (PCPATCH_LAZPERF *)patch; + return common_size + stats_size + lazsize_size + pg->lazperfsize; + } + default: + { + pcerror("%s: unknown compresed %d", __func__, patch->type); + } + } + return -1; } -static size_t -pc_patch_stats_serialize(uint8_t *buf, const PCSCHEMA *schema, const PCSTATS *stats) +static size_t pc_patch_stats_serialize(uint8_t *buf, const PCSCHEMA *schema, + const PCSTATS *stats) { - size_t sz = schema->size; - /* Copy min */ - memcpy(buf, stats->min.data, sz); - /* Copy max */ - memcpy(buf + sz, stats->max.data, sz); - /* Copy avg */ - memcpy(buf + 2*sz, stats->avg.data, sz); + size_t sz = schema->size; + /* Copy min */ + memcpy(buf, stats->min.data, sz); + /* Copy max */ + memcpy(buf + sz, stats->max.data, sz); + /* Copy avg */ + memcpy(buf + 2 * sz, stats->avg.data, sz); - return sz*3; + return sz * 3; } /** -* Stats are always three PCPOINT serializations in a row, -* min, max, avg. Their size is the uncompressed buffer size for -* a point, the schema->size. -*/ -PCSTATS * -pc_patch_stats_deserialize(const PCSCHEMA *schema, const uint8_t *buf) + * Stats are always three PCPOINT serializations in a row, + * min, max, avg. Their size is the uncompressed buffer size for + * a point, the schema->size. + */ +PCSTATS *pc_patch_stats_deserialize(const PCSCHEMA *schema, const uint8_t *buf) { - size_t sz = schema->size; - const uint8_t *buf_min = buf; - const uint8_t *buf_max = buf + sz; - const uint8_t *buf_avg = buf + 2*sz; + size_t sz = schema->size; + const uint8_t *buf_min = buf; + const uint8_t *buf_max = buf + sz; + const uint8_t *buf_avg = buf + 2 * sz; - return pc_stats_new_from_data(schema, buf_min, buf_max, buf_avg); + return pc_stats_new_from_data(schema, buf_min, buf_max, buf_avg); } -static SERIALIZED_PATCH * -pc_patch_dimensional_serialize(const PCPATCH *patch_in) +static SERIALIZED_PATCH *pc_patch_dimensional_serialize(const PCPATCH *patch_in) { - // uint32_t size; - // uint32_t pcid; - // uint32_t compression; - // uint32_t npoints; - // double xmin, xmax, ymin, ymax; - // data: - // pcpoint[3] stats; - // serialized_pcbytes[ndims] dimensions; + // uint32_t size; + // uint32_t pcid; + // uint32_t compression; + // uint32_t npoints; + // double xmin, xmax, ymin, ymax; + // data: + // pcpoint[3] stats; + // serialized_pcbytes[ndims] dimensions; - int i; - uint8_t *buf; - size_t serpch_size = pc_patch_serialized_size(patch_in); - SERIALIZED_PATCH *serpch = pcalloc(serpch_size); - const PCPATCH_DIMENSIONAL *patch = (PCPATCH_DIMENSIONAL*)patch_in; + int i; + uint8_t *buf; + size_t serpch_size = pc_patch_serialized_size(patch_in); + SERIALIZED_PATCH *serpch = pcalloc(serpch_size); + const PCPATCH_DIMENSIONAL *patch = (PCPATCH_DIMENSIONAL *)patch_in; - assert(patch_in); - assert(patch_in->type == PC_DIMENSIONAL); + assert(patch_in); + assert(patch_in->type == PC_DIMENSIONAL); - /* Copy basics */ - serpch->pcid = patch->schema->pcid; - serpch->npoints = patch->npoints; - serpch->bounds = patch->bounds; - serpch->compression = patch->type; + /* Copy basics */ + serpch->pcid = patch->schema->pcid; + serpch->npoints = patch->npoints; + serpch->bounds = patch->bounds; + serpch->compression = patch->type; - /* Get a pointer to the data area */ - buf = serpch->data; + /* Get a pointer to the data area */ + buf = serpch->data; - /* Write stats into the buffer */ - if ( patch->stats ) - { - buf += pc_patch_stats_serialize(buf, patch->schema, patch->stats); - } - else - { - pcerror("%s: stats missing!", __func__); - } + /* Write stats into the buffer */ + if (patch->stats) + { + buf += pc_patch_stats_serialize(buf, patch->schema, patch->stats); + } + else + { + pcerror("%s: stats missing!", __func__); + } - /* Write each dimension in after the stats */ - for ( i = 0; i < patch->schema->ndims; i++ ) - { - size_t bsize = 0; - PCBYTES *pcb = &(patch->bytes[i]); - pc_bytes_serialize(pcb, buf, &bsize); - buf += bsize; - } + /* Write each dimension in after the stats */ + for (i = 0; i < patch->schema->ndims; i++) + { + size_t bsize = 0; + PCBYTES *pcb = &(patch->bytes[i]); + pc_bytes_serialize(pcb, buf, &bsize); + buf += bsize; + } - SET_VARSIZE(serpch, serpch_size); - return serpch; + SET_VARSIZE(serpch, serpch_size); + return serpch; } - -static SERIALIZED_PATCH * -pc_patch_lazperf_serialize(const PCPATCH *patch_in) +static SERIALIZED_PATCH *pc_patch_lazperf_serialize(const PCPATCH *patch_in) { - size_t serpch_size = pc_patch_serialized_size(patch_in); - SERIALIZED_PATCH *serpch = pcalloc(serpch_size); - const PCPATCH_LAZPERF *patch = (PCPATCH_LAZPERF*)patch_in; - uint32_t lazsize = patch->lazperfsize; - uint8_t *buf = serpch->data; + size_t serpch_size = pc_patch_serialized_size(patch_in); + SERIALIZED_PATCH *serpch = pcalloc(serpch_size); + const PCPATCH_LAZPERF *patch = (PCPATCH_LAZPERF *)patch_in; + uint32_t lazsize = patch->lazperfsize; + uint8_t *buf = serpch->data; - assert(patch); - assert(patch->type == PC_LAZPERF); + assert(patch); + assert(patch->type == PC_LAZPERF); - /* Copy basics */ - serpch->pcid = patch->schema->pcid; - serpch->npoints = patch->npoints; - serpch->bounds = patch->bounds; - serpch->compression = patch->type; + /* Copy basics */ + serpch->pcid = patch->schema->pcid; + serpch->npoints = patch->npoints; + serpch->bounds = patch->bounds; + serpch->compression = patch->type; - /* Write stats into the buffer first */ - if ( patch->stats ) - { - buf += pc_patch_stats_serialize(buf, patch->schema, patch->stats); - } - else - { - pcerror("%s: stats missing!", __func__); - } + /* Write stats into the buffer first */ + if (patch->stats) + { + buf += pc_patch_stats_serialize(buf, patch->schema, patch->stats); + } + else + { + pcerror("%s: stats missing!", __func__); + } - /* Write buffer size */ - memcpy(buf, &(lazsize), 4); - buf += 4; + /* Write buffer size */ + memcpy(buf, &(lazsize), 4); + buf += 4; - /* Write buffer */ - memcpy(buf, patch->lazperf, patch->lazperfsize); - SET_VARSIZE(serpch, serpch_size); + /* Write buffer */ + memcpy(buf, patch->lazperf, patch->lazperfsize); + SET_VARSIZE(serpch, serpch_size); - return serpch; + return serpch; } static SERIALIZED_PATCH * pc_patch_uncompressed_serialize(const PCPATCH *patch_in) { - // uint32_t size; - // uint32_t pcid; - // uint32_t compression; - // uint32_t npoints; - // double xmin, xmax, ymin, ymax; - // data: - // pcpoint []; + // uint32_t size; + // uint32_t pcid; + // uint32_t compression; + // uint32_t npoints; + // double xmin, xmax, ymin, ymax; + // data: + // pcpoint []; - uint8_t *buf; - size_t serpch_size; - SERIALIZED_PATCH *serpch; - const PCPATCH_UNCOMPRESSED *patch = (PCPATCH_UNCOMPRESSED *)patch_in; + uint8_t *buf; + size_t serpch_size; + SERIALIZED_PATCH *serpch; + const PCPATCH_UNCOMPRESSED *patch = (PCPATCH_UNCOMPRESSED *)patch_in; - serpch_size = pc_patch_serialized_size(patch_in); - serpch = pcalloc(serpch_size); + serpch_size = pc_patch_serialized_size(patch_in); + serpch = pcalloc(serpch_size); - /* Copy basic */ - serpch->compression = patch->type; - serpch->pcid = patch->schema->pcid; - serpch->npoints = patch->npoints; - serpch->bounds = patch->bounds; + /* Copy basic */ + serpch->compression = patch->type; + serpch->pcid = patch->schema->pcid; + serpch->npoints = patch->npoints; + serpch->bounds = patch->bounds; - /* Write stats into the buffer first */ - buf = serpch->data; - if ( patch->stats ) - { - buf += pc_patch_stats_serialize(buf, patch->schema, patch->stats); - } - else - { - pcerror("%s: stats missing!", __func__); - } + /* Write stats into the buffer first */ + buf = serpch->data; + if (patch->stats) + { + buf += pc_patch_stats_serialize(buf, patch->schema, patch->stats); + } + else + { + pcerror("%s: stats missing!", __func__); + } - /* Copy point list into data buffer */ - memcpy(buf, patch->data, patch->datasize); - SET_VARSIZE(serpch, serpch_size); - return serpch; + /* Copy point list into data buffer */ + memcpy(buf, patch->data, patch->datasize); + SET_VARSIZE(serpch, serpch_size); + return serpch; } - /** -* Convert struct to byte array. -* Userdata is currently only PCDIMSTATS, hopefully updated across -* a number of iterations and saved. -*/ -SERIALIZED_PATCH * -pc_patch_serialize(const PCPATCH *patch_in, void *userdata) + * Convert struct to byte array. + * Userdata is currently only PCDIMSTATS, hopefully updated across + * a number of iterations and saved. + */ +SERIALIZED_PATCH *pc_patch_serialize(const PCPATCH *patch_in, void *userdata) { - PCPATCH *patch = (PCPATCH*)patch_in; - SERIALIZED_PATCH *serpatch = NULL; - /* - * Ensure the patch has stats calculated before going on - */ - if ( ! patch->stats ) - { - pcerror("%s: patch is missing stats", __func__); - return NULL; - } - /* - * Convert the patch to the final target compression, - * which is the one in the schema. - */ - if ( patch->type != patch->schema->compression ) - { - patch = pc_patch_compress(patch_in, userdata); - } + PCPATCH *patch = (PCPATCH *)patch_in; + SERIALIZED_PATCH *serpatch = NULL; + /* + * Ensure the patch has stats calculated before going on + */ + if (!patch->stats) + { + pcerror("%s: patch is missing stats", __func__); + return NULL; + } + /* + * Convert the patch to the final target compression, + * which is the one in the schema. + */ + if (patch->type != patch->schema->compression) + { + patch = pc_patch_compress(patch_in, userdata); + } - switch( patch->type ) - { - case PC_NONE: - { - serpatch = pc_patch_uncompressed_serialize(patch); - break; - } - case PC_DIMENSIONAL: - { - serpatch = pc_patch_dimensional_serialize(patch); - break; - } - case PC_LAZPERF: - { - serpatch = pc_patch_lazperf_serialize(patch); - break; - } - default: - { - pcerror("%s: unsupported compression type %d", __func__, patch->type); - } - } + switch (patch->type) + { + case PC_NONE: + { + serpatch = pc_patch_uncompressed_serialize(patch); + break; + } + case PC_DIMENSIONAL: + { + serpatch = pc_patch_dimensional_serialize(patch); + break; + } + case PC_LAZPERF: + { + serpatch = pc_patch_lazperf_serialize(patch); + break; + } + default: + { + pcerror("%s: unsupported compression type %d", __func__, patch->type); + } + } - if ( patch != patch_in ) - pc_patch_free(patch); + if (patch != patch_in) + pc_patch_free(patch); - return serpatch; + return serpatch; } - - - /** -* Convert struct to byte array. -* Userdata is currently only PCDIMSTATS, hopefully updated across -* a number of iterations and saved. -*/ -SERIALIZED_PATCH * -pc_patch_serialize_to_uncompressed(const PCPATCH *patch_in) + * Convert struct to byte array. + * Userdata is currently only PCDIMSTATS, hopefully updated across + * a number of iterations and saved. + */ +SERIALIZED_PATCH *pc_patch_serialize_to_uncompressed(const PCPATCH *patch_in) { - PCPATCH *patch = (PCPATCH*)patch_in; - SERIALIZED_PATCH *serpatch; + PCPATCH *patch = (PCPATCH *)patch_in; + SERIALIZED_PATCH *serpatch; - /* Convert the patch to uncompressed, if necessary */ - if ( patch->type != PC_NONE ) - { - patch = pc_patch_uncompress(patch_in); - } + /* Convert the patch to uncompressed, if necessary */ + if (patch->type != PC_NONE) + { + patch = pc_patch_uncompress(patch_in); + } - serpatch = pc_patch_uncompressed_serialize(patch); + serpatch = pc_patch_uncompressed_serialize(patch); - /* An uncompressed input won't result in a copy */ - if ( patch != patch_in ) - pc_patch_free(patch); + /* An uncompressed input won't result in a copy */ + if (patch != patch_in) + pc_patch_free(patch); - return serpatch; + return serpatch; } static PCPATCH * -pc_patch_uncompressed_deserialize(const SERIALIZED_PATCH *serpatch, const PCSCHEMA *schema) +pc_patch_uncompressed_deserialize(const SERIALIZED_PATCH *serpatch, + const PCSCHEMA *schema) { - // typedef struct - // { - // uint32_t size; - // uint32_t pcid; - // uint32_t compression; - // uint32_t npoints; - // double xmin, xmax, ymin, ymax; - // data: - // pcpoint[3] pcstats(min, max, avg) - // pcpoint[npoints] - // } - // SERIALIZED_PATCH; + // typedef struct + // { + // uint32_t size; + // uint32_t pcid; + // uint32_t compression; + // uint32_t npoints; + // double xmin, xmax, ymin, ymax; + // data: + // pcpoint[3] pcstats(min, max, avg) + // pcpoint[npoints] + // } + // SERIALIZED_PATCH; - uint8_t *buf; - size_t stats_size = pc_stats_size(schema); // 3 pcpoints worth of stats - PCPATCH_UNCOMPRESSED *patch = pcalloc(sizeof(PCPATCH_UNCOMPRESSED)); + uint8_t *buf; + size_t stats_size = pc_stats_size(schema); // 3 pcpoints worth of stats + PCPATCH_UNCOMPRESSED *patch = pcalloc(sizeof(PCPATCH_UNCOMPRESSED)); - /* Set up basic info */ - patch->type = serpatch->compression; - patch->schema = schema; - patch->readonly = true; - patch->npoints = serpatch->npoints; - patch->maxpoints = 0; - patch->bounds = serpatch->bounds; + /* Set up basic info */ + patch->type = serpatch->compression; + patch->schema = schema; + patch->readonly = true; + patch->npoints = serpatch->npoints; + patch->maxpoints = 0; + patch->bounds = serpatch->bounds; - buf = (uint8_t*)serpatch->data; + buf = (uint8_t *)serpatch->data; - /* Point into the stats area */ - patch->stats = pc_patch_stats_deserialize(schema, buf); + /* Point into the stats area */ + patch->stats = pc_patch_stats_deserialize(schema, buf); - /* Advance data pointer past the stats serialization */ - patch->data = buf + stats_size; + /* Advance data pointer past the stats serialization */ + patch->data = buf + stats_size; - /* Calculate the point data buffer size */ - patch->datasize = VARSIZE(serpatch) - BUFFERALIGN(sizeof(SERIALIZED_PATCH)) + 1 - stats_size; - if ( patch->datasize != patch->npoints * schema->size ) - pcerror("%s: calculated patch data sizes don't match (%d != %d)", __func__, patch->datasize, patch->npoints * schema->size); + /* Calculate the point data buffer size */ + patch->datasize = VARSIZE(serpatch) - BUFFERALIGN(sizeof(SERIALIZED_PATCH)) + + 1 - stats_size; + if (patch->datasize != patch->npoints * schema->size) + pcerror("%s: calculated patch data sizes don't match (%d != %d)", __func__, + patch->datasize, patch->npoints * schema->size); - return (PCPATCH*)patch; + return (PCPATCH *)patch; } static PCPATCH * -pc_patch_dimensional_deserialize(const SERIALIZED_PATCH *serpatch, const PCSCHEMA *schema) +pc_patch_dimensional_deserialize(const SERIALIZED_PATCH *serpatch, + const PCSCHEMA *schema) { - // typedef struct - // { - // uint32_t size; - // uint32_t pcid; - // uint32_t compression; - // uint32_t npoints; - // double xmin, xmax, ymin, ymax; - // data: - // pcpoint[3] pcstats(min, max, avg) - // pcbytes[ndims]; - // } - // SERIALIZED_PATCH; + // typedef struct + // { + // uint32_t size; + // uint32_t pcid; + // uint32_t compression; + // uint32_t npoints; + // double xmin, xmax, ymin, ymax; + // data: + // pcpoint[3] pcstats(min, max, avg) + // pcbytes[ndims]; + // } + // SERIALIZED_PATCH; - PCPATCH_DIMENSIONAL *patch; - int i; - const uint8_t *buf; - int ndims = schema->ndims; - int npoints = serpatch->npoints; - size_t stats_size = pc_stats_size(schema); // 3 pcpoints worth of stats + PCPATCH_DIMENSIONAL *patch; + int i; + const uint8_t *buf; + int ndims = schema->ndims; + int npoints = serpatch->npoints; + size_t stats_size = pc_stats_size(schema); // 3 pcpoints worth of stats - /* Reference the external data */ - patch = pcalloc(sizeof(PCPATCH_DIMENSIONAL)); + /* Reference the external data */ + patch = pcalloc(sizeof(PCPATCH_DIMENSIONAL)); - /* Set up basic info */ - patch->type = serpatch->compression; - patch->schema = schema; - patch->readonly = true; - patch->npoints = npoints; - patch->bounds = serpatch->bounds; + /* Set up basic info */ + patch->type = serpatch->compression; + patch->schema = schema; + patch->readonly = true; + patch->npoints = npoints; + patch->bounds = serpatch->bounds; - /* Point into the stats area */ - patch->stats = pc_patch_stats_deserialize(schema, serpatch->data); + /* Point into the stats area */ + patch->stats = pc_patch_stats_deserialize(schema, serpatch->data); - /* Set up dimensions */ - patch->bytes = pcalloc(ndims * sizeof(PCBYTES)); - buf = serpatch->data + stats_size; + /* Set up dimensions */ + patch->bytes = pcalloc(ndims * sizeof(PCBYTES)); + buf = serpatch->data + stats_size; - for ( i = 0; i < ndims; i++ ) - { - PCBYTES *pcb = &(patch->bytes[i]); - PCDIMENSION *dim = schema->dims[i]; - pc_bytes_deserialize(buf, dim, pcb, true /*readonly*/, false /*flipendian*/); - pcb->npoints = npoints; - buf += pc_bytes_serialized_size(pcb); - } + for (i = 0; i < ndims; i++) + { + PCBYTES *pcb = &(patch->bytes[i]); + PCDIMENSION *dim = schema->dims[i]; + pc_bytes_deserialize(buf, dim, pcb, true /*readonly*/, + false /*flipendian*/); + pcb->npoints = npoints; + buf += pc_bytes_serialized_size(pcb); + } - return (PCPATCH*)patch; + return (PCPATCH *)patch; } /* -* We don't do any radical deserialization here. Don't build out the tree, just -* set up pointers to the start of the buffer, so we can build it out later -* if necessary. -*/ -static PCPATCH * -pc_patch_lazperf_deserialize(const SERIALIZED_PATCH *serpatch, const PCSCHEMA *schema) + * We don't do any radical deserialization here. Don't build out the tree, just + * set up pointers to the start of the buffer, so we can build it out later + * if necessary. + */ +static PCPATCH *pc_patch_lazperf_deserialize(const SERIALIZED_PATCH *serpatch, + const PCSCHEMA *schema) { - PCPATCH_LAZPERF *patch; - uint32_t lazperfsize; - int npoints = serpatch->npoints; - size_t stats_size = pc_stats_size(schema); - uint8_t *buf = (uint8_t*)serpatch->data + stats_size; + PCPATCH_LAZPERF *patch; + uint32_t lazperfsize; + int npoints = serpatch->npoints; + size_t stats_size = pc_stats_size(schema); + uint8_t *buf = (uint8_t *)serpatch->data + stats_size; - /* Reference the external data */ - patch = pcalloc(sizeof(PCPATCH_LAZPERF)); + /* Reference the external data */ + patch = pcalloc(sizeof(PCPATCH_LAZPERF)); - /* Set up basic info */ - patch->type = serpatch->compression; - patch->schema = schema; - patch->readonly = true; - patch->npoints = npoints; - patch->bounds = serpatch->bounds; + /* Set up basic info */ + patch->type = serpatch->compression; + patch->schema = schema; + patch->readonly = true; + patch->npoints = npoints; + patch->bounds = serpatch->bounds; - /* Point into the stats area */ - patch->stats = pc_patch_stats_deserialize(schema, serpatch->data); + /* Point into the stats area */ + patch->stats = pc_patch_stats_deserialize(schema, serpatch->data); - /* Set up buffer */ - memcpy(&lazperfsize, buf, 4); - patch->lazperfsize = lazperfsize; - buf += 4; + /* Set up buffer */ + memcpy(&lazperfsize, buf, 4); + patch->lazperfsize = lazperfsize; + buf += 4; - patch->lazperf = pcalloc( patch->lazperfsize ); - memcpy(patch->lazperf, buf, patch->lazperfsize); + patch->lazperf = pcalloc(patch->lazperfsize); + memcpy(patch->lazperf, buf, patch->lazperfsize); - return (PCPATCH*)patch; + return (PCPATCH *)patch; } -PCPATCH * -pc_patch_deserialize(const SERIALIZED_PATCH *serpatch, const PCSCHEMA *schema) +PCPATCH *pc_patch_deserialize(const SERIALIZED_PATCH *serpatch, + const PCSCHEMA *schema) { - switch(serpatch->compression) - { - case PC_NONE: - return pc_patch_uncompressed_deserialize(serpatch, schema); - case PC_DIMENSIONAL: - return pc_patch_dimensional_deserialize(serpatch, schema); - case PC_LAZPERF: - return pc_patch_lazperf_deserialize(serpatch, schema); - } - pcerror("%s: unsupported compression type", __func__); - return NULL; + switch (serpatch->compression) + { + case PC_NONE: + return pc_patch_uncompressed_deserialize(serpatch, schema); + case PC_DIMENSIONAL: + return pc_patch_dimensional_deserialize(serpatch, schema); + case PC_LAZPERF: + return pc_patch_lazperf_deserialize(serpatch, schema); + } + pcerror("%s: unsupported compression type", __func__); + return NULL; } - -static uint8_t * -pc_patch_wkb_set_double(uint8_t *wkb, double d) +static uint8_t *pc_patch_wkb_set_double(uint8_t *wkb, double d) { - memcpy(wkb, &d, 8); - wkb += 8; - return wkb; + memcpy(wkb, &d, 8); + wkb += 8; + return wkb; } -static uint8_t * -pc_patch_wkb_set_int32(uint8_t *wkb, uint32_t i) +static uint8_t *pc_patch_wkb_set_int32(uint8_t *wkb, uint32_t i) { - memcpy(wkb, &i, 4); - wkb += 4; - return wkb; + memcpy(wkb, &i, 4); + wkb += 4; + return wkb; } -static uint8_t * -pc_patch_wkb_set_char(uint8_t *wkb, char c) +static uint8_t *pc_patch_wkb_set_char(uint8_t *wkb, char c) { - memcpy(wkb, &c, 1); - wkb += 1; - return wkb; + memcpy(wkb, &c, 1); + wkb += 1; + return wkb; } /* 0 = xdr | big endian */ /* 1 = ndr | little endian */ -static char -machine_endian(void) +static char machine_endian(void) { - static int check_int = 1; /* dont modify this!!! */ - return *((char *) &check_int); + static int check_int = 1; /* dont modify this!!! */ + return *((char *)&check_int); } -uint8_t * -pc_patch_to_geometry_wkb_envelope(const SERIALIZED_PATCH *pa, const PCSCHEMA *schema, size_t *wkbsize) +uint8_t *pc_patch_to_geometry_wkb_envelope(const SERIALIZED_PATCH *pa, + const PCSCHEMA *schema, + size_t *wkbsize) { - static uint32_t srid_mask = 0x20000000; - static uint32_t nrings = 1; - static uint32_t npoints = 5; - uint32_t wkbtype = 3; /* WKB POLYGON */ - uint8_t *wkb, *ptr; - int has_srid = false; - size_t size = 1 + 4 + 4 + 4 + 2*npoints*8; /* endian + type + nrings + npoints + 5 dbl pts */ + static uint32_t srid_mask = 0x20000000; + static uint32_t nrings = 1; + static uint32_t npoints = 5; + uint32_t wkbtype = 3; /* WKB POLYGON */ + uint8_t *wkb, *ptr; + int has_srid = false; + size_t size = + 1 + 4 + 4 + 4 + + 2 * npoints * 8; /* endian + type + nrings + npoints + 5 dbl pts */ - /* Bounds! */ - double xmin = pa->bounds.xmin; - double ymin = pa->bounds.ymin; - double xmax = pa->bounds.xmax; - double ymax = pa->bounds.ymax; + /* Bounds! */ + double xmin = pa->bounds.xmin; + double ymin = pa->bounds.ymin; + double xmax = pa->bounds.xmax; + double ymax = pa->bounds.ymax; - /* Make sure they're slightly bigger than a point */ - if ( xmin == xmax ) xmax += xmax * 0.0000001; - if ( ymin == ymax ) ymax += ymax * 0.0000001; + /* Make sure they're slightly bigger than a point */ + if (xmin == xmax) + xmax += xmax * 0.0000001; + if (ymin == ymax) + ymax += ymax * 0.0000001; - if ( schema->srid > 0 ) - { - has_srid = true; - wkbtype |= srid_mask; - size += 4; - } + if (schema->srid > 0) + { + has_srid = true; + wkbtype |= srid_mask; + size += 4; + } - wkb = palloc(size); - ptr = wkb; + wkb = palloc(size); + ptr = wkb; - ptr = pc_patch_wkb_set_char(ptr, machine_endian()); /* Endian flag */ + ptr = pc_patch_wkb_set_char(ptr, machine_endian()); /* Endian flag */ - ptr = pc_patch_wkb_set_int32(ptr, wkbtype); /* TYPE = Polygon */ + ptr = pc_patch_wkb_set_int32(ptr, wkbtype); /* TYPE = Polygon */ - if ( has_srid ) - { - ptr = pc_patch_wkb_set_int32(ptr, schema->srid); /* SRID */ - } + if (has_srid) + { + ptr = pc_patch_wkb_set_int32(ptr, schema->srid); /* SRID */ + } - ptr = pc_patch_wkb_set_int32(ptr, nrings); /* NRINGS = 1 */ - ptr = pc_patch_wkb_set_int32(ptr, npoints); /* NPOINTS = 5 */ + ptr = pc_patch_wkb_set_int32(ptr, nrings); /* NRINGS = 1 */ + ptr = pc_patch_wkb_set_int32(ptr, npoints); /* NPOINTS = 5 */ - /* Point 0 */ - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmin); - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymin); + /* Point 0 */ + ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmin); + ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymin); - /* Point 1 */ - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmin); - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymax); + /* Point 1 */ + ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmin); + ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymax); - /* Point 2 */ - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmax); - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymax); + /* Point 2 */ + ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmax); + ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymax); - /* Point 3 */ - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmax); - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymin); + /* Point 3 */ + ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmax); + ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymin); - /* Point 4 */ - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmin); - ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymin); + /* Point 4 */ + ptr = pc_patch_wkb_set_double(ptr, pa->bounds.xmin); + ptr = pc_patch_wkb_set_double(ptr, pa->bounds.ymin); - if ( wkbsize ) *wkbsize = size; - return wkb; + if (wkbsize) + *wkbsize = size; + return wkb; } diff --git a/pgsql/pc_pgsql.h b/pgsql/pc_pgsql.h index e714b1e..9ca6667 100644 --- a/pgsql/pc_pgsql.h +++ b/pgsql/pc_pgsql.h @@ -1,13 +1,13 @@ /*********************************************************************** -* pc_pgsql.h -* -* Common header file for all PgSQL pointcloud functions. -* -* PgSQL Pointcloud is free and open source software provided -* by the Government of Canada -* Copyright (c) 2013 Natural Resources Canada -* -***********************************************************************/ + * pc_pgsql.h + * + * Common header file for all PgSQL pointcloud functions. + * + * PgSQL Pointcloud is free and open source software provided + * by the Government of Canada + * Copyright (c) 2013 Natural Resources Canada + * + ***********************************************************************/ #include "pc_api.h" @@ -15,119 +15,136 @@ #include "utils/elog.h" /* Try to move these down */ -#include "utils/array.h" -#include "utils/builtins.h" /* for pg_atoi */ -#include "lib/stringinfo.h" /* For binary input */ #include "catalog/pg_type.h" /* for CSTRINGOID */ +#include "lib/stringinfo.h" /* For binary input */ +#include "utils/array.h" +#include "utils/builtins.h" /* for pg_atoi */ #define POINTCLOUD_FORMATS "pointcloud_formats" #define POINTCLOUD_FORMATS_XML "schema" #define POINTCLOUD_FORMATS_SRID "srid" -#define PG_GETARG_SERPOINT_P(argnum) (SERIALIZED_POINT*)PG_DETOAST_DATUM(PG_GETARG_DATUM(argnum)) -#define PG_GETARG_SERPATCH_P(argnum) (SERIALIZED_PATCH*)PG_DETOAST_DATUM(PG_GETARG_DATUM(argnum)) +#define PG_GETARG_SERPOINT_P(argnum) \ + (SERIALIZED_POINT *)PG_DETOAST_DATUM(PG_GETARG_DATUM(argnum)) +#define PG_GETARG_SERPATCH_P(argnum) \ + (SERIALIZED_PATCH *)PG_DETOAST_DATUM(PG_GETARG_DATUM(argnum)) -#define PG_GETHEADER_SERPATCH_P(argnum) (SERIALIZED_PATCH*)PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(argnum), 0, sizeof(SERIALIZED_PATCH)) +#define PG_GETHEADER_SERPATCH_P(argnum) \ + (SERIALIZED_PATCH *)PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(argnum), 0, \ + sizeof(SERIALIZED_PATCH)) -#define PG_GETHEADERX_SERPATCH_P(argnum, extra) (SERIALIZED_PATCH*)PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(argnum), 0, sizeof(SERIALIZED_PATCH)+extra) +#define PG_GETHEADERX_SERPATCH_P(argnum, extra) \ + (SERIALIZED_PATCH *)PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(argnum), 0, \ + sizeof(SERIALIZED_PATCH) + extra) -#define PG_GETHEADER_STATS_P(argnum, statsize) (uint8_t*)(((SERIALIZED_PATCH*)PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(argnum), 0, sizeof(SERIALIZED_PATCH) + statsize))->data) +#define PG_GETHEADER_STATS_P(argnum, statsize) \ + (uint8_t *)(((SERIALIZED_PATCH *)PG_DETOAST_DATUM_SLICE( \ + PG_GETARG_DATUM(argnum), 0, \ + sizeof(SERIALIZED_PATCH) + statsize)) \ + ->data) #define AUTOCOMPRESS_NO 0 #define AUTOCOMPRESS_YES 1 /** -* Serialized point type for clouds. Variable length, because there can be -* an arbitrary number of dimensions. The pcid is a foreign key -* reference to the POINTCLOUD_SCHEMAS table, where -* the underlying structure of the data is described in XML, -* the spatial reference system is indicated, and the data -* packing scheme is indicated. -*/ + * Serialized point type for clouds. Variable length, because there can be + * an arbitrary number of dimensions. The pcid is a foreign key + * reference to the POINTCLOUD_SCHEMAS table, where + * the underlying structure of the data is described in XML, + * the spatial reference system is indicated, and the data + * packing scheme is indicated. + */ typedef struct { - uint32_t size; - uint32_t pcid; - uint8_t data[1]; -} -SERIALIZED_POINT; + uint32_t size; + uint32_t pcid; + uint8_t data[1]; +} SERIALIZED_POINT; /** -* PgSQL patch type (collection of points) for clouds. -* Variable length, because there can be -* an arbitrary number of points encoded within. -* The pcid is a foriegn key reference to the -* POINTCLOUD_SCHEMAS table, where -* the underlying structure of the data is described in XML, -* the spatial reference system is indicated, and the data -* packing scheme is indicated. -*/ + * PgSQL patch type (collection of points) for clouds. + * Variable length, because there can be + * an arbitrary number of points encoded within. + * The pcid is a foriegn key reference to the + * POINTCLOUD_SCHEMAS table, where + * the underlying structure of the data is described in XML, + * the spatial reference system is indicated, and the data + * packing scheme is indicated. + */ typedef struct { - uint32_t size; - uint32_t pcid; - uint32_t compression; - uint32_t npoints; - PCBOUNDS bounds; - uint8_t data[1]; -} -SERIALIZED_PATCH; - + uint32_t size; + uint32_t pcid; + uint32_t compression; + uint32_t npoints; + PCBOUNDS bounds; + uint8_t data[1]; +} SERIALIZED_PATCH; /* PGSQL / POINTCLOUD UTILITY FUNCTIONS */ uint32 pcid_from_typmod(const int32 typmod); -/** Look-up the PCID in the POINTCLOUD_FORMATS table, and construct a PC_SCHEMA from the XML therein */ +/** Look-up the PCID in the POINTCLOUD_FORMATS table, and construct a PC_SCHEMA + * from the XML therein */ #if PGSQL_VERSION < 120 -PCSCHEMA* pc_schema_from_pcid(uint32_t pcid, FunctionCallInfoData *fcinfo); +PCSCHEMA *pc_schema_from_pcid(uint32_t pcid, FunctionCallInfoData *fcinfo); #else -PCSCHEMA* pc_schema_from_pcid(uint32_t pcid, FunctionCallInfo fcinfo); +PCSCHEMA *pc_schema_from_pcid(uint32_t pcid, FunctionCallInfo fcinfo); #endif -/** Look-up the PCID in the POINTCLOUD_FORMATS table, and construct a PC_SCHEMA from the XML therein */ -PCSCHEMA* pc_schema_from_pcid_uncached(uint32 pcid); +/** Look-up the PCID in the POINTCLOUD_FORMATS table, and construct a PC_SCHEMA + * from the XML therein */ +PCSCHEMA *pc_schema_from_pcid_uncached(uint32 pcid); /** Turn a PCPOINT into a byte buffer suitable for saving in PgSQL */ -SERIALIZED_POINT* pc_point_serialize(const PCPOINT *pcpt); +SERIALIZED_POINT *pc_point_serialize(const PCPOINT *pcpt); /** Turn a byte buffer into a PCPOINT for processing */ -PCPOINT* pc_point_deserialize(const SERIALIZED_POINT *serpt, const PCSCHEMA *schema); +PCPOINT *pc_point_deserialize(const SERIALIZED_POINT *serpt, + const PCSCHEMA *schema); /** Create a new readwrite PCPOINT from a hex string */ #if PGSQL_VERSION < 120 -PCPOINT* pc_point_from_hexwkb(const char *hexwkb, size_t hexlen, FunctionCallInfoData *fcinfo); +PCPOINT *pc_point_from_hexwkb(const char *hexwkb, size_t hexlen, + FunctionCallInfoData *fcinfo); #else -PCPOINT* pc_point_from_hexwkb(const char *hexwkb, size_t hexlen, FunctionCallInfo fcinfo); +PCPOINT *pc_point_from_hexwkb(const char *hexwkb, size_t hexlen, + FunctionCallInfo fcinfo); #endif /** Create a hex representation of a PCPOINT */ -char* pc_point_to_hexwkb(const PCPOINT *pt); +char *pc_point_to_hexwkb(const PCPOINT *pt); /** How big will this thing be on disk? */ size_t pc_patch_serialized_size(const PCPATCH *patch); /** Turn a PCPATCH into a byte buffer suitable for saving in PgSQL */ -SERIALIZED_PATCH* pc_patch_serialize(const PCPATCH *patch, void *userdata); +SERIALIZED_PATCH *pc_patch_serialize(const PCPATCH *patch, void *userdata); /** Turn a PCPATCH into an uncompressed byte buffer */ -SERIALIZED_PATCH* pc_patch_serialize_to_uncompressed(const PCPATCH *patch); +SERIALIZED_PATCH *pc_patch_serialize_to_uncompressed(const PCPATCH *patch); /** Turn a byte buffer into a PCPATCH for processing */ -PCPATCH* pc_patch_deserialize(const SERIALIZED_PATCH *serpatch, const PCSCHEMA *schema); +PCPATCH *pc_patch_deserialize(const SERIALIZED_PATCH *serpatch, + const PCSCHEMA *schema); /** Create a new readwrite PCPATCH from a hex string */ #if PGSQL_VERSION < 120 -PCPATCH* pc_patch_from_hexwkb(const char *hexwkb, size_t hexlen, FunctionCallInfoData *fcinfo); +PCPATCH *pc_patch_from_hexwkb(const char *hexwkb, size_t hexlen, + FunctionCallInfoData *fcinfo); #else -PCPATCH* pc_patch_from_hexwkb(const char *hexwkb, size_t hexlen, FunctionCallInfo fcinfo); +PCPATCH *pc_patch_from_hexwkb(const char *hexwkb, size_t hexlen, + FunctionCallInfo fcinfo); #endif /** Create a hex representation of a PCPOINT */ -char* pc_patch_to_hexwkb(const PCPATCH *patch); +char *pc_patch_to_hexwkb(const PCPATCH *patch); /** Returns OGC WKB for envelope of PCPATCH */ -uint8_t* pc_patch_to_geometry_wkb_envelope(const SERIALIZED_PATCH *pa, const PCSCHEMA *schema, size_t *wkbsize); +uint8_t *pc_patch_to_geometry_wkb_envelope(const SERIALIZED_PATCH *pa, + const PCSCHEMA *schema, + size_t *wkbsize); /** Read the first few bytes off an object to get the datum */ uint32 pcid_from_datum(Datum d); -PCSTATS* pc_patch_stats_deserialize(const PCSCHEMA *schema, const uint8_t *buf); +PCSTATS *pc_patch_stats_deserialize(const PCSCHEMA *schema, const uint8_t *buf); diff --git a/tools/code_layout.sh b/tools/code_layout.sh index 606a534..23d0606 100644 --- a/tools/code_layout.sh +++ b/tools/code_layout.sh @@ -1,3 +1,3 @@ #! /bin/bash -clang-format -i -style=file lib/*.c lib/*.h lib/cunit/*.c lib/*.cpp lib/*.hpp lib/cunit/*.h +clang-format -i -style=file pgsql/*.c pgsql/*.h lib/*.c lib/*.h lib/cunit/*.c lib/*.cpp lib/*.hpp lib/cunit/*.h