1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-16 06:01:02 +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:
Teodor Sigaev
2017-12-25 18:59:38 +03:00
parent 4e2970f880
commit ff963b393c
13 changed files with 491 additions and 8 deletions

View File

@ -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);
}