Commit 9cbd0c15 authored by Tom Lane's avatar Tom Lane

Remove the Query structure from the executor's API. This allows us to stop

storing mostly-redundant Query trees in prepared statements, portals, etc.
To replace Query, a new node type called PlannedStmt is inserted by the
planner at the top of a completed plan tree; this carries just the fields of
Query that are still needed at runtime.  The statement lists kept in portals
etc. now consist of intermixed PlannedStmt and bare utility-statement nodes
--- no Query.  This incidentally allows us to remove some fields from Query
and Plan nodes that shouldn't have been there in the first place.

Still to do: simplify the execution-time range table; at the moment the
range table passed to the executor still contains Query trees for subqueries.

initdb forced due to change of stored rules.
parent 71b0cf2f
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.275 2007/01/25 02:17:26 momjian Exp $ * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.276 2007/02/20 17:32:13 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -986,10 +986,11 @@ DoCopy(const CopyStmt *stmt) ...@@ -986,10 +986,11 @@ DoCopy(const CopyStmt *stmt)
{ {
Query *query = stmt->query; Query *query = stmt->query;
List *rewritten; List *rewritten;
Plan *plan; PlannedStmt *plan;
DestReceiver *dest; DestReceiver *dest;
Assert(query); Assert(query);
Assert(query->commandType == CMD_SELECT);
Assert(!is_from); Assert(!is_from);
cstate->rel = NULL; cstate->rel = NULL;
...@@ -999,6 +1000,7 @@ DoCopy(const CopyStmt *stmt) ...@@ -999,6 +1000,7 @@ DoCopy(const CopyStmt *stmt)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("COPY (SELECT) WITH OIDS is not supported"))); errmsg("COPY (SELECT) WITH OIDS is not supported")));
/* Query mustn't use INTO, either */
if (query->into) if (query->into)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
...@@ -1016,7 +1018,6 @@ DoCopy(const CopyStmt *stmt) ...@@ -1016,7 +1018,6 @@ DoCopy(const CopyStmt *stmt)
* shouldn't modify its input ... FIXME someday. * shouldn't modify its input ... FIXME someday.
*/ */
query = copyObject(query); query = copyObject(query);
Assert(query->commandType == CMD_SELECT);
/* /*
* Must acquire locks in case we didn't come fresh from the parser. * Must acquire locks in case we didn't come fresh from the parser.
...@@ -1051,7 +1052,7 @@ DoCopy(const CopyStmt *stmt) ...@@ -1051,7 +1052,7 @@ DoCopy(const CopyStmt *stmt)
((DR_copy *) dest)->cstate = cstate; ((DR_copy *) dest)->cstate = cstate;
/* Create a QueryDesc requesting no output */ /* Create a QueryDesc requesting no output */
cstate->queryDesc = CreateQueryDesc(query, plan, cstate->queryDesc = CreateQueryDesc(plan,
ActiveSnapshot, InvalidSnapshot, ActiveSnapshot, InvalidSnapshot,
dest, NULL, false); dest, NULL, false);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994-5, Regents of the University of California * Portions Copyright (c) 1994-5, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.155 2007/02/19 02:23:11 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/explain.c,v 1.156 2007/02/20 17:32:14 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -149,7 +149,7 @@ static void ...@@ -149,7 +149,7 @@ static void
ExplainOneQuery(Query *query, ExplainStmt *stmt, ParamListInfo params, ExplainOneQuery(Query *query, ExplainStmt *stmt, ParamListInfo params,
TupOutputState *tstate) TupOutputState *tstate)
{ {
Plan *plan; PlannedStmt *plan;
QueryDesc *queryDesc; QueryDesc *queryDesc;
bool isCursor = false; bool isCursor = false;
int cursorOptions = 0; int cursorOptions = 0;
...@@ -203,7 +203,7 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, ParamListInfo params, ...@@ -203,7 +203,7 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, ParamListInfo params,
ActiveSnapshot->curcid = GetCurrentCommandId(); ActiveSnapshot->curcid = GetCurrentCommandId();
/* Create a QueryDesc requesting no output */ /* Create a QueryDesc requesting no output */
queryDesc = CreateQueryDesc(query, plan, queryDesc = CreateQueryDesc(plan,
ActiveSnapshot, InvalidSnapshot, ActiveSnapshot, InvalidSnapshot,
None_Receiver, params, None_Receiver, params,
stmt->analyze); stmt->analyze);
...@@ -260,14 +260,14 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt, ...@@ -260,14 +260,14 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
es->printNodes = stmt->verbose; es->printNodes = stmt->verbose;
es->printAnalyze = stmt->analyze; es->printAnalyze = stmt->analyze;
es->rtable = queryDesc->parsetree->rtable; es->rtable = queryDesc->plannedstmt->rtable;
if (es->printNodes) if (es->printNodes)
{ {
char *s; char *s;
char *f; char *f;
s = nodeToString(queryDesc->plantree); s = nodeToString(queryDesc->plannedstmt->planTree);
if (s) if (s)
{ {
if (Explain_pretty_print) if (Explain_pretty_print)
...@@ -282,7 +282,8 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt, ...@@ -282,7 +282,8 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
} }
initStringInfo(&buf); initStringInfo(&buf);
explain_outNode(&buf, queryDesc->plantree, queryDesc->planstate, explain_outNode(&buf,
queryDesc->plannedstmt->planTree, queryDesc->planstate,
NULL, 0, es); NULL, 0, es);
/* /*
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.60 2007/02/06 22:49:24 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.61 2007/02/20 17:32:14 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -42,7 +42,7 @@ PerformCursorOpen(DeclareCursorStmt *stmt, ParamListInfo params) ...@@ -42,7 +42,7 @@ PerformCursorOpen(DeclareCursorStmt *stmt, ParamListInfo params)
{ {
List *rewritten; List *rewritten;
Query *query; Query *query;
Plan *plan; PlannedStmt *plan;
Portal portal; Portal portal;
MemoryContext oldContext; MemoryContext oldContext;
...@@ -98,13 +98,12 @@ PerformCursorOpen(DeclareCursorStmt *stmt, ParamListInfo params) ...@@ -98,13 +98,12 @@ PerformCursorOpen(DeclareCursorStmt *stmt, ParamListInfo params)
plan = planner(query, true, stmt->options, params); plan = planner(query, true, stmt->options, params);
/* /*
* Create a portal and copy the query and plan into its memory context. * Create a portal and copy the plan into its memory context.
*/ */
portal = CreatePortal(stmt->portalname, false, false); portal = CreatePortal(stmt->portalname, false, false);
oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
query = copyObject(query);
plan = copyObject(plan); plan = copyObject(plan);
/* /*
...@@ -115,7 +114,6 @@ PerformCursorOpen(DeclareCursorStmt *stmt, ParamListInfo params) ...@@ -115,7 +114,6 @@ PerformCursorOpen(DeclareCursorStmt *stmt, ParamListInfo params)
NULL, NULL,
debug_query_string ? pstrdup(debug_query_string) : NULL, debug_query_string ? pstrdup(debug_query_string) : NULL,
"SELECT", /* cursor's query is always a SELECT */ "SELECT", /* cursor's query is always a SELECT */
list_make1(query),
list_make1(plan), list_make1(plan),
PortalGetHeapMemory(portal)); PortalGetHeapMemory(portal));
...@@ -140,7 +138,7 @@ PerformCursorOpen(DeclareCursorStmt *stmt, ParamListInfo params) ...@@ -140,7 +138,7 @@ PerformCursorOpen(DeclareCursorStmt *stmt, ParamListInfo params)
portal->cursorOptions = stmt->options; portal->cursorOptions = stmt->options;
if (!(portal->cursorOptions & (CURSOR_OPT_SCROLL | CURSOR_OPT_NO_SCROLL))) if (!(portal->cursorOptions & (CURSOR_OPT_SCROLL | CURSOR_OPT_NO_SCROLL)))
{ {
if (ExecSupportsBackwardScan(plan)) if (ExecSupportsBackwardScan(plan->planTree))
portal->cursorOptions |= CURSOR_OPT_SCROLL; portal->cursorOptions |= CURSOR_OPT_SCROLL;
else else
portal->cursorOptions |= CURSOR_OPT_NO_SCROLL; portal->cursorOptions |= CURSOR_OPT_NO_SCROLL;
......
This diff is collapsed.
This diff is collapsed.
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.144 2007/02/06 17:35:20 tgl Exp $ * $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.145 2007/02/20 17:32:14 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -242,7 +242,7 @@ InternalCreateExecutorState(MemoryContext qcontext, bool is_subquery) ...@@ -242,7 +242,7 @@ InternalCreateExecutorState(MemoryContext qcontext, bool is_subquery)
estate->es_per_tuple_exprcontext = NULL; estate->es_per_tuple_exprcontext = NULL;
estate->es_topPlan = NULL; estate->es_plannedstmt = NULL;
estate->es_evalPlanQual = NULL; estate->es_evalPlanQual = NULL;
estate->es_evTupleNull = NULL; estate->es_evTupleNull = NULL;
estate->es_evTuple = NULL; estate->es_evTuple = NULL;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.110 2007/02/02 00:02:55 tgl Exp $ * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.111 2007/02/20 17:32:15 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -33,8 +33,8 @@ ...@@ -33,8 +33,8 @@
/* /*
* We have an execution_state record for each query in a function. Each * We have an execution_state record for each query in a function. Each
* record contains a querytree and plantree for its query. If the query * record contains a plantree for its query. If the query is currently in
* is currently in F_EXEC_RUN state then there's a QueryDesc too. * F_EXEC_RUN state then there's a QueryDesc too.
*/ */
typedef enum typedef enum
{ {
...@@ -45,8 +45,7 @@ typedef struct local_es ...@@ -45,8 +45,7 @@ typedef struct local_es
{ {
struct local_es *next; struct local_es *next;
ExecStatus status; ExecStatus status;
Query *query; Node *stmt; /* PlannedStmt or utility statement */
Plan *plan;
QueryDesc *qd; /* null unless status == RUN */ QueryDesc *qd; /* null unless status == RUN */
} execution_state; } execution_state;
...@@ -105,26 +104,30 @@ init_execution_state(List *queryTree_list, bool readonly_func) ...@@ -105,26 +104,30 @@ init_execution_state(List *queryTree_list, bool readonly_func)
foreach(qtl_item, queryTree_list) foreach(qtl_item, queryTree_list)
{ {
Query *queryTree = lfirst(qtl_item); Query *queryTree = lfirst(qtl_item);
Plan *planTree; Node *stmt;
execution_state *newes; execution_state *newes;
Assert(IsA(queryTree, Query));
if (queryTree->commandType == CMD_UTILITY)
stmt = queryTree->utilityStmt;
else
stmt = (Node *) pg_plan_query(queryTree, NULL);
/* Precheck all commands for validity in a function */ /* Precheck all commands for validity in a function */
if (queryTree->commandType == CMD_UTILITY && if (IsA(stmt, TransactionStmt))
IsA(queryTree->utilityStmt, TransactionStmt))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s is a SQL statement name */ /* translator: %s is a SQL statement name */
errmsg("%s is not allowed in a SQL function", errmsg("%s is not allowed in a SQL function",
CreateQueryTag(queryTree)))); CreateCommandTag(stmt))));
if (readonly_func && !QueryIsReadOnly(queryTree)) if (readonly_func && !CommandIsReadOnly(stmt))
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
/* translator: %s is a SQL statement name */ /* translator: %s is a SQL statement name */
errmsg("%s is not allowed in a non-volatile function", errmsg("%s is not allowed in a non-volatile function",
CreateQueryTag(queryTree)))); CreateCommandTag(stmt))));
planTree = pg_plan_query(queryTree, NULL);
newes = (execution_state *) palloc(sizeof(execution_state)); newes = (execution_state *) palloc(sizeof(execution_state));
if (preves) if (preves)
...@@ -134,8 +137,7 @@ init_execution_state(List *queryTree_list, bool readonly_func) ...@@ -134,8 +137,7 @@ init_execution_state(List *queryTree_list, bool readonly_func)
newes->next = NULL; newes->next = NULL;
newes->status = F_EXEC_START; newes->status = F_EXEC_START;
newes->query = queryTree; newes->stmt = stmt;
newes->plan = planTree;
newes->qd = NULL; newes->qd = NULL;
preves = newes; preves = newes;
...@@ -298,10 +300,16 @@ postquel_start(execution_state *es, SQLFunctionCachePtr fcache) ...@@ -298,10 +300,16 @@ postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
snapshot = CopySnapshot(GetTransactionSnapshot()); snapshot = CopySnapshot(GetTransactionSnapshot());
} }
es->qd = CreateQueryDesc(es->query, es->plan, if (IsA(es->stmt, PlannedStmt))
snapshot, InvalidSnapshot, es->qd = CreateQueryDesc((PlannedStmt *) es->stmt,
None_Receiver, snapshot, InvalidSnapshot,
fcache->paramLI, false); None_Receiver,
fcache->paramLI, false);
else
es->qd = CreateUtilityQueryDesc(es->stmt,
snapshot,
None_Receiver,
fcache->paramLI);
/* We assume we don't need to set up ActiveSnapshot for ExecutorStart */ /* We assume we don't need to set up ActiveSnapshot for ExecutorStart */
...@@ -337,7 +345,7 @@ postquel_getnext(execution_state *es) ...@@ -337,7 +345,7 @@ postquel_getnext(execution_state *es)
if (es->qd->operation == CMD_UTILITY) if (es->qd->operation == CMD_UTILITY)
{ {
ProcessUtility(es->qd->parsetree->utilityStmt, es->qd->params, ProcessUtility(es->qd->utilitystmt, es->qd->params,
es->qd->dest, NULL); es->qd->dest, NULL);
result = NULL; result = NULL;
} }
...@@ -351,7 +359,7 @@ postquel_getnext(execution_state *es) ...@@ -351,7 +359,7 @@ postquel_getnext(execution_state *es)
*/ */
if (LAST_POSTQUEL_COMMAND(es) && if (LAST_POSTQUEL_COMMAND(es) &&
es->qd->operation == CMD_SELECT && es->qd->operation == CMD_SELECT &&
es->qd->parsetree->into == NULL) es->qd->plannedstmt->into == NULL)
count = 1L; count = 1L;
else else
count = 0L; count = 0L;
......
This diff is collapsed.
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.366 2007/02/19 02:23:11 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.367 2007/02/20 17:32:15 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -64,6 +64,27 @@ ...@@ -64,6 +64,27 @@
* **************************************************************** * ****************************************************************
*/ */
/*
* _copyPlannedStmt
*/
static PlannedStmt *
_copyPlannedStmt(PlannedStmt *from)
{
PlannedStmt *newnode = makeNode(PlannedStmt);
COPY_SCALAR_FIELD(commandType);
COPY_SCALAR_FIELD(canSetTag);
COPY_NODE_FIELD(planTree);
COPY_NODE_FIELD(rtable);
COPY_NODE_FIELD(resultRelations);
COPY_NODE_FIELD(into);
COPY_NODE_FIELD(returningLists);
COPY_NODE_FIELD(rowMarks);
COPY_SCALAR_FIELD(nParamExec);
return newnode;
}
/* /*
* CopyPlanFields * CopyPlanFields
* *
...@@ -84,7 +105,6 @@ CopyPlanFields(Plan *from, Plan *newnode) ...@@ -84,7 +105,6 @@ CopyPlanFields(Plan *from, Plan *newnode)
COPY_NODE_FIELD(initPlan); COPY_NODE_FIELD(initPlan);
COPY_BITMAPSET_FIELD(extParam); COPY_BITMAPSET_FIELD(extParam);
COPY_BITMAPSET_FIELD(allParam); COPY_BITMAPSET_FIELD(allParam);
COPY_SCALAR_FIELD(nParamExec);
} }
/* /*
...@@ -698,6 +718,23 @@ _copyRangeVar(RangeVar *from) ...@@ -698,6 +718,23 @@ _copyRangeVar(RangeVar *from)
return newnode; return newnode;
} }
/*
* _copyIntoClause
*/
static IntoClause *
_copyIntoClause(IntoClause *from)
{
IntoClause *newnode = makeNode(IntoClause);
COPY_NODE_FIELD(rel);
COPY_NODE_FIELD(colNames);
COPY_NODE_FIELD(options);
COPY_SCALAR_FIELD(onCommit);
COPY_STRING_FIELD(tableSpaceName);
return newnode;
}
/* /*
* We don't need a _copyExpr because Expr is an abstract supertype which * We don't need a _copyExpr because Expr is an abstract supertype which
* should never actually get instantiated. Also, since it has no common * should never actually get instantiated. Also, since it has no common
...@@ -1762,9 +1799,6 @@ _copyQuery(Query *from) ...@@ -1762,9 +1799,6 @@ _copyQuery(Query *from)
COPY_NODE_FIELD(utilityStmt); COPY_NODE_FIELD(utilityStmt);
COPY_SCALAR_FIELD(resultRelation); COPY_SCALAR_FIELD(resultRelation);
COPY_NODE_FIELD(into); COPY_NODE_FIELD(into);
COPY_NODE_FIELD(intoOptions);
COPY_SCALAR_FIELD(intoOnCommit);
COPY_STRING_FIELD(intoTableSpaceName);
COPY_SCALAR_FIELD(hasAggs); COPY_SCALAR_FIELD(hasAggs);
COPY_SCALAR_FIELD(hasSubLinks); COPY_SCALAR_FIELD(hasSubLinks);
COPY_NODE_FIELD(rtable); COPY_NODE_FIELD(rtable);
...@@ -1779,8 +1813,6 @@ _copyQuery(Query *from) ...@@ -1779,8 +1813,6 @@ _copyQuery(Query *from)
COPY_NODE_FIELD(limitCount); COPY_NODE_FIELD(limitCount);
COPY_NODE_FIELD(rowMarks); COPY_NODE_FIELD(rowMarks);
COPY_NODE_FIELD(setOperations); COPY_NODE_FIELD(setOperations);
COPY_NODE_FIELD(resultRelations);
COPY_NODE_FIELD(returningLists);
return newnode; return newnode;
} }
...@@ -1832,10 +1864,6 @@ _copySelectStmt(SelectStmt *from) ...@@ -1832,10 +1864,6 @@ _copySelectStmt(SelectStmt *from)
COPY_NODE_FIELD(distinctClause); COPY_NODE_FIELD(distinctClause);
COPY_NODE_FIELD(into); COPY_NODE_FIELD(into);
COPY_NODE_FIELD(intoColNames);
COPY_NODE_FIELD(intoOptions);
COPY_SCALAR_FIELD(intoOnCommit);
COPY_STRING_FIELD(intoTableSpaceName);
COPY_NODE_FIELD(targetList); COPY_NODE_FIELD(targetList);
COPY_NODE_FIELD(fromClause); COPY_NODE_FIELD(fromClause);
COPY_NODE_FIELD(whereClause); COPY_NODE_FIELD(whereClause);
...@@ -2768,9 +2796,6 @@ _copyExecuteStmt(ExecuteStmt *from) ...@@ -2768,9 +2796,6 @@ _copyExecuteStmt(ExecuteStmt *from)
COPY_STRING_FIELD(name); COPY_STRING_FIELD(name);
COPY_NODE_FIELD(into); COPY_NODE_FIELD(into);
COPY_NODE_FIELD(intoOptions);
COPY_SCALAR_FIELD(into_on_commit);
COPY_STRING_FIELD(into_tbl_space);
COPY_NODE_FIELD(params); COPY_NODE_FIELD(params);
return newnode; return newnode;
...@@ -2902,6 +2927,9 @@ copyObject(void *from) ...@@ -2902,6 +2927,9 @@ copyObject(void *from)
/* /*
* PLAN NODES * PLAN NODES
*/ */
case T_PlannedStmt:
retval = _copyPlannedStmt(from);
break;
case T_Plan: case T_Plan:
retval = _copyPlan(from); retval = _copyPlan(from);
break; break;
...@@ -2990,6 +3018,9 @@ copyObject(void *from) ...@@ -2990,6 +3018,9 @@ copyObject(void *from)
case T_RangeVar: case T_RangeVar:
retval = _copyRangeVar(from); retval = _copyRangeVar(from);
break; break;
case T_IntoClause:
retval = _copyIntoClause(from);
break;
case T_Var: case T_Var:
retval = _copyVar(from); retval = _copyVar(from);
break; break;
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.298 2007/02/03 14:06:54 petere Exp $ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.299 2007/02/20 17:32:15 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -102,6 +102,18 @@ _equalRangeVar(RangeVar *a, RangeVar *b) ...@@ -102,6 +102,18 @@ _equalRangeVar(RangeVar *a, RangeVar *b)
return true; return true;
} }
static bool
_equalIntoClause(IntoClause *a, IntoClause *b)
{
COMPARE_NODE_FIELD(rel);
COMPARE_NODE_FIELD(colNames);
COMPARE_NODE_FIELD(options);
COMPARE_SCALAR_FIELD(onCommit);
COMPARE_STRING_FIELD(tableSpaceName);
return true;
}
/* /*
* We don't need an _equalExpr because Expr is an abstract supertype which * We don't need an _equalExpr because Expr is an abstract supertype which
* should never actually get instantiated. Also, since it has no common * should never actually get instantiated. Also, since it has no common
...@@ -690,9 +702,6 @@ _equalQuery(Query *a, Query *b) ...@@ -690,9 +702,6 @@ _equalQuery(Query *a, Query *b)
COMPARE_NODE_FIELD(utilityStmt); COMPARE_NODE_FIELD(utilityStmt);
COMPARE_SCALAR_FIELD(resultRelation); COMPARE_SCALAR_FIELD(resultRelation);
COMPARE_NODE_FIELD(into); COMPARE_NODE_FIELD(into);
COMPARE_NODE_FIELD(intoOptions);
COMPARE_SCALAR_FIELD(intoOnCommit);
COMPARE_STRING_FIELD(intoTableSpaceName);
COMPARE_SCALAR_FIELD(hasAggs); COMPARE_SCALAR_FIELD(hasAggs);
COMPARE_SCALAR_FIELD(hasSubLinks); COMPARE_SCALAR_FIELD(hasSubLinks);
COMPARE_NODE_FIELD(rtable); COMPARE_NODE_FIELD(rtable);
...@@ -707,8 +716,6 @@ _equalQuery(Query *a, Query *b) ...@@ -707,8 +716,6 @@ _equalQuery(Query *a, Query *b)
COMPARE_NODE_FIELD(limitCount); COMPARE_NODE_FIELD(limitCount);
COMPARE_NODE_FIELD(rowMarks); COMPARE_NODE_FIELD(rowMarks);
COMPARE_NODE_FIELD(setOperations); COMPARE_NODE_FIELD(setOperations);
COMPARE_NODE_FIELD(resultRelations);
COMPARE_NODE_FIELD(returningLists);
return true; return true;
} }
...@@ -752,10 +759,6 @@ _equalSelectStmt(SelectStmt *a, SelectStmt *b) ...@@ -752,10 +759,6 @@ _equalSelectStmt(SelectStmt *a, SelectStmt *b)
{ {
COMPARE_NODE_FIELD(distinctClause); COMPARE_NODE_FIELD(distinctClause);
COMPARE_NODE_FIELD(into); COMPARE_NODE_FIELD(into);
COMPARE_NODE_FIELD(intoColNames);
COMPARE_NODE_FIELD(intoOptions);
COMPARE_SCALAR_FIELD(intoOnCommit);
COMPARE_STRING_FIELD(intoTableSpaceName);
COMPARE_NODE_FIELD(targetList); COMPARE_NODE_FIELD(targetList);
COMPARE_NODE_FIELD(fromClause); COMPARE_NODE_FIELD(fromClause);
COMPARE_NODE_FIELD(whereClause); COMPARE_NODE_FIELD(whereClause);
...@@ -1545,9 +1548,6 @@ _equalExecuteStmt(ExecuteStmt *a, ExecuteStmt *b) ...@@ -1545,9 +1548,6 @@ _equalExecuteStmt(ExecuteStmt *a, ExecuteStmt *b)
{ {
COMPARE_STRING_FIELD(name); COMPARE_STRING_FIELD(name);
COMPARE_NODE_FIELD(into); COMPARE_NODE_FIELD(into);
COMPARE_NODE_FIELD(intoOptions);
COMPARE_SCALAR_FIELD(into_on_commit);
COMPARE_STRING_FIELD(into_tbl_space);
COMPARE_NODE_FIELD(params); COMPARE_NODE_FIELD(params);
return true; return true;
...@@ -1967,6 +1967,9 @@ equal(void *a, void *b) ...@@ -1967,6 +1967,9 @@ equal(void *a, void *b)
case T_RangeVar: case T_RangeVar:
retval = _equalRangeVar(a, b); retval = _equalRangeVar(a, b);
break; break;
case T_IntoClause:
retval = _equalIntoClause(a, b);
break;
case T_Var: case T_Var:
retval = _equalVar(a, b); retval = _equalVar(a, b);
break; break;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.299 2007/02/19 07:03:27 tgl Exp $ * $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.300 2007/02/20 17:32:15 tgl Exp $
* *
* NOTES * NOTES
* Every node type that can appear in stored rules' parsetrees *must* * Every node type that can appear in stored rules' parsetrees *must*
...@@ -234,6 +234,22 @@ _outDatum(StringInfo str, Datum value, int typlen, bool typbyval) ...@@ -234,6 +234,22 @@ _outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
* Stuff from plannodes.h * Stuff from plannodes.h
*/ */
static void
_outPlannedStmt(StringInfo str, PlannedStmt *node)
{
WRITE_NODE_TYPE("PLANNEDSTMT");
WRITE_ENUM_FIELD(commandType, CmdType);
WRITE_BOOL_FIELD(canSetTag);
WRITE_NODE_FIELD(planTree);
WRITE_NODE_FIELD(rtable);
WRITE_NODE_FIELD(resultRelations);
WRITE_NODE_FIELD(into);
WRITE_NODE_FIELD(returningLists);
WRITE_NODE_FIELD(rowMarks);
WRITE_INT_FIELD(nParamExec);
}
/* /*
* print the basic stuff of all nodes that inherit from Plan * print the basic stuff of all nodes that inherit from Plan
*/ */
...@@ -251,7 +267,6 @@ _outPlanInfo(StringInfo str, Plan *node) ...@@ -251,7 +267,6 @@ _outPlanInfo(StringInfo str, Plan *node)
WRITE_NODE_FIELD(initPlan); WRITE_NODE_FIELD(initPlan);
WRITE_BITMAPSET_FIELD(extParam); WRITE_BITMAPSET_FIELD(extParam);
WRITE_BITMAPSET_FIELD(allParam); WRITE_BITMAPSET_FIELD(allParam);
WRITE_INT_FIELD(nParamExec);
} }
/* /*
...@@ -635,6 +650,18 @@ _outRangeVar(StringInfo str, RangeVar *node) ...@@ -635,6 +650,18 @@ _outRangeVar(StringInfo str, RangeVar *node)
WRITE_NODE_FIELD(alias); WRITE_NODE_FIELD(alias);
} }
static void
_outIntoClause(StringInfo str, IntoClause *node)
{
WRITE_NODE_TYPE("INTOCLAUSE");
WRITE_NODE_FIELD(rel);
WRITE_NODE_FIELD(colNames);
WRITE_NODE_FIELD(options);
WRITE_ENUM_FIELD(onCommit, OnCommitAction);
WRITE_STRING_FIELD(tableSpaceName);
}
static void static void
_outVar(StringInfo str, Var *node) _outVar(StringInfo str, Var *node)
{ {
...@@ -1245,6 +1272,8 @@ _outPlannerInfo(StringInfo str, PlannerInfo *node) ...@@ -1245,6 +1272,8 @@ _outPlannerInfo(StringInfo str, PlannerInfo *node)
WRITE_NODE_FIELD(glob); WRITE_NODE_FIELD(glob);
WRITE_UINT_FIELD(query_level); WRITE_UINT_FIELD(query_level);
WRITE_NODE_FIELD(join_rel_list); WRITE_NODE_FIELD(join_rel_list);
WRITE_NODE_FIELD(resultRelations);
WRITE_NODE_FIELD(returningLists);
WRITE_NODE_FIELD(init_plans); WRITE_NODE_FIELD(init_plans);
WRITE_NODE_FIELD(eq_classes); WRITE_NODE_FIELD(eq_classes);
WRITE_NODE_FIELD(canon_pathkeys); WRITE_NODE_FIELD(canon_pathkeys);
...@@ -1502,10 +1531,6 @@ _outSelectStmt(StringInfo str, SelectStmt *node) ...@@ -1502,10 +1531,6 @@ _outSelectStmt(StringInfo str, SelectStmt *node)
WRITE_NODE_FIELD(distinctClause); WRITE_NODE_FIELD(distinctClause);
WRITE_NODE_FIELD(into); WRITE_NODE_FIELD(into);
WRITE_NODE_FIELD(intoColNames);
WRITE_NODE_FIELD(intoOptions);
WRITE_ENUM_FIELD(intoOnCommit, OnCommitAction);
WRITE_STRING_FIELD(intoTableSpaceName);
WRITE_NODE_FIELD(targetList); WRITE_NODE_FIELD(targetList);
WRITE_NODE_FIELD(fromClause); WRITE_NODE_FIELD(fromClause);
WRITE_NODE_FIELD(whereClause); WRITE_NODE_FIELD(whereClause);
...@@ -1651,9 +1676,6 @@ _outQuery(StringInfo str, Query *node) ...@@ -1651,9 +1676,6 @@ _outQuery(StringInfo str, Query *node)
WRITE_INT_FIELD(resultRelation); WRITE_INT_FIELD(resultRelation);
WRITE_NODE_FIELD(into); WRITE_NODE_FIELD(into);
WRITE_NODE_FIELD(intoOptions);
WRITE_ENUM_FIELD(intoOnCommit, OnCommitAction);
WRITE_STRING_FIELD(intoTableSpaceName);
WRITE_BOOL_FIELD(hasAggs); WRITE_BOOL_FIELD(hasAggs);
WRITE_BOOL_FIELD(hasSubLinks); WRITE_BOOL_FIELD(hasSubLinks);
WRITE_NODE_FIELD(rtable); WRITE_NODE_FIELD(rtable);
...@@ -1668,8 +1690,6 @@ _outQuery(StringInfo str, Query *node) ...@@ -1668,8 +1690,6 @@ _outQuery(StringInfo str, Query *node)
WRITE_NODE_FIELD(limitCount); WRITE_NODE_FIELD(limitCount);
WRITE_NODE_FIELD(rowMarks); WRITE_NODE_FIELD(rowMarks);
WRITE_NODE_FIELD(setOperations); WRITE_NODE_FIELD(setOperations);
WRITE_NODE_FIELD(resultRelations);
WRITE_NODE_FIELD(returningLists);
} }
static void static void
...@@ -1988,6 +2008,9 @@ _outNode(StringInfo str, void *obj) ...@@ -1988,6 +2008,9 @@ _outNode(StringInfo str, void *obj)
appendStringInfoChar(str, '{'); appendStringInfoChar(str, '{');
switch (nodeTag(obj)) switch (nodeTag(obj))
{ {
case T_PlannedStmt:
_outPlannedStmt(str, obj);
break;
case T_Plan: case T_Plan:
_outPlan(str, obj); _outPlan(str, obj);
break; break;
...@@ -2072,6 +2095,9 @@ _outNode(StringInfo str, void *obj) ...@@ -2072,6 +2095,9 @@ _outNode(StringInfo str, void *obj)
case T_RangeVar: case T_RangeVar:
_outRangeVar(str, obj); _outRangeVar(str, obj);
break; break;
case T_IntoClause:
_outIntoClause(str, obj);
break;
case T_Var: case T_Var:
_outVar(str, obj); _outVar(str, obj);
break; break;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.202 2007/02/03 14:06:54 petere Exp $ * $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.203 2007/02/20 17:32:15 tgl Exp $
* *
* NOTES * NOTES
* Path and Plan nodes do not have any readfuncs support, because we * Path and Plan nodes do not have any readfuncs support, because we
...@@ -140,9 +140,6 @@ _readQuery(void) ...@@ -140,9 +140,6 @@ _readQuery(void)
READ_NODE_FIELD(utilityStmt); READ_NODE_FIELD(utilityStmt);
READ_INT_FIELD(resultRelation); READ_INT_FIELD(resultRelation);
READ_NODE_FIELD(into); READ_NODE_FIELD(into);
READ_NODE_FIELD(intoOptions);
READ_ENUM_FIELD(intoOnCommit, OnCommitAction);
READ_STRING_FIELD(intoTableSpaceName);
READ_BOOL_FIELD(hasAggs); READ_BOOL_FIELD(hasAggs);
READ_BOOL_FIELD(hasSubLinks); READ_BOOL_FIELD(hasSubLinks);
READ_NODE_FIELD(rtable); READ_NODE_FIELD(rtable);
...@@ -157,8 +154,6 @@ _readQuery(void) ...@@ -157,8 +154,6 @@ _readQuery(void)
READ_NODE_FIELD(limitCount); READ_NODE_FIELD(limitCount);
READ_NODE_FIELD(rowMarks); READ_NODE_FIELD(rowMarks);
READ_NODE_FIELD(setOperations); READ_NODE_FIELD(setOperations);
READ_NODE_FIELD(resultRelations);
READ_NODE_FIELD(returningLists);
READ_DONE(); READ_DONE();
} }
...@@ -287,6 +282,20 @@ _readRangeVar(void) ...@@ -287,6 +282,20 @@ _readRangeVar(void)
READ_DONE(); READ_DONE();
} }
static IntoClause *
_readIntoClause(void)
{
READ_LOCALS(IntoClause);
READ_NODE_FIELD(rel);
READ_NODE_FIELD(colNames);
READ_NODE_FIELD(options);
READ_ENUM_FIELD(onCommit, OnCommitAction);
READ_STRING_FIELD(tableSpaceName);
READ_DONE();
}
/* /*
* _readVar * _readVar
*/ */
...@@ -984,6 +993,8 @@ parseNodeString(void) ...@@ -984,6 +993,8 @@ parseNodeString(void)
return_value = _readAlias(); return_value = _readAlias();
else if (MATCH("RANGEVAR", 8)) else if (MATCH("RANGEVAR", 8))
return_value = _readRangeVar(); return_value = _readRangeVar();
else if (MATCH("INTOCLAUSE", 10))
return_value = _readIntoClause();
else if (MATCH("VAR", 3)) else if (MATCH("VAR", 3))
return_value = _readVar(); return_value = _readVar();
else if (MATCH("CONST", 5)) else if (MATCH("CONST", 5))
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.159 2007/02/19 07:03:28 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.160 2007/02/20 17:32:15 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -444,8 +444,8 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel, ...@@ -444,8 +444,8 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
Query *subquery = rte->subquery; Query *subquery = rte->subquery;
bool *differentTypes; bool *differentTypes;
double tuple_fraction; double tuple_fraction;
PlannerInfo *subroot;
List *pathkeys; List *pathkeys;
List *subquery_pathkeys;
/* We need a workspace for keeping track of set-op type coercions */ /* We need a workspace for keeping track of set-op type coercions */
differentTypes = (bool *) differentTypes = (bool *)
...@@ -520,7 +520,7 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel, ...@@ -520,7 +520,7 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
rel->subplan = subquery_planner(root->glob, subquery, rel->subplan = subquery_planner(root->glob, subquery,
root->query_level + 1, root->query_level + 1,
tuple_fraction, tuple_fraction,
&subquery_pathkeys); &subroot);
/* Copy number of output rows from subplan */ /* Copy number of output rows from subplan */
rel->tuples = rel->subplan->plan_rows; rel->tuples = rel->subplan->plan_rows;
...@@ -529,7 +529,7 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel, ...@@ -529,7 +529,7 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
set_baserel_size_estimates(root, rel); set_baserel_size_estimates(root, rel);
/* Convert subquery pathkeys to outer representation */ /* Convert subquery pathkeys to outer representation */
pathkeys = convert_subquery_pathkeys(root, rel, subquery_pathkeys); pathkeys = convert_subquery_pathkeys(root, rel, subroot->query_pathkeys);
/* Generate appropriate path */ /* Generate appropriate path */
add_path(rel, create_subqueryscan_path(rel, pathkeys)); add_path(rel, create_subqueryscan_path(rel, pathkeys));
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.27 2007/02/19 07:03:29 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.28 2007/02/20 17:32:15 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -453,8 +453,7 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info) ...@@ -453,8 +453,7 @@ make_agg_subplan(PlannerInfo *root, MinMaxAggInfo *info)
subroot.init_plans = NIL; subroot.init_plans = NIL;
subparse->commandType = CMD_SELECT; subparse->commandType = CMD_SELECT;
subparse->resultRelation = 0; subparse->resultRelation = 0;
subparse->resultRelations = NIL; subparse->returningList = NIL;
subparse->returningLists = NIL;
subparse->into = NULL; subparse->into = NULL;
subparse->hasAggs = false; subparse->hasAggs = false;
subparse->groupClause = NIL; subparse->groupClause = NIL;
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.213 2007/02/19 07:03:29 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/plan/planner.c,v 1.214 2007/02/20 17:32:15 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -79,13 +79,15 @@ static List *postprocess_setop_tlist(List *new_tlist, List *orig_tlist); ...@@ -79,13 +79,15 @@ static List *postprocess_setop_tlist(List *new_tlist, List *orig_tlist);
* Query optimizer entry point * Query optimizer entry point
* *
*****************************************************************************/ *****************************************************************************/
Plan * PlannedStmt *
planner(Query *parse, bool isCursor, int cursorOptions, planner(Query *parse, bool isCursor, int cursorOptions,
ParamListInfo boundParams) ParamListInfo boundParams)
{ {
PlannedStmt *result;
PlannerGlobal *glob; PlannerGlobal *glob;
double tuple_fraction; double tuple_fraction;
Plan *result_plan; PlannerInfo *root;
Plan *top_plan;
/* /*
* Set up global state for this planner invocation. This data is needed * Set up global state for this planner invocation. This data is needed
...@@ -117,7 +119,7 @@ planner(Query *parse, bool isCursor, int cursorOptions, ...@@ -117,7 +119,7 @@ planner(Query *parse, bool isCursor, int cursorOptions,
} }
/* primary planning entry point (may recurse for subqueries) */ /* primary planning entry point (may recurse for subqueries) */
result_plan = subquery_planner(glob, parse, 1, tuple_fraction, NULL); top_plan = subquery_planner(glob, parse, 1, tuple_fraction, &root);
/* /*
* If creating a plan for a scrollable cursor, make sure it can run * If creating a plan for a scrollable cursor, make sure it can run
...@@ -125,17 +127,27 @@ planner(Query *parse, bool isCursor, int cursorOptions, ...@@ -125,17 +127,27 @@ planner(Query *parse, bool isCursor, int cursorOptions,
*/ */
if (isCursor && (cursorOptions & CURSOR_OPT_SCROLL)) if (isCursor && (cursorOptions & CURSOR_OPT_SCROLL))
{ {
if (!ExecSupportsBackwardScan(result_plan)) if (!ExecSupportsBackwardScan(top_plan))
result_plan = materialize_finished_plan(result_plan); top_plan = materialize_finished_plan(top_plan);
} }
/* final cleanup of the plan */ /* final cleanup of the plan */
result_plan = set_plan_references(result_plan, parse->rtable); top_plan = set_plan_references(top_plan, parse->rtable);
/* executor wants to know total number of Params used overall */ /* build the PlannedStmt result */
result_plan->nParamExec = list_length(glob->paramlist); result = makeNode(PlannedStmt);
return result_plan; result->commandType = parse->commandType;
result->canSetTag = parse->canSetTag;
result->planTree = top_plan;
result->rtable = parse->rtable;
result->resultRelations = root->resultRelations;
result->into = parse->into;
result->returningLists = root->returningLists;
result->rowMarks = parse->rowMarks;
result->nParamExec = list_length(glob->paramlist);
return result;
} }
...@@ -150,8 +162,8 @@ planner(Query *parse, bool isCursor, int cursorOptions, ...@@ -150,8 +162,8 @@ planner(Query *parse, bool isCursor, int cursorOptions,
* tuple_fraction is the fraction of tuples we expect will be retrieved. * tuple_fraction is the fraction of tuples we expect will be retrieved.
* tuple_fraction is interpreted as explained for grouping_planner, below. * tuple_fraction is interpreted as explained for grouping_planner, below.
* *
* If subquery_pathkeys isn't NULL, it receives a list of pathkeys indicating * If subroot isn't NULL, we pass back the query's final PlannerInfo struct;
* the output sort ordering of the completed plan. * among other things this tells the output sort ordering of the plan.
* *
* Basically, this routine does the stuff that should only be done once * Basically, this routine does the stuff that should only be done once
* per Query object. It then calls grouping_planner. At one time, * per Query object. It then calls grouping_planner. At one time,
...@@ -168,7 +180,7 @@ planner(Query *parse, bool isCursor, int cursorOptions, ...@@ -168,7 +180,7 @@ planner(Query *parse, bool isCursor, int cursorOptions,
Plan * Plan *
subquery_planner(PlannerGlobal *glob, Query *parse, subquery_planner(PlannerGlobal *glob, Query *parse,
Index level, double tuple_fraction, Index level, double tuple_fraction,
List **subquery_pathkeys) PlannerInfo **subroot)
{ {
int saved_plan_id = glob->next_plan_id; int saved_plan_id = glob->next_plan_id;
PlannerInfo *root; PlannerInfo *root;
...@@ -375,9 +387,9 @@ subquery_planner(PlannerGlobal *glob, Query *parse, ...@@ -375,9 +387,9 @@ subquery_planner(PlannerGlobal *glob, Query *parse,
if (root->glob->next_plan_id != saved_plan_id || root->query_level > 1) if (root->glob->next_plan_id != saved_plan_id || root->query_level > 1)
SS_finalize_plan(root, plan); SS_finalize_plan(root, plan);
/* Return sort ordering info if caller wants it */ /* Return internal info if caller wants it */
if (subquery_pathkeys) if (subroot)
*subquery_pathkeys = root->query_pathkeys; *subroot = root;
return plan; return plan;
} }
...@@ -593,14 +605,14 @@ inheritance_planner(PlannerInfo *root) ...@@ -593,14 +605,14 @@ inheritance_planner(PlannerInfo *root)
/* Build list of per-relation RETURNING targetlists */ /* Build list of per-relation RETURNING targetlists */
if (parse->returningList) if (parse->returningList)
{ {
Assert(list_length(subroot.parse->returningLists) == 1); Assert(list_length(subroot.returningLists) == 1);
returningLists = list_concat(returningLists, returningLists = list_concat(returningLists,
subroot.parse->returningLists); subroot.returningLists);
} }
} }
parse->resultRelations = resultRelations; root->resultRelations = resultRelations;
parse->returningLists = returningLists; root->returningLists = returningLists;
/* Mark result as unordered (probably unnecessary) */ /* Mark result as unordered (probably unnecessary) */
root->query_pathkeys = NIL; root->query_pathkeys = NIL;
...@@ -1101,8 +1113,16 @@ grouping_planner(PlannerInfo *root, double tuple_fraction) ...@@ -1101,8 +1113,16 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
rlist = set_returning_clause_references(parse->returningList, rlist = set_returning_clause_references(parse->returningList,
result_plan, result_plan,
parse->resultRelation); parse->resultRelation);
parse->returningLists = list_make1(rlist); root->returningLists = list_make1(rlist);
} }
else
root->returningLists = NIL;
/* Compute result-relations list if needed */
if (parse->resultRelation)
root->resultRelations = list_make1_int(parse->resultRelation);
else
root->resultRelations = NIL;
/* /*
* Return the actual output ordering in query_pathkeys for possible use by * Return the actual output ordering in query_pathkeys for possible use by
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.360 2007/02/01 19:10:27 momjian Exp $ * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.361 2007/02/20 17:32:16 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2143,11 +2143,8 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) ...@@ -2143,11 +2143,8 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt)
if (stmt->into) if (stmt->into)
{ {
qry->into = stmt->into; qry->into = stmt->into;
if (stmt->intoColNames) if (stmt->into->colNames)
applyColumnNames(qry->targetList, stmt->intoColNames); applyColumnNames(qry->targetList, stmt->into->colNames);
qry->intoOptions = copyObject(stmt->intoOptions);
qry->intoOnCommit = stmt->intoOnCommit;
qry->intoTableSpaceName = stmt->intoTableSpaceName;
} }
qry->rtable = pstate->p_rtable; qry->rtable = pstate->p_rtable;
...@@ -2315,11 +2312,8 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) ...@@ -2315,11 +2312,8 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt)
if (stmt->into) if (stmt->into)
{ {
qry->into = stmt->into; qry->into = stmt->into;
if (stmt->intoColNames) if (stmt->into->colNames)
applyColumnNames(qry->targetList, stmt->intoColNames); applyColumnNames(qry->targetList, stmt->into->colNames);
qry->intoOptions = copyObject(stmt->intoOptions);
qry->intoOnCommit = stmt->intoOnCommit;
qry->intoTableSpaceName = stmt->intoTableSpaceName;
} }
/* /*
...@@ -2399,9 +2393,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) ...@@ -2399,9 +2393,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
/* /*
* Find leftmost leaf SelectStmt; extract the one-time-only items from it * Find leftmost leaf SelectStmt; extract the one-time-only items from it
* and from the top-level node. (Most of the INTO options can be * and from the top-level node.
* transferred to the Query immediately, but intoColNames has to be saved
* to apply below.)
*/ */
leftmostSelect = stmt->larg; leftmostSelect = stmt->larg;
while (leftmostSelect && leftmostSelect->op != SETOP_NONE) while (leftmostSelect && leftmostSelect->op != SETOP_NONE)
...@@ -2411,10 +2403,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) ...@@ -2411,10 +2403,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt)
if (leftmostSelect->into) if (leftmostSelect->into)
{ {
qry->into = leftmostSelect->into; qry->into = leftmostSelect->into;
intoColNames = leftmostSelect->intoColNames; intoColNames = leftmostSelect->into->colNames;
qry->intoOptions = copyObject(leftmostSelect->intoOptions);
qry->intoOnCommit = leftmostSelect->intoOnCommit;
qry->intoTableSpaceName = leftmostSelect->intoTableSpaceName;
} }
/* clear this to prevent complaints in transformSetOperationTree() */ /* clear this to prevent complaints in transformSetOperationTree() */
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.579 2007/02/03 14:06:54 petere Exp $ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.580 2007/02/20 17:32:16 tgl Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -139,6 +139,7 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args) ...@@ -139,6 +139,7 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
IndexElem *ielem; IndexElem *ielem;
Alias *alias; Alias *alias;
RangeVar *range; RangeVar *range;
IntoClause *into;
A_Indices *aind; A_Indices *aind;
ResTarget *target; ResTarget *target;
PrivTarget *privtarget; PrivTarget *privtarget;
...@@ -248,7 +249,8 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args) ...@@ -248,7 +249,8 @@ static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args)
prep_type_clause prep_type_clause
execute_param_clause using_clause returning_clause execute_param_clause using_clause returning_clause
%type <range> into_clause OptTempTableName %type <range> OptTempTableName
%type <into> into_clause create_as_target
%type <defelt> createfunc_opt_item common_func_opt_item %type <defelt> createfunc_opt_item common_func_opt_item
%type <fun_param> func_arg %type <fun_param> func_arg
...@@ -2253,8 +2255,7 @@ OptConsTableSpace: USING INDEX TABLESPACE name { $$ = $4; } ...@@ -2253,8 +2255,7 @@ OptConsTableSpace: USING INDEX TABLESPACE name { $$ = $4; }
*/ */
CreateAsStmt: CreateAsStmt:
CREATE OptTemp TABLE qualified_name OptCreateAs CREATE OptTemp TABLE create_as_target AS SelectStmt
OptWith OnCommitOption OptTableSpace AS SelectStmt
{ {
/* /*
* When the SelectStmt is a set-operation tree, we must * When the SelectStmt is a set-operation tree, we must
...@@ -2263,18 +2264,26 @@ CreateAsStmt: ...@@ -2263,18 +2264,26 @@ CreateAsStmt:
* to find it. Similarly, the output column names must * to find it. Similarly, the output column names must
* be attached to that Select's target list. * be attached to that Select's target list.
*/ */
SelectStmt *n = findLeftmostSelect((SelectStmt *) $10); SelectStmt *n = findLeftmostSelect((SelectStmt *) $6);
if (n->into != NULL) if (n->into != NULL)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("CREATE TABLE AS cannot specify INTO"))); errmsg("CREATE TABLE AS cannot specify INTO")));
$4->istemp = $2; $4->rel->istemp = $2;
n->into = $4; n->into = $4;
n->intoColNames = $5; $$ = $6;
n->intoOptions = $6; }
n->intoOnCommit = $7; ;
n->intoTableSpaceName = $8;
$$ = $10; create_as_target:
qualified_name OptCreateAs OptWith OnCommitOption OptTableSpace
{
$$ = makeNode(IntoClause);
$$->rel = $1;
$$->colNames = $2;
$$->options = $3;
$$->onCommit = $4;
$$->tableSpaceName = $5;
} }
; ;
...@@ -5459,19 +5468,15 @@ ExecuteStmt: EXECUTE name execute_param_clause ...@@ -5459,19 +5468,15 @@ ExecuteStmt: EXECUTE name execute_param_clause
n->into = NULL; n->into = NULL;
$$ = (Node *) n; $$ = (Node *) n;
} }
| CREATE OptTemp TABLE qualified_name OptCreateAs | CREATE OptTemp TABLE create_as_target AS
OptWith OnCommitOption OptTableSpace AS
EXECUTE name execute_param_clause EXECUTE name execute_param_clause
{ {
ExecuteStmt *n = makeNode(ExecuteStmt); ExecuteStmt *n = makeNode(ExecuteStmt);
n->name = $11; n->name = $7;
n->params = $12; n->params = $8;
$4->istemp = $2; $4->rel->istemp = $2;
n->into = $4; n->into = $4;
n->intoOptions = $6; if ($4->colNames)
n->into_on_commit = $7;
n->into_tbl_space = $8;
if ($5)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED), (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("column name list not allowed in CREATE TABLE / AS EXECUTE"))); errmsg("column name list not allowed in CREATE TABLE / AS EXECUTE")));
...@@ -5854,7 +5859,6 @@ simple_select: ...@@ -5854,7 +5859,6 @@ simple_select:
n->distinctClause = $2; n->distinctClause = $2;
n->targetList = $3; n->targetList = $3;
n->into = $4; n->into = $4;
n->intoColNames = NIL;
n->fromClause = $5; n->fromClause = $5;
n->whereClause = $6; n->whereClause = $6;
n->groupClause = $7; n->groupClause = $7;
...@@ -5877,8 +5881,17 @@ simple_select: ...@@ -5877,8 +5881,17 @@ simple_select:
; ;
into_clause: into_clause:
INTO OptTempTableName { $$ = $2; } INTO OptTempTableName
| /*EMPTY*/ { $$ = NULL; } {
$$ = makeNode(IntoClause);
$$->rel = $2;
$$->colNames = NIL;
$$->options = NIL;
$$->onCommit = ONCOMMIT_NOOP;
$$->tableSpaceName = NULL;
}
| /*EMPTY*/
{ $$ = NULL; }
; ;
/* /*
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.98 2007/01/05 22:19:47 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.99 2007/02/20 17:32:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -141,29 +141,45 @@ GetPortalByName(const char *name) ...@@ -141,29 +141,45 @@ GetPortalByName(const char *name)
} }
/* /*
* PortalListGetPrimaryQuery * PortalListGetPrimaryStmt
* Get the "primary" Query within a portal, ie, the one marked canSetTag. * Get the "primary" stmt within a portal, ie, the one marked canSetTag.
* *
* Returns NULL if no such Query. If multiple Query structs within the * Returns NULL if no such stmt. If multiple PlannedStmt structs within the
* portal are marked canSetTag, returns the first one. Neither of these * portal are marked canSetTag, returns the first one. Neither of these
* cases should occur in present usages of this function. * cases should occur in present usages of this function.
* *
* Copes if given a list of Querys --- can't happen in a portal, but this
* code also supports prepared statements, which need both cases.
*
* Note: the reason this is just handed a List is so that prepared statements * Note: the reason this is just handed a List is so that prepared statements
* can share the code. For use with a portal, use PortalGetPrimaryQuery * can share the code. For use with a portal, use PortalGetPrimaryStmt
* rather than calling this directly. * rather than calling this directly.
*/ */
Query * Node *
PortalListGetPrimaryQuery(List *parseTrees) PortalListGetPrimaryStmt(List *stmts)
{ {
ListCell *lc; ListCell *lc;
foreach(lc, parseTrees) foreach(lc, stmts)
{ {
Query *query = (Query *) lfirst(lc); Node *stmt = (Node *) lfirst(lc);
Assert(IsA(query, Query)); if (IsA(stmt, PlannedStmt))
if (query->canSetTag) {
return query; if (((PlannedStmt *) stmt)->canSetTag)
return stmt;
}
else if (IsA(stmt, Query))
{
if (((Query *) stmt)->canSetTag)
return stmt;
}
else
{
/* Utility stmts are assumed canSetTag if they're the only stmt */
if (list_length(stmts) == 1)
return stmt;
}
} }
return NULL; return NULL;
} }
...@@ -261,30 +277,25 @@ CreateNewPortal(void) ...@@ -261,30 +277,25 @@ CreateNewPortal(void)
* (before rewriting) was an empty string. Also, the passed commandTag must * (before rewriting) was an empty string. Also, the passed commandTag must
* be a pointer to a constant string, since it is not copied. The caller is * be a pointer to a constant string, since it is not copied. The caller is
* responsible for ensuring that the passed prepStmtName (if any), sourceText * responsible for ensuring that the passed prepStmtName (if any), sourceText
* (if any), parse and plan trees have adequate lifetime. Also, queryContext * (if any), and plan trees have adequate lifetime.
* must accurately describe the location of the parse trees.
*/ */
void void
PortalDefineQuery(Portal portal, PortalDefineQuery(Portal portal,
const char *prepStmtName, const char *prepStmtName,
const char *sourceText, const char *sourceText,
const char *commandTag, const char *commandTag,
List *parseTrees, List *stmts,
List *planTrees,
MemoryContext queryContext) MemoryContext queryContext)
{ {
AssertArg(PortalIsValid(portal)); AssertArg(PortalIsValid(portal));
AssertState(portal->queryContext == NULL); /* else defined already */ AssertState(portal->queryContext == NULL); /* else defined already */
Assert(list_length(parseTrees) == list_length(planTrees)); Assert(commandTag != NULL || stmts == NIL);
Assert(commandTag != NULL || parseTrees == NIL);
portal->prepStmtName = prepStmtName; portal->prepStmtName = prepStmtName;
portal->sourceText = sourceText; portal->sourceText = sourceText;
portal->commandTag = commandTag; portal->commandTag = commandTag;
portal->parseTrees = parseTrees; portal->stmts = stmts;
portal->planTrees = planTrees;
portal->queryContext = queryContext; portal->queryContext = queryContext;
} }
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.387 2007/02/20 10:00:25 petere Exp $ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.388 2007/02/20 17:32:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -53,6 +53,6 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200702201 #define CATALOG_VERSION_NO 200702202
#endif #endif
...@@ -7,13 +7,14 @@ ...@@ -7,13 +7,14 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/commands/portalcmds.h,v 1.20 2007/01/05 22:19:53 momjian Exp $ * $PostgreSQL: pgsql/src/include/commands/portalcmds.h,v 1.21 2007/02/20 17:32:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef PORTALCMDS_H #ifndef PORTALCMDS_H
#define PORTALCMDS_H #define PORTALCMDS_H
#include "nodes/parsenodes.h"
#include "utils/portal.h" #include "utils/portal.h"
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 2002-2007, PostgreSQL Global Development Group * Copyright (c) 2002-2007, PostgreSQL Global Development Group
* *
* $PostgreSQL: pgsql/src/include/commands/prepare.h,v 1.23 2007/01/05 22:19:53 momjian Exp $ * $PostgreSQL: pgsql/src/include/commands/prepare.h,v 1.24 2007/02/20 17:32:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -19,6 +19,10 @@ ...@@ -19,6 +19,10 @@
/* /*
* The data structure representing a prepared statement * The data structure representing a prepared statement
* *
* A prepared statement might be fully planned, or only parsed-and-rewritten.
* If fully planned, stmt_list contains PlannedStmts and/or utility statements;
* if not, it contains Query nodes.
*
* Note: all subsidiary storage lives in the context denoted by the context * Note: all subsidiary storage lives in the context denoted by the context
* field. However, the string referenced by commandTag is not subsidiary * field. However, the string referenced by commandTag is not subsidiary
* storage; it is assumed to be a compile-time-constant string. As with * storage; it is assumed to be a compile-time-constant string. As with
...@@ -31,11 +35,11 @@ typedef struct ...@@ -31,11 +35,11 @@ typedef struct
char stmt_name[NAMEDATALEN]; char stmt_name[NAMEDATALEN];
char *query_string; /* text of query, or NULL */ char *query_string; /* text of query, or NULL */
const char *commandTag; /* command tag (a constant!), or NULL */ const char *commandTag; /* command tag (a constant!), or NULL */
List *query_list; /* list of queries, rewritten */ List *stmt_list; /* list of statement or Query nodes */
List *plan_list; /* list of plans */
List *argtype_list; /* list of parameter type OIDs */ List *argtype_list; /* list of parameter type OIDs */
bool fully_planned; /* what is in stmt_list, exactly? */
bool from_sql; /* prepared via SQL, not FE/BE protocol? */
TimestampTz prepare_time; /* the time when the stmt was prepared */ TimestampTz prepare_time; /* the time when the stmt was prepared */
bool from_sql; /* stmt prepared via SQL, not FE/BE protocol? */
MemoryContext context; /* context containing this query */ MemoryContext context; /* context containing this query */
} PreparedStatement; } PreparedStatement;
...@@ -52,9 +56,9 @@ extern void ExplainExecuteQuery(ExplainStmt *stmt, ParamListInfo params, ...@@ -52,9 +56,9 @@ extern void ExplainExecuteQuery(ExplainStmt *stmt, ParamListInfo params,
extern void StorePreparedStatement(const char *stmt_name, extern void StorePreparedStatement(const char *stmt_name,
const char *query_string, const char *query_string,
const char *commandTag, const char *commandTag,
List *query_list, List *stmt_list,
List *plan_list,
List *argtype_list, List *argtype_list,
bool fully_planned,
bool from_sql); bool from_sql);
extern PreparedStatement *FetchPreparedStatement(const char *stmt_name, extern PreparedStatement *FetchPreparedStatement(const char *stmt_name,
bool throwError); bool throwError);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/executor/execdesc.h,v 1.33 2007/01/05 22:19:54 momjian Exp $ * $PostgreSQL: pgsql/src/include/executor/execdesc.h,v 1.34 2007/02/20 17:32:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
#define EXECDESC_H #define EXECDESC_H
#include "nodes/execnodes.h" #include "nodes/execnodes.h"
#include "nodes/parsenodes.h" #include "nodes/plannodes.h"
#include "tcop/dest.h" #include "tcop/dest.h"
...@@ -24,15 +24,19 @@ ...@@ -24,15 +24,19 @@
* query descriptor: * query descriptor:
* *
* a QueryDesc encapsulates everything that the executor * a QueryDesc encapsulates everything that the executor
* needs to execute the query * needs to execute the query.
*
* For the convenience of SQL-language functions, we also support QueryDescs
* containing utility statements; these must not be passed to the executor
* however.
* --------------------- * ---------------------
*/ */
typedef struct QueryDesc typedef struct QueryDesc
{ {
/* These fields are provided by CreateQueryDesc */ /* These fields are provided by CreateQueryDesc */
CmdType operation; /* CMD_SELECT, CMD_UPDATE, etc. */ CmdType operation; /* CMD_SELECT, CMD_UPDATE, etc. */
Query *parsetree; /* rewritten parsetree */ PlannedStmt *plannedstmt; /* planner's output, or null if utility */
Plan *plantree; /* planner's output */ Node *utilitystmt; /* utility statement, or null */
Snapshot snapshot; /* snapshot to use for query */ Snapshot snapshot; /* snapshot to use for query */
Snapshot crosscheck_snapshot; /* crosscheck for RI update/delete */ Snapshot crosscheck_snapshot; /* crosscheck for RI update/delete */
DestReceiver *dest; /* the destination for tuple output */ DestReceiver *dest; /* the destination for tuple output */
...@@ -46,13 +50,18 @@ typedef struct QueryDesc ...@@ -46,13 +50,18 @@ typedef struct QueryDesc
} QueryDesc; } QueryDesc;
/* in pquery.c */ /* in pquery.c */
extern QueryDesc *CreateQueryDesc(Query *parsetree, Plan *plantree, extern QueryDesc *CreateQueryDesc(PlannedStmt *plannedstmt,
Snapshot snapshot, Snapshot snapshot,
Snapshot crosscheck_snapshot, Snapshot crosscheck_snapshot,
DestReceiver *dest, DestReceiver *dest,
ParamListInfo params, ParamListInfo params,
bool doInstrument); bool doInstrument);
extern QueryDesc *CreateUtilityQueryDesc(Node *utilitystmt,
Snapshot snapshot,
DestReceiver *dest,
ParamListInfo params);
extern void FreeQueryDesc(QueryDesc *qdesc); extern void FreeQueryDesc(QueryDesc *qdesc);
#endif /* EXECDESC_H */ #endif /* EXECDESC_H */
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.136 2007/02/06 02:59:13 tgl Exp $ * $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.137 2007/02/20 17:32:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#define EXECUTOR_H #define EXECUTOR_H
#include "executor/execdesc.h" #include "executor/execdesc.h"
#include "nodes/parsenodes.h"
/* /*
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/executor/spi_priv.h,v 1.26 2007/01/05 22:19:55 momjian Exp $ * $PostgreSQL: pgsql/src/include/executor/spi_priv.h,v 1.27 2007/02/20 17:32:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -35,10 +35,11 @@ typedef struct ...@@ -35,10 +35,11 @@ typedef struct
MemoryContext plancxt; MemoryContext plancxt;
/* Original query string (used for error reporting) */ /* Original query string (used for error reporting) */
const char *query; const char *query;
/* List of List of querytrees; one sublist per original parsetree */ /*
List *qtlist; * List of List of PlannedStmts and utility stmts; one sublist per
/* List of plan trees --- length == # of querytrees, but flat list */ * original parsetree
List *ptlist; */
List *stmt_list_list;
/* Argument types, if a prepared plan */ /* Argument types, if a prepared plan */
int nargs; int nargs;
Oid *argtypes; Oid *argtypes;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.167 2007/02/06 02:59:13 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.168 2007/02/20 17:32:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -344,7 +344,7 @@ typedef struct EState ...@@ -344,7 +344,7 @@ typedef struct EState
ExprContext *es_per_tuple_exprcontext; ExprContext *es_per_tuple_exprcontext;
/* Below is to re-evaluate plan qual in READ COMMITTED mode */ /* Below is to re-evaluate plan qual in READ COMMITTED mode */
Plan *es_topPlan; /* link to top of plan tree */ PlannedStmt *es_plannedstmt; /* link to top of plan tree */
struct evalPlanQual *es_evalPlanQual; /* chain of PlanQual states */ struct evalPlanQual *es_evalPlanQual; /* chain of PlanQual states */
bool *es_evTupleNull; /* local array of EPQ status */ bool *es_evTupleNull; /* local array of EPQ status */
HeapTuple *es_evTuple; /* shared array of EPQ substitute tuples */ HeapTuple *es_evTuple; /* shared array of EPQ substitute tuples */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.195 2007/02/19 07:03:31 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.196 2007/02/20 17:32:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -141,6 +141,7 @@ typedef enum NodeTag ...@@ -141,6 +141,7 @@ typedef enum NodeTag
T_RangeTblRef, T_RangeTblRef,
T_JoinExpr, T_JoinExpr,
T_FromExpr, T_FromExpr,
T_IntoClause,
/* /*
* TAGS FOR EXPRESSION STATE NODES (execnodes.h) * TAGS FOR EXPRESSION STATE NODES (execnodes.h)
...@@ -225,9 +226,10 @@ typedef enum NodeTag ...@@ -225,9 +226,10 @@ typedef enum NodeTag
T_OidList, T_OidList,
/* /*
* TAGS FOR PARSE TREE NODES (parsenodes.h) * TAGS FOR STATEMENT NODES (mostly in parsenodes.h)
*/ */
T_Query = 700, T_Query = 700,
T_PlannedStmt,
T_InsertStmt, T_InsertStmt,
T_DeleteStmt, T_DeleteStmt,
T_UpdateStmt, T_UpdateStmt,
...@@ -302,8 +304,12 @@ typedef enum NodeTag ...@@ -302,8 +304,12 @@ typedef enum NodeTag
T_AlterOwnerStmt, T_AlterOwnerStmt,
T_DropOwnedStmt, T_DropOwnedStmt,
T_ReassignOwnedStmt, T_ReassignOwnedStmt,
T_CompositeTypeStmt,
T_A_Expr = 800, /*
* TAGS FOR PARSE TREE NODES (parsenodes.h)
*/
T_A_Expr = 900,
T_ColumnRef, T_ColumnRef,
T_ParamRef, T_ParamRef,
T_A_Const, T_A_Const,
...@@ -328,7 +334,6 @@ typedef enum NodeTag ...@@ -328,7 +334,6 @@ typedef enum NodeTag
T_FuncWithArgs, T_FuncWithArgs,
T_PrivTarget, T_PrivTarget,
T_CreateOpClassItem, T_CreateOpClassItem,
T_CompositeTypeStmt,
T_InhRelation, T_InhRelation,
T_FunctionParameter, T_FunctionParameter,
T_LockingClause, T_LockingClause,
...@@ -343,7 +348,7 @@ typedef enum NodeTag ...@@ -343,7 +348,7 @@ typedef enum NodeTag
* purposes (usually because they are involved in APIs where we want to * purposes (usually because they are involved in APIs where we want to
* pass multiple object types through the same pointer). * pass multiple object types through the same pointer).
*/ */
T_TriggerData = 900, /* in commands/trigger.h */ T_TriggerData = 950, /* in commands/trigger.h */
T_ReturnSetInfo, /* in nodes/execnodes.h */ T_ReturnSetInfo, /* in nodes/execnodes.h */
T_TIDBitmap /* in nodes/tidbitmap.h */ T_TIDBitmap /* in nodes/tidbitmap.h */
} NodeTag; } NodeTag;
...@@ -430,10 +435,9 @@ typedef double Cost; /* execution cost (in page-access units) */ ...@@ -430,10 +435,9 @@ typedef double Cost; /* execution cost (in page-access units) */
/* /*
* CmdType - * CmdType -
* enums for type of operation represented by a Query * enums for type of operation represented by a Query or PlannedStmt
* *
* ??? could have put this in parsenodes.h but many files not in the * This is needed in both parsenodes.h and plannodes.h, so put it here...
* optimizer also need this...
*/ */
typedef enum CmdType typedef enum CmdType
{ {
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.340 2007/02/03 14:06:55 petere Exp $ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.341 2007/02/20 17:32:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -27,15 +27,6 @@ typedef enum QuerySource ...@@ -27,15 +27,6 @@ typedef enum QuerySource
QSRC_NON_INSTEAD_RULE /* added by non-INSTEAD rule */ QSRC_NON_INSTEAD_RULE /* added by non-INSTEAD rule */
} QuerySource; } QuerySource;
/* What to do at commit time for temporary relations */
typedef enum OnCommitAction
{
ONCOMMIT_NOOP, /* No ON COMMIT clause (do nothing) */
ONCOMMIT_PRESERVE_ROWS, /* ON COMMIT PRESERVE ROWS (do nothing) */
ONCOMMIT_DELETE_ROWS, /* ON COMMIT DELETE ROWS */
ONCOMMIT_DROP /* ON COMMIT DROP */
} OnCommitAction;
/* Sort ordering options for ORDER BY and CREATE INDEX */ /* Sort ordering options for ORDER BY and CREATE INDEX */
typedef enum SortByDir typedef enum SortByDir
{ {
...@@ -86,11 +77,14 @@ typedef uint32 AclMode; /* a bitmask of privilege bits */ ...@@ -86,11 +77,14 @@ typedef uint32 AclMode; /* a bitmask of privilege bits */
/* /*
* Query - * Query -
* all statements are turned into a Query tree (via transformStmt) * Parse analysis turns all statements into a Query tree (via transformStmt)
* for further processing by the optimizer * for further processing by the rewriter and planner.
* *
* utility statements (i.e. non-optimizable statements) have the * Utility statements (i.e. non-optimizable statements) have the
* utilityStmt field set, and the Query itself is mostly dummy. * utilityStmt field set, and the Query itself is mostly dummy.
*
* Planning converts a Query tree into a Plan tree headed by a PlannedStmt
* noded --- the Query structure is not used by the executor.
*/ */
typedef struct Query typedef struct Query
{ {
...@@ -108,10 +102,7 @@ typedef struct Query ...@@ -108,10 +102,7 @@ typedef struct Query
int resultRelation; /* rtable index of target relation for int resultRelation; /* rtable index of target relation for
* INSERT/UPDATE/DELETE; 0 for SELECT */ * INSERT/UPDATE/DELETE; 0 for SELECT */
RangeVar *into; /* target relation for SELECT INTO */ IntoClause *into; /* target for SELECT INTO / CREATE TABLE AS */
List *intoOptions; /* options from WITH clause */
OnCommitAction intoOnCommit; /* what do we do at COMMIT? */
char *intoTableSpaceName; /* table space to use, or NULL */
bool hasAggs; /* has aggregates in tlist or havingQual */ bool hasAggs; /* has aggregates in tlist or havingQual */
bool hasSubLinks; /* has subquery SubLink */ bool hasSubLinks; /* has subquery SubLink */
...@@ -138,29 +129,6 @@ typedef struct Query ...@@ -138,29 +129,6 @@ typedef struct Query
Node *setOperations; /* set-operation tree if this is top level of Node *setOperations; /* set-operation tree if this is top level of
* a UNION/INTERSECT/EXCEPT query */ * a UNION/INTERSECT/EXCEPT query */
/*
* If the resultRelation turns out to be the parent of an inheritance
* tree, the planner will add all the child tables to the rtable and store
* a list of the rtindexes of all the result relations here. This is done
* at plan time, not parse time, since we don't want to commit to the
* exact set of child tables at parse time. XXX This field ought to go in
* some sort of TopPlan plan node, not in the Query.
*/
List *resultRelations; /* integer list of RT indexes, or NIL */
/*
* If the query has a returningList then the planner will store a list of
* processed targetlists (one per result relation) here. We must have a
* separate RETURNING targetlist for each result rel because column
* numbers may vary within an inheritance tree. In the targetlists, Vars
* referencing the result relation will have their original varno and
* varattno, while Vars referencing other rels will be converted to have
* varno OUTER and varattno referencing a resjunk entry in the top plan
* node's targetlist. XXX This field ought to go in some sort of TopPlan
* plan node, not in the Query.
*/
List *returningLists; /* list of lists of TargetEntry, or NIL */
} Query; } Query;
...@@ -761,17 +729,10 @@ typedef struct SelectStmt ...@@ -761,17 +729,10 @@ typedef struct SelectStmt
/* /*
* These fields are used only in "leaf" SelectStmts. * These fields are used only in "leaf" SelectStmts.
*
* into, intoColNames, intoOptions, intoOnCommit, and intoTableSpaceName
* are a kluge; they belong somewhere else...
*/ */
List *distinctClause; /* NULL, list of DISTINCT ON exprs, or List *distinctClause; /* NULL, list of DISTINCT ON exprs, or
* lcons(NIL,NIL) for all (SELECT DISTINCT) */ * lcons(NIL,NIL) for all (SELECT DISTINCT) */
RangeVar *into; /* target table (for select into table) */ IntoClause *into; /* target for SELECT INTO / CREATE TABLE AS */
List *intoColNames; /* column names for into table */
List *intoOptions; /* options from WITH clause */
OnCommitAction intoOnCommit; /* what do we do at COMMIT? */
char *intoTableSpaceName; /* table space to use, or NULL */
List *targetList; /* the target list (of ResTarget) */ List *targetList; /* the target list (of ResTarget) */
List *fromClause; /* the FROM clause */ List *fromClause; /* the FROM clause */
Node *whereClause; /* WHERE qualification */ Node *whereClause; /* WHERE qualification */
...@@ -1994,10 +1955,7 @@ typedef struct ExecuteStmt ...@@ -1994,10 +1955,7 @@ typedef struct ExecuteStmt
{ {
NodeTag type; NodeTag type;
char *name; /* The name of the plan to execute */ char *name; /* The name of the plan to execute */
RangeVar *into; /* Optional table to store results in */ IntoClause *into; /* Optional table to store results in */
List *intoOptions; /* Options from WITH clause */
OnCommitAction into_on_commit; /* What do we do at COMMIT? */
char *into_tbl_space; /* Tablespace to use, or NULL */
List *params; /* Values to assign to parameters */ List *params; /* Values to assign to parameters */
} ExecuteStmt; } ExecuteStmt;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.90 2007/02/19 02:23:12 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/plannodes.h,v 1.91 2007/02/20 17:32:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -24,6 +24,48 @@ ...@@ -24,6 +24,48 @@
* ---------------------------------------------------------------- * ----------------------------------------------------------------
*/ */
/* ----------------
* PlannedStmt node
*
* The output of the planner is a Plan tree headed by a PlannedStmt node.
* PlannedStmt holds the "one time" information needed by the executor.
* ----------------
*/
typedef struct PlannedStmt
{
NodeTag type;
CmdType commandType; /* select|insert|update|delete */
bool canSetTag; /* do I set the command result tag? */
struct Plan *planTree; /* tree of Plan nodes */
List *rtable; /* list of RangeTblEntry nodes */
/* rtable indexes of target relations for INSERT/UPDATE/DELETE */
List *resultRelations; /* integer list of RT indexes, or NIL */
IntoClause *into; /* target for SELECT INTO / CREATE TABLE AS */
/*
* If the query has a returningList then the planner will store a list of
* processed targetlists (one per result relation) here. We must have a
* separate RETURNING targetlist for each result rel because column
* numbers may vary within an inheritance tree. In the targetlists, Vars
* referencing the result relation will have their original varno and
* varattno, while Vars referencing other rels will be converted to have
* varno OUTER and varattno referencing a resjunk entry in the top plan
* node's targetlist.
*/
List *returningLists; /* list of lists of TargetEntry, or NIL */
List *rowMarks; /* a list of RowMarkClause's */
int nParamExec; /* number of PARAM_EXEC Params used */
} PlannedStmt;
/* ---------------- /* ----------------
* Plan node * Plan node
* *
...@@ -75,15 +117,6 @@ typedef struct Plan ...@@ -75,15 +117,6 @@ typedef struct Plan
*/ */
Bitmapset *extParam; Bitmapset *extParam;
Bitmapset *allParam; Bitmapset *allParam;
/*
* We really need in some TopPlan node to store range table and
* resultRelation from Query there and get rid of Query itself from
* Executor. Some other stuff like below could be put there, too.
*/
int nParamExec; /* Number of them in entire query. This is to
* get Executor know about how many PARAM_EXEC
* there are in query plan. */
} Plan; } Plan;
/* ---------------- /* ----------------
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.125 2007/02/19 07:03:31 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.126 2007/02/20 17:32:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -49,6 +49,15 @@ typedef enum InhOption ...@@ -49,6 +49,15 @@ typedef enum InhOption
INH_DEFAULT /* Use current SQL_inheritance option */ INH_DEFAULT /* Use current SQL_inheritance option */
} InhOption; } InhOption;
/* What to do at commit time for temporary relations */
typedef enum OnCommitAction
{
ONCOMMIT_NOOP, /* No ON COMMIT clause (do nothing) */
ONCOMMIT_PRESERVE_ROWS, /* ON COMMIT PRESERVE ROWS (do nothing) */
ONCOMMIT_DELETE_ROWS, /* ON COMMIT DELETE ROWS */
ONCOMMIT_DROP /* ON COMMIT DROP */
} OnCommitAction;
/* /*
* RangeVar - range variable, used in FROM clauses * RangeVar - range variable, used in FROM clauses
* *
...@@ -69,6 +78,20 @@ typedef struct RangeVar ...@@ -69,6 +78,20 @@ typedef struct RangeVar
Alias *alias; /* table alias & optional column aliases */ Alias *alias; /* table alias & optional column aliases */
} RangeVar; } RangeVar;
/*
* IntoClause - target information for SELECT INTO and CREATE TABLE AS
*/
typedef struct IntoClause
{
NodeTag type;
RangeVar *rel; /* target relation name */
List *colNames; /* column names to assign, or NIL */
List *options; /* options from WITH clause */
OnCommitAction onCommit; /* what do we do at COMMIT? */
char *tableSpaceName; /* table space to use, or NULL */
} IntoClause;
/* ---------------------------------------------------------------- /* ----------------------------------------------------------------
* node types for executable expressions * node types for executable expressions
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.136 2007/02/19 07:03:33 tgl Exp $ * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.137 2007/02/20 17:32:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -110,6 +110,10 @@ typedef struct PlannerInfo ...@@ -110,6 +110,10 @@ typedef struct PlannerInfo
List *join_rel_list; /* list of join-relation RelOptInfos */ List *join_rel_list; /* list of join-relation RelOptInfos */
struct HTAB *join_rel_hash; /* optional hashtable for join relations */ struct HTAB *join_rel_hash; /* optional hashtable for join relations */
List *resultRelations; /* integer list of RT indexes, or NIL */
List *returningLists; /* list of lists of TargetEntry, or NIL */
List *init_plans; /* init subplans for query */ List *init_plans; /* init subplans for query */
List *eq_classes; /* list of active EquivalenceClasses */ List *eq_classes; /* list of active EquivalenceClasses */
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/optimizer/planner.h,v 1.37 2007/02/19 07:03:34 tgl Exp $ * $PostgreSQL: pgsql/src/include/optimizer/planner.h,v 1.38 2007/02/20 17:32:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -18,10 +18,10 @@ ...@@ -18,10 +18,10 @@
#include "nodes/relation.h" #include "nodes/relation.h"
extern Plan *planner(Query *parse, bool isCursor, int cursorOptions, extern PlannedStmt *planner(Query *parse, bool isCursor, int cursorOptions,
ParamListInfo boundParams); ParamListInfo boundParams);
extern Plan *subquery_planner(PlannerGlobal *glob, Query *parse, extern Plan *subquery_planner(PlannerGlobal *glob, Query *parse,
Index level, double tuple_fraction, Index level, double tuple_fraction,
List **subquery_pathkeys); PlannerInfo **subroot);
#endif /* PLANNER_H */ #endif /* PLANNER_H */
...@@ -7,23 +7,26 @@ ...@@ -7,23 +7,26 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/tcop/pquery.h,v 1.40 2007/01/05 22:19:58 momjian Exp $ * $PostgreSQL: pgsql/src/include/tcop/pquery.h,v 1.41 2007/02/20 17:32:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#ifndef PQUERY_H #ifndef PQUERY_H
#define PQUERY_H #define PQUERY_H
#include "nodes/parsenodes.h"
#include "utils/portal.h" #include "utils/portal.h"
extern DLLIMPORT Portal ActivePortal; extern DLLIMPORT Portal ActivePortal;
extern PortalStrategy ChoosePortalStrategy(List *parseTrees); extern PortalStrategy ChoosePortalStrategy(List *stmts);
extern List *FetchPortalTargetList(Portal portal); extern List *FetchPortalTargetList(Portal portal);
extern List *FetchStatementTargetList(Node *stmt);
extern void PortalStart(Portal portal, ParamListInfo params, extern void PortalStart(Portal portal, ParamListInfo params,
Snapshot snapshot); Snapshot snapshot);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.86 2007/01/05 22:19:58 momjian Exp $ * $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.87 2007/02/20 17:32:17 tgl Exp $
* *
* OLD COMMENTS * OLD COMMENTS
* This file was created so that other c files could get the two * This file was created so that other c files could get the two
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#define TCOPPROT_H #define TCOPPROT_H
#include "executor/execdesc.h" #include "executor/execdesc.h"
#include "nodes/parsenodes.h"
#include "utils/guc.h" #include "utils/guc.h"
...@@ -50,7 +51,7 @@ extern List *pg_parse_and_rewrite(const char *query_string, ...@@ -50,7 +51,7 @@ extern List *pg_parse_and_rewrite(const char *query_string,
extern List *pg_parse_query(const char *query_string); extern List *pg_parse_query(const char *query_string);
extern List *pg_analyze_and_rewrite(Node *parsetree, const char *query_string, extern List *pg_analyze_and_rewrite(Node *parsetree, const char *query_string,
Oid *paramTypes, int numParams); Oid *paramTypes, int numParams);
extern Plan *pg_plan_query(Query *querytree, ParamListInfo boundParams); extern PlannedStmt *pg_plan_query(Query *querytree, ParamListInfo boundParams);
extern List *pg_plan_queries(List *querytrees, ParamListInfo boundParams, extern List *pg_plan_queries(List *querytrees, ParamListInfo boundParams,
bool needSnapshot); bool needSnapshot);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/tcop/utility.h,v 1.30 2007/01/05 22:19:58 momjian Exp $ * $PostgreSQL: pgsql/src/include/tcop/utility.h,v 1.31 2007/02/20 17:32:17 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -26,15 +26,9 @@ extern TupleDesc UtilityTupleDescriptor(Node *parsetree); ...@@ -26,15 +26,9 @@ extern TupleDesc UtilityTupleDescriptor(Node *parsetree);
extern const char *CreateCommandTag(Node *parsetree); extern const char *CreateCommandTag(Node *parsetree);
extern const char *CreateQueryTag(Query *parsetree);
extern LogStmtLevel GetCommandLogLevel(Node *parsetree); extern LogStmtLevel GetCommandLogLevel(Node *parsetree);
extern LogStmtLevel GetQueryLogLevel(Query *parsetree); extern bool CommandIsReadOnly(Node *parsetree);
extern bool QueryReturnsTuples(Query *parsetree);
extern bool QueryIsReadOnly(Query *parsetree);
extern void CheckRelationOwnership(RangeVar *rel, bool noCatalogs); extern void CheckRelationOwnership(RangeVar *rel, bool noCatalogs);
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* to let the client suspend an update-type query partway through! Because * to let the client suspend an update-type query partway through! Because
* the query rewriter does not allow arbitrary ON SELECT rewrite rules, * the query rewriter does not allow arbitrary ON SELECT rewrite rules,
* only queries that were originally update-type could produce multiple * only queries that were originally update-type could produce multiple
* parse/plan trees; so the restriction to a single query is not a problem * plan trees; so the restriction to a single query is not a problem
* in practice. * in practice.
* *
* For SQL cursors, we support three kinds of scroll behavior: * For SQL cursors, we support three kinds of scroll behavior:
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/utils/portal.h,v 1.72 2007/01/05 22:19:59 momjian Exp $ * $PostgreSQL: pgsql/src/include/utils/portal.h,v 1.73 2007/02/20 17:32:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -124,9 +124,8 @@ typedef struct PortalData ...@@ -124,9 +124,8 @@ typedef struct PortalData
/* The query or queries the portal will execute */ /* The query or queries the portal will execute */
const char *sourceText; /* text of query, if known (may be NULL) */ const char *sourceText; /* text of query, if known (may be NULL) */
const char *commandTag; /* command tag for original query */ const char *commandTag; /* command tag for original query */
List *parseTrees; /* parse tree(s) */ List *stmts; /* PlannedStmts and/or utility statements */
List *planTrees; /* plan tree(s) */ MemoryContext queryContext; /* where the plan trees live */
MemoryContext queryContext; /* where the parse trees live */
/* /*
* Note: queryContext effectively identifies which prepared statement the * Note: queryContext effectively identifies which prepared statement the
...@@ -191,7 +190,7 @@ typedef struct PortalData ...@@ -191,7 +190,7 @@ typedef struct PortalData
*/ */
#define PortalGetQueryDesc(portal) ((portal)->queryDesc) #define PortalGetQueryDesc(portal) ((portal)->queryDesc)
#define PortalGetHeapMemory(portal) ((portal)->heap) #define PortalGetHeapMemory(portal) ((portal)->heap)
#define PortalGetPrimaryQuery(portal) PortalListGetPrimaryQuery((portal)->parseTrees) #define PortalGetPrimaryStmt(portal) PortalListGetPrimaryStmt((portal)->stmts)
/* Prototypes for functions in utils/mmgr/portalmem.c */ /* Prototypes for functions in utils/mmgr/portalmem.c */
...@@ -217,10 +216,9 @@ extern void PortalDefineQuery(Portal portal, ...@@ -217,10 +216,9 @@ extern void PortalDefineQuery(Portal portal,
const char *prepStmtName, const char *prepStmtName,
const char *sourceText, const char *sourceText,
const char *commandTag, const char *commandTag,
List *parseTrees, List *stmts,
List *planTrees,
MemoryContext queryContext); MemoryContext queryContext);
extern Query *PortalListGetPrimaryQuery(List *parseTrees); extern Node *PortalListGetPrimaryStmt(List *stmts);
extern void PortalCreateHoldStore(Portal portal); extern void PortalCreateHoldStore(Portal portal);
#endif /* PORTAL_H */ #endif /* PORTAL_H */
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.188 2007/02/08 18:37:30 tgl Exp $ * $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.189 2007/02/20 17:32:18 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -2380,20 +2380,20 @@ exec_stmt_execsql(PLpgSQL_execstate *estate, ...@@ -2380,20 +2380,20 @@ exec_stmt_execsql(PLpgSQL_execstate *estate,
exec_prepare_plan(estate, expr); exec_prepare_plan(estate, expr);
stmt->mod_stmt = false; stmt->mod_stmt = false;
spi_plan = (_SPI_plan *) expr->plan; spi_plan = (_SPI_plan *) expr->plan;
foreach(l, spi_plan->qtlist) foreach(l, spi_plan->stmt_list_list)
{ {
ListCell *l2; ListCell *l2;
foreach(l2, (List *) lfirst(l)) foreach(l2, (List *) lfirst(l))
{ {
Query *q = (Query *) lfirst(l2); PlannedStmt *p = (PlannedStmt *) lfirst(l2);
Assert(IsA(q, Query)); if (IsA(p, PlannedStmt) &&
if (q->canSetTag) p->canSetTag)
{ {
if (q->commandType == CMD_INSERT || if (p->commandType == CMD_INSERT ||
q->commandType == CMD_UPDATE || p->commandType == CMD_UPDATE ||
q->commandType == CMD_DELETE) p->commandType == CMD_DELETE)
stmt->mod_stmt = true; stmt->mod_stmt = true;
} }
} }
...@@ -4674,6 +4674,8 @@ static void ...@@ -4674,6 +4674,8 @@ static void
exec_simple_check_plan(PLpgSQL_expr *expr) exec_simple_check_plan(PLpgSQL_expr *expr)
{ {
_SPI_plan *spi_plan = (_SPI_plan *) expr->plan; _SPI_plan *spi_plan = (_SPI_plan *) expr->plan;
List *sublist;
PlannedStmt *stmt;
Plan *plan; Plan *plan;
TargetEntry *tle; TargetEntry *tle;
...@@ -4683,17 +4685,20 @@ exec_simple_check_plan(PLpgSQL_expr *expr) ...@@ -4683,17 +4685,20 @@ exec_simple_check_plan(PLpgSQL_expr *expr)
* 1. We can only evaluate queries that resulted in one single execution * 1. We can only evaluate queries that resulted in one single execution
* plan * plan
*/ */
if (list_length(spi_plan->ptlist) != 1) if (list_length(spi_plan->stmt_list_list) != 1)
return;
sublist = (List *) linitial(spi_plan->stmt_list_list);
if (list_length(sublist) != 1)
return; return;
plan = (Plan *) linitial(spi_plan->ptlist); stmt = (PlannedStmt *) linitial(sublist);
/* /*
* 2. It must be a RESULT plan --> no scan's required * 2. It must be a RESULT plan --> no scan's required
*/ */
if (plan == NULL) /* utility statement produces this */ if (!IsA(stmt, PlannedStmt))
return; return;
plan = stmt->planTree;
if (!IsA(plan, Result)) if (!IsA(plan, Result))
return; return;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment