diff options
Diffstat (limited to 'src/backend/commands')
-rw-r--r-- | src/backend/commands/copy.c | 9 | ||||
-rw-r--r-- | src/backend/commands/explain.c | 13 | ||||
-rw-r--r-- | src/backend/commands/portalcmds.c | 10 | ||||
-rw-r--r-- | src/backend/commands/prepare.c | 186 |
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); |