summaryrefslogtreecommitdiff
path: root/src/backend/commands
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/commands')
-rw-r--r--src/backend/commands/copy.c9
-rw-r--r--src/backend/commands/explain.c13
-rw-r--r--src/backend/commands/portalcmds.c10
-rw-r--r--src/backend/commands/prepare.c186
4 files changed, 107 insertions, 111 deletions
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index e61384beec..30118d5237 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -8,7 +8,7 @@
*
*
* 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)
{
Query *query = stmt->query;
List *rewritten;
- Plan *plan;
+ PlannedStmt *plan;
DestReceiver *dest;
Assert(query);
+ Assert(query->commandType == CMD_SELECT);
Assert(!is_from);
cstate->rel = NULL;
@@ -999,6 +1000,7 @@ DoCopy(const CopyStmt *stmt)
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("COPY (SELECT) WITH OIDS is not supported")));
+ /* Query mustn't use INTO, either */
if (query->into)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -1016,7 +1018,6 @@ DoCopy(const CopyStmt *stmt)
* shouldn't modify its input ... FIXME someday.
*/
query = copyObject(query);
- Assert(query->commandType == CMD_SELECT);
/*
* Must acquire locks in case we didn't come fresh from the parser.
@@ -1051,7 +1052,7 @@ DoCopy(const CopyStmt *stmt)
((DR_copy *) dest)->cstate = cstate;
/* Create a QueryDesc requesting no output */
- cstate->queryDesc = CreateQueryDesc(query, plan,
+ cstate->queryDesc = CreateQueryDesc(plan,
ActiveSnapshot, InvalidSnapshot,
dest, NULL, false);
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 7b2c521a35..58b7e6ded9 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994-5, Regents of the University of California
*
* 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
ExplainOneQuery(Query *query, ExplainStmt *stmt, ParamListInfo params,
TupOutputState *tstate)
{
- Plan *plan;
+ PlannedStmt *plan;
QueryDesc *queryDesc;
bool isCursor = false;
int cursorOptions = 0;
@@ -203,7 +203,7 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, ParamListInfo params,
ActiveSnapshot->curcid = GetCurrentCommandId();
/* Create a QueryDesc requesting no output */
- queryDesc = CreateQueryDesc(query, plan,
+ queryDesc = CreateQueryDesc(plan,
ActiveSnapshot, InvalidSnapshot,
None_Receiver, params,
stmt->analyze);
@@ -260,14 +260,14 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
es->printNodes = stmt->verbose;
es->printAnalyze = stmt->analyze;
- es->rtable = queryDesc->parsetree->rtable;
+ es->rtable = queryDesc->plannedstmt->rtable;
if (es->printNodes)
{
char *s;
char *f;
- s = nodeToString(queryDesc->plantree);
+ s = nodeToString(queryDesc->plannedstmt->planTree);
if (s)
{
if (Explain_pretty_print)
@@ -282,7 +282,8 @@ ExplainOnePlan(QueryDesc *queryDesc, ExplainStmt *stmt,
}
initStringInfo(&buf);
- explain_outNode(&buf, queryDesc->plantree, queryDesc->planstate,
+ explain_outNode(&buf,
+ queryDesc->plannedstmt->planTree, queryDesc->planstate,
NULL, 0, es);
/*
diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c
index d1c119ca08..0219650c06 100644
--- a/src/backend/commands/portalcmds.c
+++ b/src/backend/commands/portalcmds.c
@@ -14,7 +14,7 @@
*
*
* 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)
{
List *rewritten;
Query *query;
- Plan *plan;
+ PlannedStmt *plan;
Portal portal;
MemoryContext oldContext;
@@ -98,13 +98,12 @@ PerformCursorOpen(DeclareCursorStmt *stmt, ParamListInfo 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);
oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
- query = copyObject(query);
plan = copyObject(plan);
/*
@@ -115,7 +114,6 @@ PerformCursorOpen(DeclareCursorStmt *stmt, ParamListInfo params)
NULL,
debug_query_string ? pstrdup(debug_query_string) : NULL,
"SELECT", /* cursor's query is always a SELECT */
- list_make1(query),
list_make1(plan),
PortalGetHeapMemory(portal));
@@ -140,7 +138,7 @@ PerformCursorOpen(DeclareCursorStmt *stmt, ParamListInfo params)
portal->cursorOptions = stmt->options;
if (!(portal->cursorOptions & (CURSOR_OPT_SCROLL | CURSOR_OPT_NO_SCROLL)))
{
- if (ExecSupportsBackwardScan(plan))
+ if (ExecSupportsBackwardScan(plan->planTree))
portal->cursorOptions |= CURSOR_OPT_SCROLL;
else
portal->cursorOptions |= CURSOR_OPT_NO_SCROLL;
diff --git a/src/backend/commands/prepare.c b/src/backend/commands/prepare.c
index ecd5074211..8a5382c737 100644
--- a/src/backend/commands/prepare.c
+++ b/src/backend/commands/prepare.c
@@ -10,7 +10,7 @@
* Copyright (c) 2002-2007, PostgreSQL Global Development Group
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.68 2007/01/28 19:05:35 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/prepare.c,v 1.69 2007/02/20 17:32:14 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -114,9 +114,9 @@ PrepareQuery(PrepareStmt *stmt)
StorePreparedStatement(stmt->name,
debug_query_string,
commandTag,
- query_list,
plan_list,
stmt->argtype_oids,
+ true,
true);
}
@@ -129,8 +129,7 @@ ExecuteQuery(ExecuteStmt *stmt, ParamListInfo params,
{
PreparedStatement *entry;
char *query_string;
- List *query_list,
- *plan_list;
+ List *plan_list;
MemoryContext qcontext;
ParamListInfo paramLI = NULL;
EState *estate = NULL;
@@ -139,13 +138,18 @@ ExecuteQuery(ExecuteStmt *stmt, ParamListInfo params,
/* Look it up in the hash table */
entry = FetchPreparedStatement(stmt->name, true);
+ /*
+ * Punt if not fully planned. (Currently, that only happens for the
+ * protocol-level unnamed statement, which can't be accessed from SQL;
+ * so there's no point in doing more than a quick check here.)
+ */
+ if (!entry->fully_planned)
+ elog(ERROR, "EXECUTE does not support unplanned prepared statements");
+
query_string = entry->query_string;
- query_list = entry->query_list;
- plan_list = entry->plan_list;
+ plan_list = entry->stmt_list;
qcontext = entry->context;
- Assert(list_length(query_list) == list_length(plan_list));
-
/* Evaluate parameters, if any */
if (entry->argtype_list != NIL)
{
@@ -172,30 +176,26 @@ ExecuteQuery(ExecuteStmt *stmt, ParamListInfo params,
if (stmt->into)
{
MemoryContext oldContext;
- Query *query;
+ PlannedStmt *pstmt;
- oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
+ qcontext = PortalGetHeapMemory(portal);
+ oldContext = MemoryContextSwitchTo(qcontext);
if (query_string)
query_string = pstrdup(query_string);
- query_list = copyObject(query_list);
plan_list = copyObject(plan_list);
- qcontext = PortalGetHeapMemory(portal);
- if (list_length(query_list) != 1)
+ if (list_length(plan_list) != 1)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("prepared statement is not a SELECT")));
- query = (Query *) linitial(query_list);
- if (query->commandType != CMD_SELECT)
+ pstmt = (PlannedStmt *) linitial(plan_list);
+ if (!IsA(pstmt, PlannedStmt) ||
+ pstmt->commandType != CMD_SELECT)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("prepared statement is not a SELECT")));
- query->into = copyObject(stmt->into);
- query->intoOptions = copyObject(stmt->intoOptions);
- query->intoOnCommit = stmt->into_on_commit;
- if (stmt->into_tbl_space)
- query->intoTableSpaceName = pstrdup(stmt->into_tbl_space);
+ pstmt->into = copyObject(stmt->into);
MemoryContextSwitchTo(oldContext);
}
@@ -204,7 +204,6 @@ ExecuteQuery(ExecuteStmt *stmt, ParamListInfo params,
NULL,
query_string,
entry->commandTag,
- query_list,
plan_list,
qcontext);
@@ -305,9 +304,9 @@ void
StorePreparedStatement(const char *stmt_name,
const char *query_string,
const char *commandTag,
- List *query_list,
- List *plan_list,
+ List *stmt_list,
List *argtype_list,
+ bool fully_planned,
bool from_sql)
{
PreparedStatement *entry;
@@ -345,8 +344,7 @@ StorePreparedStatement(const char *stmt_name,
* incomplete (ie corrupt) hashtable entry.
*/
qstring = query_string ? pstrdup(query_string) : NULL;
- query_list = (List *) copyObject(query_list);
- plan_list = (List *) copyObject(plan_list);
+ stmt_list = (List *) copyObject(stmt_list);
argtype_list = list_copy(argtype_list);
/* Now we can add entry to hash table */
@@ -363,12 +361,12 @@ StorePreparedStatement(const char *stmt_name,
/* Fill in the hash table entry with copied data */
entry->query_string = qstring;
entry->commandTag = commandTag;
- entry->query_list = query_list;
- entry->plan_list = plan_list;
+ entry->stmt_list = stmt_list;
entry->argtype_list = argtype_list;
+ entry->fully_planned = fully_planned;
+ entry->from_sql = from_sql;
entry->context = entrycxt;
entry->prepare_time = GetCurrentStatementStartTimestamp();
- entry->from_sql = from_sql;
MemoryContextSwitchTo(oldcxt);
}
@@ -426,21 +424,54 @@ FetchPreparedStatementParams(const char *stmt_name)
TupleDesc
FetchPreparedStatementResultDesc(PreparedStatement *stmt)
{
+ Node *node;
Query *query;
+ PlannedStmt *pstmt;
- switch (ChoosePortalStrategy(stmt->query_list))
+ switch (ChoosePortalStrategy(stmt->stmt_list))
{
case PORTAL_ONE_SELECT:
- query = (Query *) linitial(stmt->query_list);
- return ExecCleanTypeFromTL(query->targetList, false);
+ node = (Node *) linitial(stmt->stmt_list);
+ if (IsA(node, Query))
+ {
+ query = (Query *) node;
+ return ExecCleanTypeFromTL(query->targetList, false);
+ }
+ if (IsA(node, PlannedStmt))
+ {
+ pstmt = (PlannedStmt *) node;
+ return ExecCleanTypeFromTL(pstmt->planTree->targetlist, false);
+ }
+ /* other cases shouldn't happen, but return NULL */
+ break;
case PORTAL_ONE_RETURNING:
- query = PortalListGetPrimaryQuery(stmt->query_list);
- return ExecCleanTypeFromTL(query->returningList, false);
+ node = PortalListGetPrimaryStmt(stmt->stmt_list);
+ if (IsA(node, Query))
+ {
+ query = (Query *) node;
+ Assert(query->returningList);
+ return ExecCleanTypeFromTL(query->returningList, false);
+ }
+ if (IsA(node, PlannedStmt))
+ {
+ pstmt = (PlannedStmt *) node;
+ Assert(pstmt->returningLists);
+ return ExecCleanTypeFromTL((List *) linitial(pstmt->returningLists), false);
+ }
+ /* other cases shouldn't happen, but return NULL */
+ break;
case PORTAL_UTIL_SELECT:
- query = (Query *) linitial(stmt->query_list);
- return UtilityTupleDescriptor(query->utilityStmt);
+ node = (Node *) linitial(stmt->stmt_list);
+ if (IsA(node, Query))
+ {
+ query = (Query *) node;
+ Assert(query->utilityStmt);
+ return UtilityTupleDescriptor(query->utilityStmt);
+ }
+ /* else it's a bare utility statement */
+ return UtilityTupleDescriptor(node);
case PORTAL_MULTI_QUERY:
/* will not return tuples */
@@ -460,7 +491,7 @@ FetchPreparedStatementResultDesc(PreparedStatement *stmt)
bool
PreparedStatementReturnsTuples(PreparedStatement *stmt)
{
- switch (ChoosePortalStrategy(stmt->query_list))
+ switch (ChoosePortalStrategy(stmt->stmt_list))
{
case PORTAL_ONE_SELECT:
case PORTAL_ONE_RETURNING:
@@ -480,52 +511,15 @@ PreparedStatementReturnsTuples(PreparedStatement *stmt)
* targetlist.
*
* Note: do not modify the result.
- *
- * XXX be careful to keep this in sync with FetchPortalTargetList,
- * and with UtilityReturnsTuples.
*/
List *
FetchPreparedStatementTargetList(PreparedStatement *stmt)
{
- PortalStrategy strategy = ChoosePortalStrategy(stmt->query_list);
-
- if (strategy == PORTAL_ONE_SELECT)
- return ((Query *) linitial(stmt->query_list))->targetList;
- if (strategy == PORTAL_ONE_RETURNING)
- return (PortalListGetPrimaryQuery(stmt->query_list))->returningList;
- if (strategy == PORTAL_UTIL_SELECT)
- {
- Node *utilityStmt;
-
- utilityStmt = ((Query *) linitial(stmt->query_list))->utilityStmt;
- switch (nodeTag(utilityStmt))
- {
- case T_FetchStmt:
- {
- FetchStmt *substmt = (FetchStmt *) utilityStmt;
- Portal subportal;
-
- Assert(!substmt->ismove);
- subportal = GetPortalByName(substmt->portalname);
- Assert(PortalIsValid(subportal));
- return FetchPortalTargetList(subportal);
- }
-
- case T_ExecuteStmt:
- {
- ExecuteStmt *substmt = (ExecuteStmt *) utilityStmt;
- PreparedStatement *entry;
-
- Assert(!substmt->into);
- entry = FetchPreparedStatement(substmt->name, true);
- return FetchPreparedStatementTargetList(entry);
- }
-
- default:
- break;
- }
- }
- return NIL;
+ /* no point in looking if it doesn't return tuples */
+ if (ChoosePortalStrategy(stmt->stmt_list) == PORTAL_MULTI_QUERY)
+ return NIL;
+ /* get the primary statement and find out what it returns */
+ return FetchStatementTargetList(PortalListGetPrimaryStmt(stmt->stmt_list));
}
/*
@@ -574,10 +568,8 @@ ExplainExecuteQuery(ExplainStmt *stmt, ParamListInfo params,
{
ExecuteStmt *execstmt = (ExecuteStmt *) stmt->query->utilityStmt;
PreparedStatement *entry;
- ListCell *q,
- *p;
- List *query_list,
- *plan_list;
+ List *plan_list;
+ ListCell *p;
ParamListInfo paramLI = NULL;
EState *estate = NULL;
@@ -587,10 +579,15 @@ ExplainExecuteQuery(ExplainStmt *stmt, ParamListInfo params,
/* Look it up in the hash table */
entry = FetchPreparedStatement(execstmt->name, true);
- query_list = entry->query_list;
- plan_list = entry->plan_list;
+ /*
+ * Punt if not fully planned. (Currently, that only happens for the
+ * protocol-level unnamed statement, which can't be accessed from SQL;
+ * so there's no point in doing more than a quick check here.)
+ */
+ if (!entry->fully_planned)
+ elog(ERROR, "EXPLAIN EXECUTE does not support unplanned prepared statements");
- Assert(list_length(query_list) == list_length(plan_list));
+ plan_list = entry->stmt_list;
/* Evaluate parameters, if any */
if (entry->argtype_list != NIL)
@@ -606,17 +603,16 @@ ExplainExecuteQuery(ExplainStmt *stmt, ParamListInfo params,
}
/* Explain each query */
- forboth(q, query_list, p, plan_list)
+ foreach(p, plan_list)
{
- Query *query = (Query *) lfirst(q);
- Plan *plan = (Plan *) lfirst(p);
+ PlannedStmt *pstmt = (PlannedStmt *) lfirst(p);
bool is_last_query;
is_last_query = (lnext(p) == NULL);
- if (query->commandType == CMD_UTILITY)
+ if (!IsA(pstmt, PlannedStmt))
{
- if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
+ if (IsA(pstmt, NotifyStmt))
do_text_output_oneline(tstate, "NOTIFY");
else
do_text_output_oneline(tstate, "UTILITY");
@@ -627,15 +623,15 @@ ExplainExecuteQuery(ExplainStmt *stmt, ParamListInfo params,
if (execstmt->into)
{
- if (query->commandType != CMD_SELECT)
+ if (pstmt->commandType != CMD_SELECT)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("prepared statement is not a SELECT")));
- /* Copy the query so we can modify it */
- query = copyObject(query);
+ /* Copy the stmt so we can modify it */
+ pstmt = copyObject(pstmt);
- query->into = execstmt->into;
+ pstmt->into = execstmt->into;
}
/*
@@ -648,7 +644,7 @@ ExplainExecuteQuery(ExplainStmt *stmt, ParamListInfo params,
ActiveSnapshot->curcid = GetCurrentCommandId();
/* Create a QueryDesc requesting no output */
- qdesc = CreateQueryDesc(query, plan,
+ qdesc = CreateQueryDesc(pstmt,
ActiveSnapshot, InvalidSnapshot,
None_Receiver,
paramLI, stmt->analyze);