mirror of
https://github.com/postgres/postgres.git
synced 2025-04-27 22:56:53 +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>
|
<literal>|&></literal>
|
||||||
</entry>
|
</entry>
|
||||||
</row>
|
</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>
|
<row>
|
||||||
<entry><literal>text_ops</literal></entry>
|
<entry><literal>text_ops</literal></entry>
|
||||||
<entry><type>text</type></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 point_inside(Point *p, int npts, Point *plist);
|
||||||
static int lseg_crossing(double x, double y, double px, double py);
|
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_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 BOX *box_fill(BOX *result, double x1, double x2, double y1, double y2);
|
||||||
static bool box_ov(BOX *box1, BOX *box2);
|
static bool box_ov(BOX *box1, BOX *box2);
|
||||||
static double box_ht(BOX *box);
|
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
|
/* box_copy - copy a box
|
||||||
*/
|
*/
|
||||||
static BOX *
|
BOX *
|
||||||
box_copy(BOX *box)
|
box_copy(BOX *box)
|
||||||
{
|
{
|
||||||
BOX *result = (BOX *) palloc(sizeof(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);
|
spgChooseIn *in = (spgChooseIn *) PG_GETARG_POINTER(0);
|
||||||
spgChooseOut *out = (spgChooseOut *) PG_GETARG_POINTER(1);
|
spgChooseOut *out = (spgChooseOut *) PG_GETARG_POINTER(1);
|
||||||
BOX *centroid = DatumGetBoxP(in->prefixDatum),
|
BOX *centroid = DatumGetBoxP(in->prefixDatum),
|
||||||
*box = DatumGetBoxP(in->datum);
|
*box = DatumGetBoxP(in->leafDatum);
|
||||||
|
|
||||||
out->resultType = spgMatchNode;
|
out->resultType = spgMatchNode;
|
||||||
out->result.matchNode.restDatum = BoxPGetDatum(box);
|
out->result.matchNode.restDatum = BoxPGetDatum(box);
|
||||||
@ -473,6 +473,51 @@ spg_box_quad_picksplit(PG_FUNCTION_ARGS)
|
|||||||
PG_RETURN_VOID();
|
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
|
* SP-GiST inner consistent function
|
||||||
*/
|
*/
|
||||||
@ -515,7 +560,11 @@ spg_box_quad_inner_consistent(PG_FUNCTION_ARGS)
|
|||||||
centroid = getRangeBox(DatumGetBoxP(in->prefixDatum));
|
centroid = getRangeBox(DatumGetBoxP(in->prefixDatum));
|
||||||
queries = (RangeBox **) palloc(in->nkeys * sizeof(RangeBox *));
|
queries = (RangeBox **) palloc(in->nkeys * sizeof(RangeBox *));
|
||||||
for (i = 0; i < in->nkeys; i++)
|
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 */
|
/* Allocate enough memory for nodes */
|
||||||
out->nNodes = 0;
|
out->nNodes = 0;
|
||||||
@ -637,8 +686,10 @@ spg_box_quad_leaf_consistent(PG_FUNCTION_ARGS)
|
|||||||
/* Perform the required comparison(s) */
|
/* Perform the required comparison(s) */
|
||||||
for (i = 0; i < in->nkeys; i++)
|
for (i = 0; i < in->nkeys; i++)
|
||||||
{
|
{
|
||||||
StrategyNumber strategy = in->scankeys[i].sk_strategy;
|
StrategyNumber strategy = in->scankeys[i].sk_strategy;
|
||||||
Datum query = in->scankeys[i].sk_argument;
|
BOX *box = spg_box_quad_get_scankey_bbox(&in->scankeys[i],
|
||||||
|
&out->recheck);
|
||||||
|
Datum query = BoxPGetDatum(box);
|
||||||
|
|
||||||
switch (strategy)
|
switch (strategy)
|
||||||
{
|
{
|
||||||
@ -713,3 +764,36 @@ spg_box_quad_leaf_consistent(PG_FUNCTION_ARGS)
|
|||||||
|
|
||||||
PG_RETURN_BOOL(flag);
|
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 */
|
/* yyyymmddN */
|
||||||
#define CATALOG_VERSION_NO 201711301
|
#define CATALOG_VERSION_NO 201712251
|
||||||
|
|
||||||
#endif
|
#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 11 s 2573 4000 0 ));
|
||||||
DATA(insert ( 5000 603 603 12 s 2572 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
|
* 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 3 5014 ));
|
||||||
DATA(insert ( 5000 603 603 4 5015 ));
|
DATA(insert ( 5000 603 603 4 5015 ));
|
||||||
DATA(insert ( 5000 603 603 5 5016 ));
|
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 */
|
/* BRIN opclasses */
|
||||||
/* minmax bytea */
|
/* 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 quad_point_ops PGNSP PGUID 4015 600 t 0 ));
|
||||||
DATA(insert ( 4000 kd_point_ops PGNSP PGUID 4016 600 f 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 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 ( 403 jsonb_ops PGNSP PGUID 4033 3802 t 0 ));
|
||||||
DATA(insert ( 405 jsonb_ops PGNSP PGUID 4034 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 ));
|
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 = 4082 ( 3580 pg_lsn_minmax_ops PGNSP PGUID ));
|
||||||
DATA(insert OID = 4104 ( 3580 box_inclusion_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 = 5000 ( 4000 box_ops PGNSP PGUID ));
|
||||||
|
DATA(insert OID = 5008 ( 4000 poly_ops PGNSP PGUID ));
|
||||||
|
|
||||||
#endif /* PG_OPFAMILY_H */
|
#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_ ));
|
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");
|
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 */
|
/* 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_ ));
|
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");
|
DESCR("create a physical replication slot");
|
||||||
|
@ -178,9 +178,10 @@ typedef struct
|
|||||||
* in geo_ops.c
|
* in geo_ops.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* private point routines */
|
/* private routines */
|
||||||
extern double point_dt(Point *pt1, Point *pt2);
|
extern double point_dt(Point *pt1, Point *pt2);
|
||||||
extern double point_sl(Point *pt1, Point *pt2);
|
extern double point_sl(Point *pt1, Point *pt2);
|
||||||
extern double pg_hypot(double x, double y);
|
extern double pg_hypot(double x, double y);
|
||||||
|
extern BOX *box_copy(BOX *box);
|
||||||
|
|
||||||
#endif /* GEO_DECLS_H */
|
#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
|
0 | 0 | 0 | 1.4142135623731 | 3.2
|
||||||
(1 row)
|
(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
|
polygon_tbl|t
|
||||||
quad_box_tbl|t
|
quad_box_tbl|t
|
||||||
quad_point_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
|
radix_text_tbl|t
|
||||||
ramp|f
|
ramp|f
|
||||||
real_city|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,
|
'(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,
|
'(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;
|
'(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