partial-knn-1.patch
application/octet-stream
Patch
Format: unified
| File | + | − |
|---|---|---|
| src/backend/access/gist/gistget.c | 0 | 0 |
| src/backend/access/gist/gistproc.c | 0 | 0 |
| src/backend/access/gist/gistscan.c | 0 | 0 |
| src/backend/utils/adt/geo_ops.c | 0 | 0 |
| src/include/access/gist_private.h | 0 | 0 |
| src/include/catalog/pg_amop.h | 0 | 0 |
| src/include/catalog/pg_amproc.h | 0 | 0 |
| src/include/catalog/pg_operator.h | 0 | 0 |
| src/include/catalog/pg_proc.h | 0 | 0 |
| src/include/utils/geo_decls.h | 0 | 0 |
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
new file mode 100644
index e97ab8f..6ad5677
*** a/src/backend/access/gist/gistget.c
--- b/src/backend/access/gist/gistget.c
***************
*** 16,21 ****
--- 16,22 ----
#include "access/gist_private.h"
#include "access/relscan.h"
+ #include "catalog/index.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "utils/builtins.h"
*************** gistindex_keytest(IndexScanDesc scan,
*** 55,61 ****
GISTSTATE *giststate = so->giststate;
ScanKey key = scan->keyData;
int keySize = scan->numberOfKeys;
! double *distance_p;
Relation r = scan->indexRelation;
*recheck_p = false;
--- 56,62 ----
GISTSTATE *giststate = so->giststate;
ScanKey key = scan->keyData;
int keySize = scan->numberOfKeys;
! GISTSearchTreeItemDistance *distance_p;
Relation r = scan->indexRelation;
*recheck_p = false;
*************** gistindex_keytest(IndexScanDesc scan,
*** 72,78 ****
if (GistPageIsLeaf(page)) /* shouldn't happen */
elog(ERROR, "invalid GiST tuple found on leaf page");
for (i = 0; i < scan->numberOfOrderBys; i++)
! so->distances[i] = -get_float8_infinity();
return true;
}
--- 73,82 ----
if (GistPageIsLeaf(page)) /* shouldn't happen */
elog(ERROR, "invalid GiST tuple found on leaf page");
for (i = 0; i < scan->numberOfOrderBys; i++)
! {
! so->distances[i].value = -get_float8_infinity();
! so->distances[i].recheck = false;
! }
return true;
}
*************** gistindex_keytest(IndexScanDesc scan,
*** 170,176 ****
if ((key->sk_flags & SK_ISNULL) || isNull)
{
/* Assume distance computes as null and sorts to the end */
! *distance_p = get_float8_infinity();
}
else
{
--- 174,181 ----
if ((key->sk_flags & SK_ISNULL) || isNull)
{
/* Assume distance computes as null and sorts to the end */
! distance_p->value = get_float8_infinity();
! distance_p->recheck = false;
}
else
{
*************** gistindex_keytest(IndexScanDesc scan,
*** 195,208 ****
* can't tolerate lossy distance calculations on leaf tuples;
* there is no opportunity to re-sort the tuples afterwards.
*/
! dist = FunctionCall4Coll(&key->sk_func,
key->sk_collation,
PointerGetDatum(&de),
key->sk_argument,
Int32GetDatum(key->sk_strategy),
! ObjectIdGetDatum(key->sk_subtype));
! *distance_p = DatumGetFloat8(dist);
}
key++;
--- 200,215 ----
* can't tolerate lossy distance calculations on leaf tuples;
* there is no opportunity to re-sort the tuples afterwards.
*/
! distance_p->recheck = false;
! dist = FunctionCall5Coll(&key->sk_func,
key->sk_collation,
PointerGetDatum(&de),
key->sk_argument,
Int32GetDatum(key->sk_strategy),
! ObjectIdGetDatum(key->sk_subtype),
! PointerGetDatum(&distance_p->recheck));
! distance_p->value = DatumGetFloat8(dist);
}
key++;
*************** gistindex_keytest(IndexScanDesc scan,
*** 234,240 ****
* sibling will be processed next.
*/
static void
! gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
TIDBitmap *tbm, int64 *ntids)
{
GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
--- 241,247 ----
* sibling will be processed next.
*/
static void
! gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, GISTSearchTreeItemDistance *myDistances,
TIDBitmap *tbm, int64 *ntids)
{
GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
*************** gistScanPage(IndexScanDesc scan, GISTSea
*** 284,290 ****
tmpItem->head = item;
tmpItem->lastHeap = NULL;
memcpy(tmpItem->distances, myDistances,
! sizeof(double) * scan->numberOfOrderBys);
(void) rb_insert(so->queue, (RBNode *) tmpItem, &isNew);
--- 291,297 ----
tmpItem->head = item;
tmpItem->lastHeap = NULL;
memcpy(tmpItem->distances, myDistances,
! sizeof(GISTSearchTreeItemDistance) * scan->numberOfOrderBys);
(void) rb_insert(so->queue, (RBNode *) tmpItem, &isNew);
*************** gistScanPage(IndexScanDesc scan, GISTSea
*** 375,381 ****
tmpItem->head = item;
tmpItem->lastHeap = GISTSearchItemIsHeap(*item) ? item : NULL;
memcpy(tmpItem->distances, so->distances,
! sizeof(double) * scan->numberOfOrderBys);
(void) rb_insert(so->queue, (RBNode *) tmpItem, &isNew);
--- 382,388 ----
tmpItem->head = item;
tmpItem->lastHeap = GISTSearchItemIsHeap(*item) ? item : NULL;
memcpy(tmpItem->distances, so->distances,
! sizeof(GISTSearchTreeItemDistance) * scan->numberOfOrderBys);
(void) rb_insert(so->queue, (RBNode *) tmpItem, &isNew);
*************** gistScanPage(IndexScanDesc scan, GISTSea
*** 387,392 ****
--- 394,485 ----
}
/*
+ * Do this tree item distance values needs recheck?
+ */
+ static bool
+ searchTreeItemNeedDistanceRecheck(IndexScanDesc scan, GISTSearchTreeItem *item)
+ {
+ int i;
+ for (i = 0; i < scan->numberOfOrderBys; i++)
+ {
+ if (item->distances[i].recheck)
+ return true;
+ }
+ return false;
+ }
+
+ /*
+ * Recheck distance values of item from heap and reinsert it into RB-tree.
+ */
+ static void
+ searchTreeItemDistanceRecheck(IndexScanDesc scan, GISTSearchTreeItem *treeItem,
+ GISTSearchItem *item)
+ {
+ GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
+ GISTSearchTreeItem *tmpItem = so->tmpTreeItem;
+ Buffer buffer;
+ bool got_heap_tuple, all_dead;
+ HeapTupleData tup;
+ Datum values[INDEX_MAX_KEYS];
+ bool isnull[INDEX_MAX_KEYS];
+ bool isNew;
+ int i;
+
+ buffer = ReadBuffer(scan->heapRelation,
+ ItemPointerGetBlockNumber(&item->data.heap.heapPtr));
+ LockBuffer(buffer, BUFFER_LOCK_SHARE);
+ got_heap_tuple = heap_hot_search_buffer(&item->data.heap.heapPtr,
+ scan->heapRelation,
+ buffer,
+ scan->xs_snapshot,
+ &tup,
+ &all_dead,
+ true);
+ if (!got_heap_tuple)
+ {
+ UnlockReleaseBuffer(buffer);
+ pfree(item);
+ return;
+ }
+
+ memcpy(tmpItem, treeItem, GSTIHDRSZ +
+ sizeof(GISTSearchTreeItemDistance) * scan->numberOfOrderBys);
+ tmpItem->head = item;
+ tmpItem->lastHeap = item;
+ item->next = NULL;
+
+ ExecStoreTuple(&tup, so->slot, InvalidBuffer, false);
+ FormIndexDatum(so->indexInfo, so->slot, so->estate, values, isnull);
+
+ for (i = 0; i < scan->numberOfOrderBys; i++)
+ {
+ if (tmpItem->distances[i].recheck)
+ {
+ ScanKey key = scan->orderByData + i;
+ float8 newDistance;
+
+ tmpItem->distances[i].recheck = false;
+ if (isnull[key->sk_attno - 1])
+ {
+ tmpItem->distances[i].value = -get_float8_infinity();
+ continue;
+ }
+
+ newDistance = DatumGetFloat8(
+ FunctionCall2Coll(&so->orderByRechecks[i],
+ key->sk_collation,
+ values[key->sk_attno - 1],
+ key->sk_argument));
+
+ tmpItem->distances[i].value = newDistance;
+
+ }
+ }
+ (void) rb_insert(so->queue, (RBNode *) tmpItem, &isNew);
+ UnlockReleaseBuffer(buffer);
+ }
+
+ /*
* Extract next item (in order) from search queue
*
* Returns a GISTSearchItem or NULL. Caller must pfree item when done with it.
*************** gistScanPage(IndexScanDesc scan, GISTSea
*** 396,403 ****
* the distances value for the item.
*/
static GISTSearchItem *
! getNextGISTSearchItem(GISTScanOpaque so)
{
for (;;)
{
GISTSearchItem *item;
--- 489,498 ----
* the distances value for the item.
*/
static GISTSearchItem *
! getNextGISTSearchItem(IndexScanDesc scan)
{
+ GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
+
for (;;)
{
GISTSearchItem *item;
*************** getNextGISTSearchItem(GISTScanOpaque so)
*** 418,423 ****
--- 513,526 ----
so->curTreeItem->head = item->next;
if (item == so->curTreeItem->lastHeap)
so->curTreeItem->lastHeap = NULL;
+
+ /* Recheck distance from heap tuple if needed */
+ if (GISTSearchItemIsHeap(*item) &&
+ searchTreeItemNeedDistanceRecheck(scan, so->curTreeItem))
+ {
+ searchTreeItemDistanceRecheck(scan, so->curTreeItem, item);
+ continue;
+ }
/* Return item; caller is responsible to pfree it */
return item;
}
*************** getNextNearest(IndexScanDesc scan)
*** 441,447 ****
do
{
! GISTSearchItem *item = getNextGISTSearchItem(so);
if (!item)
break;
--- 544,550 ----
do
{
! GISTSearchItem *item = getNextGISTSearchItem(scan);
if (!item)
break;
*************** gistgettuple(PG_FUNCTION_ARGS)
*** 521,527 ****
/* find and process the next index page */
do
{
! GISTSearchItem *item = getNextGISTSearchItem(so);
if (!item)
PG_RETURN_BOOL(false);
--- 624,630 ----
/* find and process the next index page */
do
{
! GISTSearchItem *item = getNextGISTSearchItem(scan);
if (!item)
PG_RETURN_BOOL(false);
*************** gistgetbitmap(PG_FUNCTION_ARGS)
*** 573,579 ****
*/
for (;;)
{
! GISTSearchItem *item = getNextGISTSearchItem(so);
if (!item)
break;
--- 676,682 ----
*/
for (;;)
{
! GISTSearchItem *item = getNextGISTSearchItem(scan);
if (!item)
break;
diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c
new file mode 100644
index 3a45781..afe447f
*** a/src/backend/access/gist/gistproc.c
--- b/src/backend/access/gist/gistproc.c
*************** gist_poly_consistent(PG_FUNCTION_ARGS)
*** 1094,1099 ****
--- 1094,1100 ----
PG_RETURN_BOOL(result);
}
+
/**************************************************
* Circle ops
**************************************************/
*************** computeDistance(bool isLeaf, BOX *box, P
*** 1270,1275 ****
--- 1271,1337 ----
return result;
}
+ static double
+ computeDistanceMBR(BOX *box, Point *point)
+ {
+ double result = 0.0;
+
+ if (point->x <= box->high.x && point->x >= box->low.x &&
+ point->y <= box->high.y && point->y >= box->low.y)
+ {
+ /* point inside the box */
+ result = 0.0;
+ }
+ else if (point->x <= box->high.x && point->x >= box->low.x)
+ {
+ /* point is over or below box */
+ Assert(box->low.y <= box->high.y);
+ if (point->y > box->high.y)
+ result = point->y - box->high.y;
+ else if (point->y < box->low.y)
+ result = box->low.y - point->y;
+ else
+ elog(ERROR, "inconsistent point values");
+ }
+ else if (point->y <= box->high.y && point->y >= box->low.y)
+ {
+ /* point is to left or right of box */
+ Assert(box->low.x <= box->high.x);
+ if (point->x > box->high.x)
+ result = point->x - box->high.x;
+ else if (point->x < box->low.x)
+ result = box->low.x - point->x;
+ else
+ elog(ERROR, "inconsistent point values");
+ }
+ else
+ {
+ /* closest point will be a vertex */
+ Point p;
+ double subresult;
+
+ result = point_point_distance(point, &box->low);
+
+ subresult = point_point_distance(point, &box->high);
+ if (result > subresult)
+ result = subresult;
+
+ p.x = box->low.x;
+ p.y = box->high.y;
+ subresult = point_point_distance(point, &p);
+ if (result > subresult)
+ result = subresult;
+
+ p.x = box->high.x;
+ p.y = box->low.y;
+ subresult = point_point_distance(point, &p);
+ if (result > subresult)
+ result = subresult;
+ }
+
+ return result;
+ }
+
static bool
gist_point_consistent_internal(StrategyNumber strategy,
bool isLeaf, BOX *key, Point *query)
*************** gist_point_distance(PG_FUNCTION_ARGS)
*** 1451,1453 ****
--- 1513,1540 ----
PG_RETURN_FLOAT8(distance);
}
+
+ Datum
+ gist_poly_distance(PG_FUNCTION_ARGS)
+ {
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
+ bool *recheck = (bool *) PG_GETARG_POINTER(4);
+ double distance;
+ StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset;
+
+ *recheck = true;
+
+ switch (strategyGroup)
+ {
+ case PointStrategyNumberGroup:
+ distance = computeDistanceMBR(DatumGetBoxP(entry->key),
+ PG_GETARG_POINT_P(1));
+ break;
+ default:
+ elog(ERROR, "unknown strategy number: %d", strategy);
+ distance = 0.0; /* keep compiler quiet */
+ }
+
+ PG_RETURN_FLOAT8(distance);
+ }
diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
new file mode 100644
index b5553ff..61e5597
*** a/src/backend/access/gist/gistscan.c
--- b/src/backend/access/gist/gistscan.c
***************
*** 17,22 ****
--- 17,25 ----
#include "access/gist_private.h"
#include "access/gistscan.h"
#include "access/relscan.h"
+ #include "catalog/index.h"
+ #include "executor/executor.h"
+ #include "executor/tuptable.h"
#include "utils/memutils.h"
#include "utils/rel.h"
*************** GISTSearchTreeItemComparator(const RBNod
*** 36,43 ****
/* Order according to distance comparison */
for (i = 0; i < scan->numberOfOrderBys; i++)
{
! if (sa->distances[i] != sb->distances[i])
! return (sa->distances[i] > sb->distances[i]) ? 1 : -1;
}
return 0;
--- 39,53 ----
/* Order according to distance comparison */
for (i = 0; i < scan->numberOfOrderBys; i++)
{
! if (sa->distances[i].value != sb->distances[i].value)
! return (sa->distances[i].value > sb->distances[i].value) ? 1 : -1;
!
! /*
! * Items without recheck can be immediately returned. So they are
! * placed first.
! */
! if (sa->distances[i].recheck != sb->distances[i].recheck)
! return sa->distances[i].recheck ? 1 : -1;
}
return 0;
*************** GISTSearchTreeItemAllocator(void *arg)
*** 83,89 ****
{
IndexScanDesc scan = (IndexScanDesc) arg;
! return palloc(GSTIHDRSZ + sizeof(double) * scan->numberOfOrderBys);
}
static void
--- 93,99 ----
{
IndexScanDesc scan = (IndexScanDesc) arg;
! return palloc(GSTIHDRSZ + sizeof(GISTSearchTreeItemDistance) * scan->numberOfOrderBys);
}
static void
*************** gistbeginscan(PG_FUNCTION_ARGS)
*** 127,136 ****
so->queueCxt = giststate->scanCxt; /* see gistrescan */
/* workspaces with size dependent on numberOfOrderBys: */
! so->tmpTreeItem = palloc(GSTIHDRSZ + sizeof(double) * scan->numberOfOrderBys);
! so->distances = palloc(sizeof(double) * scan->numberOfOrderBys);
so->qual_ok = true; /* in case there are zero keys */
scan->opaque = so;
MemoryContextSwitchTo(oldCxt);
--- 137,153 ----
so->queueCxt = giststate->scanCxt; /* see gistrescan */
/* workspaces with size dependent on numberOfOrderBys: */
! so->tmpTreeItem = palloc(GSTIHDRSZ + sizeof(GISTSearchTreeItemDistance) * scan->numberOfOrderBys);
! so->distances = palloc(sizeof(GISTSearchTreeItemDistance) * scan->numberOfOrderBys);
so->qual_ok = true; /* in case there are zero keys */
+ if (scan->numberOfOrderBys > 0)
+ {
+ so->orderByRechecks = (FmgrInfo *)palloc(sizeof(FmgrInfo) * scan->numberOfOrderBys);
+ so->indexInfo = BuildIndexInfo(scan->indexRelation);
+ so->estate = CreateExecutorState();
+ }
+
scan->opaque = so;
MemoryContextSwitchTo(oldCxt);
*************** gistrescan(PG_FUNCTION_ARGS)
*** 186,194 ****
first_time = false;
}
/* create new, empty RBTree for search queue */
oldCxt = MemoryContextSwitchTo(so->queueCxt);
! so->queue = rb_create(GSTIHDRSZ + sizeof(double) * scan->numberOfOrderBys,
GISTSearchTreeItemComparator,
GISTSearchTreeItemCombiner,
GISTSearchTreeItemAllocator,
--- 203,216 ----
first_time = false;
}
+ if (scan->numberOfOrderBys > 0 && !so->slot)
+ {
+ so->slot = MakeSingleTupleTableSlot(RelationGetDescr(scan->heapRelation));
+ }
+
/* create new, empty RBTree for search queue */
oldCxt = MemoryContextSwitchTo(so->queueCxt);
! so->queue = rb_create(GSTIHDRSZ + sizeof(GISTSearchTreeItemDistance) * scan->numberOfOrderBys,
GISTSearchTreeItemComparator,
GISTSearchTreeItemCombiner,
GISTSearchTreeItemAllocator,
*************** gistrescan(PG_FUNCTION_ARGS)
*** 289,294 ****
--- 311,319 ----
GIST_DISTANCE_PROC, skey->sk_attno,
RelationGetRelationName(scan->indexRelation));
+ fmgr_info_copy(&so->orderByRechecks[i], &(skey->sk_func),
+ so->giststate->scanCxt);
+
fmgr_info_copy(&(skey->sk_func), finfo, so->giststate->scanCxt);
/* Restore prior fn_extra pointers, if not first time */
*************** gistendscan(PG_FUNCTION_ARGS)
*** 323,328 ****
--- 348,356 ----
IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
+ if (so->slot)
+ ExecDropSingleTupleTableSlot(so->slot);
+
/*
* freeGISTstate is enough to clean up everything made by gistbeginscan,
* as well as the queueCxt if there is a separate context for it.
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
new file mode 100644
index 41178a6..16b60fe
*** a/src/backend/utils/adt/geo_ops.c
--- b/src/backend/utils/adt/geo_ops.c
*************** dist_cpoly(PG_FUNCTION_ARGS)
*** 2664,2669 ****
--- 2664,2715 ----
PG_RETURN_FLOAT8(result);
}
+ Datum
+ dist_polyp(PG_FUNCTION_ARGS)
+ {
+ POLYGON *poly = PG_GETARG_POLYGON_P(0);
+ Point *point = PG_GETARG_POINT_P(1);
+ float8 result;
+ float8 d;
+ int i;
+ LSEG seg;
+
+ if (point_inside(point, poly->npts, poly->p) != 0)
+ {
+ #ifdef GEODEBUG
+ printf("dist_polyp- point inside of polygon\n");
+ #endif
+ PG_RETURN_FLOAT8(0.0);
+ }
+
+ /* initialize distance with segment between first and last points */
+ seg.p[0].x = poly->p[0].x;
+ seg.p[0].y = poly->p[0].y;
+ seg.p[1].x = poly->p[poly->npts - 1].x;
+ seg.p[1].y = poly->p[poly->npts - 1].y;
+ result = dist_ps_internal(point, &seg);
+ #ifdef GEODEBUG
+ printf("dist_polyp- segment 0/n distance is %f\n", result);
+ #endif
+
+ /* check distances for other segments */
+ for (i = 0; (i < poly->npts - 1); i++)
+ {
+ seg.p[0].x = poly->p[i].x;
+ seg.p[0].y = poly->p[i].y;
+ seg.p[1].x = poly->p[i + 1].x;
+ seg.p[1].y = poly->p[i + 1].y;
+ d = dist_ps_internal(point, &seg);
+ #ifdef GEODEBUG
+ printf("dist_polyp- segment %d distance is %f\n", (i + 1), d);
+ #endif
+ if (d < result)
+ result = d;
+ }
+
+ PG_RETURN_FLOAT8(result);
+ }
+
/*---------------------------------------------------------------------
* interpt_
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
new file mode 100644
index cae6dbc..b2572df
*** a/src/include/access/gist_private.h
--- b/src/include/access/gist_private.h
***************
*** 16,22 ****
--- 16,24 ----
#include "access/gist.h"
#include "access/itup.h"
+ #include "executor/tuptable.h"
#include "fmgr.h"
+ #include "nodes/execnodes.h"
#include "storage/bufmgr.h"
#include "storage/buffile.h"
#include "utils/rbtree.h"
*************** typedef struct GISTSearchItem
*** 119,124 ****
--- 121,132 ----
#define GISTSearchItemIsHeap(item) ((item).blkno == InvalidBlockNumber)
+ typedef struct GISTSearchTreeItemDistance
+ {
+ double value;
+ bool recheck;
+ } GISTSearchTreeItemDistance;
+
/*
* Within a GISTSearchTreeItem's chain, heap items always appear before
* index-page items, since we want to visit heap items first. lastHeap points
*************** typedef struct GISTSearchTreeItem
*** 129,135 ****
RBNode rbnode; /* this is an RBTree item */
GISTSearchItem *head; /* first chain member */
GISTSearchItem *lastHeap; /* last heap-tuple member, if any */
! double distances[1]; /* array with numberOfOrderBys entries */
} GISTSearchTreeItem;
#define GSTIHDRSZ offsetof(GISTSearchTreeItem, distances)
--- 137,143 ----
RBNode rbnode; /* this is an RBTree item */
GISTSearchItem *head; /* first chain member */
GISTSearchItem *lastHeap; /* last heap-tuple member, if any */
! GISTSearchTreeItemDistance distances[1]; /* array with numberOfOrderBys entries */
} GISTSearchTreeItem;
#define GSTIHDRSZ offsetof(GISTSearchTreeItem, distances)
*************** typedef struct GISTScanOpaqueData
*** 149,160 ****
/* pre-allocated workspace arrays */
GISTSearchTreeItem *tmpTreeItem; /* workspace to pass to rb_insert */
! double *distances; /* output area for gistindex_keytest */
/* In a non-ordered search, returnable heap items are stored here: */
GISTSearchHeapItem pageData[BLCKSZ / sizeof(IndexTupleData)];
OffsetNumber nPageData; /* number of valid items in array */
OffsetNumber curPageData; /* next item to return */
} GISTScanOpaqueData;
typedef GISTScanOpaqueData *GISTScanOpaque;
--- 157,172 ----
/* pre-allocated workspace arrays */
GISTSearchTreeItem *tmpTreeItem; /* workspace to pass to rb_insert */
! GISTSearchTreeItemDistance *distances; /* output area for gistindex_keytest */
/* In a non-ordered search, returnable heap items are stored here: */
GISTSearchHeapItem pageData[BLCKSZ / sizeof(IndexTupleData)];
OffsetNumber nPageData; /* number of valid items in array */
OffsetNumber curPageData; /* next item to return */
+ FmgrInfo *orderByRechecks;
+ IndexInfo *indexInfo;
+ TupleTableSlot *slot;
+ EState *estate;
} GISTScanOpaqueData;
typedef GISTScanOpaqueData *GISTScanOpaque;
diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h
new file mode 100644
index c8a548c..e7a79c6
*** a/src/include/catalog/pg_amop.h
--- b/src/include/catalog/pg_amop.h
*************** DATA(insert ( 2594 604 604 11 s 2577 7
*** 638,643 ****
--- 638,644 ----
DATA(insert ( 2594 604 604 12 s 2576 783 0 ));
DATA(insert ( 2594 604 604 13 s 2861 783 0 ));
DATA(insert ( 2594 604 604 14 s 2860 783 0 ));
+ DATA(insert ( 2594 604 600 15 o 3569 783 1970 ));
/*
* gist circle_ops
diff --git a/src/include/catalog/pg_amproc.h b/src/include/catalog/pg_amproc.h
new file mode 100644
index 53a3a7a..29c7c09
*** a/src/include/catalog/pg_amproc.h
--- b/src/include/catalog/pg_amproc.h
*************** DATA(insert ( 2594 604 604 4 2580 ));
*** 188,193 ****
--- 188,194 ----
DATA(insert ( 2594 604 604 5 2581 ));
DATA(insert ( 2594 604 604 6 2582 ));
DATA(insert ( 2594 604 604 7 2584 ));
+ DATA(insert ( 2594 604 604 8 3567 ));
DATA(insert ( 2595 718 718 1 2591 ));
DATA(insert ( 2595 718 718 2 2583 ));
DATA(insert ( 2595 718 718 3 2592 ));
diff --git a/src/include/catalog/pg_operator.h b/src/include/catalog/pg_operator.h
new file mode 100644
index 78efaa5..32ac483
*** a/src/include/catalog/pg_operator.h
--- b/src/include/catalog/pg_operator.h
*************** DATA(insert OID = 709 ( "<->" PGNSP
*** 591,596 ****
--- 591,598 ----
DESCR("distance between");
DATA(insert OID = 712 ( "<->" PGNSP PGUID b f f 604 604 701 712 0 poly_distance - - ));
DESCR("distance between");
+ DATA(insert OID = 3569 ( "<->" PGNSP PGUID b f f 604 600 701 0 0 dist_polyp - - ));
+ DESCR("distance between");
DATA(insert OID = 713 ( "<>" PGNSP PGUID b f f 600 600 16 713 510 point_ne neqsel neqjoinsel ));
DESCR("not equal");
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
new file mode 100644
index 0117500..85d077b
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
*************** DATA(insert OID = 726 ( dist_lb PGN
*** 809,814 ****
--- 809,815 ----
DATA(insert OID = 727 ( dist_sl PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "601 628" _null_ _null_ _null_ _null_ dist_sl _null_ _null_ _null_ ));
DATA(insert OID = 728 ( dist_cpoly PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "718 604" _null_ _null_ _null_ _null_ dist_cpoly _null_ _null_ _null_ ));
DATA(insert OID = 729 ( poly_distance PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "604 604" _null_ _null_ _null_ _null_ poly_distance _null_ _null_ _null_ ));
+ DATA(insert OID = 3568 ( dist_polyp PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 701 "604 600" _null_ _null_ _null_ _null_ dist_polyp _null_ _null_ _null_ ));
DATA(insert OID = 740 ( text_lt PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "25 25" _null_ _null_ _null_ _null_ text_lt _null_ _null_ _null_ ));
DATA(insert OID = 741 ( text_le PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "25 25" _null_ _null_ _null_ _null_ text_le _null_ _null_ _null_ ));
*************** DATA(insert OID = 2585 ( gist_poly_cons
*** 3937,3942 ****
--- 3938,3945 ----
DESCR("GiST support");
DATA(insert OID = 2586 ( gist_poly_compress PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ gist_poly_compress _null_ _null_ _null_ ));
DESCR("GiST support");
+ DATA(insert OID = 3567 ( gist_poly_distance PGNSP PGUID 12 1 0 0 0 f f f f t f i 4 0 701 "2281 600 23 26" _null_ _null_ _null_ _null_ gist_poly_distance _null_ _null_ _null_ ));
+ DESCR("GiST support");
DATA(insert OID = 2591 ( gist_circle_consistent PGNSP PGUID 12 1 0 0 0 f f f f t f i 5 0 16 "2281 718 23 26 2281" _null_ _null_ _null_ _null_ gist_circle_consistent _null_ _null_ _null_ ));
DESCR("GiST support");
DATA(insert OID = 2592 ( gist_circle_compress PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2281 "2281" _null_ _null_ _null_ _null_ gist_circle_compress _null_ _null_ _null_ ));
diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h
new file mode 100644
index 1e648c0..b8a04cb
*** a/src/include/utils/geo_decls.h
--- b/src/include/utils/geo_decls.h
*************** extern Datum circle_radius(PG_FUNCTION_A
*** 395,400 ****
--- 395,401 ----
extern Datum circle_distance(PG_FUNCTION_ARGS);
extern Datum dist_pc(PG_FUNCTION_ARGS);
extern Datum dist_cpoly(PG_FUNCTION_ARGS);
+ extern Datum dist_polyp(PG_FUNCTION_ARGS);
extern Datum circle_center(PG_FUNCTION_ARGS);
extern Datum cr_circle(PG_FUNCTION_ARGS);
extern Datum box_circle(PG_FUNCTION_ARGS);
*************** extern Datum gist_circle_consistent(PG_F
*** 418,423 ****
--- 419,425 ----
extern Datum gist_point_compress(PG_FUNCTION_ARGS);
extern Datum gist_point_consistent(PG_FUNCTION_ARGS);
extern Datum gist_point_distance(PG_FUNCTION_ARGS);
+ extern Datum gist_poly_distance(PG_FUNCTION_ARGS);
/* geo_selfuncs.c */
extern Datum areasel(PG_FUNCTION_ARGS);