From 4cbe473938779ec414d90c2063c4398e68a70838 Mon Sep 17 00:00:00 2001 From: Teodor Sigaev Date: Thu, 14 Jan 2010 16:31:09 +0000 Subject: [PATCH] Add point_ops opclass for GiST. --- src/backend/access/gist/gistproc.c | 174 +++++++++++++++++++++++++- src/backend/utils/adt/geo_ops.c | 12 +- src/include/catalog/catversion.h | 4 +- src/include/catalog/pg_amop.h | 18 ++- src/include/catalog/pg_amproc.h | 9 +- src/include/catalog/pg_opclass.h | 3 +- src/include/catalog/pg_operator.h | 13 +- src/include/catalog/pg_opfamily.h | 3 +- src/include/catalog/pg_proc.h | 8 +- src/include/utils/geo_decls.h | 5 +- src/test/regress/expected/create_index.out | 190 +++++++++++++++++++++++++++++ src/test/regress/expected/opr_sanity.out | 10 +- src/test/regress/expected/point.out | 18 +++ src/test/regress/expected/sanity_check.out | 2 +- src/test/regress/sql/create_index.sql | 56 +++++++++ src/test/regress/sql/point.sql | 6 + 16 files changed, 511 insertions(+), 20 deletions(-) diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c index cf3442763e..18ee0259a5 100644 --- a/src/backend/access/gist/gistproc.c +++ b/src/backend/access/gist/gistproc.c @@ -10,7 +10,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.19 2010/01/02 16:57:34 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/gist/gistproc.c,v 1.20 2010/01/14 16:31:09 teodor Exp $ * *------------------------------------------------------------------------- */ @@ -165,7 +165,8 @@ gist_box_compress(PG_FUNCTION_ARGS) } /* - * GiST DeCompress method for boxes (also used for polygons and circles) + * GiST DeCompress method for boxes (also used for points, polygons + * and circles) * * do not do anything --- we just use the stored box as is. */ @@ -176,7 +177,7 @@ gist_box_decompress(PG_FUNCTION_ARGS) } /* - * The GiST Penalty method for boxes + * The GiST Penalty method for boxes (also used for points) * * As in the R-tree paper, we use change in area as our penalty metric */ @@ -341,6 +342,8 @@ fallbackSplit(GistEntryVector *entryvec, GIST_SPLITVEC *v) * * New linear algorithm, see 'New Linear Node Splitting Algorithm for R-tree', * C.H.Ang and T.C.Tan + * + * This is used for both boxes and points. */ Datum gist_box_picksplit(PG_FUNCTION_ARGS) @@ -533,6 +536,8 @@ gist_box_picksplit(PG_FUNCTION_ARGS) /* * Equality method + * + * This is used for both boxes and points. */ Datum gist_box_same(PG_FUNCTION_ARGS) @@ -872,3 +877,166 @@ gist_circle_consistent(PG_FUNCTION_ARGS) PG_RETURN_BOOL(result); } + +/************************************************** + * Point ops + **************************************************/ + +Datum +gist_point_compress(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + + if (entry->leafkey) /* Point, actually */ + { + BOX *box = palloc(sizeof(BOX)); + Point *point = DatumGetPointP(entry->key); + GISTENTRY *retval = palloc(sizeof(GISTENTRY)); + + box->high = box->low = *point; + + gistentryinit(*retval, BoxPGetDatum(box), + entry->rel, entry->page, entry->offset, FALSE); + + PG_RETURN_POINTER(retval); + } + + PG_RETURN_POINTER(entry); +} + +static bool +gist_point_consistent_internal(StrategyNumber strategy, + bool isLeaf, BOX *key, Point *query) +{ + bool result = false; + + switch (strategy) + { + case RTLeftStrategyNumber: + result = FPlt(key->low.x, query->x); + break; + case RTRightStrategyNumber: + result = FPgt(key->high.x, query->x); + break; + case RTAboveStrategyNumber: + result = FPgt(key->high.y, query->y); + break; + case RTBelowStrategyNumber: + result = FPlt(key->low.y, query->y); + break; + case RTSameStrategyNumber: + if (isLeaf) + { + result = FPeq(key->low.x, query->x) + && FPeq(key->low.y, query->y); + } + else + { + result = (query->x <= key->high.x && query->x >= key->low.x && + query->y <= key->high.y && query->y >= key->low.y); + } + break; + default: + elog(ERROR, "unknown strategy number: %d", strategy); + } + + return result; +} + +#define GeoStrategyNumberOffset 20 +#define PointStrategyNumberGroup 0 +#define BoxStrategyNumberGroup 1 +#define PolygonStrategyNumberGroup 2 +#define CircleStrategyNumberGroup 3 + +Datum +gist_point_consistent(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); + bool result; + bool *recheck = (bool *) PG_GETARG_POINTER(4); + StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset; + + switch (strategyGroup) + { + case PointStrategyNumberGroup: + result = gist_point_consistent_internal(strategy % GeoStrategyNumberOffset, + GIST_LEAF(entry), + DatumGetBoxP(entry->key), + PG_GETARG_POINT_P(1)); + *recheck = false; + break; + case BoxStrategyNumberGroup: + result = DatumGetBool(DirectFunctionCall5( + gist_box_consistent, + PointerGetDatum(entry), + PG_GETARG_DATUM(1), + Int16GetDatum(RTOverlapStrategyNumber), + 0, PointerGetDatum(recheck))); + break; + case PolygonStrategyNumberGroup: + { + POLYGON *query = PG_GETARG_POLYGON_P(1); + + result = DatumGetBool(DirectFunctionCall5( + gist_poly_consistent, + PointerGetDatum(entry), + PolygonPGetDatum(query), + Int16GetDatum(RTOverlapStrategyNumber), + 0, PointerGetDatum(recheck))); + + if (GIST_LEAF(entry) && result) + { + /* + * We are on leaf page and quick check shows overlapping + * of polygon's bounding box and point + */ + BOX *box = DatumGetBoxP(entry->key); + + Assert(box->high.x == box->low.x + && box->high.y == box->low.y); + result = DatumGetBool(DirectFunctionCall2( + poly_contain_pt, + PolygonPGetDatum(query), + PointPGetDatum(&box->high))); + *recheck = false; + } + } + break; + case CircleStrategyNumberGroup: + { + CIRCLE *query = PG_GETARG_CIRCLE_P(1); + + result = DatumGetBool(DirectFunctionCall5( + gist_circle_consistent, + PointerGetDatum(entry), + CirclePGetDatum(query), + Int16GetDatum(RTOverlapStrategyNumber), + 0, PointerGetDatum(recheck))); + + if (GIST_LEAF(entry) && result) + { + /* + * We are on leaf page and quick check shows overlapping + * of polygon's bounding box and point + */ + BOX *box = DatumGetBoxP(entry->key); + + Assert(box->high.x == box->low.x + && box->high.y == box->low.y); + result = DatumGetBool(DirectFunctionCall2( + circle_contain_pt, + CirclePGetDatum(query), + PointPGetDatum(&box->high))); + *recheck = false; + } + } + break; + default: + result = false; /* silence compiler warning */ + elog(ERROR, "unknown strategy number: %d", strategy); + } + + PG_RETURN_BOOL(result); +} diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c index 2eb7242881..35f1a13ab6 100644 --- a/src/backend/utils/adt/geo_ops.c +++ b/src/backend/utils/adt/geo_ops.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/geo_ops.c,v 1.106 2010/01/02 16:57:54 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/geo_ops.c,v 1.107 2010/01/14 16:31:09 teodor Exp $ * *------------------------------------------------------------------------- */ @@ -3202,6 +3202,16 @@ on_pb(PG_FUNCTION_ARGS) pt->y <= box->high.y && pt->y >= box->low.y); } +Datum +box_contain_pt(PG_FUNCTION_ARGS) +{ + BOX *box = PG_GETARG_BOX_P(0); + Point *pt = PG_GETARG_POINT_P(1); + + PG_RETURN_BOOL(pt->x <= box->high.x && pt->x >= box->low.x && + pt->y <= box->high.y && pt->y >= box->low.y); +} + /* on_ppath - * Whether a point lies within (on) a polyline. * If open, we have to (groan) check each segment. diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 5217147f36..e981823320 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.571 2010/01/12 02:42:52 momjian Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.572 2010/01/14 16:31:09 teodor Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 201001111 +#define CATALOG_VERSION_NO 201001141 #endif diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h index b107c6e4ba..1f0c1d81d6 100644 --- a/src/include/catalog/pg_amop.h +++ b/src/include/catalog/pg_amop.h @@ -29,7 +29,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.92 2010/01/05 01:06:56 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_amop.h,v 1.93 2010/01/14 16:31:09 teodor Exp $ * * NOTES * the genbki.pl script reads this file and generates .bki @@ -583,6 +583,22 @@ DATA(insert ( 2593 603 603 13 2863 783 )); DATA(insert ( 2593 603 603 14 2862 783 )); /* + * gist point_ops + */ +DATA(insert ( 1029 600 600 11 506 783 )); +DATA(insert ( 1029 600 600 1 507 783 )); +DATA(insert ( 1029 600 600 5 508 783 )); +DATA(insert ( 1029 600 600 10 509 783 )); +DATA(insert ( 1029 600 600 6 510 783 )); +DATA(insert ( 1029 603 600 27 433 783 )); +DATA(insert ( 1029 600 603 28 511 783 )); +DATA(insert ( 1029 604 600 47 757 783 )); +DATA(insert ( 1029 600 604 48 756 783 )); +DATA(insert ( 1029 718 600 67 759 783 )); +DATA(insert ( 1029 600 718 68 758 783 )); + + +/* * gist poly_ops (supports polygons) */ diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h index 739f2c4b64..0f0f6e1fe0 100644 --- a/src/include/catalog/pg_amproc.h +++ b/src/include/catalog/pg_amproc.h @@ -22,7 +22,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.77 2010/01/05 01:06:56 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_amproc.h,v 1.78 2010/01/14 16:31:09 teodor Exp $ * * NOTES * the genbki.pl script reads this file and generates .bki @@ -197,6 +197,13 @@ DATA(insert ( 3702 3615 3615 4 3696 )); DATA(insert ( 3702 3615 3615 5 3700 )); DATA(insert ( 3702 3615 3615 6 3697 )); DATA(insert ( 3702 3615 3615 7 3699 )); +DATA(insert ( 1029 600 600 1 2179 )); +DATA(insert ( 1029 600 600 2 2583 )); +DATA(insert ( 1029 600 600 3 1030 )); +DATA(insert ( 1029 600 600 4 2580 )); +DATA(insert ( 1029 600 600 5 2581 )); +DATA(insert ( 1029 600 600 6 2582 )); +DATA(insert ( 1029 600 600 7 2584 )); /* gin */ diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h index e5f19c895a..6281121365 100644 --- a/src/include/catalog/pg_opclass.h +++ b/src/include/catalog/pg_opclass.h @@ -28,7 +28,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_opclass.h,v 1.87 2010/01/05 01:06:56 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_opclass.h,v 1.88 2010/01/14 16:31:09 teodor Exp $ * * NOTES * the genbki.pl script reads this file and generates .bki @@ -170,6 +170,7 @@ DATA(insert ( 403 reltime_ops PGNSP PGUID 2233 703 t 0 )); DATA(insert ( 403 tinterval_ops PGNSP PGUID 2234 704 t 0 )); DATA(insert ( 405 aclitem_ops PGNSP PGUID 2235 1033 t 0 )); DATA(insert ( 783 box_ops PGNSP PGUID 2593 603 t 0 )); +DATA(insert ( 783 point_ops PGNSP PGUID 1029 600 t 603 )); DATA(insert ( 783 poly_ops PGNSP PGUID 2594 604 t 603 )); DATA(insert ( 783 circle_ops PGNSP PGUID 2595 718 t 603 )); DATA(insert ( 2742 _int4_ops PGNSP PGUID 2745 1007 t 23 )); diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h index fd59882006..25429cf151 100644 --- a/src/include/catalog/pg_operator.h +++ b/src/include/catalog/pg_operator.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.169 2010/01/05 01:06:56 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_operator.h,v 1.170 2010/01/14 16:31:09 teodor Exp $ * * NOTES * the genbki.pl script reads this file and generates .bki @@ -171,7 +171,8 @@ DATA(insert OID = 507 ( "<<" PGNSP PGUID b f f 600 600 16 0 0 point_left p DATA(insert OID = 508 ( ">>" PGNSP PGUID b f f 600 600 16 0 0 point_right positionsel positionjoinsel )); DATA(insert OID = 509 ( "<^" PGNSP PGUID b f f 600 600 16 0 0 point_below positionsel positionjoinsel )); DATA(insert OID = 510 ( "~=" PGNSP PGUID b f f 600 600 16 510 713 point_eq eqsel eqjoinsel )); -DATA(insert OID = 511 ( "<@" PGNSP PGUID b f f 600 603 16 0 0 on_pb - - )); +DATA(insert OID = 511 ( "<@" PGNSP PGUID b f f 600 603 16 433 0 on_pb contsel contjoinsel )); +DATA(insert OID = 433 ( "@>" PGNSP PGUID b f f 603 600 16 511 0 box_contain_pt contsel contjoinsel )); DATA(insert OID = 512 ( "<@" PGNSP PGUID b f f 600 602 16 755 0 on_ppath - - )); DATA(insert OID = 513 ( "@@" PGNSP PGUID l f f 0 603 600 0 0 box_center - - )); DATA(insert OID = 514 ( "*" PGNSP PGUID b f f 23 23 23 514 0 int4mul - - )); @@ -359,10 +360,10 @@ DATA(insert OID = 737 ( "-" PGNSP PGUID b f f 602 600 602 0 0 path_sub_ DATA(insert OID = 738 ( "*" PGNSP PGUID b f f 602 600 602 0 0 path_mul_pt - - )); DATA(insert OID = 739 ( "/" PGNSP PGUID b f f 602 600 602 0 0 path_div_pt - - )); DATA(insert OID = 755 ( "@>" PGNSP PGUID b f f 602 600 16 512 0 path_contain_pt - - )); -DATA(insert OID = 756 ( "<@" PGNSP PGUID b f f 600 604 16 757 0 pt_contained_poly - - )); -DATA(insert OID = 757 ( "@>" PGNSP PGUID b f f 604 600 16 756 0 poly_contain_pt - - )); -DATA(insert OID = 758 ( "<@" PGNSP PGUID b f f 600 718 16 759 0 pt_contained_circle - - )); -DATA(insert OID = 759 ( "@>" PGNSP PGUID b f f 718 600 16 758 0 circle_contain_pt - - )); +DATA(insert OID = 756 ( "<@" PGNSP PGUID b f f 600 604 16 757 0 pt_contained_poly contsel contjoinsel )); +DATA(insert OID = 757 ( "@>" PGNSP PGUID b f f 604 600 16 756 0 poly_contain_pt contsel contjoinsel )); +DATA(insert OID = 758 ( "<@" PGNSP PGUID b f f 600 718 16 759 0 pt_contained_circle contsel contjoinsel )); +DATA(insert OID = 759 ( "@>" PGNSP PGUID b f f 718 600 16 758 0 circle_contain_pt contsel contjoinsel )); DATA(insert OID = 773 ( "@" PGNSP PGUID l f f 0 23 23 0 0 int4abs - - )); diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h index aa93df8eca..5db9cb6f68 100644 --- a/src/include/catalog/pg_opfamily.h +++ b/src/include/catalog/pg_opfamily.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_opfamily.h,v 1.13 2010/01/05 01:06:56 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_opfamily.h,v 1.14 2010/01/14 16:31:09 teodor Exp $ * * NOTES * the genbki.pl script reads this file and generates .bki @@ -127,6 +127,7 @@ DATA(insert OID = 2235 ( 405 aclitem_ops PGNSP PGUID )); DATA(insert OID = 2593 ( 783 box_ops PGNSP PGUID )); DATA(insert OID = 2594 ( 783 poly_ops PGNSP PGUID )); DATA(insert OID = 2595 ( 783 circle_ops PGNSP PGUID )); +DATA(insert OID = 1029 ( 783 point_ops PGNSP PGUID )); DATA(insert OID = 2745 ( 2742 array_ops PGNSP PGUID )); DATA(insert OID = 2968 ( 403 uuid_ops PGNSP PGUID )); DATA(insert OID = 2969 ( 405 uuid_ops PGNSP PGUID )); diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index b39c02f7f2..7a16e3faa7 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.560 2010/01/07 20:17:44 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.561 2010/01/14 16:31:09 teodor Exp $ * * NOTES * The script catalog/genbki.pl reads this file and generates .bki @@ -396,6 +396,8 @@ DATA(insert OID = 191 ( box_right PGNSP PGUID 12 1 0 0 f f f t f i 2 0 16 " DESCR("is right of"); DATA(insert OID = 192 ( box_contained PGNSP PGUID 12 1 0 0 f f f t f i 2 0 16 "603 603" _null_ _null_ _null_ _null_ box_contained _null_ _null_ _null_ )); DESCR("is contained by?"); +DATA(insert OID = 193 ( box_contain_pt PGNSP PGUID 12 1 0 0 f f f t f i 2 0 16 "603 600" _null_ _null_ _null_ _null_ box_contain_pt _null_ _null_ _null_ )); +DESCR("contains?"); /* OIDS 200 - 299 */ @@ -4205,6 +4207,10 @@ DATA(insert OID = 2591 ( gist_circle_consistent PGNSP PGUID 12 1 0 0 f f f t f DESCR("GiST support"); DATA(insert OID = 2592 ( gist_circle_compress PGNSP PGUID 12 1 0 0 f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ gist_circle_compress _null_ _null_ _null_ )); DESCR("GiST support"); +DATA(insert OID = 1030 ( gist_point_compress PGNSP PGUID 12 1 0 0 f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ gist_point_compress _null_ _null_ _null_ )); +DESCR("GiST support"); +DATA(insert OID = 2179 ( gist_point_consistent PGNSP PGUID 12 1 0 0 f f f t f i 5 0 16 "2281 603 23 26 2281" _null_ _null_ _null_ _null_ gist_point_consistent _null_ _null_ _null_ )); +DESCR("GiST support"); /* GIN */ DATA(insert OID = 2731 ( gingetbitmap PGNSP PGUID 12 1 0 0 f f f t f v 2 0 20 "2281 2281" _null_ _null_ _null_ _null_ gingetbitmap _null_ _null_ _null_ )); diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h index 7863f5e619..f43d2d5fdc 100644 --- a/src/include/utils/geo_decls.h +++ b/src/include/utils/geo_decls.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/geo_decls.h,v 1.56 2010/01/02 16:58:10 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/geo_decls.h,v 1.57 2010/01/14 16:31:09 teodor Exp $ * * NOTE * These routines do *not* use the float types from adt/. @@ -290,6 +290,7 @@ extern Datum box_above(PG_FUNCTION_ARGS); extern Datum box_overabove(PG_FUNCTION_ARGS); extern Datum box_contained(PG_FUNCTION_ARGS); extern Datum box_contain(PG_FUNCTION_ARGS); +extern Datum box_contain_pt(PG_FUNCTION_ARGS); extern Datum box_below_eq(PG_FUNCTION_ARGS); extern Datum box_above_eq(PG_FUNCTION_ARGS); extern Datum box_lt(PG_FUNCTION_ARGS); @@ -420,6 +421,8 @@ extern Datum gist_poly_compress(PG_FUNCTION_ARGS); extern Datum gist_poly_consistent(PG_FUNCTION_ARGS); extern Datum gist_circle_compress(PG_FUNCTION_ARGS); extern Datum gist_circle_consistent(PG_FUNCTION_ARGS); +extern Datum gist_point_compress(PG_FUNCTION_ARGS); +extern Datum gist_point_consistent(PG_FUNCTION_ARGS); /* geo_selfuncs.c */ extern Datum areasel(PG_FUNCTION_ARGS); diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out index b67f4e06f3..2275343704 100644 --- a/src/test/regress/expected/create_index.out +++ b/src/test/regress/expected/create_index.out @@ -51,6 +51,7 @@ CREATE INDEX onek2_stu1_prtl ON onek2 USING btree(stringu1 name_ops) CREATE INDEX grect2ind ON fast_emp4000 USING gist (home_base); CREATE INDEX gpolygonind ON polygon_tbl USING gist (f1); CREATE INDEX gcircleind ON circle_tbl USING gist (f1); +CREATE INDEX gpointind ON point_tbl USING gist (f1); CREATE TEMP TABLE gpolygon_tbl AS SELECT polygon(home_base) AS f1 FROM slow_emp4000; INSERT INTO gpolygon_tbl VALUES ( '(1000,0,0,1000)' ); @@ -112,6 +113,60 @@ SELECT count(*) FROM gcircle_tbl WHERE f1 && '<(500,500),500>'::circle; 2 (1 row) +SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)'; + count +------- + 3 +(1 row) + +SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1; + count +------- + 3 +(1 row) + +SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)'; + count +------- + 3 +(1 row) + +SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>'; + count +------- + 1 +(1 row) + +SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)'; + count +------- + 3 +(1 row) + +SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)'; + count +------- + 2 +(1 row) + +SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)'; + count +------- + 1 +(1 row) + +SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)'; + count +------- + 3 +(1 row) + +SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)'; + count +------- + 1 +(1 row) + SET enable_seqscan = OFF; SET enable_indexscan = ON; SET enable_bitmapscan = ON; @@ -245,6 +300,141 @@ SELECT count(*) FROM gcircle_tbl WHERE f1 && '<(500,500),500>'::circle; 2 (1 row) +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)'; + QUERY PLAN +---------------------------------------------------- + Aggregate + -> Index Scan using gpointind on point_tbl + Index Cond: (f1 <@ '(100,100),(0,0)'::box) +(3 rows) + +SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)'; + count +------- + 3 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1; + QUERY PLAN +---------------------------------------------------- + Aggregate + -> Index Scan using gpointind on point_tbl + Index Cond: ('(100,100),(0,0)'::box @> f1) +(3 rows) + +SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1; + count +------- + 3 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)'; + QUERY PLAN +---------------------------------------------------------------------------------------- + Aggregate + -> Index Scan using gpointind on point_tbl + Index Cond: (f1 <@ '((0,0),(0,100),(100,100),(50,50),(100,0),(0,0))'::polygon) +(3 rows) + +SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)'; + count +------- + 3 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>'; + QUERY PLAN +---------------------------------------------------- + Aggregate + -> Index Scan using gpointind on point_tbl + Index Cond: (f1 <@ '<(50,50),50>'::circle) +(3 rows) + +SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>'; + count +------- + 1 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)'; + QUERY PLAN +------------------------------------------------- + Aggregate + -> Index Scan using gpointind on point_tbl p + Index Cond: (f1 << '(0,0)'::point) +(3 rows) + +SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)'; + count +------- + 3 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)'; + QUERY PLAN +------------------------------------------------- + Aggregate + -> Index Scan using gpointind on point_tbl p + Index Cond: (f1 >> '(0,0)'::point) +(3 rows) + +SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)'; + count +------- + 2 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)'; + QUERY PLAN +------------------------------------------------- + Aggregate + -> Index Scan using gpointind on point_tbl p + Index Cond: (f1 <^ '(0,0)'::point) +(3 rows) + +SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)'; + count +------- + 1 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)'; + QUERY PLAN +------------------------------------------------- + Aggregate + -> Index Scan using gpointind on point_tbl p + Index Cond: (f1 >^ '(0,0)'::point) +(3 rows) + +SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)'; + count +------- + 3 +(1 row) + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)'; + QUERY PLAN +------------------------------------------------- + Aggregate + -> Index Scan using gpointind on point_tbl p + Index Cond: (f1 ~= '(-5,-12)'::point) +(3 rows) + +SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)'; + count +------- + 1 +(1 row) + RESET enable_seqscan; RESET enable_indexscan; RESET enable_bitmapscan; diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out index 24a2e8a8e6..5e36d481df 100644 --- a/src/test/regress/expected/opr_sanity.out +++ b/src/test/regress/expected/opr_sanity.out @@ -902,17 +902,25 @@ ORDER BY 1, 2, 3; 783 | 8 | <@ 783 | 9 | &<| 783 | 10 | <<| + 783 | 10 | <^ + 783 | 11 | >^ 783 | 11 | |>> 783 | 12 | |&> 783 | 13 | ~ 783 | 14 | @ + 783 | 27 | @> + 783 | 28 | <@ + 783 | 47 | @> + 783 | 48 | <@ + 783 | 67 | @> + 783 | 68 | <@ 2742 | 1 | && 2742 | 1 | @@ 2742 | 2 | @> 2742 | 2 | @@@ 2742 | 3 | <@ 2742 | 4 | = -(31 rows) +(39 rows) -- Check that all operators linked to by opclass entries have selectivity -- estimators. This is not absolutely required, but it seems a reasonable diff --git a/src/test/regress/expected/point.out b/src/test/regress/expected/point.out index 9d1bd434e9..278837d091 100644 --- a/src/test/regress/expected/point.out +++ b/src/test/regress/expected/point.out @@ -82,6 +82,15 @@ SELECT '' AS three, p.* FROM POINT_TBL p (3 rows) SELECT '' AS three, p.* FROM POINT_TBL p + WHERE box '(0,0,100,100)' @> p.f1; + three | f1 +-------+------------ + | (0,0) + | (5.1,34.5) + | (10,10) +(3 rows) + +SELECT '' AS three, p.* FROM POINT_TBL p WHERE not p.f1 <@ box '(0,0,100,100)'; three | f1 -------+---------- @@ -98,6 +107,15 @@ SELECT '' AS two, p.* FROM POINT_TBL p | (-10,0) (2 rows) +SELECT '' AS three, p.* FROM POINT_TBL p + WHERE not box '(0,0,100,100)' @> p.f1; + three | f1 +-------+---------- + | (-10,0) + | (-3,4) + | (-5,-12) +(3 rows) + SELECT '' AS six, p.f1, p.f1 <-> point '(0,0)' AS dist FROM POINT_TBL p ORDER BY dist; diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out index 2a4dc4755d..4dc59d9b5d 100644 --- a/src/test/regress/expected/sanity_check.out +++ b/src/test/regress/expected/sanity_check.out @@ -127,7 +127,7 @@ SELECT relname, relhasindex pg_ts_template | t pg_type | t pg_user_mapping | t - point_tbl | f + point_tbl | t polygon_tbl | t ramp | f real_city | f diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql index 519c3181a8..a4261c0f5e 100644 --- a/src/test/regress/sql/create_index.sql +++ b/src/test/regress/sql/create_index.sql @@ -76,6 +76,8 @@ CREATE INDEX gpolygonind ON polygon_tbl USING gist (f1); CREATE INDEX gcircleind ON circle_tbl USING gist (f1); +CREATE INDEX gpointind ON point_tbl USING gist (f1); + CREATE TEMP TABLE gpolygon_tbl AS SELECT polygon(home_base) AS f1 FROM slow_emp4000; INSERT INTO gpolygon_tbl VALUES ( '(1000,0,0,1000)' ); @@ -110,6 +112,24 @@ SELECT count(*) FROM gpolygon_tbl WHERE f1 && '(1000,1000,0,0)'::polygon; SELECT count(*) FROM gcircle_tbl WHERE f1 && '<(500,500),500>'::circle; +SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)'; + +SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1; + +SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)'; + +SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>'; + +SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)'; + +SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)'; + +SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)'; + +SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)'; + +SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)'; + SET enable_seqscan = OFF; SET enable_indexscan = ON; SET enable_bitmapscan = ON; @@ -150,6 +170,42 @@ EXPLAIN (COSTS OFF) SELECT count(*) FROM gcircle_tbl WHERE f1 && '<(500,500),500>'::circle; SELECT count(*) FROM gcircle_tbl WHERE f1 && '<(500,500),500>'::circle; +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)'; +SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)'; + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1; +SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1; + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)'; +SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)'; + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>'; +SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>'; + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)'; +SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)'; + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)'; +SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)'; + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)'; +SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)'; + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)'; +SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)'; + +EXPLAIN (COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)'; +SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)'; + RESET enable_seqscan; RESET enable_indexscan; RESET enable_bitmapscan; diff --git a/src/test/regress/sql/point.sql b/src/test/regress/sql/point.sql index 8523c2ee9f..40cd4ec022 100644 --- a/src/test/regress/sql/point.sql +++ b/src/test/regress/sql/point.sql @@ -46,11 +46,17 @@ SELECT '' AS three, p.* FROM POINT_TBL p WHERE p.f1 <@ box '(0,0,100,100)'; SELECT '' AS three, p.* FROM POINT_TBL p + WHERE box '(0,0,100,100)' @> p.f1; + +SELECT '' AS three, p.* FROM POINT_TBL p WHERE not p.f1 <@ box '(0,0,100,100)'; SELECT '' AS two, p.* FROM POINT_TBL p WHERE p.f1 <@ path '[(0,0),(-10,0),(-10,10)]'; +SELECT '' AS three, p.* FROM POINT_TBL p + WHERE not box '(0,0,100,100)' @> p.f1; + SELECT '' AS six, p.f1, p.f1 <-> point '(0,0)' AS dist FROM POINT_TBL p ORDER BY dist; -- 2.11.0