From: Paul Ramsey Date: Tue, 10 Nov 2009 20:39:20 +0000 (+0000) Subject: Stub implementation of ordering operators (#292) X-Git-Tag: 1.5.0b1~262 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8631879806af2ab70809ccb14bceb824dd2d942a;p=postgis Stub implementation of ordering operators (#292) git-svn-id: http://svn.osgeo.org/postgis/trunk@4779 b70326c6-7e19-0410-871a-916f4a2858ee --- diff --git a/postgis/Makefile.in b/postgis/Makefile.in index f587d3ad0..5264acdcc 100644 --- a/postgis/Makefile.in +++ b/postgis/Makefile.in @@ -53,6 +53,7 @@ PG_OBJS=lwgeom_pg.o \ lwgeom_rtree.o \ geography_inout.o \ geography_gist.o \ + geography_btree.o \ geography_estimate.o \ geography_measurement.o diff --git a/postgis/geography.sql.in.c b/postgis/geography.sql.in.c index e4e9df28e..896cffafa 100644 --- a/postgis/geography.sql.in.c +++ b/postgis/geography.sql.in.c @@ -273,6 +273,86 @@ CREATE OPERATOR CLASS gist_geography_ops FUNCTION 6 geography_gist_picksplit (internal, internal), FUNCTION 7 geography_gist_same (box2d, box2d, internal); + +-- ---------- ---------- ---------- ---------- ---------- ---------- ---------- +-- B-Tree Functions +-- For sorting and grouping +-- Availability: 1.5.0 +-- ---------- ---------- ---------- ---------- ---------- ---------- ---------- + +CREATE OR REPLACE FUNCTION geography_lt(geography, geography) + RETURNS bool + AS 'MODULE_PATHNAME', 'geography_lt' + LANGUAGE 'C' IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION geography_le(geography, geography) + RETURNS bool + AS 'MODULE_PATHNAME', 'geography_le' + LANGUAGE 'C' IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION geography_gt(geography, geography) + RETURNS bool + AS 'MODULE_PATHNAME', 'geography_gt' + LANGUAGE 'C' IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION geography_ge(geography, geography) + RETURNS bool + AS 'MODULE_PATHNAME', 'geography_ge' + LANGUAGE 'C' IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION geography_eq(geography, geography) + RETURNS bool + AS 'MODULE_PATHNAME', 'geography_eq' + LANGUAGE 'C' IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION geography_cmp(geography, geography) + RETURNS integer + AS 'MODULE_PATHNAME', 'geography_cmp' + LANGUAGE 'C' IMMUTABLE STRICT; + +-- +-- Sorting operators for Btree +-- + +CREATE OPERATOR < ( + LEFTARG = geography, RIGHTARG = geography, PROCEDURE = geography_lt, + COMMUTATOR = '>', NEGATOR = '>=', + RESTRICT = contsel, JOIN = contjoinsel +); + +CREATE OPERATOR <= ( + LEFTARG = geography, RIGHTARG = geography, PROCEDURE = geography_le, + COMMUTATOR = '>=', NEGATOR = '>', + RESTRICT = contsel, JOIN = contjoinsel +); + +CREATE OPERATOR = ( + LEFTARG = geography, RIGHTARG = geography, PROCEDURE = geography_eq, + COMMUTATOR = '=', -- we might implement a faster negator here + RESTRICT = contsel, JOIN = contjoinsel +); + +CREATE OPERATOR >= ( + LEFTARG = geography, RIGHTARG = geography, PROCEDURE = geography_ge, + COMMUTATOR = '<=', NEGATOR = '<', + RESTRICT = contsel, JOIN = contjoinsel +); +CREATE OPERATOR > ( + LEFTARG = geography, RIGHTARG = geography, PROCEDURE = geography_gt, + COMMUTATOR = '<', NEGATOR = '<=', + RESTRICT = contsel, JOIN = contjoinsel +); + +CREATE OPERATOR CLASS btree_geography_ops + DEFAULT FOR TYPE geography USING btree AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 geography_cmp (geography, geography); + + -- ---------- ---------- ---------- ---------- ---------- ---------- ---------- -- Export Functions -- Availability: 1.5.0 diff --git a/postgis/geography_btree.c b/postgis/geography_btree.c new file mode 100644 index 000000000..e892f8eba --- /dev/null +++ b/postgis/geography_btree.c @@ -0,0 +1,237 @@ +/********************************************************************** + * $Id: geography_gist.c 4778 2009-11-10 19:30:43Z pramsey $ + * + * PostGIS - Spatial Types for PostgreSQL + * Copyright 2009 Paul Ramsey + * + * This is free software; you can redistribute and/or modify it under + * the terms of the GNU General Public Licence. See the COPYING file. + * + **********************************************************************/ + +/* +** R-Tree Bibliography +** +** [1] A. Guttman. R-tree: a dynamic index structure for spatial searching. +** Proceedings of the ACM SIGMOD Conference, pp 47-57, June 1984. +** [2] C.-H. Ang and T. C. Tan. New linear node splitting algorithm for +** R-Trees. Advances in Spatial Databases - 5th International Symposium, +** 1997 +** [3] N. Beckmann, H.-P. Kriegel, R. Schneider, B. Seeger. The R*tree: an +** efficient and robust access method for points and rectangles. +** Proceedings of the ACM SIGMOD Conference. June 1990. +*/ + +#include "postgres.h" +#include "access/gist.h" /* For GiST */ +#include "access/itup.h" +#include "access/skey.h" + +#include "../postgis_config.h" + +#include "libgeom.h" /* For standard geometry types. */ +#include "lwgeom_pg.h" /* For debugging macros. */ +#include "geography.h" /* For utility functions. */ + +Datum geography_lt(PG_FUNCTION_ARGS); +Datum geography_le(PG_FUNCTION_ARGS); +Datum geography_eq(PG_FUNCTION_ARGS); +Datum geography_ge(PG_FUNCTION_ARGS); +Datum geography_gt(PG_FUNCTION_ARGS); +Datum geography_cmp(PG_FUNCTION_ARGS); + +/* +** Utility function to return the center point of a +** geocentric bounding box. We don't divide by two +** because we're only using the values for comparison. +*/ +static void geography_gidx_center(GIDX *gidx, POINT3D *p) +{ + p->x = GIDX_GET_MIN(gidx, 0) + GIDX_GET_MAX(gidx, 0); + p->y = GIDX_GET_MIN(gidx, 1) + GIDX_GET_MAX(gidx, 1); + p->z = GIDX_GET_MIN(gidx, 2) + GIDX_GET_MAX(gidx, 2); +} + +/* +** BTree support function. Based on two geographies return true if +** they are "less than" and false otherwise. +*/ +PG_FUNCTION_INFO_V1(geography_lt); +Datum geography_lt(PG_FUNCTION_ARGS) +{ + /* Put aside some stack memory and use it for GIDX pointers. */ + char gboxmem1[GIDX_MAX_SIZE]; + char gboxmem2[GIDX_MAX_SIZE]; + GIDX *gbox1 = (GIDX*)gboxmem1; + GIDX *gbox2 = (GIDX*)gboxmem2; + POINT3D p1, p2; + + /* Must be able to build box for each argument (ie, not empty geometry) */ + if( ! geography_datum_gidx(PG_GETARG_DATUM(0), gbox1) || + ! geography_datum_gidx(PG_GETARG_DATUM(1), gbox2) ) + { + PG_RETURN_BOOL(FALSE); + } + + geography_gidx_center(gbox1, &p1); + geography_gidx_center(gbox2, &p2); + + if( p1.x < p2.x || p1.y < p2.y || p1.z < p2.z ) + PG_RETURN_BOOL(TRUE); + + PG_RETURN_BOOL(FALSE); +} + +/* +** BTree support function. Based on two geographies return true if +** they are "less than or equal" and false otherwise. +*/ +PG_FUNCTION_INFO_V1(geography_le); +Datum geography_le(PG_FUNCTION_ARGS) +{ + /* Put aside some stack memory and use it for GIDX pointers. */ + char gboxmem1[GIDX_MAX_SIZE]; + char gboxmem2[GIDX_MAX_SIZE]; + GIDX *gbox1 = (GIDX*)gboxmem1; + GIDX *gbox2 = (GIDX*)gboxmem2; + POINT3D p1, p2; + + /* Must be able to build box for each argument (ie, not empty geometry) */ + if( ! geography_datum_gidx(PG_GETARG_DATUM(0), gbox1) || + ! geography_datum_gidx(PG_GETARG_DATUM(1), gbox2) ) + { + PG_RETURN_BOOL(FALSE); + } + + geography_gidx_center(gbox1, &p1); + geography_gidx_center(gbox2, &p2); + + if( p1.x <= p2.x || p1.y <= p2.y || p1.z <= p2.z ) + PG_RETURN_BOOL(TRUE); + + PG_RETURN_BOOL(FALSE); +} + +/* +** BTree support function. Based on two geographies return true if +** they are "greater than" and false otherwise. +*/ +PG_FUNCTION_INFO_V1(geography_gt); +Datum geography_gt(PG_FUNCTION_ARGS) +{ + /* Put aside some stack memory and use it for GIDX pointers. */ + char gboxmem1[GIDX_MAX_SIZE]; + char gboxmem2[GIDX_MAX_SIZE]; + GIDX *gbox1 = (GIDX*)gboxmem1; + GIDX *gbox2 = (GIDX*)gboxmem2; + POINT3D p1, p2; + + /* Must be able to build box for each argument (ie, not empty geometry) */ + if( ! geography_datum_gidx(PG_GETARG_DATUM(0), gbox1) || + ! geography_datum_gidx(PG_GETARG_DATUM(1), gbox2) ) + { + PG_RETURN_BOOL(FALSE); + } + + geography_gidx_center(gbox1, &p1); + geography_gidx_center(gbox2, &p2); + + if( p1.x > p2.x && p1.y > p2.y && p1.z > p2.z ) + PG_RETURN_BOOL(TRUE); + + PG_RETURN_BOOL(FALSE); +} + +/* +** BTree support function. Based on two geographies return true if +** they are "greater than or equal" and false otherwise. +*/ +PG_FUNCTION_INFO_V1(geography_ge); +Datum geography_ge(PG_FUNCTION_ARGS) +{ + /* Put aside some stack memory and use it for GIDX pointers. */ + char gboxmem1[GIDX_MAX_SIZE]; + char gboxmem2[GIDX_MAX_SIZE]; + GIDX *gbox1 = (GIDX*)gboxmem1; + GIDX *gbox2 = (GIDX*)gboxmem2; + POINT3D p1, p2; + + /* Must be able to build box for each argument (ie, not empty geometry) */ + if( ! geography_datum_gidx(PG_GETARG_DATUM(0), gbox1) || + ! geography_datum_gidx(PG_GETARG_DATUM(1), gbox2) ) + { + PG_RETURN_BOOL(FALSE); + } + + geography_gidx_center(gbox1, &p1); + geography_gidx_center(gbox2, &p2); + + if( p1.x >= p2.x && p1.y >= p2.y && p1.z >= p2.z ) + PG_RETURN_BOOL(TRUE); + + PG_RETURN_BOOL(FALSE); +} + +/* +** BTree support function. Based on two geographies return true if +** they are "equal" and false otherwise. +*/ +PG_FUNCTION_INFO_V1(geography_eq); +Datum geography_eq(PG_FUNCTION_ARGS) +{ + /* Put aside some stack memory and use it for GIDX pointers. */ + char gboxmem1[GIDX_MAX_SIZE]; + char gboxmem2[GIDX_MAX_SIZE]; + GIDX *gbox1 = (GIDX*)gboxmem1; + GIDX *gbox2 = (GIDX*)gboxmem2; + POINT3D p1, p2; + + /* Must be able to build box for each argument (ie, not empty geometry) */ + if( ! geography_datum_gidx(PG_GETARG_DATUM(0), gbox1) || + ! geography_datum_gidx(PG_GETARG_DATUM(1), gbox2) ) + { + PG_RETURN_BOOL(FALSE); + } + + geography_gidx_center(gbox1, &p1); + geography_gidx_center(gbox2, &p2); + + if( FP_EQUALS(p1.x, p2.x) && FP_EQUALS(p1.y, p2.y) && FP_EQUALS(p1.z, p2.z) ) + PG_RETURN_BOOL(TRUE); + + PG_RETURN_BOOL(FALSE); +} + +/* +** BTree support function. Based on two geographies return true if +** they are "equal" and false otherwise. +*/ +PG_FUNCTION_INFO_V1(geography_cmp); +Datum geography_cmp(PG_FUNCTION_ARGS) +{ + /* Put aside some stack memory and use it for GIDX pointers. */ + char gboxmem1[GIDX_MAX_SIZE]; + char gboxmem2[GIDX_MAX_SIZE]; + GIDX *gbox1 = (GIDX*)gboxmem1; + GIDX *gbox2 = (GIDX*)gboxmem2; + POINT3D p1, p2; + + /* Must be able to build box for each argument (ie, not empty geometry) */ + if( ! geography_datum_gidx(PG_GETARG_DATUM(0), gbox1) || + ! geography_datum_gidx(PG_GETARG_DATUM(1), gbox2) ) + { + PG_RETURN_BOOL(FALSE); + } + + geography_gidx_center(gbox1, &p1); + geography_gidx_center(gbox2, &p2); + + if( p1.x > p2.x && p1.y > p2.y && p1.z > p2.z ) + PG_RETURN_INT32(1); + + if( FP_EQUALS(p1.x, p2.x) && FP_EQUALS(p1.y, p2.y) && FP_EQUALS(p1.z, p2.z) ) + PG_RETURN_INT32(0); + + PG_RETURN_INT32(-1); + +} \ No newline at end of file