mirror of
https://github.com/postgres/postgres.git
synced 2025-09-02 04:21:28 +03:00
Create core infrastructure for KNNGIST.
This is a heavily revised version of builtin_knngist_core-0.9. The ordering operators are no longer mixed in with actual quals, which would have confused not only humans but significant parts of the planner. Instead, ordering operators are carried separately throughout planning and execution. Since the API for ambeginscan and amrescan functions had to be changed anyway, this commit takes the opportunity to rationalize that a bit. RelationGetIndexScan no longer forces a premature index_rescan call; instead, callers of index_beginscan must call index_rescan too. Aside from making the AM-side initialization logic a bit less peculiar, this has the advantage that we do not make a useless extra am_rescan call when there are runtime key values. AMs formerly could not assume that the key values passed to amrescan were actually valid; now they can. Teodor Sigaev and Tom Lane
This commit is contained in:
@@ -57,22 +57,20 @@
|
||||
/* ----------------
|
||||
* RelationGetIndexScan -- Create and fill an IndexScanDesc.
|
||||
*
|
||||
* This routine creates an index scan structure and sets its contents
|
||||
* up correctly. This routine calls AMrescan to set up the scan with
|
||||
* the passed key.
|
||||
* This routine creates an index scan structure and sets up initial
|
||||
* contents for it.
|
||||
*
|
||||
* Parameters:
|
||||
* indexRelation -- index relation for scan.
|
||||
* nkeys -- count of scan keys.
|
||||
* key -- array of scan keys to restrict the index scan.
|
||||
* nkeys -- count of scan keys (index qual conditions).
|
||||
* norderbys -- count of index order-by operators.
|
||||
*
|
||||
* Returns:
|
||||
* An initialized IndexScanDesc.
|
||||
* ----------------
|
||||
*/
|
||||
IndexScanDesc
|
||||
RelationGetIndexScan(Relation indexRelation,
|
||||
int nkeys, ScanKey key)
|
||||
RelationGetIndexScan(Relation indexRelation, int nkeys, int norderbys)
|
||||
{
|
||||
IndexScanDesc scan;
|
||||
|
||||
@@ -82,15 +80,19 @@ RelationGetIndexScan(Relation indexRelation,
|
||||
scan->indexRelation = indexRelation;
|
||||
scan->xs_snapshot = SnapshotNow; /* may be set later */
|
||||
scan->numberOfKeys = nkeys;
|
||||
scan->numberOfOrderBys = norderbys;
|
||||
|
||||
/*
|
||||
* We allocate the key space here, but the AM is responsible for actually
|
||||
* filling it from the passed key array.
|
||||
* We allocate key workspace here, but it won't get filled until amrescan.
|
||||
*/
|
||||
if (nkeys > 0)
|
||||
scan->keyData = (ScanKey) palloc(sizeof(ScanKeyData) * nkeys);
|
||||
else
|
||||
scan->keyData = NULL;
|
||||
if (norderbys > 0)
|
||||
scan->orderByData = (ScanKey) palloc(sizeof(ScanKeyData) * norderbys);
|
||||
else
|
||||
scan->orderByData = NULL;
|
||||
|
||||
/*
|
||||
* During recovery we ignore killed tuples and don't bother to kill them
|
||||
@@ -115,11 +117,6 @@ RelationGetIndexScan(Relation indexRelation,
|
||||
scan->xs_next_hot = InvalidOffsetNumber;
|
||||
scan->xs_prev_xmax = InvalidTransactionId;
|
||||
|
||||
/*
|
||||
* Let the AM fill in the key and any opaque data it wants.
|
||||
*/
|
||||
index_rescan(scan, key);
|
||||
|
||||
return scan;
|
||||
}
|
||||
|
||||
@@ -140,6 +137,8 @@ IndexScanEnd(IndexScanDesc scan)
|
||||
{
|
||||
if (scan->keyData != NULL)
|
||||
pfree(scan->keyData);
|
||||
if (scan->orderByData != NULL)
|
||||
pfree(scan->orderByData);
|
||||
|
||||
pfree(scan);
|
||||
}
|
||||
@@ -286,7 +285,8 @@ systable_beginscan(Relation heapRelation,
|
||||
}
|
||||
|
||||
sysscan->iscan = index_beginscan(heapRelation, irel,
|
||||
snapshot, nkeys, key);
|
||||
snapshot, nkeys, 0);
|
||||
index_rescan(sysscan->iscan, key, nkeys, NULL, 0);
|
||||
sysscan->scan = NULL;
|
||||
}
|
||||
else
|
||||
@@ -450,7 +450,8 @@ systable_beginscan_ordered(Relation heapRelation,
|
||||
}
|
||||
|
||||
sysscan->iscan = index_beginscan(heapRelation, indexRelation,
|
||||
snapshot, nkeys, key);
|
||||
snapshot, nkeys, 0);
|
||||
index_rescan(sysscan->iscan, key, nkeys, NULL, 0);
|
||||
sysscan->scan = NULL;
|
||||
|
||||
return sysscan;
|
||||
|
@@ -114,7 +114,7 @@ do { \
|
||||
} while(0)
|
||||
|
||||
static IndexScanDesc index_beginscan_internal(Relation indexRelation,
|
||||
int nkeys, ScanKey key);
|
||||
int nkeys, int norderbys);
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
@@ -213,11 +213,11 @@ IndexScanDesc
|
||||
index_beginscan(Relation heapRelation,
|
||||
Relation indexRelation,
|
||||
Snapshot snapshot,
|
||||
int nkeys, ScanKey key)
|
||||
int nkeys, int norderbys)
|
||||
{
|
||||
IndexScanDesc scan;
|
||||
|
||||
scan = index_beginscan_internal(indexRelation, nkeys, key);
|
||||
scan = index_beginscan_internal(indexRelation, nkeys, norderbys);
|
||||
|
||||
/*
|
||||
* Save additional parameters into the scandesc. Everything else was set
|
||||
@@ -238,11 +238,11 @@ index_beginscan(Relation heapRelation,
|
||||
IndexScanDesc
|
||||
index_beginscan_bitmap(Relation indexRelation,
|
||||
Snapshot snapshot,
|
||||
int nkeys, ScanKey key)
|
||||
int nkeys)
|
||||
{
|
||||
IndexScanDesc scan;
|
||||
|
||||
scan = index_beginscan_internal(indexRelation, nkeys, key);
|
||||
scan = index_beginscan_internal(indexRelation, nkeys, 0);
|
||||
|
||||
/*
|
||||
* Save additional parameters into the scandesc. Everything else was set
|
||||
@@ -258,7 +258,7 @@ index_beginscan_bitmap(Relation indexRelation,
|
||||
*/
|
||||
static IndexScanDesc
|
||||
index_beginscan_internal(Relation indexRelation,
|
||||
int nkeys, ScanKey key)
|
||||
int nkeys, int norderbys)
|
||||
{
|
||||
IndexScanDesc scan;
|
||||
FmgrInfo *procedure;
|
||||
@@ -278,7 +278,7 @@ index_beginscan_internal(Relation indexRelation,
|
||||
DatumGetPointer(FunctionCall3(procedure,
|
||||
PointerGetDatum(indexRelation),
|
||||
Int32GetDatum(nkeys),
|
||||
PointerGetDatum(key)));
|
||||
Int32GetDatum(norderbys)));
|
||||
|
||||
return scan;
|
||||
}
|
||||
@@ -286,23 +286,28 @@ index_beginscan_internal(Relation indexRelation,
|
||||
/* ----------------
|
||||
* index_rescan - (re)start a scan of an index
|
||||
*
|
||||
* The caller may specify a new set of scankeys (but the number of keys
|
||||
* cannot change). To restart the scan without changing keys, pass NULL
|
||||
* for the key array.
|
||||
*
|
||||
* Note that this is also called when first starting an indexscan;
|
||||
* see RelationGetIndexScan. Keys *must* be passed in that case,
|
||||
* unless scan->numberOfKeys is zero.
|
||||
* During a restart, the caller may specify a new set of scankeys and/or
|
||||
* orderbykeys; but the number of keys cannot differ from what index_beginscan
|
||||
* was told. (Later we might relax that to "must not exceed", but currently
|
||||
* the index AMs tend to assume that scan->numberOfKeys is what to believe.)
|
||||
* To restart the scan without changing keys, pass NULL for the key arrays.
|
||||
* (Of course, keys *must* be passed on the first call, unless
|
||||
* scan->numberOfKeys is zero.)
|
||||
* ----------------
|
||||
*/
|
||||
void
|
||||
index_rescan(IndexScanDesc scan, ScanKey key)
|
||||
index_rescan(IndexScanDesc scan,
|
||||
ScanKey keys, int nkeys,
|
||||
ScanKey orderbys, int norderbys)
|
||||
{
|
||||
FmgrInfo *procedure;
|
||||
|
||||
SCAN_CHECKS;
|
||||
GET_SCAN_PROCEDURE(amrescan);
|
||||
|
||||
Assert(nkeys == scan->numberOfKeys);
|
||||
Assert(norderbys == scan->numberOfOrderBys);
|
||||
|
||||
/* Release any held pin on a heap page */
|
||||
if (BufferIsValid(scan->xs_cbuf))
|
||||
{
|
||||
@@ -314,9 +319,12 @@ index_rescan(IndexScanDesc scan, ScanKey key)
|
||||
|
||||
scan->kill_prior_tuple = false; /* for safety */
|
||||
|
||||
FunctionCall2(procedure,
|
||||
FunctionCall5(procedure,
|
||||
PointerGetDatum(scan),
|
||||
PointerGetDatum(key));
|
||||
PointerGetDatum(keys),
|
||||
Int32GetDatum(nkeys),
|
||||
PointerGetDatum(orderbys),
|
||||
Int32GetDatum(norderbys));
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
|
Reference in New Issue
Block a user