diff --git a/doc/src/sgml/spgist.sgml b/doc/src/sgml/spgist.sgml
new file mode 100644
index dcdc297..bac9979
*** a/doc/src/sgml/spgist.sgml
--- b/doc/src/sgml/spgist.sgml
***************
*** 131,136 ****
--- 131,172 ----
+ circle_ops>
+ circle>
+
+ <<>
+ &<>
+ &&>
+ &>>
+ >>>
+ ~=>
+ @>>
+ <@>
+ &<|>
+ <<|>
+ |>>>
+ |&>>
+
+
+
+ poly_ops>
+ polygon>
+
+ <<>
+ &<>
+ &&>
+ &>>
+ >>>
+ ~=>
+ @>>
+ <@>
+ &<|>
+ <<|>
+ |>>>
+ |&>>
+
+
+
text_ops>
text>
diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c
new file mode 100644
index d1919fc..1c11f1f
*** a/src/backend/access/gist/gistproc.c
--- b/src/backend/access/gist/gistproc.c
*************** gist_circle_compress(PG_FUNCTION_ARGS)
*** 1115,1126 ****
CIRCLE *in = DatumGetCircleP(entry->key);
BOX *r;
! r = (BOX *) palloc(sizeof(BOX));
! r->high.x = in->center.x + in->radius;
! r->low.x = in->center.x - in->radius;
! r->high.y = in->center.y + in->radius;
! r->low.y = in->center.y - in->radius;
!
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page,
--- 1115,1121 ----
CIRCLE *in = DatumGetCircleP(entry->key);
BOX *r;
! r = circle_bbox(in);
retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
gistentryinit(*retval, PointerGetDatum(r),
entry->rel, entry->page,
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
new file mode 100644
index 0348855..fce9f73
*** a/src/backend/utils/adt/geo_ops.c
--- b/src/backend/utils/adt/geo_ops.c
*************** enum path_delim
*** 41,47 ****
static int point_inside(Point *p, int npts, Point *plist);
static int lseg_crossing(double x, double y, double px, double py);
static BOX *box_construct(double x1, double x2, double y1, double y2);
- static BOX *box_copy(BOX *box);
static BOX *box_fill(BOX *result, double x1, double x2, double y1, double y2);
static bool box_ov(BOX *box1, BOX *box2);
static double box_ht(BOX *box);
--- 41,46 ----
*************** box_fill(BOX *result, double x1, double
*** 482,488 ****
/* box_copy - copy a box
*/
! static BOX *
box_copy(BOX *box)
{
BOX *result = (BOX *) palloc(sizeof(BOX));
--- 481,487 ----
/* box_copy - copy a box
*/
! BOX *
box_copy(BOX *box)
{
BOX *result = (BOX *) palloc(sizeof(BOX));
*************** circle_ar(CIRCLE *circle)
*** 5089,5094 ****
--- 5088,5122 ----
return M_PI * (circle->radius * circle->radius);
}
+ /* circle_bbox - returns bounding box of the circle.
+ */
+ BOX *
+ circle_bbox(CIRCLE *circle)
+ {
+ BOX *bbox = (BOX *) palloc(sizeof(BOX));
+
+ bbox->high.x = circle->center.x + circle->radius;
+ bbox->low.x = circle->center.x - circle->radius;
+ bbox->high.y = circle->center.y + circle->radius;
+ bbox->low.y = circle->center.y - circle->radius;
+
+ if (isnan(bbox->low.x))
+ {
+ double tmp = bbox->low.x;
+ bbox->low.x = bbox->high.x;
+ bbox->high.x = tmp;
+ }
+
+ if (isnan(bbox->low.y))
+ {
+ double tmp = bbox->low.y;
+ bbox->low.y = bbox->high.y;
+ bbox->high.y = tmp;
+ }
+
+ return bbox;
+ }
+
/*----------------------------------------------------------
* Conversion operators.
diff --git a/src/backend/utils/adt/geo_spgist.c b/src/backend/utils/adt/geo_spgist.c
new file mode 100644
index f6334ba..1237bd2
*** a/src/backend/utils/adt/geo_spgist.c
--- b/src/backend/utils/adt/geo_spgist.c
*************** spg_box_quad_choose(PG_FUNCTION_ARGS)
*** 391,397 ****
spgChooseIn *in = (spgChooseIn *) PG_GETARG_POINTER(0);
spgChooseOut *out = (spgChooseOut *) PG_GETARG_POINTER(1);
BOX *centroid = DatumGetBoxP(in->prefixDatum),
! *box = DatumGetBoxP(in->datum);
out->resultType = spgMatchNode;
out->result.matchNode.restDatum = BoxPGetDatum(box);
--- 391,397 ----
spgChooseIn *in = (spgChooseIn *) PG_GETARG_POINTER(0);
spgChooseOut *out = (spgChooseOut *) PG_GETARG_POINTER(1);
BOX *centroid = DatumGetBoxP(in->prefixDatum),
! *box = DatumGetBoxP(in->leafDatum);
out->resultType = spgMatchNode;
out->result.matchNode.restDatum = BoxPGetDatum(box);
*************** spg_box_quad_picksplit(PG_FUNCTION_ARGS)
*** 474,479 ****
--- 474,529 ----
}
/*
+ * Check if result of consistent method based on bounding box is exact.
+ */
+ static bool
+ is_bounding_box_test_exact(StrategyNumber strategy)
+ {
+ switch (strategy)
+ {
+ case RTLeftStrategyNumber:
+ case RTOverLeftStrategyNumber:
+ case RTOverRightStrategyNumber:
+ case RTRightStrategyNumber:
+ case RTOverBelowStrategyNumber:
+ case RTBelowStrategyNumber:
+ case RTAboveStrategyNumber:
+ case RTOverAboveStrategyNumber:
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ /*
+ * Get bounding box for ScanKey.
+ */
+ static BOX *
+ spg_box_quad_get_scankey_bbox(ScanKey sk, bool *recheck)
+ {
+ switch (sk->sk_subtype)
+ {
+ case BOXOID:
+ return DatumGetBoxP(sk->sk_argument);
+
+ case CIRCLEOID:
+ if (recheck && !is_bounding_box_test_exact(sk->sk_strategy))
+ *recheck = true;
+ return circle_bbox(DatumGetCircleP(sk->sk_argument));
+
+ case POLYGONOID:
+ if (recheck && !is_bounding_box_test_exact(sk->sk_strategy))
+ *recheck = true;
+ return &DatumGetPolygonP(sk->sk_argument)->boundbox;
+
+ default:
+ elog(ERROR, "unrecognized scankey subtype: %d", sk->sk_subtype);
+ return NULL;
+ }
+ }
+
+ /*
* SP-GiST inner consistent function
*/
Datum
*************** spg_box_quad_inner_consistent(PG_FUNCTIO
*** 515,521 ****
centroid = getRangeBox(DatumGetBoxP(in->prefixDatum));
queries = (RangeBox **) palloc(in->nkeys * sizeof(RangeBox *));
for (i = 0; i < in->nkeys; i++)
! queries[i] = getRangeBox(DatumGetBoxP(in->scankeys[i].sk_argument));
/* Allocate enough memory for nodes */
out->nNodes = 0;
--- 565,575 ----
centroid = getRangeBox(DatumGetBoxP(in->prefixDatum));
queries = (RangeBox **) palloc(in->nkeys * sizeof(RangeBox *));
for (i = 0; i < in->nkeys; i++)
! {
! BOX *box = spg_box_quad_get_scankey_bbox(&in->scankeys[i], NULL);
!
! queries[i] = getRangeBox(box);
! }
/* Allocate enough memory for nodes */
out->nNodes = 0;
*************** spg_box_quad_leaf_consistent(PG_FUNCTION
*** 637,644 ****
/* Perform the required comparison(s) */
for (i = 0; i < in->nkeys; i++)
{
! StrategyNumber strategy = in->scankeys[i].sk_strategy;
! Datum query = in->scankeys[i].sk_argument;
switch (strategy)
{
--- 691,700 ----
/* Perform the required comparison(s) */
for (i = 0; i < in->nkeys; i++)
{
! StrategyNumber strategy = in->scankeys[i].sk_strategy;
! BOX *box = spg_box_quad_get_scankey_bbox(&in->scankeys[i],
! &out->recheck);
! Datum query = BoxPGetDatum(box);
switch (strategy)
{
*************** spg_box_quad_leaf_consistent(PG_FUNCTION
*** 713,715 ****
--- 769,818 ----
PG_RETURN_BOOL(flag);
}
+
+
+ /*
+ * SP-GiST config function for 2-D types that are lossy represented by their
+ * bounding boxes
+ */
+ Datum
+ spg_bbox_quad_config(PG_FUNCTION_ARGS)
+ {
+ spgConfigOut *cfg = (spgConfigOut *) PG_GETARG_POINTER(1);
+
+ cfg->prefixType = BOXOID; /* A type represented by its bounding box */
+ cfg->labelType = VOIDOID; /* We don't need node labels. */
+ cfg->leafType = BOXOID;
+ cfg->canReturnData = false;
+ cfg->longValuesOK = false;
+
+ PG_RETURN_VOID();
+ }
+
+ /*
+ * SP-GiST compress function for circles
+ */
+ Datum
+ spg_circle_quad_compress(PG_FUNCTION_ARGS)
+ {
+ CIRCLE *circle = PG_GETARG_CIRCLE_P(0);
+ BOX *box;
+
+ box = circle_bbox(circle);
+
+ PG_RETURN_BOX_P(box);
+ }
+
+ /*
+ * SP-GiST compress function for polygons
+ */
+ Datum
+ spg_poly_quad_compress(PG_FUNCTION_ARGS)
+ {
+ POLYGON *polygon = PG_GETARG_POLYGON_P(0);
+ BOX *box;
+
+ box = box_copy(&polygon->boundbox);
+
+ PG_RETURN_BOX_P(box);
+ }
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
new file mode 100644
index f850be4..d1527db
*** a/src/include/catalog/pg_amop.h
--- b/src/include/catalog/pg_amop.h
*************** DATA(insert ( 5000 603 603 11 s 2573 40
*** 858,863 ****
--- 858,895 ----
DATA(insert ( 5000 603 603 12 s 2572 4000 0 ));
/*
+ * SP-GiST circle_ops
+ */
+ DATA(insert ( 5007 718 718 1 s 1506 4000 0 ));
+ DATA(insert ( 5007 718 718 2 s 1507 4000 0 ));
+ DATA(insert ( 5007 718 718 3 s 1513 4000 0 ));
+ DATA(insert ( 5007 718 718 4 s 1508 4000 0 ));
+ DATA(insert ( 5007 718 718 5 s 1509 4000 0 ));
+ DATA(insert ( 5007 718 718 6 s 1512 4000 0 ));
+ DATA(insert ( 5007 718 718 7 s 1511 4000 0 ));
+ DATA(insert ( 5007 718 718 8 s 1510 4000 0 ));
+ DATA(insert ( 5007 718 718 9 s 2589 4000 0 ));
+ DATA(insert ( 5007 718 718 10 s 1515 4000 0 ));
+ DATA(insert ( 5007 718 718 11 s 1514 4000 0 ));
+ DATA(insert ( 5007 718 718 12 s 2590 4000 0 ));
+
+ /*
+ * SP-GiST poly_ops (supports polygons)
+ */
+ DATA(insert ( 5008 604 604 1 s 485 4000 0 ));
+ DATA(insert ( 5008 604 604 2 s 486 4000 0 ));
+ DATA(insert ( 5008 604 604 3 s 492 4000 0 ));
+ DATA(insert ( 5008 604 604 4 s 487 4000 0 ));
+ DATA(insert ( 5008 604 604 5 s 488 4000 0 ));
+ DATA(insert ( 5008 604 604 6 s 491 4000 0 ));
+ DATA(insert ( 5008 604 604 7 s 490 4000 0 ));
+ DATA(insert ( 5008 604 604 8 s 489 4000 0 ));
+ DATA(insert ( 5008 604 604 9 s 2575 4000 0 ));
+ DATA(insert ( 5008 604 604 10 s 2574 4000 0 ));
+ DATA(insert ( 5008 604 604 11 s 2577 4000 0 ));
+ DATA(insert ( 5008 604 604 12 s 2576 4000 0 ));
+
+ /*
* GiST inet_ops
*/
DATA(insert ( 3550 869 869 3 s 3552 783 0 ));
diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h
new file mode 100644
index 1c95846..e21bc8a
*** a/src/include/catalog/pg_amproc.h
--- b/src/include/catalog/pg_amproc.h
*************** DATA(insert ( 5000 603 603 2 5013 ));
*** 334,339 ****
--- 334,351 ----
DATA(insert ( 5000 603 603 3 5014 ));
DATA(insert ( 5000 603 603 4 5015 ));
DATA(insert ( 5000 603 603 5 5016 ));
+ DATA(insert ( 5007 718 718 1 5009 ));
+ DATA(insert ( 5007 718 718 2 5013 ));
+ DATA(insert ( 5007 718 718 3 5014 ));
+ DATA(insert ( 5007 718 718 4 5015 ));
+ DATA(insert ( 5007 718 718 5 5016 ));
+ DATA(insert ( 5007 718 718 6 5010 ));
+ DATA(insert ( 5008 604 604 1 5009 ));
+ DATA(insert ( 5008 604 604 2 5013 ));
+ DATA(insert ( 5008 604 604 3 5014 ));
+ DATA(insert ( 5008 604 604 4 5015 ));
+ DATA(insert ( 5008 604 604 5 5016 ));
+ DATA(insert ( 5008 604 604 6 5011 ));
/* BRIN opclasses */
/* minmax bytea */
diff --git a/src/include/catalog/pg_opclass.h b/src/include/catalog/pg_opclass.h
new file mode 100644
index 28dbc74..ec803d1
*** a/src/include/catalog/pg_opclass.h
--- b/src/include/catalog/pg_opclass.h
*************** DATA(insert ( 4000 box_ops PGNSP PGUI
*** 205,210 ****
--- 205,212 ----
DATA(insert ( 4000 quad_point_ops PGNSP PGUID 4015 600 t 0 ));
DATA(insert ( 4000 kd_point_ops PGNSP PGUID 4016 600 f 0 ));
DATA(insert ( 4000 text_ops PGNSP PGUID 4017 25 t 0 ));
+ DATA(insert ( 4000 circle_ops PGNSP PGUID 5007 718 t 603 ));
+ DATA(insert ( 4000 poly_ops PGNSP PGUID 5008 604 t 603 ));
DATA(insert ( 403 jsonb_ops PGNSP PGUID 4033 3802 t 0 ));
DATA(insert ( 405 jsonb_ops PGNSP PGUID 4034 3802 t 0 ));
DATA(insert ( 2742 jsonb_ops PGNSP PGUID 4036 3802 t 25 ));
diff --git a/src/include/catalog/pg_opfamily.h b/src/include/catalog/pg_opfamily.h
new file mode 100644
index 0d0ba7c..5a6bc1d
*** a/src/include/catalog/pg_opfamily.h
--- b/src/include/catalog/pg_opfamily.h
*************** DATA(insert OID = 4103 ( 3580 range_incl
*** 186,190 ****
--- 186,192 ----
DATA(insert OID = 4082 ( 3580 pg_lsn_minmax_ops PGNSP PGUID ));
DATA(insert OID = 4104 ( 3580 box_inclusion_ops PGNSP PGUID ));
DATA(insert OID = 5000 ( 4000 box_ops PGNSP PGUID ));
+ DATA(insert OID = 5007 ( 4000 circle_ops PGNSP PGUID ));
+ DATA(insert OID = 5008 ( 4000 poly_ops PGNSP PGUID ));
#endif /* PG_OPFAMILY_H */
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
new file mode 100644
index 93c031a..95e2f34
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
*************** DESCR("SP-GiST support for quad tree ove
*** 5335,5340 ****
--- 5335,5347 ----
DATA(insert OID = 5016 ( spg_box_quad_leaf_consistent PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 16 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_box_quad_leaf_consistent _null_ _null_ _null_ ));
DESCR("SP-GiST support for quad tree over box");
+ DATA(insert OID = 5009 ( spg_bbox_quad_config PGNSP PGUID 12 1 0 0 0 f f f f t f i s 2 0 2278 "2281 2281" _null_ _null_ _null_ _null_ _null_ spg_bbox_quad_config _null_ _null_ _null_ ));
+ DESCR("SP-GiST support for quad tree over 2-D types represented by their bounding boxes");
+ DATA(insert OID = 5010 ( spg_circle_quad_compress PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 603 "718" _null_ _null_ _null_ _null_ _null_ spg_circle_quad_compress _null_ _null_ _null_ ));
+ DESCR("SP-GiST support for quad tree over circle");
+ DATA(insert OID = 5011 ( spg_poly_quad_compress PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1 0 603 "604" _null_ _null_ _null_ _null_ _null_ spg_poly_quad_compress _null_ _null_ _null_ ));
+ DESCR("SP-GiST support for quad tree over polygons");
+
/* replication slots */
DATA(insert OID = 3779 ( pg_create_physical_replication_slot PGNSP PGUID 12 1 0 0 0 f f f f t f v u 3 0 2249 "19 16 16" "{19,16,16,19,3220}" "{i,i,i,o,o}" "{slot_name,immediately_reserve,temporary,slot_name,lsn}" _null_ _null_ pg_create_physical_replication_slot _null_ _null_ _null_ ));
DESCR("create a physical replication slot");
diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h
new file mode 100644
index 44c6381..1804643
*** a/src/include/utils/geo_decls.h
--- b/src/include/utils/geo_decls.h
*************** typedef struct
*** 178,186 ****
* in geo_ops.c
*/
! /* private point routines */
extern double point_dt(Point *pt1, Point *pt2);
extern double point_sl(Point *pt1, Point *pt2);
extern double pg_hypot(double x, double y);
#endif /* GEO_DECLS_H */
--- 178,188 ----
* in geo_ops.c
*/
! /* private routines */
extern double point_dt(Point *pt1, Point *pt2);
extern double point_sl(Point *pt1, Point *pt2);
extern double pg_hypot(double x, double y);
+ extern BOX *box_copy(BOX *box);
+ extern BOX *circle_bbox(CIRCLE *circle);
#endif /* GEO_DECLS_H */
diff --git a/src/test/regress/expected/circle.out b/src/test/regress/expected/circle.out
new file mode 100644
index 9ba4a04..7e87b56
*** a/src/test/regress/expected/circle.out
--- b/src/test/regress/expected/circle.out
*************** SELECT '' as five, c1.f1 AS one, c2.f1 A
*** 97,99 ****
--- 97,339 ----
| <(1,2),3> | <(100,200),10> | 208.370729772479
(5 rows)
+ --
+ -- Test the SP-GiST index
+ --
+ CREATE TEMPORARY TABLE quad_circle_tbl (id int, c circle);
+ INSERT INTO quad_circle_tbl
+ SELECT (x - 1) * 100 + y, circle(point(x * 10, y * 10), 1 + (x + y) % 10)
+ FROM generate_series(1, 100) x,
+ generate_series(1, 100) y;
+ INSERT INTO quad_circle_tbl
+ SELECT i, '<(200, 300), 5>'
+ FROM generate_series(10001, 11000) AS i;
+ INSERT INTO quad_circle_tbl
+ VALUES
+ (11001, NULL),
+ (11002, NULL),
+ (11003, '<(0,100), infinity>'),
+ (11004, '<(-infinity,0),1000>'),
+ (11005, '<(infinity,-infinity),infinity>');
+ CREATE INDEX quad_circle_tbl_idx ON quad_circle_tbl USING spgist(c);
+ -- get reference results for ORDER BY distance from seq scan
+ SET enable_seqscan = ON;
+ SET enable_indexscan = OFF;
+ SET enable_bitmapscan = OFF;
+ CREATE TEMP TABLE quad_circle_tbl_ord_seq1 AS
+ SELECT rank() OVER (ORDER BY c <-> point '123,456') n, c <-> point '123,456' dist, id
+ FROM quad_circle_tbl;
+ CREATE TEMP TABLE quad_circle_tbl_ord_seq2 AS
+ SELECT rank() OVER (ORDER BY c <-> point '123,456') n, c <-> point '123,456' dist, id
+ FROM quad_circle_tbl WHERE c <@ circle '<(300,400),200>';
+ -- check results results from index scan
+ SET enable_seqscan = OFF;
+ SET enable_indexscan = OFF;
+ SET enable_bitmapscan = ON;
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c << circle '<(300,400),200>';
+ QUERY PLAN
+ ------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_circle_tbl
+ Recheck Cond: (c << '<(300,400),200>'::circle)
+ -> Bitmap Index Scan on quad_circle_tbl_idx
+ Index Cond: (c << '<(300,400),200>'::circle)
+ (5 rows)
+
+ SELECT count(*) FROM quad_circle_tbl WHERE c << circle '<(300,400),200>';
+ count
+ -------
+ 891
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c &< circle '<(300,400),200>';
+ QUERY PLAN
+ ------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_circle_tbl
+ Recheck Cond: (c &< '<(300,400),200>'::circle)
+ -> Bitmap Index Scan on quad_circle_tbl_idx
+ Index Cond: (c &< '<(300,400),200>'::circle)
+ (5 rows)
+
+ SELECT count(*) FROM quad_circle_tbl WHERE c &< circle '<(300,400),200>';
+ count
+ -------
+ 5901
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c && circle '<(300,400),200>';
+ QUERY PLAN
+ ------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_circle_tbl
+ Recheck Cond: (c && '<(300,400),200>'::circle)
+ -> Bitmap Index Scan on quad_circle_tbl_idx
+ Index Cond: (c && '<(300,400),200>'::circle)
+ (5 rows)
+
+ SELECT count(*) FROM quad_circle_tbl WHERE c && circle '<(300,400),200>';
+ count
+ -------
+ 2334
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c &> circle '<(300,400),200>';
+ QUERY PLAN
+ ------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_circle_tbl
+ Recheck Cond: (c &> '<(300,400),200>'::circle)
+ -> Bitmap Index Scan on quad_circle_tbl_idx
+ Index Cond: (c &> '<(300,400),200>'::circle)
+ (5 rows)
+
+ SELECT count(*) FROM quad_circle_tbl WHERE c &> circle '<(300,400),200>';
+ count
+ -------
+ 10000
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c >> circle '<(300,400),200>';
+ QUERY PLAN
+ ------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_circle_tbl
+ Recheck Cond: (c >> '<(300,400),200>'::circle)
+ -> Bitmap Index Scan on quad_circle_tbl_idx
+ Index Cond: (c >> '<(300,400),200>'::circle)
+ (5 rows)
+
+ SELECT count(*) FROM quad_circle_tbl WHERE c >> circle '<(300,400),200>';
+ count
+ -------
+ 4990
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c <<| circle '<(300,400),200>';
+ QUERY PLAN
+ -------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_circle_tbl
+ Recheck Cond: (c <<| '<(300,400),200>'::circle)
+ -> Bitmap Index Scan on quad_circle_tbl_idx
+ Index Cond: (c <<| '<(300,400),200>'::circle)
+ (5 rows)
+
+ SELECT count(*) FROM quad_circle_tbl WHERE c <<| circle '<(300,400),200>';
+ count
+ -------
+ 1890
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c &<| circle '<(300,400),200>';
+ QUERY PLAN
+ -------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_circle_tbl
+ Recheck Cond: (c &<| '<(300,400),200>'::circle)
+ -> Bitmap Index Scan on quad_circle_tbl_idx
+ Index Cond: (c &<| '<(300,400),200>'::circle)
+ (5 rows)
+
+ SELECT count(*) FROM quad_circle_tbl WHERE c &<| circle '<(300,400),200>';
+ count
+ -------
+ 6900
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c |&> circle '<(300,400),200>';
+ QUERY PLAN
+ -------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_circle_tbl
+ Recheck Cond: (c |&> '<(300,400),200>'::circle)
+ -> Bitmap Index Scan on quad_circle_tbl_idx
+ Index Cond: (c |&> '<(300,400),200>'::circle)
+ (5 rows)
+
+ SELECT count(*) FROM quad_circle_tbl WHERE c |&> circle '<(300,400),200>';
+ count
+ -------
+ 9000
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c |>> circle '<(300,400),200>';
+ QUERY PLAN
+ -------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_circle_tbl
+ Recheck Cond: (c |>> '<(300,400),200>'::circle)
+ -> Bitmap Index Scan on quad_circle_tbl_idx
+ Index Cond: (c |>> '<(300,400),200>'::circle)
+ (5 rows)
+
+ SELECT count(*) FROM quad_circle_tbl WHERE c |>> circle '<(300,400),200>';
+ count
+ -------
+ 3990
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c @> circle '<(300,400),1>';
+ QUERY PLAN
+ ----------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_circle_tbl
+ Recheck Cond: (c @> '<(300,400),1>'::circle)
+ -> Bitmap Index Scan on quad_circle_tbl_idx
+ Index Cond: (c @> '<(300,400),1>'::circle)
+ (5 rows)
+
+ SELECT count(*) FROM quad_circle_tbl WHERE c @> circle '<(300,400),1>';
+ count
+ -------
+ 2
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c <@ circle '<(300,400),200>';
+ QUERY PLAN
+ ------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_circle_tbl
+ Recheck Cond: (c <@ '<(300,400),200>'::circle)
+ -> Bitmap Index Scan on quad_circle_tbl_idx
+ Index Cond: (c <@ '<(300,400),200>'::circle)
+ (5 rows)
+
+ SELECT count(*) FROM quad_circle_tbl WHERE c <@ circle '<(300,400),200>';
+ count
+ -------
+ 2181
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c ~= circle '<(300,400),1>';
+ QUERY PLAN
+ ----------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_circle_tbl
+ Recheck Cond: (c ~= '<(300,400),1>'::circle)
+ -> Bitmap Index Scan on quad_circle_tbl_idx
+ Index Cond: (c ~= '<(300,400),1>'::circle)
+ (5 rows)
+
+ SELECT count(*) FROM quad_circle_tbl WHERE c ~= circle '<(300,400),1>';
+ count
+ -------
+ 1
+ (1 row)
+
+ RESET enable_seqscan;
+ RESET enable_indexscan;
+ RESET enable_bitmapscan;
diff --git a/src/test/regress/expected/polygon.out b/src/test/regress/expected/polygon.out
new file mode 100644
index 2361274..a9e7752
*** a/src/test/regress/expected/polygon.out
--- b/src/test/regress/expected/polygon.out
*************** SELECT '(0,0)'::point <-> '((0,0),(1,2),
*** 227,229 ****
--- 227,467 ----
0 | 0 | 0 | 1.4142135623731 | 3.2
(1 row)
+ --
+ -- Test the SP-GiST index
+ --
+ CREATE TEMPORARY TABLE quad_poly_tbl (id int, p polygon);
+ INSERT INTO quad_poly_tbl
+ SELECT (x - 1) * 100 + y, polygon(circle(point(x * 10, y * 10), 1 + (x + y) % 10))
+ FROM generate_series(1, 100) x,
+ generate_series(1, 100) y;
+ INSERT INTO quad_poly_tbl
+ SELECT i, polygon '((200, 300),(210, 310),(230, 290))'
+ FROM generate_series(10001, 11000) AS i;
+ INSERT INTO quad_poly_tbl
+ VALUES
+ (11001, NULL),
+ (11002, NULL),
+ (11003, NULL);
+ CREATE INDEX quad_poly_tbl_idx ON quad_poly_tbl USING spgist(p);
+ -- get reference results for ORDER BY distance from seq scan
+ SET enable_seqscan = ON;
+ SET enable_indexscan = OFF;
+ SET enable_bitmapscan = OFF;
+ CREATE TEMP TABLE quad_poly_tbl_ord_seq1 AS
+ SELECT rank() OVER (ORDER BY p <-> point '123,456') n, p <-> point '123,456' dist, id
+ FROM quad_poly_tbl;
+ CREATE TEMP TABLE quad_poly_tbl_ord_seq2 AS
+ SELECT rank() OVER (ORDER BY p <-> point '123,456') n, p <-> point '123,456' dist, id
+ FROM quad_poly_tbl WHERE p <@ polygon '((300,300),(400,600),(600,500),(700,200))';
+ -- check results results from index scan
+ SET enable_seqscan = OFF;
+ SET enable_indexscan = OFF;
+ SET enable_bitmapscan = ON;
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p << polygon '((300,300),(400,600),(600,500),(700,200))';
+ QUERY PLAN
+ ---------------------------------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_poly_tbl
+ Recheck Cond: (p << '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ -> Bitmap Index Scan on quad_poly_tbl_idx
+ Index Cond: (p << '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ (5 rows)
+
+ SELECT count(*) FROM quad_poly_tbl WHERE p << polygon '((300,300),(400,600),(600,500),(700,200))';
+ count
+ -------
+ 3890
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p &< polygon '((300,300),(400,600),(600,500),(700,200))';
+ QUERY PLAN
+ ---------------------------------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_poly_tbl
+ Recheck Cond: (p &< '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ -> Bitmap Index Scan on quad_poly_tbl_idx
+ Index Cond: (p &< '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ (5 rows)
+
+ SELECT count(*) FROM quad_poly_tbl WHERE p &< polygon '((300,300),(400,600),(600,500),(700,200))';
+ count
+ -------
+ 7900
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p && polygon '((300,300),(400,600),(600,500),(700,200))';
+ QUERY PLAN
+ ---------------------------------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_poly_tbl
+ Recheck Cond: (p && '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ -> Bitmap Index Scan on quad_poly_tbl_idx
+ Index Cond: (p && '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ (5 rows)
+
+ SELECT count(*) FROM quad_poly_tbl WHERE p && polygon '((300,300),(400,600),(600,500),(700,200))';
+ count
+ -------
+ 977
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p &> polygon '((300,300),(400,600),(600,500),(700,200))';
+ QUERY PLAN
+ ---------------------------------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_poly_tbl
+ Recheck Cond: (p &> '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ -> Bitmap Index Scan on quad_poly_tbl_idx
+ Index Cond: (p &> '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ (5 rows)
+
+ SELECT count(*) FROM quad_poly_tbl WHERE p &> polygon '((300,300),(400,600),(600,500),(700,200))';
+ count
+ -------
+ 7000
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p >> polygon '((300,300),(400,600),(600,500),(700,200))';
+ QUERY PLAN
+ ---------------------------------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_poly_tbl
+ Recheck Cond: (p >> '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ -> Bitmap Index Scan on quad_poly_tbl_idx
+ Index Cond: (p >> '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ (5 rows)
+
+ SELECT count(*) FROM quad_poly_tbl WHERE p >> polygon '((300,300),(400,600),(600,500),(700,200))';
+ count
+ -------
+ 2990
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p <<| polygon '((300,300),(400,600),(600,500),(700,200))';
+ QUERY PLAN
+ ----------------------------------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_poly_tbl
+ Recheck Cond: (p <<| '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ -> Bitmap Index Scan on quad_poly_tbl_idx
+ Index Cond: (p <<| '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ (5 rows)
+
+ SELECT count(*) FROM quad_poly_tbl WHERE p <<| polygon '((300,300),(400,600),(600,500),(700,200))';
+ count
+ -------
+ 1890
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p &<| polygon '((300,300),(400,600),(600,500),(700,200))';
+ QUERY PLAN
+ ----------------------------------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_poly_tbl
+ Recheck Cond: (p &<| '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ -> Bitmap Index Scan on quad_poly_tbl_idx
+ Index Cond: (p &<| '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ (5 rows)
+
+ SELECT count(*) FROM quad_poly_tbl WHERE p &<| polygon '((300,300),(400,600),(600,500),(700,200))';
+ count
+ -------
+ 6900
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p |&> polygon '((300,300),(400,600),(600,500),(700,200))';
+ QUERY PLAN
+ ----------------------------------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_poly_tbl
+ Recheck Cond: (p |&> '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ -> Bitmap Index Scan on quad_poly_tbl_idx
+ Index Cond: (p |&> '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ (5 rows)
+
+ SELECT count(*) FROM quad_poly_tbl WHERE p |&> polygon '((300,300),(400,600),(600,500),(700,200))';
+ count
+ -------
+ 9000
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p |>> polygon '((300,300),(400,600),(600,500),(700,200))';
+ QUERY PLAN
+ ----------------------------------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_poly_tbl
+ Recheck Cond: (p |>> '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ -> Bitmap Index Scan on quad_poly_tbl_idx
+ Index Cond: (p |>> '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ (5 rows)
+
+ SELECT count(*) FROM quad_poly_tbl WHERE p |>> polygon '((300,300),(400,600),(600,500),(700,200))';
+ count
+ -------
+ 3990
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p <@ polygon '((300,300),(400,600),(600,500),(700,200))';
+ QUERY PLAN
+ ---------------------------------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_poly_tbl
+ Recheck Cond: (p <@ '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ -> Bitmap Index Scan on quad_poly_tbl_idx
+ Index Cond: (p <@ '((300,300),(400,600),(600,500),(700,200))'::polygon)
+ (5 rows)
+
+ SELECT count(*) FROM quad_poly_tbl WHERE p <@ polygon '((300,300),(400,600),(600,500),(700,200))';
+ count
+ -------
+ 831
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p @> polygon '((340,550),(343,552),(341,553))';
+ QUERY PLAN
+ -----------------------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_poly_tbl
+ Recheck Cond: (p @> '((340,550),(343,552),(341,553))'::polygon)
+ -> Bitmap Index Scan on quad_poly_tbl_idx
+ Index Cond: (p @> '((340,550),(343,552),(341,553))'::polygon)
+ (5 rows)
+
+ SELECT count(*) FROM quad_poly_tbl WHERE p @> polygon '((340,550),(343,552),(341,553))';
+ count
+ -------
+ 1
+ (1 row)
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p ~= polygon '((200, 300),(210, 310),(230, 290))';
+ QUERY PLAN
+ -----------------------------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on quad_poly_tbl
+ Recheck Cond: (p ~= '((200,300),(210,310),(230,290))'::polygon)
+ -> Bitmap Index Scan on quad_poly_tbl_idx
+ Index Cond: (p ~= '((200,300),(210,310),(230,290))'::polygon)
+ (5 rows)
+
+ SELECT count(*) FROM quad_poly_tbl WHERE p ~= polygon '((200, 300),(210, 310),(230, 290))';
+ count
+ -------
+ 1000
+ (1 row)
+
+ RESET enable_seqscan;
+ RESET enable_indexscan;
+ RESET enable_bitmapscan;
diff --git a/src/test/regress/sql/circle.sql b/src/test/regress/sql/circle.sql
new file mode 100644
index c0284b2..63da10c
*** a/src/test/regress/sql/circle.sql
--- b/src/test/regress/sql/circle.sql
*************** SELECT '' as five, c1.f1 AS one, c2.f1 A
*** 43,45 ****
--- 43,140 ----
FROM CIRCLE_TBL c1, CIRCLE_TBL c2
WHERE (c1.f1 < c2.f1) AND ((c1.f1 <-> c2.f1) > 0)
ORDER BY distance, area(c1.f1), area(c2.f1);
+
+ --
+ -- Test the SP-GiST index
+ --
+
+ CREATE TEMPORARY TABLE quad_circle_tbl (id int, c circle);
+
+ INSERT INTO quad_circle_tbl
+ SELECT (x - 1) * 100 + y, circle(point(x * 10, y * 10), 1 + (x + y) % 10)
+ FROM generate_series(1, 100) x,
+ generate_series(1, 100) y;
+
+ INSERT INTO quad_circle_tbl
+ SELECT i, '<(200, 300), 5>'
+ FROM generate_series(10001, 11000) AS i;
+
+ INSERT INTO quad_circle_tbl
+ VALUES
+ (11001, NULL),
+ (11002, NULL),
+ (11003, '<(0,100), infinity>'),
+ (11004, '<(-infinity,0),1000>'),
+ (11005, '<(infinity,-infinity),infinity>');
+
+ CREATE INDEX quad_circle_tbl_idx ON quad_circle_tbl USING spgist(c);
+
+ -- get reference results for ORDER BY distance from seq scan
+ SET enable_seqscan = ON;
+ SET enable_indexscan = OFF;
+ SET enable_bitmapscan = OFF;
+
+ CREATE TEMP TABLE quad_circle_tbl_ord_seq1 AS
+ SELECT rank() OVER (ORDER BY c <-> point '123,456') n, c <-> point '123,456' dist, id
+ FROM quad_circle_tbl;
+
+ CREATE TEMP TABLE quad_circle_tbl_ord_seq2 AS
+ SELECT rank() OVER (ORDER BY c <-> point '123,456') n, c <-> point '123,456' dist, id
+ FROM quad_circle_tbl WHERE c <@ circle '<(300,400),200>';
+
+ -- check results results from index scan
+ SET enable_seqscan = OFF;
+ SET enable_indexscan = OFF;
+ SET enable_bitmapscan = ON;
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c << circle '<(300,400),200>';
+ SELECT count(*) FROM quad_circle_tbl WHERE c << circle '<(300,400),200>';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c &< circle '<(300,400),200>';
+ SELECT count(*) FROM quad_circle_tbl WHERE c &< circle '<(300,400),200>';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c && circle '<(300,400),200>';
+ SELECT count(*) FROM quad_circle_tbl WHERE c && circle '<(300,400),200>';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c &> circle '<(300,400),200>';
+ SELECT count(*) FROM quad_circle_tbl WHERE c &> circle '<(300,400),200>';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c >> circle '<(300,400),200>';
+ SELECT count(*) FROM quad_circle_tbl WHERE c >> circle '<(300,400),200>';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c <<| circle '<(300,400),200>';
+ SELECT count(*) FROM quad_circle_tbl WHERE c <<| circle '<(300,400),200>';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c &<| circle '<(300,400),200>';
+ SELECT count(*) FROM quad_circle_tbl WHERE c &<| circle '<(300,400),200>';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c |&> circle '<(300,400),200>';
+ SELECT count(*) FROM quad_circle_tbl WHERE c |&> circle '<(300,400),200>';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c |>> circle '<(300,400),200>';
+ SELECT count(*) FROM quad_circle_tbl WHERE c |>> circle '<(300,400),200>';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c @> circle '<(300,400),1>';
+ SELECT count(*) FROM quad_circle_tbl WHERE c @> circle '<(300,400),1>';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c <@ circle '<(300,400),200>';
+ SELECT count(*) FROM quad_circle_tbl WHERE c <@ circle '<(300,400),200>';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_circle_tbl WHERE c ~= circle '<(300,400),1>';
+ SELECT count(*) FROM quad_circle_tbl WHERE c ~= circle '<(300,400),1>';
+
+ RESET enable_seqscan;
+ RESET enable_indexscan;
+ RESET enable_bitmapscan;
diff --git a/src/test/regress/sql/polygon.sql b/src/test/regress/sql/polygon.sql
new file mode 100644
index 7ac8079..c58277b
*** a/src/test/regress/sql/polygon.sql
--- b/src/test/regress/sql/polygon.sql
*************** SELECT '(0,0)'::point <-> '((0,0),(1,2),
*** 116,118 ****
--- 116,211 ----
'(2,2)'::point <-> '((0,0),(1,4),(3,1))'::polygon as inside,
'(3,3)'::point <-> '((0,2),(2,0),(2,2))'::polygon as near_corner,
'(4,4)'::point <-> '((0,0),(0,3),(4,0))'::polygon as near_segment;
+
+ --
+ -- Test the SP-GiST index
+ --
+
+ CREATE TEMPORARY TABLE quad_poly_tbl (id int, p polygon);
+
+ INSERT INTO quad_poly_tbl
+ SELECT (x - 1) * 100 + y, polygon(circle(point(x * 10, y * 10), 1 + (x + y) % 10))
+ FROM generate_series(1, 100) x,
+ generate_series(1, 100) y;
+
+ INSERT INTO quad_poly_tbl
+ SELECT i, polygon '((200, 300),(210, 310),(230, 290))'
+ FROM generate_series(10001, 11000) AS i;
+
+ INSERT INTO quad_poly_tbl
+ VALUES
+ (11001, NULL),
+ (11002, NULL),
+ (11003, NULL);
+
+ CREATE INDEX quad_poly_tbl_idx ON quad_poly_tbl USING spgist(p);
+
+ -- get reference results for ORDER BY distance from seq scan
+ SET enable_seqscan = ON;
+ SET enable_indexscan = OFF;
+ SET enable_bitmapscan = OFF;
+
+ CREATE TEMP TABLE quad_poly_tbl_ord_seq1 AS
+ SELECT rank() OVER (ORDER BY p <-> point '123,456') n, p <-> point '123,456' dist, id
+ FROM quad_poly_tbl;
+
+ CREATE TEMP TABLE quad_poly_tbl_ord_seq2 AS
+ SELECT rank() OVER (ORDER BY p <-> point '123,456') n, p <-> point '123,456' dist, id
+ FROM quad_poly_tbl WHERE p <@ polygon '((300,300),(400,600),(600,500),(700,200))';
+
+ -- check results results from index scan
+ SET enable_seqscan = OFF;
+ SET enable_indexscan = OFF;
+ SET enable_bitmapscan = ON;
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p << polygon '((300,300),(400,600),(600,500),(700,200))';
+ SELECT count(*) FROM quad_poly_tbl WHERE p << polygon '((300,300),(400,600),(600,500),(700,200))';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p &< polygon '((300,300),(400,600),(600,500),(700,200))';
+ SELECT count(*) FROM quad_poly_tbl WHERE p &< polygon '((300,300),(400,600),(600,500),(700,200))';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p && polygon '((300,300),(400,600),(600,500),(700,200))';
+ SELECT count(*) FROM quad_poly_tbl WHERE p && polygon '((300,300),(400,600),(600,500),(700,200))';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p &> polygon '((300,300),(400,600),(600,500),(700,200))';
+ SELECT count(*) FROM quad_poly_tbl WHERE p &> polygon '((300,300),(400,600),(600,500),(700,200))';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p >> polygon '((300,300),(400,600),(600,500),(700,200))';
+ SELECT count(*) FROM quad_poly_tbl WHERE p >> polygon '((300,300),(400,600),(600,500),(700,200))';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p <<| polygon '((300,300),(400,600),(600,500),(700,200))';
+ SELECT count(*) FROM quad_poly_tbl WHERE p <<| polygon '((300,300),(400,600),(600,500),(700,200))';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p &<| polygon '((300,300),(400,600),(600,500),(700,200))';
+ SELECT count(*) FROM quad_poly_tbl WHERE p &<| polygon '((300,300),(400,600),(600,500),(700,200))';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p |&> polygon '((300,300),(400,600),(600,500),(700,200))';
+ SELECT count(*) FROM quad_poly_tbl WHERE p |&> polygon '((300,300),(400,600),(600,500),(700,200))';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p |>> polygon '((300,300),(400,600),(600,500),(700,200))';
+ SELECT count(*) FROM quad_poly_tbl WHERE p |>> polygon '((300,300),(400,600),(600,500),(700,200))';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p <@ polygon '((300,300),(400,600),(600,500),(700,200))';
+ SELECT count(*) FROM quad_poly_tbl WHERE p <@ polygon '((300,300),(400,600),(600,500),(700,200))';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p @> polygon '((340,550),(343,552),(341,553))';
+ SELECT count(*) FROM quad_poly_tbl WHERE p @> polygon '((340,550),(343,552),(341,553))';
+
+ EXPLAIN (COSTS OFF)
+ SELECT count(*) FROM quad_poly_tbl WHERE p ~= polygon '((200, 300),(210, 310),(230, 290))';
+ SELECT count(*) FROM quad_poly_tbl WHERE p ~= polygon '((200, 300),(210, 310),(230, 290))';
+
+ RESET enable_seqscan;
+ RESET enable_indexscan;
+ RESET enable_bitmapscan;