Skip to content
Open
13 changes: 13 additions & 0 deletions pgsql/expected/pointcloud.out
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
66 changes: 66 additions & 0 deletions pgsql/pc_inout.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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)
{
Expand Down
17 changes: 15 additions & 2 deletions pgsql/pointcloud.sql.in
Original file line number Diff line number Diff line change
Expand Up @@ -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 = ':',
Expand All @@ -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;
Expand Down
8 changes: 8 additions & 0 deletions pgsql/sql/pointcloud.sql
Original file line number Diff line number Diff line change
Expand Up @@ -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[]));
Expand Down