aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeIndexscan.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2000-07-12 02:37:39 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2000-07-12 02:37:39 +0000
commitbadce86a2c327b40c6146242526d1523455d64a6 (patch)
tree6e0cb658889a2688e76d9ac19a56555c5eb0e738 /src/backend/executor/nodeIndexscan.c
parent46fb9c29e2990ba470bb741ff6dd60f2ae218e64 (diff)
downloadpostgresql-badce86a2c327b40c6146242526d1523455d64a6.tar.gz
postgresql-badce86a2c327b40c6146242526d1523455d64a6.zip
First stage of reclaiming memory in executor by resetting short-term
memory contexts. Currently, only leaks in expressions executed as quals or projections are handled. Clean up some old dead cruft in executor while at it --- unused fields in state nodes, that sort of thing.
Diffstat (limited to 'src/backend/executor/nodeIndexscan.c')
-rw-r--r--src/backend/executor/nodeIndexscan.c182
1 files changed, 91 insertions, 91 deletions
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index be5617d5ef4..0eb3b9f5ae9 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.51 2000/06/15 04:09:52 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.52 2000/07/12 02:37:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -79,6 +79,7 @@ IndexNext(IndexScan *node)
EState *estate;
CommonScanState *scanstate;
IndexScanState *indexstate;
+ ExprContext *econtext;
ScanDirection direction;
Snapshot snapshot;
IndexScanDescPtr scanDescs;
@@ -89,7 +90,6 @@ IndexNext(IndexScan *node)
TupleTableSlot *slot;
Buffer buffer = InvalidBuffer;
int numIndices;
-
bool bBackward;
int indexNumber;
@@ -112,6 +112,7 @@ IndexNext(IndexScan *node)
scanDescs = indexstate->iss_ScanDescs;
heapRelation = scanstate->css_currentRelation;
numIndices = indexstate->iss_NumIndices;
+ econtext = scanstate->cstate.cs_ExprContext;
slot = scanstate->css_ScanTupleSlot;
/*
@@ -133,14 +134,15 @@ IndexNext(IndexScan *node)
slot->val = estate->es_evTuple[node->scan.scanrelid - 1];
slot->ttc_shouldFree = false;
- scanstate->cstate.cs_ExprContext->ecxt_scantuple = slot;
+ econtext->ecxt_scantuple = slot;
/* Does the tuple meet any of the OR'd indxqual conditions? */
+
+ ResetExprContext(econtext);
+
foreach(qual, node->indxqualorig)
{
- if (ExecQual((List *) lfirst(qual),
- scanstate->cstate.cs_ExprContext,
- false))
+ if (ExecQual((List *) lfirst(qual), econtext, false))
break;
}
if (qual == NIL) /* would not be returned by indices */
@@ -219,14 +221,13 @@ IndexNext(IndexScan *node)
* and checking for failure with all previous
* qualifications.
*/
- scanstate->cstate.cs_ExprContext->ecxt_scantuple = slot;
+ econtext->ecxt_scantuple = slot;
+ ResetExprContext(econtext);
qual = node->indxqualorig;
for (prev_index = 0; prev_index < indexstate->iss_IndexPtr;
prev_index++)
{
- if (ExecQual((List *) lfirst(qual),
- scanstate->cstate.cs_ExprContext,
- false))
+ if (ExecQual((List *) lfirst(qual), econtext, false))
{
prev_matches = true;
break;
@@ -234,7 +235,7 @@ IndexNext(IndexScan *node)
qual = lnext(qual);
}
if (!prev_matches)
- return slot;/* OK to return tuple */
+ return slot; /* OK to return tuple */
/* Duplicate tuple, so drop it and loop back for another */
ExecClearTuple(slot);
}
@@ -284,7 +285,7 @@ ExecIndexScan(IndexScan *node)
* use IndexNext as access method
* ----------------
*/
- return ExecScan(&node->scan, IndexNext);
+ return ExecScan(&node->scan, (ExecScanAccessMtd) IndexNext);
}
/* ----------------------------------------------------------------
@@ -293,9 +294,8 @@ ExecIndexScan(IndexScan *node)
* Recalculates the value of the scan keys whose value depends on
* information known at runtime and rescans the indexed relation.
* Updating the scan key was formerly done separately in
- * ExecUpdateIndexScanKeys. Integrating it into ReScan
- * makes rescans of indices and
- * relations/general streams more uniform.
+ * ExecUpdateIndexScanKeys. Integrating it into ReScan makes
+ * rescans of indices and relations/general streams more uniform.
*
* ----------------------------------------------------------------
*/
@@ -304,6 +304,7 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
{
EState *estate;
IndexScanState *indexstate;
+ ExprContext *econtext;
ScanDirection direction;
IndexScanDescPtr scanDescs;
ScanKey *scanKeys;
@@ -311,8 +312,7 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
ScanKey skey;
int numIndices;
int i;
-
- Pointer *runtimeKeyInfo;
+ int **runtimeKeyInfo;
int *numScanKeys;
List *indxqual;
List *qual;
@@ -326,22 +326,34 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
bool isNull;
bool isDone;
- indexstate = node->indxstate;
estate = node->scan.plan.state;
+ indexstate = node->indxstate;
+ econtext = indexstate->iss_RuntimeContext; /* context for runtime keys */
direction = estate->es_direction;
numIndices = indexstate->iss_NumIndices;
scanDescs = indexstate->iss_ScanDescs;
scanKeys = indexstate->iss_ScanKeys;
- runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
+ runtimeKeyInfo = indexstate->iss_RuntimeKeyInfo;
numScanKeys = indexstate->iss_NumScanKeys;
indexstate->iss_IndexPtr = -1;
if (ScanDirectionIsBackward(node->indxorderdir))
indexstate->iss_IndexPtr = numIndices;
- /* 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;
+ if (econtext)
+ {
+ /*
+ * If we are being passed an outer tuple,
+ * save it for runtime key calc
+ */
+ if (exprCtxt != NULL)
+ econtext->ecxt_outertuple = exprCtxt->ecxt_outertuple;
+ /*
+ * Reset the runtime-key context so we don't leak memory as
+ * each outer tuple is scanned. Note this assumes that we
+ * will recalculate *all* runtime keys on each call.
+ */
+ ResetExprContext(econtext);
+ }
/* If this is re-scanning of PlanQual ... */
if (estate->es_evTuple != NULL &&
@@ -364,7 +376,7 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
if (runtimeKeyInfo)
{
- run_keys = (int *) runtimeKeyInfo[i];
+ run_keys = runtimeKeyInfo[i];
for (j = 0; j < n_keys; j++)
{
@@ -373,6 +385,13 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
* expression and evaluate it with respect to the current
* outer tuple. We then stick the result into the scan
* key.
+ *
+ * Note: the result of the eval could be a pass-by-ref
+ * value that's stored in the outer scan's tuple, not in
+ * econtext->ecxt_per_tuple_memory. We assume that the
+ * outer tuple will stay put throughout our scan. If this
+ * is wrong, we could copy the result into our context
+ * explicitly, but I think that's not necessary...
*/
if (run_keys[j] != NO_OP)
{
@@ -385,10 +404,10 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
* pass in isDone but ignore it. We don't iterate in
* quals
*/
- scanvalue = (Datum)
- ExecEvalExpr(scanexpr,
- node->scan.scanstate->cstate.cs_ExprContext,
- &isNull, &isDone);
+ scanvalue = ExecEvalExprSwitchContext(scanexpr,
+ econtext,
+ &isNull,
+ &isDone);
scan_keys[j].sk_argument = scanvalue;
if (isNull)
scan_keys[j].sk_flags |= SK_ISNULL;
@@ -401,11 +420,6 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
skey = scanKeys[i];
index_rescan(scan, direction, skey);
}
- /* ----------------
- * perhaps return something meaningful
- * ----------------
- */
- return;
}
/* ----------------------------------------------------------------
@@ -421,7 +435,7 @@ ExecEndIndexScan(IndexScan *node)
{
CommonScanState *scanstate;
IndexScanState *indexstate;
- Pointer *runtimeKeyInfo;
+ int **runtimeKeyInfo;
ScanKey *scanKeys;
List *indxqual;
int *numScanKeys;
@@ -431,7 +445,7 @@ ExecEndIndexScan(IndexScan *node)
scanstate = node->scan.scanstate;
indexstate = node->indxstate;
indxqual = node->indxqual;
- runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
+ runtimeKeyInfo = indexstate->iss_RuntimeKeyInfo;
/* ----------------
* extract information from the node
@@ -451,6 +465,9 @@ ExecEndIndexScan(IndexScan *node)
* ----------------
*/
ExecFreeProjectionInfo(&scanstate->cstate);
+ ExecFreeExprContext(&scanstate->cstate);
+ if (indexstate->iss_RuntimeContext)
+ FreeExprContext(indexstate->iss_RuntimeContext);
/* ----------------
* close the heap and index relations
@@ -474,12 +491,7 @@ ExecEndIndexScan(IndexScan *node)
{
for (i = 0; i < numIndices; i++)
{
- List *qual;
- int n_keys;
-
- qual = nth(i, indxqual);
- n_keys = length(qual);
- if (n_keys > 0)
+ if (runtimeKeyInfo[i] != NULL)
pfree(runtimeKeyInfo[i]);
}
pfree(runtimeKeyInfo);
@@ -491,7 +503,6 @@ ExecEndIndexScan(IndexScan *node)
*/
ExecClearTuple(scanstate->cstate.cs_ResultTupleSlot);
ExecClearTuple(scanstate->css_ScanTupleSlot);
-/* ExecClearTuple(scanstate->css_RawTupleSlot); */
}
/* ----------------------------------------------------------------
@@ -562,7 +573,7 @@ ExecIndexRestrPos(IndexScan *node)
*
* old comments
* Creates the run-time state information for the node and
- * sets the relation id to contain relevant decriptors.
+ * sets the relation id to contain relevant descriptors.
*
* Parameters:
* node: IndexNode node produced by the planner.
@@ -583,19 +594,16 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
int *numScanKeys;
RelationPtr relationDescs;
IndexScanDescPtr scanDescs;
- Pointer *runtimeKeyInfo;
+ int **runtimeKeyInfo;
bool have_runtime_keys;
List *rangeTable;
RangeTblEntry *rtentry;
Index relid;
Oid reloid;
-
Relation currentRelation;
HeapScanDesc currentScanDesc;
ScanDirection direction;
- int baseid;
-
- List *execParam = NULL;
+ List *execParam = NIL;
/* ----------------
* assign execution state to node
@@ -610,25 +618,12 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
* --------------------------------
*/
scanstate = makeNode(CommonScanState);
-/*
- scanstate->ss_ProcOuterFlag = false;
- scanstate->ss_OldRelId = 0;
-*/
-
node->scan.scanstate = scanstate;
/* ----------------
- * assign node's base_id .. we don't use AssignNodeBaseid() because
- * the increment is done later on after we assign the index scan's
- * scanstate. see below.
- * ----------------
- */
- baseid = estate->es_BaseId;
-/* scanstate->csstate.cstate.bnode.base_id = baseid; */
- scanstate->cstate.cs_base_id = baseid;
-
- /* ----------------
- * create expression context for node
+ * Miscellaneous initialization
+ *
+ * + create expression context for node
* ----------------
*/
ExecAssignExprContext(estate, &scanstate->cstate);
@@ -640,7 +635,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
*/
ExecInitResultTupleSlot(estate, &scanstate->cstate);
ExecInitScanTupleSlot(estate, scanstate);
-/* ExecInitRawTupleSlot(estate, scanstate); */
/* ----------------
* initialize projection info. result type comes from scan desc
@@ -661,20 +655,13 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
indexstate->iss_ScanKeys = NULL;
indexstate->iss_NumScanKeys = NULL;
indexstate->iss_RuntimeKeyInfo = NULL;
+ indexstate->iss_RuntimeContext = NULL;
indexstate->iss_RelationDescs = NULL;
indexstate->iss_ScanDescs = NULL;
node->indxstate = indexstate;
/* ----------------
- * assign base id to index scan state also
- * ----------------
- */
- indexstate->cstate.cs_base_id = baseid;
- baseid++;
- estate->es_BaseId = baseid;
-
- /* ----------------
* get the index node information
* ----------------
*/
@@ -696,12 +683,11 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
scanDescs = (IndexScanDescPtr) palloc(numIndices * sizeof(IndexScanDesc));
/* ----------------
- * initialize runtime key info.
+ * initialize space for runtime key info (may not be needed)
* ----------------
*/
have_runtime_keys = false;
- runtimeKeyInfo = (Pointer *)
- palloc(numIndices * sizeof(Pointer));
+ runtimeKeyInfo = (int **) palloc(numIndices * sizeof(int *));
/* ----------------
* build the index scan keys from the index qualification
@@ -719,9 +705,9 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
qual = lfirst(indxqual);
indxqual = lnext(indxqual);
n_keys = length(qual);
- scan_keys = (n_keys <= 0) ? NULL :
+ scan_keys = (n_keys <= 0) ? (ScanKey) NULL :
(ScanKey) palloc(n_keys * sizeof(ScanKeyData));
- run_keys = (n_keys <= 0) ? NULL :
+ run_keys = (n_keys <= 0) ? (int *) NULL :
(int *) palloc(n_keys * sizeof(int));
CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);
@@ -966,12 +952,12 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
}
/* ----------------
- * store the key information into our array.
+ * store the key information into our arrays.
* ----------------
*/
numScanKeys[i] = n_keys;
scanKeys[i] = scan_keys;
- runtimeKeyInfo[i] = (Pointer) run_keys;
+ runtimeKeyInfo[i] = run_keys;
}
indexstate->iss_NumIndices = numIndices;
@@ -988,12 +974,35 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
* (one for each index) to arrays of flags (one for each key)
* which indicate that the qual needs to be evaluated at runtime.
* -cim 10/24/89
+ *
+ * If we do have runtime keys, we need an ExprContext to evaluate them;
+ * the node's standard context won't do because we want to reset that
+ * context for every tuple. So, build another context just like the
+ * other one...
+ * -tgl 7/11/00
* ----------------
*/
if (have_runtime_keys)
- indexstate->iss_RuntimeKeyInfo = (Pointer) runtimeKeyInfo;
+ {
+ ExprContext *stdecontext = scanstate->cstate.cs_ExprContext;
+
+ ExecAssignExprContext(estate, &scanstate->cstate);
+ indexstate->iss_RuntimeKeyInfo = runtimeKeyInfo;
+ indexstate->iss_RuntimeContext = scanstate->cstate.cs_ExprContext;
+ scanstate->cstate.cs_ExprContext = stdecontext;
+ }
else
+ {
indexstate->iss_RuntimeKeyInfo = NULL;
+ indexstate->iss_RuntimeContext = NULL;
+ /* Get rid of the speculatively-allocated flag arrays, too */
+ for (i = 0; i < numIndices; i++)
+ {
+ if (runtimeKeyInfo[i] != NULL)
+ pfree(runtimeKeyInfo[i]);
+ }
+ pfree(runtimeKeyInfo);
+ }
/* ----------------
* get the range table and direction information
@@ -1026,7 +1035,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
scanstate->css_currentRelation = currentRelation;
scanstate->css_currentScanDesc = currentScanDesc;
-
/* ----------------
* get the scan type from the relation descriptor.
* ----------------
@@ -1035,12 +1043,6 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
ExecAssignResultTypeFromTL((Plan *) node, &scanstate->cstate);
/* ----------------
- * index scans don't have subtrees..
- * ----------------
- */
-/* scanstate->ss_ProcOuterFlag = false; */
-
- /* ----------------
* open the index relations and initialize
* relation and scan descriptors.
* ----------------
@@ -1066,10 +1068,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
indexstate->iss_RelationDescs = relationDescs;
indexstate->iss_ScanDescs = scanDescs;
- indexstate->cstate.cs_TupFromTlist = false;
-
/*
- * if there are some PARAM_EXEC in skankeys then force index rescan on
+ * if there are some PARAM_EXEC in scankeys then force index rescan on
* first scan.
*/
((Plan *) node)->chgParam = execParam;