Skip to content

Commit ff963b3

Browse files
committed
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
1 parent 4e2970f commit ff963b3

File tree

13 files changed

+491
-8
lines changed

13 files changed

+491
-8
lines changed

doc/src/sgml/spgist.sgml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,42 @@
130130
<literal>|&amp;&gt;</literal>
131131
</entry>
132132
</row>
133+
<row>
134+
<entry><literal>poly_ops</literal></entry>
135+
<entry><type>polygon</type></entry>
136+
<entry>
137+
<literal>&lt;&lt;</literal>
138+
<literal>&amp;&lt;</literal>
139+
<literal>&amp;&amp;</literal>
140+
<literal>&amp;&gt;</literal>
141+
<literal>&gt;&gt;</literal>
142+
<literal>~=</literal>
143+
<literal>@&gt;</literal>
144+
<literal>&lt;@</literal>
145+
<literal>&amp;&lt;|</literal>
146+
<literal>&lt;&lt;|</literal>
147+
<literal>|&gt;&gt;</literal>
148+
<literal>|&amp;&gt;</literal>
149+
</entry>
150+
</row>
151+
<row>
152+
<entry><literal>poly_ops</literal></entry>
153+
<entry><type>polygon</type></entry>
154+
<entry>
155+
<literal>&lt;&lt;</literal>
156+
<literal>&amp;&lt;</literal>
157+
<literal>&amp;&amp;</literal>
158+
<literal>&amp;&gt;</literal>
159+
<literal>&gt;&gt;</literal>
160+
<literal>~=</literal>
161+
<literal>@&gt;</literal>
162+
<literal>&lt;@</literal>
163+
<literal>&amp;&lt;|</literal>
164+
<literal>&lt;&lt;|</literal>
165+
<literal>|&gt;&gt;</literal>
166+
<literal>|&amp;&gt;</literal>
167+
</entry>
168+
</row>
133169
<row>
134170
<entry><literal>text_ops</literal></entry>
135171
<entry><type>text</type></entry>

src/backend/utils/adt/geo_ops.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ enum path_delim
4141
static int point_inside(Point *p, int npts, Point *plist);
4242
static int lseg_crossing(double x, double y, double px, double py);
4343
static BOX *box_construct(double x1, double x2, double y1, double y2);
44-
static BOX *box_copy(BOX *box);
4544
static BOX *box_fill(BOX *result, double x1, double x2, double y1, double y2);
4645
static bool box_ov(BOX *box1, BOX *box2);
4746
static double box_ht(BOX *box);
@@ -482,7 +481,7 @@ box_fill(BOX *result, double x1, double x2, double y1, double y2)
482481

483482
/* box_copy - copy a box
484483
*/
485-
static BOX *
484+
BOX *
486485
box_copy(BOX *box)
487486
{
488487
BOX *result = (BOX *) palloc(sizeof(BOX));

src/backend/utils/adt/geo_spgist.c

Lines changed: 88 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ spg_box_quad_choose(PG_FUNCTION_ARGS)
391391
spgChooseIn *in = (spgChooseIn *) PG_GETARG_POINTER(0);
392392
spgChooseOut *out = (spgChooseOut *) PG_GETARG_POINTER(1);
393393
BOX *centroid = DatumGetBoxP(in->prefixDatum),
394-
*box = DatumGetBoxP(in->datum);
394+
*box = DatumGetBoxP(in->leafDatum);
395395

396396
out->resultType = spgMatchNode;
397397
out->result.matchNode.restDatum = BoxPGetDatum(box);
@@ -473,6 +473,51 @@ spg_box_quad_picksplit(PG_FUNCTION_ARGS)
473473
PG_RETURN_VOID();
474474
}
475475

476+
/*
477+
* Check if result of consistent method based on bounding box is exact.
478+
*/
479+
static bool
480+
is_bounding_box_test_exact(StrategyNumber strategy)
481+
{
482+
switch (strategy)
483+
{
484+
case RTLeftStrategyNumber:
485+
case RTOverLeftStrategyNumber:
486+
case RTOverRightStrategyNumber:
487+
case RTRightStrategyNumber:
488+
case RTOverBelowStrategyNumber:
489+
case RTBelowStrategyNumber:
490+
case RTAboveStrategyNumber:
491+
case RTOverAboveStrategyNumber:
492+
return true;
493+
494+
default:
495+
return false;
496+
}
497+
}
498+
499+
/*
500+
* Get bounding box for ScanKey.
501+
*/
502+
static BOX *
503+
spg_box_quad_get_scankey_bbox(ScanKey sk, bool *recheck)
504+
{
505+
switch (sk->sk_subtype)
506+
{
507+
case BOXOID:
508+
return DatumGetBoxP(sk->sk_argument);
509+
510+
case POLYGONOID:
511+
if (recheck && !is_bounding_box_test_exact(sk->sk_strategy))
512+
*recheck = true;
513+
return &DatumGetPolygonP(sk->sk_argument)->boundbox;
514+
515+
default:
516+
elog(ERROR, "unrecognized scankey subtype: %d", sk->sk_subtype);
517+
return NULL;
518+
}
519+
}
520+
476521
/*
477522
* SP-GiST inner consistent function
478523
*/
@@ -515,7 +560,11 @@ spg_box_quad_inner_consistent(PG_FUNCTION_ARGS)
515560
centroid = getRangeBox(DatumGetBoxP(in->prefixDatum));
516561
queries = (RangeBox **) palloc(in->nkeys * sizeof(RangeBox *));
517562
for (i = 0; i < in->nkeys; i++)
518-
queries[i] = getRangeBox(DatumGetBoxP(in->scankeys[i].sk_argument));
563+
{
564+
BOX *box = spg_box_quad_get_scankey_bbox(&in->scankeys[i], NULL);
565+
566+
queries[i] = getRangeBox(box);
567+
}
519568

520569
/* Allocate enough memory for nodes */
521570
out->nNodes = 0;
@@ -637,8 +686,10 @@ spg_box_quad_leaf_consistent(PG_FUNCTION_ARGS)
637686
/* Perform the required comparison(s) */
638687
for (i = 0; i < in->nkeys; i++)
639688
{
640-
StrategyNumber strategy = in->scankeys[i].sk_strategy;
641-
Datum query = in->scankeys[i].sk_argument;
689+
StrategyNumber strategy = in->scankeys[i].sk_strategy;
690+
BOX *box = spg_box_quad_get_scankey_bbox(&in->scankeys[i],
691+
&out->recheck);
692+
Datum query = BoxPGetDatum(box);
642693

643694
switch (strategy)
644695
{
@@ -713,3 +764,36 @@ spg_box_quad_leaf_consistent(PG_FUNCTION_ARGS)
713764

714765
PG_RETURN_BOOL(flag);
715766
}
767+
768+
769+
/*
770+
* SP-GiST config function for 2-D types that are lossy represented by their
771+
* bounding boxes
772+
*/
773+
Datum
774+
spg_bbox_quad_config(PG_FUNCTION_ARGS)
775+
{
776+
spgConfigOut *cfg = (spgConfigOut *) PG_GETARG_POINTER(1);
777+
778+
cfg->prefixType = BOXOID; /* A type represented by its bounding box */
779+
cfg->labelType = VOIDOID; /* We don't need node labels. */
780+
cfg->leafType = BOXOID;
781+
cfg->canReturnData = false;
782+
cfg->longValuesOK = false;
783+
784+
PG_RETURN_VOID();
785+
}
786+
787+
/*
788+
* SP-GiST compress function for polygons
789+
*/
790+
Datum
791+
spg_poly_quad_compress(PG_FUNCTION_ARGS)
792+
{
793+
POLYGON *polygon = PG_GETARG_POLYGON_P(0);
794+
BOX *box;
795+
796+
box = box_copy(&polygon->boundbox);
797+
798+
PG_RETURN_BOX_P(box);
799+
}

src/include/catalog/catversion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/* yyyymmddN */
56-
#define CATALOG_VERSION_NO 201711301
56+
#define CATALOG_VERSION_NO 201712251
5757

5858
#endif

src/include/catalog/pg_amop.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,22 @@ DATA(insert ( 5000 603 603 10 s 2570 4000 0 ));
857857
DATA(insert ( 5000 603 603 11 s 2573 4000 0 ));
858858
DATA(insert ( 5000 603 603 12 s 2572 4000 0 ));
859859

860+
/*
861+
* SP-GiST poly_ops (supports polygons)
862+
*/
863+
DATA(insert ( 5008 604 604 1 s 485 4000 0 ));
864+
DATA(insert ( 5008 604 604 2 s 486 4000 0 ));
865+
DATA(insert ( 5008 604 604 3 s 492 4000 0 ));
866+
DATA(insert ( 5008 604 604 4 s 487 4000 0 ));
867+
DATA(insert ( 5008 604 604 5 s 488 4000 0 ));
868+
DATA(insert ( 5008 604 604 6 s 491 4000 0 ));
869+
DATA(insert ( 5008 604 604 7 s 490 4000 0 ));
870+
DATA(insert ( 5008 604 604 8 s 489 4000 0 ));
871+
DATA(insert ( 5008 604 604 9 s 2575 4000 0 ));
872+
DATA(insert ( 5008 604 604 10 s 2574 4000 0 ));
873+
DATA(insert ( 5008 604 604 11 s 2577 4000 0 ));
874+
DATA(insert ( 5008 604 604 12 s 2576 4000 0 ));
875+
860876
/*
861877
* GiST inet_ops
862878
*/

src/include/catalog/pg_amproc.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,12 @@ DATA(insert ( 5000 603 603 2 5013 ));
334334
DATA(insert ( 5000 603 603 3 5014 ));
335335
DATA(insert ( 5000 603 603 4 5015 ));
336336
DATA(insert ( 5000 603 603 5 5016 ));
337+
DATA(insert ( 5008 604 604 1 5010 ));
338+
DATA(insert ( 5008 604 604 2 5013 ));
339+
DATA(insert ( 5008 604 604 3 5014 ));
340+
DATA(insert ( 5008 604 604 4 5015 ));
341+
DATA(insert ( 5008 604 604 5 5016 ));
342+
DATA(insert ( 5008 604 604 6 5011 ));
337343

338344
/* BRIN opclasses */
339345
/* minmax bytea */

src/include/catalog/pg_opclass.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ DATA(insert ( 4000 box_ops PGNSP PGUID 5000 603 t 0 ));
205205
DATA(insert ( 4000 quad_point_ops PGNSP PGUID 4015 600 t 0 ));
206206
DATA(insert ( 4000 kd_point_ops PGNSP PGUID 4016 600 f 0 ));
207207
DATA(insert ( 4000 text_ops PGNSP PGUID 4017 25 t 0 ));
208+
DATA(insert ( 4000 poly_ops PGNSP PGUID 5008 604 t 603 ));
208209
DATA(insert ( 403 jsonb_ops PGNSP PGUID 4033 3802 t 0 ));
209210
DATA(insert ( 405 jsonb_ops PGNSP PGUID 4034 3802 t 0 ));
210211
DATA(insert ( 2742 jsonb_ops PGNSP PGUID 4036 3802 t 25 ));

src/include/catalog/pg_opfamily.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,5 +186,6 @@ DATA(insert OID = 4103 ( 3580 range_inclusion_ops PGNSP PGUID ));
186186
DATA(insert OID = 4082 ( 3580 pg_lsn_minmax_ops PGNSP PGUID ));
187187
DATA(insert OID = 4104 ( 3580 box_inclusion_ops PGNSP PGUID ));
188188
DATA(insert OID = 5000 ( 4000 box_ops PGNSP PGUID ));
189+
DATA(insert OID = 5008 ( 4000 poly_ops PGNSP PGUID ));
189190

190191
#endif /* PG_OPFAMILY_H */

src/include/catalog/pg_proc.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5335,6 +5335,11 @@ DESCR("SP-GiST support for quad tree over box");
53355335
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_ ));
53365336
DESCR("SP-GiST support for quad tree over box");
53375337

5338+
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_ ));
5339+
DESCR("SP-GiST support for quad tree over 2-D types represented by their bounding boxes");
5340+
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_ ));
5341+
DESCR("SP-GiST support for quad tree over polygons");
5342+
53385343
/* replication slots */
53395344
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_ ));
53405345
DESCR("create a physical replication slot");

src/include/utils/geo_decls.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,10 @@ typedef struct
178178
* in geo_ops.c
179179
*/
180180

181-
/* private point routines */
181+
/* private routines */
182182
extern double point_dt(Point *pt1, Point *pt2);
183183
extern double point_sl(Point *pt1, Point *pt2);
184184
extern double pg_hypot(double x, double y);
185+
extern BOX *box_copy(BOX *box);
185186

186187
#endif /* GEO_DECLS_H */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy