#include "fmgr.h"
Go to the source code of this file.
Functions | |
Datum | gistbeginscan (PG_FUNCTION_ARGS) |
Datum | gistrescan (PG_FUNCTION_ARGS) |
Datum | gistmarkpos (PG_FUNCTION_ARGS) |
Datum | gistrestrpos (PG_FUNCTION_ARGS) |
Datum | gistendscan (PG_FUNCTION_ARGS) |
Datum gistbeginscan | ( | PG_FUNCTION_ARGS | ) |
Definition at line 101 of file gistscan.c.
References createTempGistContext(), GISTScanOpaqueData::distances, GISTScanOpaqueData::giststate, GSTIHDRSZ, IndexScanDescData::indexRelation, initGISTstate(), MemoryContextSwitchTo(), IndexScanDescData::numberOfOrderBys, IndexScanDescData::opaque, palloc(), palloc0(), PG_GETARG_INT32, PG_GETARG_POINTER, PG_RETURN_POINTER, GISTScanOpaqueData::qual_ok, GISTScanOpaqueData::queue, GISTScanOpaqueData::queueCxt, RelationGetIndexScan(), GISTSTATE::scanCxt, GISTSTATE::tempCxt, and GISTScanOpaqueData::tmpTreeItem.
{ Relation r = (Relation) PG_GETARG_POINTER(0); int nkeys = PG_GETARG_INT32(1); int norderbys = PG_GETARG_INT32(2); IndexScanDesc scan; GISTSTATE *giststate; GISTScanOpaque so; MemoryContext oldCxt; scan = RelationGetIndexScan(r, nkeys, norderbys); /* First, set up a GISTSTATE with a scan-lifespan memory context */ giststate = initGISTstate(scan->indexRelation); /* * Everything made below is in the scanCxt, or is a child of the scanCxt, * so it'll all go away automatically in gistendscan. */ oldCxt = MemoryContextSwitchTo(giststate->scanCxt); /* initialize opaque data */ so = (GISTScanOpaque) palloc0(sizeof(GISTScanOpaqueData)); so->giststate = giststate; giststate->tempCxt = createTempGistContext(); so->queue = NULL; 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); PG_RETURN_POINTER(scan); }
Datum gistendscan | ( | PG_FUNCTION_ARGS | ) |
Definition at line 314 of file gistscan.c.
References freeGISTstate(), GISTScanOpaqueData::giststate, IndexScanDescData::opaque, PG_GETARG_POINTER, and PG_RETURN_VOID.
{ IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); GISTScanOpaque so = (GISTScanOpaque) scan->opaque; /* * freeGISTstate is enough to clean up everything made by gistbeginscan, * as well as the queueCxt if there is a separate context for it. */ freeGISTstate(so->giststate); PG_RETURN_VOID(); }
Datum gistmarkpos | ( | PG_FUNCTION_ARGS | ) |
Definition at line 300 of file gistscan.c.
References elog, ERROR, and PG_RETURN_VOID.
{ elog(ERROR, "GiST does not support mark/restore"); PG_RETURN_VOID(); }
Datum gistrescan | ( | PG_FUNCTION_ARGS | ) |
Definition at line 142 of file gistscan.c.
References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), Assert, GISTSTATE::consistentFn, GISTScanOpaqueData::curTreeItem, GISTSTATE::distanceFn, elog, ERROR, GISTScanOpaqueData::firstCall, FmgrInfo::fn_extra, FmgrInfo::fn_oid, GIST_DISTANCE_PROC, GISTSearchTreeItemAllocator(), GISTSearchTreeItemCombiner(), GISTSearchTreeItemComparator(), GISTSearchTreeItemDeleter(), GISTScanOpaqueData::giststate, GSTIHDRSZ, i, IndexScanDescData::indexRelation, IndexScanDescData::keyData, memmove, MemoryContextReset(), MemoryContextSwitchTo(), NULL, IndexScanDescData::numberOfKeys, IndexScanDescData::numberOfOrderBys, OidIsValid, IndexScanDescData::opaque, IndexScanDescData::orderByData, PG_GETARG_POINTER, PG_RETURN_VOID, GISTScanOpaqueData::qual_ok, GISTScanOpaqueData::queue, GISTScanOpaqueData::queueCxt, rb_create(), RelationGetRelationName, GISTSTATE::scanCxt, ScanKeyData::sk_attno, ScanKeyData::sk_flags, ScanKeyData::sk_func, SK_ISNULL, SK_SEARCHNOTNULL, and SK_SEARCHNULL.
{ IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); ScanKey key = (ScanKey) PG_GETARG_POINTER(1); ScanKey orderbys = (ScanKey) PG_GETARG_POINTER(3); /* nkeys and norderbys arguments are ignored */ GISTScanOpaque so = (GISTScanOpaque) scan->opaque; bool first_time; int i; MemoryContext oldCxt; /* rescan an existing indexscan --- reset state */ /* * The first time through, we create the search queue in the scanCxt. * Subsequent times through, we create the queue in a separate queueCxt, * which is created on the second call and reset on later calls. Thus, in * the common case where a scan is only rescan'd once, we just put the * queue in scanCxt and don't pay the overhead of making a second memory * context. If we do rescan more than once, the first RBTree is just left * for dead until end of scan; this small wastage seems worth the savings * in the common case. */ if (so->queue == NULL) { /* first time through */ Assert(so->queueCxt == so->giststate->scanCxt); first_time = true; } else if (so->queueCxt == so->giststate->scanCxt) { /* second time through */ so->queueCxt = AllocSetContextCreate(so->giststate->scanCxt, "GiST queue context", ALLOCSET_DEFAULT_MINSIZE, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE); first_time = false; } else { /* third or later time through */ MemoryContextReset(so->queueCxt); 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, GISTSearchTreeItemDeleter, scan); MemoryContextSwitchTo(oldCxt); so->curTreeItem = NULL; so->firstCall = true; /* Update scan key, if a new one is given */ if (key && scan->numberOfKeys > 0) { /* * If this isn't the first time through, preserve the fn_extra * pointers, so that if the consistentFns are using them to cache * data, that data is not leaked across a rescan. */ if (!first_time) { for (i = 0; i < scan->numberOfKeys; i++) { ScanKey skey = scan->keyData + i; so->giststate->consistentFn[skey->sk_attno - 1].fn_extra = skey->sk_func.fn_extra; } } memmove(scan->keyData, key, scan->numberOfKeys * sizeof(ScanKeyData)); /* * Modify the scan key so that the Consistent method is called for all * comparisons. The original operator is passed to the Consistent * function in the form of its strategy number, which is available * from the sk_strategy field, and its subtype from the sk_subtype * field. * * Next, if any of keys is a NULL and that key is not marked with * SK_SEARCHNULL/SK_SEARCHNOTNULL then nothing can be found (ie, we * assume all indexable operators are strict). * * Note: we intentionally memcpy the FmgrInfo to sk_func rather than * using fmgr_info_copy. This is so that the fn_extra field gets * preserved across multiple rescans. */ so->qual_ok = true; for (i = 0; i < scan->numberOfKeys; i++) { ScanKey skey = scan->keyData + i; skey->sk_func = so->giststate->consistentFn[skey->sk_attno - 1]; if (skey->sk_flags & SK_ISNULL) { if (!(skey->sk_flags & (SK_SEARCHNULL | SK_SEARCHNOTNULL))) so->qual_ok = false; } } } /* Update order-by key, if a new one is given */ if (orderbys && scan->numberOfOrderBys > 0) { /* As above, preserve fn_extra if not first time through */ if (!first_time) { for (i = 0; i < scan->numberOfOrderBys; i++) { ScanKey skey = scan->orderByData + i; so->giststate->distanceFn[skey->sk_attno - 1].fn_extra = skey->sk_func.fn_extra; } } memmove(scan->orderByData, orderbys, scan->numberOfOrderBys * sizeof(ScanKeyData)); /* * Modify the order-by key so that the Distance method is called for * all comparisons. The original operator is passed to the Distance * function in the form of its strategy number, which is available * from the sk_strategy field, and its subtype from the sk_subtype * field. * * See above comment about why we don't use fmgr_info_copy here. */ for (i = 0; i < scan->numberOfOrderBys; i++) { ScanKey skey = scan->orderByData + i; skey->sk_func = so->giststate->distanceFn[skey->sk_attno - 1]; /* Check we actually have a distance function ... */ if (!OidIsValid(skey->sk_func.fn_oid)) elog(ERROR, "missing support function %d for attribute %d of index \"%s\"", GIST_DISTANCE_PROC, skey->sk_attno, RelationGetRelationName(scan->indexRelation)); } } PG_RETURN_VOID(); }
Datum gistrestrpos | ( | PG_FUNCTION_ARGS | ) |
Definition at line 307 of file gistscan.c.
References elog, ERROR, and PG_RETURN_VOID.
{ elog(ERROR, "GiST does not support mark/restore"); PG_RETURN_VOID(); }