Implement PC_Patch{Min,Max,Avg}(PcPatch) returns PcPoint

Closes #77

NOTE: changes the C function signature so you need to properly
      upgrade scripts for things to work again.
This commit is contained in:
Sandro Santilli 2015-05-15 13:35:56 +02:00
parent bb02dd0454
commit 38944e72df
6 changed files with 126 additions and 25 deletions

1
NEWS
View File

@ -5,6 +5,7 @@
- PC_PCId(pcpoint|pcpatch)
- PC_Get(pcpoint) returns float8[]
- PC_Summary(pcpatch)
- PC_Patch{Min,Max,Avg}(pcpatch) returns pcpoint (#77)
- Enhancements
- Support sigbits encoding for 64bit integers (#61)
- Warn about truncated values (#68)

View File

@ -380,6 +380,33 @@ Now that you have created two tables, you'll see entries for them in the `pointc
>
> 45.5
**PC_PatchAvg(p pcpatch,)** returns **pcpoint** (from 1.1.0)
> Returns a PcPoint with the *average* values of each dimension in the patch.
>
> SELECT PC_AsText(PC_PatchAvg(pa))
> FROM patches WHERE id = 7;
>
> {"pcid":1,"pt":[-126.46,45.54,54.5,5]}
**PC_PatchMax(p pcpatch)** returns **pcpoint** (from 1.1.0)
> Returns a PcPoint with the *maximum* values of each dimension in the patch.
>
> SELECT PC_PatchMax(pa)
> FROM patches WHERE id = 7;
>
> {"pcid":1,"pt":[-126.41,45.59,59,5]}
**PC_PatchMin(p pcpatch)** returns **pcpoint** (from 1.1.0)
> Returns a PcPoint with the *minimum* values of each dimension in the patch.
>
> SELECT PC_PatchMin(pa)
> FROM patches WHERE id = 7;
>
> {"pcid":1,"pt":[-126.5,45.5,50,5]}
**PC_FilterGreaterThan(p pcpatch, dimname text, float8 value)** returns **pcpatch**
> Returns a patch with only points whose values are greater than the supplied value

View File

@ -391,6 +391,25 @@ SELECT Min(PC_PatchMin(pa,'z')) FROM pa_test_dim;
1
(1 row)
-- https://github.com/pgpointcloud/pointcloud/issues/77
SELECT PC_Get(PC_PatchMax(pa)) FROM pa_test_dim order by 1 limit 1;
pc_get
------------------------
{-123.01,48.99,399,39}
(1 row)
SELECT PC_Get(PC_PatchMin(pa)) FROM pa_test_dim order by 1 limit 1;
pc_get
---------------------
{-126.99,45.01,1,0}
(1 row)
SELECT PC_Get(PC_PatchAvg(pa)) FROM pa_test_dim order by 1 limit 1;
pc_get
------------------
{-125,47,200,20}
(1 row)
SELECT PC_Summary(pa) summary FROM pa_test_dim order by 1 limit 1;
summary
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -819,6 +819,9 @@ Datum pc_version(PG_FUNCTION_ARGS)
* 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)
@ -826,11 +829,19 @@ 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);
char *dim_str = text_to_cstring(PG_GETARG_TEXT_P(1));
char *stat_str = text_to_cstring(PG_GETARG_TEXT_P(2));
int32 statno = PG_GETARG_INT32(1);
char *dim_str = 0;
PCSTATS *stats;
const PCPOINT *pt;
SERIALIZED_POINT *serpt = NULL;
float8 double_result;
int rv = 0;
int rv = 1;
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) )
{
@ -842,30 +853,40 @@ Datum pcpatch_get_stat(PG_FUNCTION_ARGS)
if ( ! stats )
PG_RETURN_NULL();
/* Max */
if ( 0 == strcasecmp("max", stat_str) )
rv = pc_point_get_double_by_name(&(stats->max), dim_str, &double_result);
/* Min */
else if ( 0 == strcasecmp("min", stat_str) )
rv = pc_point_get_double_by_name(&(stats->min), dim_str, &double_result);
if ( 0 == statno )
pt = &(stats->min);
/* Max */
else if ( 1 == statno )
pt = &(stats->max);
/* Avg */
else if ( 0 == strcasecmp("avg", stat_str) )
rv = pc_point_get_double_by_name(&(stats->avg), dim_str, &double_result);
else if ( 2 == statno )
pt = &(stats->avg);
/* Unsupported */
else
elog(ERROR, "stat type \"%s\" is not supported", stat_str);
elog(ERROR, "stat number \"%d\" is not supported", statno);
pfree(stat_str);
pc_stats_free(stats);
if ( ! rv )
elog(ERROR, "dimension \"%s\" does not exist in schema", dim_str);
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

View File

@ -176,17 +176,44 @@ CREATE OR REPLACE FUNCTION PC_PCId(p pcpoint)
RETURNS int4 AS 'MODULE_PATHNAME', 'pcpoint_pcid'
LANGUAGE 'c' IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION PC_PatchMax(p pcpatch, attr text, stat text default 'max')
-- Availability: 1.1.0
-- @param statno 0:min 1:max 2:avg
CREATE OR REPLACE FUNCTION _PC_PatchStat(p pcpatch, statno int)
RETURNS pcpoint AS 'MODULE_PATHNAME', 'pcpatch_get_stat'
LANGUAGE 'c' IMMUTABLE STRICT;
-- Availability: 1.1.0
CREATE OR REPLACE FUNCTION PC_PatchMin(p pcpatch)
RETURNS pcpoint AS $$ SELECT _PC_PatchStat(p, 0) $$
LANGUAGE 'sql' IMMUTABLE STRICT;
-- Availability: 1.1.0
CREATE OR REPLACE FUNCTION PC_PatchMax(p pcpatch)
RETURNS pcpoint AS $$ SELECT _PC_PatchStat(p, 1) $$
LANGUAGE 'sql' IMMUTABLE STRICT;
-- Availability: 1.1.0
CREATE OR REPLACE FUNCTION PC_PatchAvg(p pcpatch)
RETURNS pcpoint AS $$ SELECT _PC_PatchStat(p, 2) $$
LANGUAGE 'sql' IMMUTABLE STRICT;
-- Availability: 1.1.0
-- @param statno 0:min 1:max 2:avg
CREATE OR REPLACE FUNCTION _PC_PatchStat(p pcpatch, statno int, attr text)
RETURNS numeric AS 'MODULE_PATHNAME', 'pcpatch_get_stat'
LANGUAGE 'c' IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION PC_PatchMin(p pcpatch, attr text, stat text default 'min')
RETURNS numeric AS 'MODULE_PATHNAME', 'pcpatch_get_stat'
LANGUAGE 'c' IMMUTABLE STRICT;
RETURNS numeric AS $$ SELECT _PC_PatchStat(p, 0, attr) $$
LANGUAGE 'sql' IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION PC_PatchMax(p pcpatch, attr text, stat text default 'max')
RETURNS numeric AS $$ SELECT _PC_PatchStat(p, 1, attr) $$
LANGUAGE 'sql' IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION PC_PatchAvg(p pcpatch, attr text, stat text default 'avg')
RETURNS numeric AS 'MODULE_PATHNAME', 'pcpatch_get_stat'
LANGUAGE 'c' IMMUTABLE STRICT;
RETURNS numeric AS $$ SELECT _PC_PatchStat(p, 2, attr) $$
LANGUAGE 'sql' IMMUTABLE STRICT;
CREATE OR REPLACE FUNCTION PC_FilterLessThan(p pcpatch, attr text, v1 float8 default 0.0, v2 float8 default 0.0, mode int4 default 0)
RETURNS pcpatch AS 'MODULE_PATHNAME', 'pcpatch_filter'

View File

@ -267,6 +267,12 @@ SELECT Max(PC_PatchMax(pa,'x')) FROM pa_test_dim;
SELECT Min(PC_PatchMin(pa,'x')) FROM pa_test_dim;
SELECT Min(PC_PatchMin(pa,'z')) FROM pa_test_dim;
-- https://github.com/pgpointcloud/pointcloud/issues/77
SELECT PC_Get(PC_PatchMax(pa)) FROM pa_test_dim order by 1 limit 1;
SELECT PC_Get(PC_PatchMin(pa)) FROM pa_test_dim order by 1 limit 1;
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;