* heap_multi_insert - insert multiple tuples into a relation
* heap_delete - delete a tuple from a relation
* heap_update - replace a tuple in a relation with another tuple
- * heap_markpos - mark scan position
- * heap_restrpos - restore position to marked location
* heap_sync - sync heap, for when no WAL has been written
*
* NOTES
scan->rs_cbuf = InvalidBuffer;
scan->rs_cblock = InvalidBlockNumber;
- /* we don't have a marked position... */
- ItemPointerSetInvalid(&(scan->rs_mctid));
-
/* page-at-a-time fields are always invalid when not rs_inited */
/*
return false;
}
-/* ----------------
- * heap_markpos - mark scan position
- * ----------------
- */
-void
-heap_markpos(HeapScanDesc scan)
-{
- /* Note: no locking manipulations needed */
-
- if (scan->rs_ctup.t_data != NULL)
- {
- scan->rs_mctid = scan->rs_ctup.t_self;
- if (scan->rs_pageatatime)
- scan->rs_mindex = scan->rs_cindex;
- }
- else
- ItemPointerSetInvalid(&scan->rs_mctid);
-}
-
-/* ----------------
- * heap_restrpos - restore position to marked location
- * ----------------
- */
-void
-heap_restrpos(HeapScanDesc scan)
-{
- /* XXX no amrestrpos checking that ammarkpos called */
-
- if (!ItemPointerIsValid(&scan->rs_mctid))
- {
- scan->rs_ctup.t_data = NULL;
-
- /*
- * unpin scan buffers
- */
- if (BufferIsValid(scan->rs_cbuf))
- ReleaseBuffer(scan->rs_cbuf);
- scan->rs_cbuf = InvalidBuffer;
- scan->rs_cblock = InvalidBlockNumber;
- scan->rs_inited = false;
- }
- else
- {
- /*
- * If we reached end of scan, rs_inited will now be false. We must
- * reset it to true to keep heapgettup from doing the wrong thing.
- */
- scan->rs_inited = true;
- scan->rs_ctup.t_self = scan->rs_mctid;
- if (scan->rs_pageatatime)
- {
- scan->rs_cindex = scan->rs_mindex;
- heapgettup_pagemode(scan,
- NoMovementScanDirection,
- 0, /* needn't recheck scan keys */
- NULL);
- }
- else
- heapgettup(scan,
- NoMovementScanDirection,
- 0, /* needn't recheck scan keys */
- NULL);
- }
-}
-
/*
* If 'tuple' contains any visible XID greater than latestRemovedXid,
* ratchet forwards latestRemovedXid to the greatest one found.
* ExecMarkPos
*
* Marks the current scan position.
+ *
+ * NOTE: mark/restore capability is currently needed only for plan nodes
+ * that are the immediate inner child of a MergeJoin node. Since MergeJoin
+ * requires sorted input, there is never any need to support mark/restore in
+ * node types that cannot produce sorted output. There are some cases in
+ * which a node can pass through sorted data from its child; if we don't
+ * implement mark/restore for such a node type, the planner compensates by
+ * inserting a Material node above that node.
*/
void
ExecMarkPos(PlanState *node)
{
switch (nodeTag(node))
{
- case T_SeqScanState:
- ExecSeqMarkPos((SeqScanState *) node);
- break;
-
case T_IndexScanState:
ExecIndexMarkPos((IndexScanState *) node);
break;
ExecIndexOnlyMarkPos((IndexOnlyScanState *) node);
break;
- case T_TidScanState:
- ExecTidMarkPos((TidScanState *) node);
- break;
-
- case T_ValuesScanState:
- ExecValuesMarkPos((ValuesScanState *) node);
- break;
-
case T_CustomScanState:
ExecCustomMarkPos((CustomScanState *) node);
break;
{
switch (nodeTag(node))
{
- case T_SeqScanState:
- ExecSeqRestrPos((SeqScanState *) node);
- break;
-
case T_IndexScanState:
ExecIndexRestrPos((IndexScanState *) node);
break;
ExecIndexOnlyRestrPos((IndexOnlyScanState *) node);
break;
- case T_TidScanState:
- ExecTidRestrPos((TidScanState *) node);
- break;
-
- case T_ValuesScanState:
- ExecValuesRestrPos((ValuesScanState *) node);
- break;
-
case T_CustomScanState:
ExecCustomRestrPos((CustomScanState *) node);
break;
* This is used during planning and so must accept a Path, not a Plan.
* We keep it here to be adjacent to the routines above, which also must
* know which plan types support mark/restore.
- *
- * XXX Ideally, all plan node types would support mark/restore, and this
- * wouldn't be needed. For now, this had better match the routines above.
- *
- * (However, since the only present use of mark/restore is in mergejoin,
- * there is no need to support mark/restore in any plan type that is not
- * capable of generating ordered output. So the seqscan, tidscan,
- * and valuesscan support is actually useless code at present.)
*/
bool
ExecSupportsMarkRestore(Path *pathnode)
*/
switch (pathnode->pathtype)
{
- case T_SeqScan:
case T_IndexScan:
case T_IndexOnlyScan:
- case T_TidScan:
- case T_ValuesScan:
case T_Material:
case T_Sort:
return true;
* Although Result supports mark/restore if it has a child plan
* that does, we presently come here only for ResultPath nodes,
* which represent Result plans without a child plan. So there is
- * nothing to recurse to and we can just say "false".
+ * nothing to recurse to and we can just say "false". (This means
+ * that Result's support for mark/restore is in fact dead code.
+ * We keep it since it's not much code, and someday the planner
+ * might be smart enough to use it. That would require making
+ * this function smarter too, of course.)
*/
Assert(IsA(pathnode, ResultPath));
return false;
* ExecInitSeqScan creates and initializes a seqscan node.
* ExecEndSeqScan releases any storage allocated.
* ExecReScanSeqScan rescans the relation
- * ExecSeqMarkPos marks scan position
- * ExecSeqRestrPos restores scan position
*/
#include "postgres.h"
ExecScanReScan((ScanState *) node);
}
-
-/* ----------------------------------------------------------------
- * ExecSeqMarkPos(node)
- *
- * Marks scan position.
- * ----------------------------------------------------------------
- */
-void
-ExecSeqMarkPos(SeqScanState *node)
-{
- HeapScanDesc scan = node->ss_currentScanDesc;
-
- heap_markpos(scan);
-}
-
-/* ----------------------------------------------------------------
- * ExecSeqRestrPos
- *
- * Restores scan position.
- * ----------------------------------------------------------------
- */
-void
-ExecSeqRestrPos(SeqScanState *node)
-{
- HeapScanDesc scan = node->ss_currentScanDesc;
-
- /*
- * Clear any reference to the previously returned tuple. This is needed
- * because the slot is simply pointing at scan->rs_cbuf, which
- * heap_restrpos will change; we'd have an internally inconsistent slot if
- * we didn't do this.
- */
- ExecClearTuple(node->ss_ScanTupleSlot);
-
- heap_restrpos(scan);
-}
* ExecInitTidScan creates and initializes state info.
* ExecReScanTidScan rescans the tid relation.
* ExecEndTidScan releases all storage.
- * ExecTidMarkPos marks scan position.
- * ExecTidRestrPos restores scan position.
*/
#include "postgres.h"
ExecCloseScanRelation(node->ss.ss_currentRelation);
}
-/* ----------------------------------------------------------------
- * ExecTidMarkPos
- *
- * Marks scan position by marking the current tid.
- * Returns nothing.
- * ----------------------------------------------------------------
- */
-void
-ExecTidMarkPos(TidScanState *node)
-{
- node->tss_MarkTidPtr = node->tss_TidPtr;
-}
-
-/* ----------------------------------------------------------------
- * ExecTidRestrPos
- *
- * Restores scan position by restoring the current tid.
- * Returns nothing.
- *
- * XXX Assumes previously marked scan position belongs to current tid
- * ----------------------------------------------------------------
- */
-void
-ExecTidRestrPos(TidScanState *node)
-{
- node->tss_TidPtr = node->tss_MarkTidPtr;
-}
-
/* ----------------------------------------------------------------
* ExecInitTidScan
*
/*
* Other node-specific setup
*/
- scanstate->marked_idx = -1;
scanstate->curr_idx = -1;
scanstate->array_len = list_length(node->values_lists);
ExecClearTuple(node->ss.ss_ScanTupleSlot);
}
-/* ----------------------------------------------------------------
- * ExecValuesMarkPos
- *
- * Marks scan position.
- * ----------------------------------------------------------------
- */
-void
-ExecValuesMarkPos(ValuesScanState *node)
-{
- node->marked_idx = node->curr_idx;
-}
-
-/* ----------------------------------------------------------------
- * ExecValuesRestrPos
- *
- * Restores scan position.
- * ----------------------------------------------------------------
- */
-void
-ExecValuesRestrPos(ValuesScanState *node)
-{
- node->curr_idx = node->marked_idx;
-}
-
/* ----------------------------------------------------------------
* ExecReScanValuesScan
*
extern void simple_heap_update(Relation relation, ItemPointer otid,
HeapTuple tup);
-extern void heap_markpos(HeapScanDesc scan);
-extern void heap_restrpos(HeapScanDesc scan);
-
extern void heap_sync(Relation relation);
/* in heap/pruneheap.c */
BlockNumber rs_cblock; /* current block # in scan, if any */
Buffer rs_cbuf; /* current buffer in scan, if any */
/* NB: if rs_cbuf is not InvalidBuffer, we hold a pin on that buffer */
- ItemPointerData rs_mctid; /* marked scan position, if any */
/* these fields only used in page-at-a-time mode and for bitmap scans */
int rs_cindex; /* current tuple's index in vistuples */
- int rs_mindex; /* marked tuple's saved index */
int rs_ntuples; /* number of visible tuples on page */
OffsetNumber rs_vistuples[MaxHeapTuplesPerPage]; /* their offsets */
} HeapScanDescData;
extern SeqScanState *ExecInitSeqScan(SeqScan *node, EState *estate, int eflags);
extern TupleTableSlot *ExecSeqScan(SeqScanState *node);
extern void ExecEndSeqScan(SeqScanState *node);
-extern void ExecSeqMarkPos(SeqScanState *node);
-extern void ExecSeqRestrPos(SeqScanState *node);
extern void ExecReScanSeqScan(SeqScanState *node);
#endif /* NODESEQSCAN_H */
extern TidScanState *ExecInitTidScan(TidScan *node, EState *estate, int eflags);
extern TupleTableSlot *ExecTidScan(TidScanState *node);
extern void ExecEndTidScan(TidScanState *node);
-extern void ExecTidMarkPos(TidScanState *node);
-extern void ExecTidRestrPos(TidScanState *node);
extern void ExecReScanTidScan(TidScanState *node);
#endif /* NODETIDSCAN_H */
extern ValuesScanState *ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags);
extern TupleTableSlot *ExecValuesScan(ValuesScanState *node);
extern void ExecEndValuesScan(ValuesScanState *node);
-extern void ExecValuesMarkPos(ValuesScanState *node);
-extern void ExecValuesRestrPos(ValuesScanState *node);
extern void ExecReScanValuesScan(ValuesScanState *node);
#endif /* NODEVALUESSCAN_H */
bool tss_isCurrentOf;
int tss_NumTids;
int tss_TidPtr;
- int tss_MarkTidPtr;
ItemPointerData *tss_TidList;
HeapTupleData tss_htup;
} TidScanState;
* exprlists array of expression lists being evaluated
* array_len size of array
* curr_idx current array index (0-based)
- * marked_idx marked position (for mark/restore)
*
* Note: ss.ps.ps_ExprContext is used to evaluate any qual or projection
* expressions attached to the node. We create a second ExprContext,
List **exprlists;
int array_len;
int curr_idx;
- int marked_idx;
} ValuesScanState;
/* ----------------