summaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeTidscan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeTidscan.c')
-rw-r--r--src/backend/executor/nodeTidscan.c496
1 files changed, 0 insertions, 496 deletions
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
deleted file mode 100644
index 300735fff06..00000000000
--- a/src/backend/executor/nodeTidscan.c
+++ /dev/null
@@ -1,496 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * nodeTidscan.c
- * Routines to support direct tid scans of relations
- *
- * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeTidscan.c,v 1.25 2002/06/20 20:29:28 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-/*
- * INTERFACE ROUTINES
- *
- * ExecTidScan scans a relation using tids
- * ExecInitTidScan creates and initializes state info.
- * ExecTidReScan rescans the tid relation.
- * ExecEndTidScan releases all storage.
- * ExecTidMarkPos marks scan position.
- *
- */
-#include "postgres.h"
-
-#include "executor/execdebug.h"
-#include "executor/nodeTidscan.h"
-#include "access/heapam.h"
-#include "parser/parsetree.h"
-
-static int TidListCreate(List *, ExprContext *, ItemPointerData[]);
-static TupleTableSlot *TidNext(TidScan *node);
-
-static int
-TidListCreate(List *evalList, ExprContext *econtext, ItemPointerData tidList[])
-{
- List *lst;
- ItemPointer itemptr;
- bool isNull;
- int numTids = 0;
-
- foreach(lst, evalList)
- {
- itemptr = (ItemPointer)
- DatumGetPointer(ExecEvalExprSwitchContext(lfirst(lst),
- econtext,
- &isNull,
- NULL));
- if (!isNull && itemptr && ItemPointerIsValid(itemptr))
- {
- tidList[numTids] = *itemptr;
- numTids++;
- }
- }
- return numTids;
-}
-
-/* ----------------------------------------------------------------
- * TidNext
- *
- * Retrieve a tuple from the TidScan node's currentRelation
- * using the tids in the TidScanState information.
- *
- * ----------------------------------------------------------------
- */
-static TupleTableSlot *
-TidNext(TidScan *node)
-{
- EState *estate;
- CommonScanState *scanstate;
- TidScanState *tidstate;
- ScanDirection direction;
- Snapshot snapshot;
- Relation heapRelation;
- HeapTuple tuple;
- TupleTableSlot *slot;
- Buffer buffer = InvalidBuffer;
- int numTids;
-
- bool bBackward;
- int tidNumber;
- ItemPointerData *tidList;
-
- /*
- * extract necessary information from tid scan node
- */
- estate = node->scan.plan.state;
- direction = estate->es_direction;
- snapshot = estate->es_snapshot;
- scanstate = node->scan.scanstate;
- tidstate = node->tidstate;
- heapRelation = scanstate->css_currentRelation;
- numTids = tidstate->tss_NumTids;
- tidList = tidstate->tss_TidList;
- slot = scanstate->css_ScanTupleSlot;
-
- /*
- * Check if we are evaluating PlanQual for tuple of this relation.
- * Additional checking is not good, but no other way for now. We could
- * introduce new nodes for this case and handle TidScan --> NewNode
- * switching in Init/ReScan plan...
- */
- if (estate->es_evTuple != NULL &&
- estate->es_evTuple[node->scan.scanrelid - 1] != NULL)
- {
- ExecClearTuple(slot);
- if (estate->es_evTupleNull[node->scan.scanrelid - 1])
- return slot; /* return empty slot */
-
- /*
- * XXX shouldn't we check here to make sure tuple matches TID list?
- * In runtime-key case this is not certain, is it?
- */
-
- ExecStoreTuple(estate->es_evTuple[node->scan.scanrelid - 1],
- slot, InvalidBuffer, false);
-
- /* Flag for the next call that no more tuples */
- estate->es_evTupleNull[node->scan.scanrelid - 1] = true;
- return (slot);
- }
-
- tuple = &(tidstate->tss_htup);
-
- /*
- * ok, now that we have what we need, fetch an tid tuple. if scanning
- * this tid succeeded then return the appropriate heap tuple.. else
- * return NULL.
- */
- bBackward = ScanDirectionIsBackward(direction);
- if (bBackward)
- {
- tidNumber = numTids - tidstate->tss_TidPtr - 1;
- if (tidNumber < 0)
- {
- tidNumber = 0;
- tidstate->tss_TidPtr = numTids - 1;
- }
- }
- else
- {
- if ((tidNumber = tidstate->tss_TidPtr) < 0)
- {
- tidNumber = 0;
- tidstate->tss_TidPtr = 0;
- }
- }
- while (tidNumber < numTids)
- {
- bool slot_is_valid = false;
-
- tuple->t_self = tidList[tidstate->tss_TidPtr];
- if (heap_fetch(heapRelation, snapshot, tuple, &buffer, false, NULL))
- {
- bool prev_matches = false;
- int prev_tid;
-
- /*
- * store the scanned tuple in the scan tuple slot of the scan
- * state. Eventually we will only do this and not return a
- * tuple. Note: we pass 'false' because tuples returned by
- * amgetnext are pointers onto disk pages and were not created
- * with palloc() and so should not be pfree()'d.
- */
- ExecStoreTuple(tuple, /* tuple to store */
- slot, /* slot to store in */
- buffer, /* buffer associated with tuple */
- false); /* don't pfree */
-
- /*
- * At this point we have an extra pin on the buffer, because
- * ExecStoreTuple incremented the pin count. Drop our local
- * pin.
- */
- ReleaseBuffer(buffer);
-
- /*
- * We must check to see if the current tuple would have been
- * matched by an earlier tid, so we don't double report it. We
- * do this by passing the tuple through ExecQual and look for
- * failure with all previous qualifications.
- */
- for (prev_tid = 0; prev_tid < tidstate->tss_TidPtr;
- prev_tid++)
- {
- if (ItemPointerEquals(&tidList[prev_tid], &tuple->t_self))
- {
- prev_matches = true;
- break;
- }
- }
- if (!prev_matches)
- slot_is_valid = true;
- else
- ExecClearTuple(slot);
- }
- tidNumber++;
- if (bBackward)
- tidstate->tss_TidPtr--;
- else
- tidstate->tss_TidPtr++;
- if (slot_is_valid)
- return slot;
- }
-
- /*
- * if we get here it means the tid scan failed so we are at the end of
- * the scan..
- */
- return ExecClearTuple(slot);
-}
-
-/* ----------------------------------------------------------------
- * ExecTidScan(node)
- *
- * Scans the relation using tids and returns
- * the next qualifying tuple in the direction specified.
- * It calls ExecScan() and passes it the access methods which returns
- * the next tuple using the tids.
- *
- * Conditions:
- * -- the "cursor" maintained by the AMI is positioned at the tuple
- * returned previously.
- *
- * Initial States:
- * -- the relation indicated is opened for scanning so that the
- * "cursor" is positioned before the first qualifying tuple.
- * -- tidPtr points to the first tid.
- * -- state variable ruleFlag = nil.
- * ----------------------------------------------------------------
- */
-TupleTableSlot *
-ExecTidScan(TidScan *node)
-{
- /*
- * use TidNext as access method
- */
- return ExecScan(&node->scan, (ExecScanAccessMtd) TidNext);
-}
-
-/* ----------------------------------------------------------------
- * ExecTidReScan(node)
- * ----------------------------------------------------------------
- */
-void
-ExecTidReScan(TidScan *node, ExprContext *exprCtxt, Plan *parent)
-{
- EState *estate;
- TidScanState *tidstate;
- ItemPointerData *tidList;
-
- estate = node->scan.plan.state;
- tidstate = node->tidstate;
- tidList = tidstate->tss_TidList;
-
- /* If we are being passed an outer tuple, save it for runtime key calc */
- if (exprCtxt != NULL)
- node->scan.scanstate->cstate.cs_ExprContext->ecxt_outertuple =
- exprCtxt->ecxt_outertuple;
-
- /* do runtime calc of target TIDs, if needed */
- if (node->needRescan)
- tidstate->tss_NumTids =
- TidListCreate(node->tideval,
- node->scan.scanstate->cstate.cs_ExprContext,
- tidList);
-
- /* If this is re-scanning of PlanQual ... */
- if (estate->es_evTuple != NULL &&
- estate->es_evTuple[node->scan.scanrelid - 1] != NULL)
- {
- estate->es_evTupleNull[node->scan.scanrelid - 1] = false;
- return;
- }
-
- tidstate->tss_TidPtr = -1;
-
- /*
- * perhaps return something meaningful
- */
- return;
-}
-
-/* ----------------------------------------------------------------
- * ExecEndTidScan
- *
- * Releases any storage allocated through C routines.
- * Returns nothing.
- * ----------------------------------------------------------------
- */
-void
-ExecEndTidScan(TidScan *node)
-{
- CommonScanState *scanstate;
- TidScanState *tidstate;
-
- /*
- * extract information from the node
- */
- scanstate = node->scan.scanstate;
- tidstate = node->tidstate;
- if (tidstate && tidstate->tss_TidList)
- pfree(tidstate->tss_TidList);
-
- /*
- * Free the projection info and the scan attribute info
- *
- * Note: we don't ExecFreeResultType(scanstate) because the rule manager
- * depends on the tupType returned by ExecMain(). So for now, this is
- * freed at end-transaction time. -cim 6/2/91
- */
- ExecFreeProjectionInfo(&scanstate->cstate);
- ExecFreeExprContext(&scanstate->cstate);
-
- /*
- * close the heap relation.
- *
- * Currently, we do not release the AccessShareLock acquired by
- * ExecInitTidScan. This lock should be held till end of transaction.
- * (There is a faction that considers this too much locking, however.)
- */
- heap_close(scanstate->css_currentRelation, NoLock);
-
- /*
- * clear out tuple table slots
- */
- ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
- ExecClearTuple(scanstate->css_ScanTupleSlot);
-}
-
-/* ----------------------------------------------------------------
- * ExecTidMarkPos
- *
- * Marks scan position by marking the current tid.
- * Returns nothing.
- * ----------------------------------------------------------------
- */
-void
-ExecTidMarkPos(TidScan *node)
-{
- TidScanState *tidstate;
-
- tidstate = node->tidstate;
- tidstate->tss_MarkTidPtr = tidstate->tss_TidPtr;
-}
-
-#ifdef NOT_USED
-/* ----------------------------------------------------------------
- * ExecTidRestrPos
- *
- * Restores scan position by restoring the current tid.
- * Returns nothing.
- *
- * XXX Assumes previously marked scan position belongs to current tid
- * ----------------------------------------------------------------
- */
-void
-ExecTidRestrPos(TidScan *node)
-{
- TidScanState *tidstate;
-
- tidstate = node->tidstate;
- tidstate->tss_TidPtr = tidstate->tss_MarkTidPtr;
-}
-#endif
-
-/* ----------------------------------------------------------------
- * ExecInitTidScan
- *
- * Initializes the tid scan's state information, creates
- * scan keys, and opens the base and tid relations.
- *
- * Parameters:
- * node: TidNode node produced by the planner.
- * estate: the execution state initialized in InitPlan.
- * ----------------------------------------------------------------
- */
-bool
-ExecInitTidScan(TidScan *node, EState *estate, Plan *parent)
-{
- TidScanState *tidstate;
- CommonScanState *scanstate;
- ItemPointerData *tidList;
- int numTids;
- int tidPtr;
- List *rangeTable;
- RangeTblEntry *rtentry;
- Oid relid;
- Oid reloid;
- Relation currentRelation;
- List *execParam = NIL;
-
- /*
- * assign execution state to node
- */
- node->scan.plan.state = estate;
-
- /*
- * Part 1) initialize scan state
- *
- * create new CommonScanState for node
- */
- scanstate = makeNode(CommonScanState);
- node->scan.scanstate = scanstate;
-
- /*
- * Miscellaneous initialization
- *
- * create expression context for node
- */
- ExecAssignExprContext(estate, &scanstate->cstate);
-
-#define TIDSCAN_NSLOTS 2
-
- /*
- * tuple table initialization
- */
- ExecInitResultTupleSlot(estate, &scanstate->cstate);
- ExecInitScanTupleSlot(estate, scanstate);
-
- /*
- * initialize projection info. result type comes from scan desc
- * below..
- */
- ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
-
- /*
- * Part 2) initialize tid scan state
- *
- * create new TidScanState for node
- */
- tidstate = makeNode(TidScanState);
- node->tidstate = tidstate;
-
- /*
- * get the tid node information
- */
- tidList = (ItemPointerData *) palloc(length(node->tideval) * sizeof(ItemPointerData));
- numTids = 0;
- if (!node->needRescan)
- numTids = TidListCreate(node->tideval,
- scanstate->cstate.cs_ExprContext,
- tidList);
- tidPtr = -1;
-
- CXT1_printf("ExecInitTidScan: context is %d\n", CurrentMemoryContext);
-
- tidstate->tss_NumTids = numTids;
- tidstate->tss_TidPtr = tidPtr;
- tidstate->tss_TidList = tidList;
-
- /*
- * get the range table and direction information from the execution
- * state (these are needed to open the relations).
- */
- rangeTable = estate->es_range_table;
-
- /*
- * open the base relation
- *
- * We acquire AccessShareLock for the duration of the scan.
- */
- relid = node->scan.scanrelid;
- rtentry = rt_fetch(relid, rangeTable);
- reloid = rtentry->relid;
-
- currentRelation = heap_open(reloid, AccessShareLock);
-
- scanstate->css_currentRelation = currentRelation;
- scanstate->css_currentScanDesc = NULL; /* no heap scan here */
-
- /*
- * get the scan type from the relation descriptor.
- */
- ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false);
- ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
-
- /*
- * if there are some PARAM_EXEC in skankeys then force tid rescan on
- * first scan.
- */
- ((Plan *) node)->chgParam = execParam;
-
- /*
- * all done.
- */
- return TRUE;
-}
-
-int
-ExecCountSlotsTidScan(TidScan *node)
-{
- return ExecCountSlotsNode(outerPlan((Plan *) node)) +
- ExecCountSlotsNode(innerPlan((Plan *) node)) + TIDSCAN_NSLOTS;
-}