1996-07-09 06:22:35 +00:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-13 23:22:53 +00:00
|
|
|
* nodeSeqscan.c
|
1997-09-07 05:04:48 +00:00
|
|
|
* Support routines for sequential scans of relations.
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
2001-01-24 19:43:33 +00:00
|
|
|
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
2000-01-26 05:58:53 +00:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2001-10-28 06:26:15 +00:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/executor/nodeSeqscan.c,v 1.33 2001/10/28 06:25:43 momjian Exp $
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
* INTERFACE ROUTINES
|
1997-09-07 05:04:48 +00:00
|
|
|
* ExecSeqScan sequentially scans a relation.
|
|
|
|
* ExecSeqNext retrieve next tuple in sequential order.
|
|
|
|
* ExecInitSeqScan creates and initializes a seqscan node.
|
|
|
|
* ExecEndSeqScan releases any storage allocated.
|
|
|
|
* ExecSeqReScan rescans the relation
|
|
|
|
* ExecMarkPos marks scan position
|
|
|
|
* ExecRestrPos restores scan position
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
|
|
|
*/
|
1996-10-31 10:12:26 +00:00
|
|
|
#include "postgres.h"
|
|
|
|
|
1999-07-16 05:00:38 +00:00
|
|
|
#include "access/heapam.h"
|
1996-11-08 06:02:30 +00:00
|
|
|
#include "executor/execdebug.h"
|
1996-07-09 06:22:35 +00:00
|
|
|
#include "executor/nodeSeqscan.h"
|
|
|
|
#include "parser/parsetree.h"
|
|
|
|
|
1998-09-01 04:40:42 +00:00
|
|
|
static Oid InitScanRelation(SeqScan *node, EState *estate,
|
2001-03-22 04:01:46 +00:00
|
|
|
CommonScanState *scanstate);
|
1997-09-08 21:56:23 +00:00
|
|
|
static TupleTableSlot *SeqNext(SeqScan *node);
|
1997-08-19 21:40:56 +00:00
|
|
|
|
1996-07-09 06:22:35 +00:00
|
|
|
/* ----------------------------------------------------------------
|
1997-09-07 05:04:48 +00:00
|
|
|
* Scan Support
|
1996-07-09 06:22:35 +00:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
/* ----------------------------------------------------------------
|
1997-09-07 05:04:48 +00:00
|
|
|
* SeqNext
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
1997-09-07 05:04:48 +00:00
|
|
|
* This is a workhorse for ExecSeqScan
|
1996-07-09 06:22:35 +00:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
1997-08-19 21:40:56 +00:00
|
|
|
static TupleTableSlot *
|
1997-09-08 21:56:23 +00:00
|
|
|
SeqNext(SeqScan *node)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
HeapTuple tuple;
|
|
|
|
HeapScanDesc scandesc;
|
1997-09-07 05:04:48 +00:00
|
|
|
CommonScanState *scanstate;
|
1997-09-08 02:41:22 +00:00
|
|
|
EState *estate;
|
|
|
|
ScanDirection direction;
|
1997-09-07 05:04:48 +00:00
|
|
|
TupleTableSlot *slot;
|
|
|
|
|
2001-03-22 06:16:21 +00:00
|
|
|
/*
|
|
|
|
* get information from the estate and scan state
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
|
|
|
estate = node->plan.state;
|
|
|
|
scanstate = node->scanstate;
|
|
|
|
scandesc = scanstate->css_currentScanDesc;
|
|
|
|
direction = estate->es_direction;
|
1999-01-29 09:23:17 +00:00
|
|
|
slot = scanstate->css_ScanTupleSlot;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if we are evaluating PlanQual for tuple of this relation.
|
1999-05-25 16:15:34 +00:00
|
|
|
* Additional checking is not good, but no other way for now. We could
|
|
|
|
* introduce new nodes for this case and handle SeqScan --> NewNode
|
|
|
|
* switching in Init/ReScan plan...
|
1999-01-29 09:23:17 +00:00
|
|
|
*/
|
1999-05-25 16:15:34 +00:00
|
|
|
if (estate->es_evTuple != NULL &&
|
1999-01-29 09:23:17 +00:00
|
|
|
estate->es_evTuple[node->scanrelid - 1] != NULL)
|
|
|
|
{
|
1999-09-24 00:25:33 +00:00
|
|
|
ExecClearTuple(slot);
|
1999-01-29 09:23:17 +00:00
|
|
|
if (estate->es_evTupleNull[node->scanrelid - 1])
|
1999-09-24 00:25:33 +00:00
|
|
|
return slot; /* return empty slot */
|
|
|
|
|
2001-01-29 00:39:20 +00:00
|
|
|
ExecStoreTuple(estate->es_evTuple[node->scanrelid - 1],
|
|
|
|
slot, InvalidBuffer, false);
|
1999-05-25 16:15:34 +00:00
|
|
|
|
1999-01-29 09:23:17 +00:00
|
|
|
/*
|
1999-05-25 16:15:34 +00:00
|
|
|
* Note that unlike IndexScan, SeqScan never use keys in
|
1999-09-24 00:25:33 +00:00
|
|
|
* heap_beginscan (and this is very bad) - so, here we do not
|
1999-05-25 16:15:34 +00:00
|
|
|
* check are keys ok or not.
|
1999-01-29 09:23:17 +00:00
|
|
|
*/
|
1999-09-24 00:25:33 +00:00
|
|
|
|
1999-01-29 09:23:17 +00:00
|
|
|
/* Flag for the next call that no more tuples */
|
|
|
|
estate->es_evTupleNull[node->scanrelid - 1] = true;
|
|
|
|
return (slot);
|
|
|
|
}
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2001-03-22 06:16:21 +00:00
|
|
|
/*
|
|
|
|
* get the next tuple from the access methods
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
1998-08-19 02:04:17 +00:00
|
|
|
tuple = heap_getnext(scandesc, ScanDirectionIsBackward(direction));
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2001-03-22 06:16:21 +00:00
|
|
|
/*
|
|
|
|
* save the tuple and the buffer returned to us by the access methods
|
|
|
|
* in our scan tuple slot and return the slot. Note: we pass 'false'
|
|
|
|
* because tuples returned by heap_getnext() are pointers onto disk
|
|
|
|
* pages and were not created with palloc() and so should not be
|
|
|
|
* pfree()'d. Note also that ExecStoreTuple will increment the
|
|
|
|
* refcount of the buffer; the refcount will not be dropped until the
|
|
|
|
* tuple table slot is cleared.
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
|
|
|
|
2001-10-28 06:26:15 +00:00
|
|
|
slot = ExecStoreTuple(tuple, /* tuple to store */
|
1997-09-07 05:04:48 +00:00
|
|
|
slot, /* slot to store in */
|
1998-09-01 04:40:42 +00:00
|
|
|
scandesc->rs_cbuf, /* buffer associated with
|
|
|
|
* this tuple */
|
1997-09-07 05:04:48 +00:00
|
|
|
false); /* don't pfree this pointer */
|
|
|
|
|
|
|
|
return slot;
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------
|
1997-09-07 05:04:48 +00:00
|
|
|
* ExecSeqScan(node)
|
|
|
|
*
|
|
|
|
* Scans the relation sequentially and returns the next qualifying
|
|
|
|
* tuple.
|
|
|
|
* It calls the ExecScan() routine and passes it the access method
|
|
|
|
* which retrieve tuples sequentially.
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
TupleTableSlot *
|
1997-09-08 21:56:23 +00:00
|
|
|
ExecSeqScan(SeqScan *node)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
2001-03-22 06:16:21 +00:00
|
|
|
/*
|
|
|
|
* use SeqNext as access method
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
2000-07-12 02:37:39 +00:00
|
|
|
return ExecScan(node, (ExecScanAccessMtd) SeqNext);
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------
|
1997-09-07 05:04:48 +00:00
|
|
|
* InitScanRelation
|
1996-07-09 06:22:35 +00:00
|
|
|
*
|
1997-09-07 05:04:48 +00:00
|
|
|
* This does the initialization for scan relations and
|
|
|
|
* subplans of scans.
|
1996-07-09 06:22:35 +00:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
1997-09-08 02:41:22 +00:00
|
|
|
static Oid
|
1997-09-08 21:56:23 +00:00
|
|
|
InitScanRelation(SeqScan *node, EState *estate,
|
2000-07-12 02:37:39 +00:00
|
|
|
CommonScanState *scanstate)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
1997-09-08 02:41:22 +00:00
|
|
|
Index relid;
|
|
|
|
List *rangeTable;
|
|
|
|
RangeTblEntry *rtentry;
|
|
|
|
Oid reloid;
|
|
|
|
ScanDirection direction;
|
|
|
|
Relation currentRelation;
|
|
|
|
HeapScanDesc currentScanDesc;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2001-03-22 06:16:21 +00:00
|
|
|
/*
|
|
|
|
* get the relation object id from the relid'th entry in the range
|
|
|
|
* table, open that relation and initialize the scan state...
|
1996-07-09 06:22:35 +00:00
|
|
|
*/
|
2000-07-12 02:37:39 +00:00
|
|
|
relid = node->scanrelid;
|
|
|
|
rangeTable = estate->es_range_table;
|
|
|
|
rtentry = rt_fetch(relid, rangeTable);
|
|
|
|
reloid = rtentry->relid;
|
|
|
|
direction = estate->es_direction;
|
|
|
|
|
|
|
|
ExecOpenScanR(reloid, /* relation */
|
|
|
|
0, /* nkeys */
|
|
|
|
NULL, /* scan key */
|
Restructure index AM interface for index building and index tuple deletion,
per previous discussion on pghackers. Most of the duplicate code in
different AMs' ambuild routines has been moved out to a common routine
in index.c; this means that all index types now do the right things about
inserting recently-dead tuples, etc. (I also removed support for EXTEND
INDEX in the ambuild routines, since that's about to go away anyway, and
it cluttered the code a lot.) The retail indextuple deletion routines have
been replaced by a "bulk delete" routine in which the indexscan is inside
the access method. I haven't pushed this change as far as it should go yet,
but it should allow considerable simplification of the internal bookkeeping
for deletions. Also, add flag columns to pg_am to eliminate various
hardcoded tests on AM OIDs, and remove unused pg_am columns.
Fix rtree and gist index types to not attempt to store NULLs; before this,
gist usually crashed, while rtree managed not to crash but computed wacko
bounding boxes for NULL entries (which might have had something to do with
the performance problems we've heard about occasionally).
Add AtEOXact routines to hash, rtree, and gist, all of which have static
state that needs to be reset after an error. We discovered this need long
ago for btree, but missed the other guys.
Oh, one more thing: concurrent VACUUM is now the default.
2001-07-15 22:48:19 +00:00
|
|
|
false, /* is index */
|
2000-07-12 02:37:39 +00:00
|
|
|
direction, /* scan direction */
|
|
|
|
estate->es_snapshot,
|
2001-03-22 04:01:46 +00:00
|
|
|
¤tRelation, /* return: rel desc */
|
|
|
|
(Pointer *) ¤tScanDesc); /* return: scan desc */
|
2000-07-12 02:37:39 +00:00
|
|
|
|
|
|
|
scanstate->css_currentRelation = currentRelation;
|
|
|
|
scanstate->css_currentScanDesc = currentScanDesc;
|
|
|
|
|
2001-01-29 00:39:20 +00:00
|
|
|
ExecAssignScanType(scanstate, RelationGetDescr(currentRelation), false);
|
2000-07-12 02:37:39 +00:00
|
|
|
|
1997-09-07 05:04:48 +00:00
|
|
|
return reloid;
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------
|
1997-09-07 05:04:48 +00:00
|
|
|
* ExecInitSeqScan
|
1996-07-09 06:22:35 +00:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
bool
|
1997-09-08 21:56:23 +00:00
|
|
|
ExecInitSeqScan(SeqScan *node, EState *estate, Plan *parent)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
1997-09-07 05:04:48 +00:00
|
|
|
CommonScanState *scanstate;
|
1997-09-08 02:41:22 +00:00
|
|
|
Oid reloid;
|
|
|
|
HeapScanDesc scandesc;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2001-03-22 06:16:21 +00:00
|
|
|
/*
|
|
|
|
* Once upon a time it was possible to have an outerPlan of a SeqScan,
|
|
|
|
* but not any more.
|
2000-07-12 02:37:39 +00:00
|
|
|
*/
|
|
|
|
Assert(outerPlan((Plan *) node) == NULL);
|
|
|
|
Assert(innerPlan((Plan *) node) == NULL);
|
|
|
|
|
2001-03-22 06:16:21 +00:00
|
|
|
/*
|
|
|
|
* assign the node's execution state
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
|
|
|
node->plan.state = estate;
|
|
|
|
|
2001-03-22 06:16:21 +00:00
|
|
|
/*
|
|
|
|
* create new CommonScanState for node
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
|
|
|
scanstate = makeNode(CommonScanState);
|
|
|
|
node->scanstate = scanstate;
|
|
|
|
|
2001-03-22 06:16:21 +00:00
|
|
|
/*
|
|
|
|
* Miscellaneous initialization
|
1997-09-07 05:04:48 +00:00
|
|
|
*
|
2001-03-22 06:16:21 +00:00
|
|
|
* create expression context for node
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
|
|
|
ExecAssignExprContext(estate, &scanstate->cstate);
|
1996-07-09 06:22:35 +00:00
|
|
|
|
2001-05-27 20:42:20 +00:00
|
|
|
#define SEQSCAN_NSLOTS 2
|
2001-03-22 06:16:21 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* tuple table initialization
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
|
|
|
ExecInitResultTupleSlot(estate, &scanstate->cstate);
|
|
|
|
ExecInitScanTupleSlot(estate, scanstate);
|
|
|
|
|
2001-03-22 06:16:21 +00:00
|
|
|
/*
|
|
|
|
* initialize scan relation
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
2000-07-12 02:37:39 +00:00
|
|
|
reloid = InitScanRelation(node, estate, scanstate);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
scandesc = scanstate->css_currentScanDesc;
|
|
|
|
scanstate->cstate.cs_TupFromTlist = false;
|
|
|
|
|
2001-03-22 06:16:21 +00:00
|
|
|
/*
|
|
|
|
* initialize tuple type
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
|
|
|
ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
|
|
|
|
ExecAssignProjectionInfo((Plan *) node, &scanstate->cstate);
|
|
|
|
|
|
|
|
return TRUE;
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
1997-09-08 21:56:23 +00:00
|
|
|
ExecCountSlotsSeqScan(SeqScan *node)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
1997-09-07 05:04:48 +00:00
|
|
|
return ExecCountSlotsNode(outerPlan(node)) +
|
2001-10-25 05:50:21 +00:00
|
|
|
ExecCountSlotsNode(innerPlan(node)) +
|
|
|
|
SEQSCAN_NSLOTS;
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------
|
1997-09-07 05:04:48 +00:00
|
|
|
* ExecEndSeqScan
|
|
|
|
*
|
|
|
|
* frees any storage allocated through C routines.
|
1996-07-09 06:22:35 +00:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
void
|
1997-09-08 21:56:23 +00:00
|
|
|
ExecEndSeqScan(SeqScan *node)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
1997-09-07 05:04:48 +00:00
|
|
|
CommonScanState *scanstate;
|
|
|
|
|
2001-03-22 06:16:21 +00:00
|
|
|
/*
|
|
|
|
* get information from node
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
|
|
|
scanstate = node->scanstate;
|
|
|
|
|
2001-03-22 06:16:21 +00:00
|
|
|
/*
|
|
|
|
* Free the projection info and the scan attribute info
|
1997-09-07 05:04:48 +00:00
|
|
|
*
|
2001-03-22 06:16:21 +00:00
|
|
|
* 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
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
|
|
|
ExecFreeProjectionInfo(&scanstate->cstate);
|
2000-07-12 02:37:39 +00:00
|
|
|
ExecFreeExprContext(&scanstate->cstate);
|
1997-09-07 05:04:48 +00:00
|
|
|
|
2001-03-22 06:16:21 +00:00
|
|
|
/*
|
1997-09-07 05:04:48 +00:00
|
|
|
* close scan relation
|
|
|
|
*/
|
|
|
|
ExecCloseR((Plan *) node);
|
|
|
|
|
2001-03-22 06:16:21 +00:00
|
|
|
/*
|
|
|
|
* clean out the tuple table
|
1997-09-07 05:04:48 +00:00
|
|
|
*/
|
|
|
|
ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
|
|
|
|
ExecClearTuple(scanstate->css_ScanTupleSlot);
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------
|
1997-09-07 05:04:48 +00:00
|
|
|
* Join Support
|
1996-07-09 06:22:35 +00:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
2000-07-12 02:37:39 +00:00
|
|
|
|
1996-07-09 06:22:35 +00:00
|
|
|
/* ----------------------------------------------------------------
|
1997-09-07 05:04:48 +00:00
|
|
|
* ExecSeqReScan
|
|
|
|
*
|
|
|
|
* Rescans the relation.
|
1996-07-09 06:22:35 +00:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
void
|
1997-09-08 21:56:23 +00:00
|
|
|
ExecSeqReScan(SeqScan *node, ExprContext *exprCtxt, Plan *parent)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
1997-09-07 05:04:48 +00:00
|
|
|
CommonScanState *scanstate;
|
1997-09-08 02:41:22 +00:00
|
|
|
EState *estate;
|
1998-08-19 02:04:17 +00:00
|
|
|
Relation rel;
|
|
|
|
HeapScanDesc scan;
|
1997-09-08 02:41:22 +00:00
|
|
|
ScanDirection direction;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
scanstate = node->scanstate;
|
|
|
|
estate = node->plan.state;
|
|
|
|
|
2000-07-12 02:37:39 +00:00
|
|
|
/* If this is re-scanning of PlanQual ... */
|
|
|
|
if (estate->es_evTuple != NULL &&
|
|
|
|
estate->es_evTuple[node->scanrelid - 1] != NULL)
|
1997-09-07 05:04:48 +00:00
|
|
|
{
|
2000-07-12 02:37:39 +00:00
|
|
|
estate->es_evTupleNull[node->scanrelid - 1] = false;
|
|
|
|
return;
|
1997-09-07 05:04:48 +00:00
|
|
|
}
|
2000-07-12 02:37:39 +00:00
|
|
|
rel = scanstate->css_currentRelation;
|
|
|
|
scan = scanstate->css_currentScanDesc;
|
|
|
|
direction = estate->es_direction;
|
|
|
|
scan = ExecReScanR(rel, scan, direction, 0, NULL);
|
|
|
|
scanstate->css_currentScanDesc = scan;
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------
|
1997-09-07 05:04:48 +00:00
|
|
|
* ExecSeqMarkPos(node)
|
|
|
|
*
|
|
|
|
* Marks scan position.
|
1996-07-09 06:22:35 +00:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
void
|
1997-09-08 21:56:23 +00:00
|
|
|
ExecSeqMarkPos(SeqScan *node)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
1997-09-07 05:04:48 +00:00
|
|
|
CommonScanState *scanstate;
|
1998-08-19 02:04:17 +00:00
|
|
|
HeapScanDesc scan;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
scanstate = node->scanstate;
|
1998-08-19 02:04:17 +00:00
|
|
|
scan = scanstate->css_currentScanDesc;
|
|
|
|
heap_markpos(scan);
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------------------------------------------------------
|
1997-09-07 05:04:48 +00:00
|
|
|
* ExecSeqRestrPos
|
|
|
|
*
|
|
|
|
* Restores scan position.
|
1996-07-09 06:22:35 +00:00
|
|
|
* ----------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
void
|
1997-09-08 21:56:23 +00:00
|
|
|
ExecSeqRestrPos(SeqScan *node)
|
1996-07-09 06:22:35 +00:00
|
|
|
{
|
1997-09-07 05:04:48 +00:00
|
|
|
CommonScanState *scanstate;
|
1998-08-19 02:04:17 +00:00
|
|
|
HeapScanDesc scan;
|
1997-09-07 05:04:48 +00:00
|
|
|
|
|
|
|
scanstate = node->scanstate;
|
1998-08-19 02:04:17 +00:00
|
|
|
scan = scanstate->css_currentScanDesc;
|
|
|
|
heap_restrpos(scan);
|
1996-07-09 06:22:35 +00:00
|
|
|
}
|