1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-08 11:42:09 +03:00

Revise executor APIs so that all per-query state structure is built in

a per-query memory context created by CreateExecutorState --- and destroyed
by FreeExecutorState.  This provides a final solution to the longstanding
problem of memory leaked by various ExecEndNode calls.
This commit is contained in:
Tom Lane
2002-12-15 16:17:59 +00:00
parent 90b3a0b6fd
commit 5bab36e9f6
42 changed files with 806 additions and 547 deletions

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.186 2002/12/13 19:45:48 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.187 2002/12/15 16:17:38 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -35,7 +35,6 @@
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "optimizer/planmain.h"
#include "parser/parse_coerce.h"
#include "parser/parse_relation.h"
#include "rewrite/rewriteHandler.h"
@ -803,6 +802,8 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
slot = ExecAllocTableSlot(tupleTable);
ExecSetSlotDescriptor(slot, tupDesc, false);
econtext = GetPerTupleExprContext(estate);
/*
* Pick up the required catalog information for each attribute in the
* relation, including the input function, the element type (to pass
@ -841,8 +842,8 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
if (defexpr != NULL)
{
fix_opfuncids(defexpr);
defexprs[num_defaults] = ExecInitExpr((Expr *) defexpr, NULL);
defexprs[num_defaults] = ExecPrepareExpr((Expr *) defexpr,
estate);
defmap[num_defaults] = i;
num_defaults++;
}
@ -873,8 +874,8 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
/* check whether any constraints actually found */
if (node != (Node *) prm)
{
fix_opfuncids(node);
constraintexprs[i] = ExecInitExpr((Expr *) node, NULL);
constraintexprs[i] = ExecPrepareExpr((Expr *) node,
estate);
hasConstraints = true;
}
}
@ -934,8 +935,6 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
copy_lineno = 0;
fe_eof = false;
econtext = GetPerTupleExprContext(estate);
/* Make room for a PARAM_EXEC value for domain constraint checks */
if (hasConstraints)
econtext->ecxt_param_exec_vals = (ParamExecData *)
@ -953,9 +952,8 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
/* Reset the per-tuple exprcontext */
ResetPerTupleExprContext(estate);
/* Switch to and reset per-tuple memory context, too */
/* Switch into its memory context */
MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
MemoryContextReset(CurrentMemoryContext);
/* Initialize all values for row to NULL */
MemSet(values, 0, num_phys_attrs * sizeof(Datum));
@ -1268,6 +1266,8 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
ExecDropTupleTable(tupleTable, true);
ExecCloseIndices(resultRelInfo);
FreeExecutorState(estate);
}

View File

@ -5,7 +5,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994-5, Regents of the University of California
*
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.98 2002/12/14 00:17:50 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.99 2002/12/15 16:17:38 tgl Exp $
*
*/
@ -206,6 +206,8 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
gettimeofday(&starttime, NULL);
ExecutorEnd(queryDesc);
FreeQueryDesc(queryDesc);
CommandCounterIncrement();
totaltime += elapsed_time(&starttime);

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.94 2002/12/13 19:45:50 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.95 2002/12/15 16:17:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -27,7 +27,6 @@
#include "executor/executor.h"
#include "miscadmin.h"
#include "optimizer/clauses.h"
#include "optimizer/planmain.h"
#include "optimizer/prep.h"
#include "parser/parsetree.h"
#include "parser/parse_coerce.h"
@ -163,7 +162,6 @@ DefineIndex(RangeVar *heapRelation,
if (predicate)
{
cnfPred = canonicalize_qual((Expr *) copyObject(predicate), true);
fix_opfuncids((Node *) cnfPred);
CheckPredicate(cnfPred, rangetable, relationId);
}
@ -173,8 +171,7 @@ DefineIndex(RangeVar *heapRelation,
*/
indexInfo = makeNode(IndexInfo);
indexInfo->ii_Predicate = cnfPred;
indexInfo->ii_PredicateState = (List *)
ExecInitExpr((Expr *) cnfPred, NULL);
indexInfo->ii_PredicateState = NIL;
indexInfo->ii_FuncOid = InvalidOid;
indexInfo->ii_Unique = unique;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.5 2002/12/05 15:50:30 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.6 2002/12/15 16:17:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -31,28 +31,22 @@
void
PortalCleanup(Portal portal)
{
MemoryContext oldcontext;
/*
* sanity checks
*/
AssertArg(PortalIsValid(portal));
AssertArg(portal->cleanup == PortalCleanup);
/*
* set proper portal-executor context before calling ExecMain.
*/
oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
/*
* tell the executor to shutdown the query
*/
ExecutorEnd(PortalGetQueryDesc(portal));
/*
* switch back to previous context
* This should be unnecessary since the querydesc should be in the
* portal's memory context, but do it anyway for symmetry.
*/
MemoryContextSwitchTo(oldcontext);
FreeQueryDesc(PortalGetQueryDesc(portal));
}

View File

@ -6,7 +6,7 @@
* Copyright (c) 2002, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.10 2002/12/13 19:45:51 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/prepare.c,v 1.11 2002/12/15 16:17:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -15,7 +15,6 @@
#include "commands/prepare.h"
#include "executor/executor.h"
#include "utils/guc.h"
#include "optimizer/planmain.h"
#include "optimizer/planner.h"
#include "rewrite/rewriteHandler.h"
#include "tcop/pquery.h"
@ -50,7 +49,6 @@ static void InitQueryHashTable(void);
static void StoreQuery(const char *stmt_name, List *query_list,
List *plan_list, List *argtype_list);
static QueryHashEntry *FetchQuery(const char *plan_name);
static void RunQuery(QueryDesc *qdesc);
/*
@ -96,33 +94,37 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
*query_list,
*plan_list;
ParamListInfo paramLI = NULL;
EState *estate;
/* Look it up in the hash table */
entry = FetchQuery(stmt->name);
/* Make working copies the executor can safely scribble on */
query_list = (List *) copyObject(entry->query_list);
plan_list = (List *) copyObject(entry->plan_list);
query_list = entry->query_list;
plan_list = entry->plan_list;
Assert(length(query_list) == length(plan_list));
/*
* Need an EState to evaluate parameters; must not delete it till end
* of query, in case parameters are pass-by-reference.
*/
estate = CreateExecutorState();
/* Evaluate parameters, if any */
if (entry->argtype_list != NIL)
{
int nargs = length(entry->argtype_list);
int i = 0;
List *exprstates;
ExprContext *econtext = MakeExprContext(NULL, CurrentMemoryContext);
/* Parser should have caught this error, but check */
if (nargs != length(stmt->params))
elog(ERROR, "ExecuteQuery: wrong number of arguments");
fix_opfuncids((Node *) stmt->params);
exprstates = (List *) ExecPrepareExpr((Expr *) stmt->params, estate);
exprstates = (List *) ExecInitExpr((Expr *) stmt->params, NULL);
paramLI = (ParamListInfo) palloc0((nargs + 1) * sizeof(ParamListInfoData));
paramLI = (ParamListInfo)
palloc0((nargs + 1) * sizeof(ParamListInfoData));
foreach(l, exprstates)
{
@ -130,7 +132,7 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
bool isNull;
paramLI[i].value = ExecEvalExprSwitchContext(n,
econtext,
GetPerTupleExprContext(estate),
&isNull,
NULL);
paramLI[i].kind = PARAM_NUM;
@ -173,7 +175,13 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
qdesc->dest = None;
}
RunQuery(qdesc);
ExecutorStart(qdesc);
ExecutorRun(qdesc, ForwardScanDirection, 0L);
ExecutorEnd(qdesc);
FreeQueryDesc(qdesc);
if (log_executor_stats)
ShowUsage("EXECUTOR STATISTICS");
@ -188,7 +196,9 @@ ExecuteQuery(ExecuteStmt *stmt, CommandDest outputDest)
CommandCounterIncrement();
}
/* No need to pfree memory, MemoryContext will be reset */
FreeExecutorState(estate);
/* No need to pfree other memory, MemoryContext will be reset */
}
/*
@ -333,17 +343,6 @@ FetchQueryParams(const char *plan_name)
return entry->argtype_list;
}
/*
* Actually execute a prepared query.
*/
static void
RunQuery(QueryDesc *qdesc)
{
ExecutorStart(qdesc);
ExecutorRun(qdesc, ForwardScanDirection, 0L);
ExecutorEnd(qdesc);
}
/*
* Implements the 'DEALLOCATE' utility statement: deletes the
* specified plan from storage.

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.60 2002/12/13 19:45:51 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.61 2002/12/15 16:17:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -37,7 +37,6 @@
#include "nodes/makefuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/plancat.h"
#include "optimizer/planmain.h"
#include "optimizer/prep.h"
#include "parser/gramparse.h"
#include "parser/parse_coerce.h"
@ -2713,6 +2712,7 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr)
ParseState *pstate;
bool successful = true;
HeapScanDesc scan;
EState *estate;
ExprContext *econtext;
TupleTableSlot *slot;
HeapTuple tuple;
@ -2723,9 +2723,7 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr)
/*
* We need to make a parse state and range
* table to allow us to transformExpr and
* fix_opfuncids to get a version of the
* expression we can pass to ExecQual
* table to allow us to do transformExpr()
*/
pstate = make_parsestate(NULL);
rte = addRangeTableEntryForRelation(pstate,
@ -2765,19 +2763,22 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr)
*/
expr = eval_const_expressions(expr);
/* And fix the opfuncids */
fix_opfuncids(expr);
/* Needs to be in implicit-ANDs form for ExecQual */
qual = make_ands_implicit((Expr *) expr);
qual = makeList1(expr);
/* Need an EState to run ExecQual */
estate = CreateExecutorState();
econtext = GetPerTupleExprContext(estate);
/* build execution state for qual */
qualstate = (List *) ExecInitExpr((Expr *) qual, NULL);
qualstate = (List *) ExecPrepareExpr((Expr *) qual, estate);
/* Make tuple slot to hold tuples */
slot = MakeTupleTableSlot();
ExecSetSlotDescriptor(slot, RelationGetDescr(rel), false);
/* Make an expression context for ExecQual */
econtext = MakeExprContext(slot, CurrentMemoryContext);
/* Arrange for econtext's scan tuple to be the tuple under test */
econtext->ecxt_scantuple = slot;
/*
* Scan through the rows now, checking the expression at each row.
@ -2797,8 +2798,8 @@ AlterTableAddCheckConstraint(Relation rel, Constraint *constr)
heap_endscan(scan);
FreeExprContext(econtext);
pfree(slot);
FreeExecutorState(estate);
if (!successful)
elog(ERROR, "AlterTableAddConstraint: rejected due to CHECK constraint %s",

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.24 2002/12/13 19:45:52 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.25 2002/12/15 16:17:43 tgl Exp $
*
* DESCRIPTION
* The "DefineFoo" routines take the parse tree and pick out the
@ -47,7 +47,6 @@
#include "miscadmin.h"
#include "nodes/nodes.h"
#include "optimizer/clauses.h"
#include "optimizer/planmain.h"
#include "optimizer/var.h"
#include "parser/parse_coerce.h"
#include "parser/parse_expr.h"
@ -1242,6 +1241,7 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
List *rels;
List *rt;
Form_pg_type typTup;
EState *estate;
ExprContext *econtext;
char *ccbin;
Expr *expr;
@ -1338,11 +1338,13 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
* the constraint is being added to.
*/
expr = (Expr *) stringToNode(ccbin);
fix_opfuncids((Node *) expr);
exprstate = ExecInitExpr(expr, NULL);
/* Make an expression context for ExecEvalExpr */
econtext = MakeExprContext(NULL, CurrentMemoryContext);
/* Need an EState to run ExecEvalExpr */
estate = CreateExecutorState();
econtext = GetPerTupleExprContext(estate);
/* build execution state for expr */
exprstate = ExecPrepareExpr(expr, estate);
rels = get_rels_with_domain(domainoid);
@ -1377,7 +1379,9 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
econtext->domainValue_datum = d;
econtext->domainValue_isNull = isNull;
conResult = ExecEvalExpr(exprstate, econtext, &isNull, NULL);
conResult = ExecEvalExprSwitchContext(exprstate,
econtext,
&isNull, NULL);
if (!isNull && !DatumGetBool(conResult))
elog(ERROR, "AlterDomainAddConstraint: Domain %s constraint %s failed",
@ -1393,7 +1397,7 @@ AlterDomainAddConstraint(List *names, Node *newConstraint)
heap_close(testrel, NoLock);
}
FreeExprContext(econtext);
FreeExecutorState(estate);
/* Clean up */
heap_close(rel, NoLock);

View File

@ -13,7 +13,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.244 2002/10/31 19:25:29 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/vacuum.c,v 1.245 2002/12/15 16:17:44 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1437,6 +1437,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
* We need a ResultRelInfo and an EState so we can use the regular
* executor's index-entry-making machinery.
*/
estate = CreateExecutorState();
resultRelInfo = makeNode(ResultRelInfo);
resultRelInfo->ri_RangeTableIndex = 1; /* dummy */
resultRelInfo->ri_RelationDesc = onerel;
@ -1444,7 +1446,6 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
ExecOpenIndices(resultRelInfo);
estate = CreateExecutorState();
estate->es_result_relations = resultRelInfo;
estate->es_num_result_relations = 1;
estate->es_result_relation_info = resultRelInfo;
@ -2484,6 +2485,8 @@ repair_frag(VRelStats *vacrelstats, Relation onerel,
ExecDropTupleTable(tupleTable, true);
ExecCloseIndices(resultRelInfo);
FreeExecutorState(estate);
}
/*