From fb171dbadef43d13d51b13afd5ae5069734ce84d Mon Sep 17 00:00:00 2001 From: Paul Ramsey Date: Wed, 23 Jan 2013 11:20:12 -0800 Subject: [PATCH] Add PC_Get sql function and PCPoint type --- pgsql/Makefile | 1 + pgsql/pc_access.c | 37 +++++++++++++++++++++++++++++++++++++ pgsql/pc_pgsql.c | 4 ++-- pgsql/pc_pgsql.h | 2 ++ pgsql/pointcloud--1.0.sql | 36 ++++++++++++++++++++++++++++++++++++ 5 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 pgsql/pc_access.c diff --git a/pgsql/Makefile b/pgsql/Makefile index 3ed0eaf..f096565 100644 --- a/pgsql/Makefile +++ b/pgsql/Makefile @@ -5,6 +5,7 @@ include ../config.mk MODULE_big = pointcloud OBJS = \ pc_inout.o \ + pc_access.o \ pc_pgsql.o EXTENSION = pointcloud diff --git a/pgsql/pc_access.c b/pgsql/pc_access.c new file mode 100644 index 0000000..534ccbc --- /dev/null +++ b/pgsql/pc_access.c @@ -0,0 +1,37 @@ + +#include "pc_pgsql.h" /* Common PgSQL support for our type */ +#include "utils/numeric.h" + +/* Other SQL functions */ +Datum PC_Get(PG_FUNCTION_ARGS); + + + +/** +* Read a named dimension from a PCPOINT +*/ +PG_FUNCTION_INFO_V1(PC_Get); +Datum PC_Get(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; + + PCPOINT *pt = pc_point_deserialize(serpt); + if ( ! pt ) + PG_RETURN_NULL(); + + dim_str = text_to_cstring(dim_name); + if ( ! pc_schema_get_dimension_by_name(pt->schema, dim_str) ) + { + pc_point_free(pt); + elog(ERROR, "dimension \"%s\" does not exist in schema", dim_str); + } + + double_result = pc_point_get_double_by_name(pt, dim_str); + pfree(dim_str); + pc_point_free(pt); + PG_RETURN_DATUM(DirectFunctionCall1(float8_numeric, Float8GetDatum(double_result))); +} + diff --git a/pgsql/pc_pgsql.c b/pgsql/pc_pgsql.c index 7937788..2d52f87 100644 --- a/pgsql/pc_pgsql.c +++ b/pgsql/pc_pgsql.c @@ -162,7 +162,7 @@ hexbytes_from_bytes(const uint8_t *bytebuf, size_t bytesize) for ( i = 0; i < bytesize; i++ ) { - int incr = snprintf(ptr, 2, "%X", bytebuf[i]); + int incr = snprintf(ptr, 3, "%02X", bytebuf[i]); if ( incr < 0 ) { pcerror("write failure in hexbytes_from_bytes"); @@ -331,7 +331,7 @@ pc_schema_get_by_id(uint32_t pcid) if (SPI_processed <= 0) { SPI_finish(); - elog(ERROR, "no entry in \"%s\" for PCID (%d)", POINTCLOUD_FORMATS, pcid); + elog(ERROR, "no entry in \"%s\" for pcid = %d", POINTCLOUD_FORMATS, pcid); return NULL; } diff --git a/pgsql/pc_pgsql.h b/pgsql/pc_pgsql.h index 81fb611..63b737c 100644 --- a/pgsql/pc_pgsql.h +++ b/pgsql/pc_pgsql.h @@ -13,6 +13,8 @@ #define POINTCLOUD_FORMATS_XML "schema" #define POINTCLOUD_FORMATS_SRID "srid" +#define PG_GETARG_SERPOINT_P(datum) (SERIALIZED_POINT*)PG_DETOAST_DATUM(PG_GETARG_DATUM(datum)) + typedef struct { uint32_t size; diff --git a/pgsql/pointcloud--1.0.sql b/pgsql/pointcloud--1.0.sql index 33fde66..536d021 100644 --- a/pgsql/pointcloud--1.0.sql +++ b/pgsql/pointcloud--1.0.sql @@ -3,6 +3,10 @@ \echo Use "CREATE EXTENSION pointcloud" to load this file. \quit +------------------------------------------------------------------- +-- METADATA and SCHEMA +------------------------------------------------------------------- + -- Confirm the XML representation of a schema has everything we need CREATE OR REPLACE FUNCTION PC_SchemaIsValid(xml text) RETURNS boolean AS 'MODULE_PATHNAME','PC_SchemaIsValid' @@ -24,6 +28,38 @@ CREATE OR REPLACE FUNCTION PC_SchemaGetNDims(pcid integer) LANGUAGE 'c' IMMUTABLE STRICT; + +------------------------------------------------------------------- +-- PCPOINT +------------------------------------------------------------------- + +CREATE OR REPLACE FUNCTION pcpoint_in(cstring) + RETURNS pcpoint AS 'MODULE_PATHNAME', 'pcpoint_in' + LANGUAGE 'c' IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION pcpoint_out(pcpoint) + RETURNS cstring AS 'MODULE_PATHNAME', 'pcpoint_out' + LANGUAGE 'c' IMMUTABLE STRICT; + +CREATE TYPE pcpoint ( + internallength = variable, + input = pcpoint_in, + output = pcpoint_out, + -- send = geometry_send, + -- receive = geometry_recv, + -- typmod_in = geometry_typmod_in, + -- typmod_out = geometry_typmod_out, + -- delimiter = ':', + -- alignment = double, + -- analyze = geometry_analyze, + storage = main +); + +CREATE OR REPLACE FUNCTION PC_Get(point pcpoint, dimname text) + RETURNS numeric AS 'MODULE_PATHNAME', 'PC_Get' + LANGUAGE 'c' IMMUTABLE STRICT; + + -- Sample data INSERT INTO pointcloud_formats (pcid, srid, schema) VALUES (1, 4326, '