mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
Add polygon opclass for SP-GiST
Polygon opclass uses compress method feature of SP-GiST added earlier. For now it's a single operator class which uses this feature. SP-GiST actually indexes a bounding boxes of input polygons, so part of supported operations are lossy. Opclass uses most methods of corresponding opclass over boxes of SP-GiST and treats bounding boxes as point in 4D-space. Bump catalog version. Authors: Nikita Glukhov, Alexander Korotkov with minor editorization by me Reviewed-By: all authors + Darafei Praliaskouski Discussion: https://www.postgresql.org/message-id/flat/54907069.1030506@sigaev.ru
This commit is contained in:
parent
4e2970f880
commit
ff963b393c
@ -130,6 +130,42 @@
|
||||
<literal>|&></literal>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>poly_ops</literal></entry>
|
||||
<entry><type>polygon</type></entry>
|
||||
<entry>
|
||||
<literal><<</literal>
|
||||
<literal>&<</literal>
|
||||
<literal>&&</literal>
|
||||
<literal>&></literal>
|
||||
<literal>>></literal>
|
||||
<literal>~=</literal>
|
||||
<literal>@></literal>
|
||||
<literal><@</literal>
|
||||
<literal>&<|</literal>
|
||||
<literal><<|</literal>
|
||||
<literal>|>></literal>
|
||||
<literal>|&></literal>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>poly_ops</literal></entry>
|
||||
<entry><type>polygon</type></entry>
|
||||
<entry>
|
||||
<literal><<</literal>
|
||||
<literal>&<</literal>
|
||||
<literal>&&</literal>
|
||||
<literal>&></literal>
|
||||
<literal>>></literal>
|
||||
<literal>~=</literal>
|
||||
<literal>@></literal>
|
||||
<literal><@</literal>
|
||||
<literal>&<|</literal>
|
||||
<literal><<|</literal>
|
||||
<literal>|>></literal>
|
||||
<literal>|&></literal>
|
||||
</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry><literal>text_ops</literal></entry>
|
||||
<entry><type>text</type></entry>
|
||||
|
@ -41,7 +41,6 @@ enum path_delim
|
||||
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);
|
||||
@ -482,7 +481,7 @@ box_fill(BOX *result, double x1, double x2, double y1, double y2)
|
||||
|
||||
/* box_copy - copy a box
|
||||
*/
|
||||
static BOX *
|
||||
BOX *
|
||||
box_copy(BOX *box)
|
||||
{
|
||||
BOX *result = (BOX *) palloc(sizeof(BOX));
|
||||
|
@ -391,7 +391,7 @@ spg_box_quad_choose(PG_FUNCTION_ARGS)
|
||||
spgChooseIn *in = (spgChooseIn *) PG_GETARG_POINTER(0);
|
||||
spgChooseOut *out = (spgChooseOut *) PG_GETARG_POINTER(1);
|
||||
BOX *centroid = DatumGetBoxP(in->prefixDatum),
|
||||
*box = DatumGetBoxP(in->datum);
|
||||
*box = DatumGetBoxP(in->leafDatum);
|
||||
|
||||
out->resultType = spgMatchNode;
|
||||
out->result.matchNode.restDatum = BoxPGetDatum(box);
|
||||
@ -473,6 +473,51 @@ spg_box_quad_picksplit(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 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
|
||||
*/
|
||||
@ -515,7 +560,11 @@ spg_box_quad_inner_consistent(PG_FUNCTION_ARGS)
|
||||
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));
|
||||
{
|
||||
BOX *box = spg_box_quad_get_scankey_bbox(&in->scankeys[i], NULL);
|
||||
|
||||
queries[i] = getRangeBox(box);
|
||||
}
|
||||
|
||||
/* Allocate enough memory for nodes */
|
||||
out->nNodes = 0;
|
||||
@ -637,8 +686,10 @@ spg_box_quad_leaf_consistent(PG_FUNCTION_ARGS)
|
||||
/* 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;
|
||||
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)
|
||||
{
|
||||
@ -713,3 +764,36 @@ spg_box_quad_leaf_consistent(PG_FUNCTION_ARGS)
|
||||
|
||||
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 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);
|
||||
}
|
||||
|
@ -53,6 +53,6 @@
|
||||
*/
|
||||
|
||||
/* yyyymmddN */
|
||||
#define CATALOG_VERSION_NO 201711301
|
||||
#define CATALOG_VERSION_NO 201712251
|
||||
|
||||
#endif
|
||||
|
@ -857,6 +857,22 @@ DATA(insert ( 5000 603 603 10 s 2570 4000 0 ));
|
||||
DATA(insert ( 5000 603 603 11 s 2573 4000 0 ));
|
||||
DATA(insert ( 5000 603 603 12 s 2572 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
|
||||
*/
|
||||
|
@ -334,6 +334,12 @@ DATA(insert ( 5000 603 603 2 5013 ));
|
||||
DATA(insert ( 5000 603 603 3 5014 ));
|
||||
DATA(insert ( 5000 603 603 4 5015 ));
|
||||
DATA(insert ( 5000 603 603 5 5016 ));
|
||||
DATA(insert ( 5008 604 604 1 5010 ));
|
||||
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 */
|
||||
|
@ -205,6 +205,7 @@ DATA(insert ( 4000 box_ops PGNSP PGUID 5000 603 t 0 ));
|
||||
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 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 ));
|
||||
|
@ -186,5 +186,6 @@ DATA(insert OID = 4103 ( 3580 range_inclusion_ops PGNSP PGUID ));
|
||||
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 = 5008 ( 4000 poly_ops PGNSP PGUID ));
|
||||
|
||||
#endif /* PG_OPFAMILY_H */
|
||||
|
@ -5335,6 +5335,11 @@ DESCR("SP-GiST support for quad tree over box");
|
||||
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 = 5010 ( 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 = 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");
|
||||
|
@ -178,9 +178,10 @@ typedef struct
|
||||
* in geo_ops.c
|
||||
*/
|
||||
|
||||
/* private point routines */
|
||||
/* 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);
|
||||
|
||||
#endif /* GEO_DECLS_H */
|
||||
|
@ -227,3 +227,241 @@ SELECT '(0,0)'::point <-> '((0,0),(1,2),(2,1))'::polygon as on_corner,
|
||||
0 | 0 | 0 | 1.4142135623731 | 3.2
|
||||
(1 row)
|
||||
|
||||
--
|
||||
-- Test the SP-GiST index
|
||||
--
|
||||
CREATE 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 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 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;
|
||||
|
@ -166,6 +166,9 @@ point_tbl|t
|
||||
polygon_tbl|t
|
||||
quad_box_tbl|t
|
||||
quad_point_tbl|t
|
||||
quad_poly_tbl|t
|
||||
quad_poly_tbl_ord_seq1|f
|
||||
quad_poly_tbl_ord_seq2|f
|
||||
radix_text_tbl|t
|
||||
ramp|f
|
||||
real_city|f
|
||||
|
@ -116,3 +116,96 @@ SELECT '(0,0)'::point <-> '((0,0),(1,2),(2,1))'::polygon as on_corner,
|
||||
'(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 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 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 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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user