diff options
author | Teodor Sigaev <teodor@sigaev.ru> | 2017-12-25 18:59:38 +0300 |
---|---|---|
committer | Teodor Sigaev <teodor@sigaev.ru> | 2017-12-25 18:59:38 +0300 |
commit | ff963b393ca93a71d2f398c4c584b322cd351c2c (patch) | |
tree | 531c491b2ec392d511767b1d3ee26af9bdf87979 /src/backend/utils/adt/geo_spgist.c | |
parent | 4e2970f8807f1ccfc8029979a70dc80ee102ce48 (diff) | |
download | postgresql-ff963b393ca93a71d2f398c4c584b322cd351c2c.tar.gz postgresql-ff963b393ca93a71d2f398c4c584b322cd351c2c.zip |
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
Diffstat (limited to 'src/backend/utils/adt/geo_spgist.c')
-rw-r--r-- | src/backend/utils/adt/geo_spgist.c | 92 |
1 files changed, 88 insertions, 4 deletions
diff --git a/src/backend/utils/adt/geo_spgist.c b/src/backend/utils/adt/geo_spgist.c index f6334bae14e..a10543600fe 100644 --- a/src/backend/utils/adt/geo_spgist.c +++ b/src/backend/utils/adt/geo_spgist.c @@ -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); @@ -474,6 +474,51 @@ spg_box_quad_picksplit(PG_FUNCTION_ARGS) } /* + * 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 */ Datum @@ -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); +} |