diff --git a/pgsql/expected/pointcloud.out b/pgsql/expected/pointcloud.out index e7e7f906..2b0c959a 100644 --- a/pgsql/expected/pointcloud.out +++ b/pgsql/expected/pointcloud.out @@ -478,10 +478,23 @@ SELECT PC_Summary(pa) summary FROM pa_test_dim order by 1 limit 1; {"pcid":3, "npts":1, "srid":0, "compr":"dimensional","dims":[{"pos":0,"name":"X","size":4,"type":"int32_t","compr":"zlib","stats":{"min":-111,"max":-111,"avg":-111}},{"pos":1,"name":"Y","size":4,"type":"int32_t","compr":"zlib","stats":{"min":61,"max":61,"avg":61}},{"pos":2,"name":"Z","size":4,"type":"int32_t","compr":"zlib","stats":{"min":1600,"max":1600,"avg":1600}},{"pos":3,"name":"Intensity","size":2,"type":"uint16_t","compr":"zlib","stats":{"min":160,"max":160,"avg":160}}]} (1 row) +-- test binary +COPY pa_test TO '/tmp/__pgpointcloud_pa_test_file__' WITH BINARY; +CREATE TABLE IF NOT EXISTS pa_test_in ( + pa PCPATCH(1) +); +COPY pa_test_in FROM '/tmp/__pgpointcloud_pa_test_file__' WITH BINARY; +SELECT 'patch', count(*) FROM pa_test i, pa_test_in o WHERE PC_AsText(i.pa) = PC_AsText(o.pa); + ?column? | count +----------+------- + patch | 10 +(1 row) + --DROP TABLE pts_collection; DROP TABLE pt_test; DROP TABLE pa_test; DROP TABLE pa_test_dim; +DROP TABLE pa_test_in; -- See https://github.com/pgpointcloud/pointcloud/issues/44 SELECT PC_AsText(PC_Patch(ARRAY[PC_MakePoint(3, ARRAY[-127, 45, 124.0, 4.0])]::pcpoint[])); pc_astext diff --git a/pgsql/pc_inout.c b/pgsql/pc_inout.c index 51ef3544..428a37ce 100644 --- a/pgsql/pc_inout.c +++ b/pgsql/pc_inout.c @@ -18,6 +18,8 @@ Datum pcpoint_in(PG_FUNCTION_ARGS); Datum pcpoint_out(PG_FUNCTION_ARGS); Datum pcpatch_in(PG_FUNCTION_ARGS); Datum pcpatch_out(PG_FUNCTION_ARGS); +Datum pcpatch_send(PG_FUNCTION_ARGS); +Datum pcpatch_recv(PG_FUNCTION_ARGS); /* Typmod support */ Datum pc_typmod_in(PG_FUNCTION_ARGS); @@ -166,6 +168,70 @@ Datum pcpatch_out(PG_FUNCTION_ARGS) PG_RETURN_CSTRING(hexwkb); } +PG_FUNCTION_INFO_V1(pcpatch_recv); +Datum pcpatch_recv(PG_FUNCTION_ARGS) +{ + StringInfo buf = (StringInfo)PG_GETARG_POINTER(0); + size_t wkblen; + uint32 pcid = 0; + PCPATCH *patch; + SERIALIZED_PATCH *serpatch = NULL; + + PCSCHEMA *schema; + + wkblen = buf->len - buf->cursor; + uint8 *wkb = &buf->data[buf->cursor]; + + buf->cursor += buf->len; + + 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__); + + patch = pc_patch_from_wkb(schema, wkb, wkblen); + + pcid_consistent(patch->schema->pcid, pcid); + serpatch = pc_patch_serialize(patch, NULL); + pc_patch_free(patch); + + if (serpatch) + PG_RETURN_POINTER(serpatch); + else + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(pcpatch_send); +Datum pcpatch_send(PG_FUNCTION_ARGS) +{ + PCPATCH *patch = NULL; + SERIALIZED_PATCH *serpatch = NULL; + PCSCHEMA *schema = NULL; + size_t wkb_size; + uint8 *wkb; + + bytea *result = NULL; + int result_size = 0; + + serpatch = PG_GETARG_SERPATCH_P(0); + schema = pc_schema_from_pcid(serpatch->pcid, fcinfo); + patch = pc_patch_deserialize(serpatch, schema); + wkb = pc_patch_to_wkb(patch, &wkb_size); + pc_patch_free(patch); + + result_size = wkb_size + VARHDRSZ; + result = (bytea *)palloc(result_size); + SET_VARSIZE(result, result_size); + memcpy(VARDATA(result), wkb, VARSIZE(result) - VARHDRSZ); + + pfree(wkb); + + PG_RETURN_BYTEA_P(result); +} + PG_FUNCTION_INFO_V1(pcschema_is_valid); Datum pcschema_is_valid(PG_FUNCTION_ARGS) { diff --git a/pgsql/pointcloud.sql.in b/pgsql/pointcloud.sql.in index a15343c1..9b86bbe3 100644 --- a/pgsql/pointcloud.sql.in +++ b/pgsql/pointcloud.sql.in @@ -236,12 +236,22 @@ CREATE OR REPLACE FUNCTION pcpatch_out(pcpatch) RETURNS cstring AS 'MODULE_PATHNAME', 'pcpatch_out' LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL; +-- Availability: 1.2.0next +CREATE OR REPLACE FUNCTION pcpatch_send(pcpatch) + RETURNS bytea AS 'MODULE_PATHNAME', 'pcpatch_send' + LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL; + +-- Availability: 1.2.0next +CREATE OR REPLACE FUNCTION pcpatch_recv(internal) + RETURNS pcpatch AS 'MODULE_PATHNAME', 'pcpatch_recv' + LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL; + CREATE TYPE pcpatch ( internallength = variable, input = pcpatch_in, output = pcpatch_out, - -- send = geometry_send, - -- receive = geometry_recv, + send = pcpatch_send, + receive = pcpatch_recv, typmod_in = pc_typmod_in, typmod_out = pc_typmod_out, -- delimiter = ':', @@ -250,6 +260,9 @@ CREATE TYPE pcpatch ( storage = external ); +-- Availability: 1.2.0next +UPDATE pg_type SET typsend = 'pcpatch_send', typreceive = 'pcpatch_recv' WHERE typname='pcpatch' AND (typsend::text != 'pcpatch_send' OR typreceive::text != 'pcpatch_recv'); + CREATE OR REPLACE FUNCTION PC_AsText(p pcpatch) RETURNS text AS 'MODULE_PATHNAME', 'pcpatch_as_text' LANGUAGE 'c' IMMUTABLE STRICT _PARALLEL; diff --git a/pgsql/sql/pointcloud.sql b/pgsql/sql/pointcloud.sql index af4ced24..79005490 100644 --- a/pgsql/sql/pointcloud.sql +++ b/pgsql/sql/pointcloud.sql @@ -322,11 +322,19 @@ SELECT PC_Get(PC_PatchAvg(pa)) FROM pa_test_dim order by 1 limit 1; SELECT PC_Summary(pa) summary FROM pa_test_dim order by 1 limit 1; +-- test binary +COPY pa_test TO '/tmp/__pgpointcloud_pa_test_file__' WITH BINARY; +CREATE TABLE IF NOT EXISTS pa_test_in ( + pa PCPATCH(1) +); +COPY pa_test_in FROM '/tmp/__pgpointcloud_pa_test_file__' WITH BINARY; +SELECT 'patch', count(*) FROM pa_test i, pa_test_in o WHERE PC_AsText(i.pa) = PC_AsText(o.pa); --DROP TABLE pts_collection; DROP TABLE pt_test; DROP TABLE pa_test; DROP TABLE pa_test_dim; +DROP TABLE pa_test_in; -- See https://github.com/pgpointcloud/pointcloud/issues/44 SELECT PC_AsText(PC_Patch(ARRAY[PC_MakePoint(3, ARRAY[-127, 45, 124.0, 4.0])]::pcpoint[]));