0003-Extract-index_store_orderby_distances-v01.patch
text/x-patch
Filename: 0003-Extract-index_store_orderby_distances-v01.patch
Type: text/x-patch
Part: 2
Message:
[PATCH] kNN for SP-GiST
Patch
Format: unified
Series: patch v1-0003
| File | + | − |
|---|---|---|
| src/backend/access/gist/gistget.c | 5 | 41 |
| src/backend/access/index/indexam.c | 70 | 0 |
| src/include/access/genam.h | 2 | 0 |
diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c
index eea366b..d1ba2b6 100644
--- a/src/backend/access/gist/gistget.c
+++ b/src/backend/access/gist/gistget.c
@@ -14,9 +14,9 @@
*/
#include "postgres.h"
+#include "access/genam.h"
#include "access/gist_private.h"
#include "access/relscan.h"
-#include "catalog/pg_type.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "lib/pairingheap.h"
@@ -538,7 +538,6 @@ getNextNearest(IndexScanDesc scan)
{
GISTScanOpaque so = (GISTScanOpaque) scan->opaque;
bool res = false;
- int i;
if (scan->xs_itup)
{
@@ -559,45 +558,10 @@ getNextNearest(IndexScanDesc scan)
/* found a heap item at currently minimal distance */
scan->xs_ctup.t_self = item->data.heap.heapPtr;
scan->xs_recheck = item->data.heap.recheck;
- scan->xs_recheckorderby = item->data.heap.recheckDistances;
- for (i = 0; i < scan->numberOfOrderBys; i++)
- {
- if (so->orderByTypes[i] == FLOAT8OID)
- {
-#ifndef USE_FLOAT8_BYVAL
- /* must free any old value to avoid memory leakage */
- if (!scan->xs_orderbynulls[i])
- pfree(DatumGetPointer(scan->xs_orderbyvals[i]));
-#endif
- scan->xs_orderbyvals[i] = Float8GetDatum(item->distances[i]);
- scan->xs_orderbynulls[i] = false;
- }
- else if (so->orderByTypes[i] == FLOAT4OID)
- {
- /* convert distance function's result to ORDER BY type */
-#ifndef USE_FLOAT4_BYVAL
- /* must free any old value to avoid memory leakage */
- if (!scan->xs_orderbynulls[i])
- pfree(DatumGetPointer(scan->xs_orderbyvals[i]));
-#endif
- scan->xs_orderbyvals[i] = Float4GetDatum((float4) item->distances[i]);
- scan->xs_orderbynulls[i] = false;
- }
- else
- {
- /*
- * If the ordering operator's return value is anything
- * else, we don't know how to convert the float8 bound
- * calculated by the distance function to that. The
- * executor won't actually need the order by values we
- * return here, if there are no lossy results, so only
- * insist on converting if the *recheck flag is set.
- */
- if (scan->xs_recheckorderby)
- elog(ERROR, "GiST operator family's FOR ORDER BY operator must return float8 or float4 if the distance function is lossy");
- scan->xs_orderbynulls[i] = true;
- }
- }
+
+ index_store_orderby_distances(scan, so->orderByTypes,
+ item->distances,
+ item->data.heap.recheckDistances);
/* in an index-only scan, also return the reconstructed tuple. */
if (scan->xs_want_itup)
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 4822af9..9cfe841 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -71,6 +71,7 @@
#include "access/xlog.h"
#include "catalog/catalog.h"
#include "catalog/index.h"
+#include "catalog/pg_type.h"
#include "pgstat.h"
#include "storage/bufmgr.h"
#include "storage/lmgr.h"
@@ -771,3 +772,72 @@ index_getprocinfo(Relation irel,
return locinfo;
}
+
+/* ----------------
+ * index_store_orderby_distances
+ *
+ * Convert AM distance function's results (that can be inexact)
+ * to ORDER BY types and save them into xs_orderbyvals/xs_orderbynulls
+ * for a possible recheck.
+ * ----------------
+ */
+void
+index_store_orderby_distances(IndexScanDesc scan, Oid *orderByTypes,
+ double *distances, bool recheckOrderBy)
+{
+ int i;
+
+ scan->xs_recheckorderby = recheckOrderBy;
+
+ if (!distances)
+ {
+ Assert(!scan->xs_recheckorderby);
+
+ for (i = 0; i < scan->numberOfOrderBys; i++)
+ {
+ scan->xs_orderbyvals[i] = (Datum) 0;
+ scan->xs_orderbynulls[i] = true;
+ }
+
+ return;
+ }
+
+ for (i = 0; i < scan->numberOfOrderBys; i++)
+ {
+ if (orderByTypes[i] == FLOAT8OID)
+ {
+#ifndef USE_FLOAT8_BYVAL
+ /* must free any old value to avoid memory leakage */
+ if (!scan->xs_orderbynulls[i])
+ pfree(DatumGetPointer(scan->xs_orderbyvals[i]));
+#endif
+ scan->xs_orderbyvals[i] = Float8GetDatum(distances[i]);
+ scan->xs_orderbynulls[i] = false;
+ }
+ else if (orderByTypes[i] == FLOAT4OID)
+ {
+ /* convert distance function's result to ORDER BY type */
+#ifndef USE_FLOAT4_BYVAL
+ /* must free any old value to avoid memory leakage */
+ if (!scan->xs_orderbynulls[i])
+ pfree(DatumGetPointer(scan->xs_orderbyvals[i]));
+#endif
+ scan->xs_orderbyvals[i] = Float4GetDatum((float4) distances[i]);
+ scan->xs_orderbynulls[i] = false;
+ }
+ else
+ {
+ /*
+ * If the ordering operator's return value is anything
+ * else, we don't know how to convert the float8 bound
+ * calculated by the distance function to that. The
+ * executor won't actually need the order by values we
+ * return here, if there are no lossy results, so only
+ * insist on converting if the *recheck flag is set.
+ */
+ if (scan->xs_recheckorderby)
+ elog(ERROR, "GiST operator family's FOR ORDER BY operator must return float8 or float4 if the distance function is lossy");
+ scan->xs_orderbynulls[i] = true;
+ }
+ }
+}
diff --git a/src/include/access/genam.h b/src/include/access/genam.h
index b2e078a..5b75ca6 100644
--- a/src/include/access/genam.h
+++ b/src/include/access/genam.h
@@ -161,6 +161,8 @@ extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum,
uint16 procnum);
extern FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum,
uint16 procnum);
+extern void index_store_orderby_distances(IndexScanDesc scan, Oid *orderByTypes,
+ double *distances, bool recheckOrderBy);
/*
* index access method support routines (in genam.c)