diff options
Diffstat (limited to 'src/backend/tcop')
-rw-r--r-- | src/backend/tcop/dest.c | 4 | ||||
-rw-r--r-- | src/backend/tcop/postgres.c | 6 | ||||
-rw-r--r-- | src/backend/tcop/pquery.c | 39 | ||||
-rw-r--r-- | src/backend/tcop/utility.c | 81 |
4 files changed, 83 insertions, 47 deletions
diff --git a/src/backend/tcop/dest.c b/src/backend/tcop/dest.c index 943b6c141ca..c6ab54aa3bb 100644 --- a/src/backend/tcop/dest.c +++ b/src/backend/tcop/dest.c @@ -31,7 +31,7 @@ #include "access/printtup.h" #include "access/xact.h" #include "commands/copy.h" -#include "executor/executor.h" +#include "commands/createas.h" #include "executor/functions.h" #include "executor/tstoreReceiver.h" #include "libpq/libpq.h" @@ -118,7 +118,7 @@ CreateDestReceiver(CommandDest dest) return CreateTuplestoreDestReceiver(); case DestIntoRel: - return CreateIntoRelDestReceiver(); + return CreateIntoRelDestReceiver(NULL); case DestCopyOut: return CreateCopyDestReceiver(); diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 397c0734c29..14ca7681392 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -624,7 +624,7 @@ pg_analyze_and_rewrite_params(Node *parsetree, pstate->p_sourcetext = query_string; (*parserSetup) (pstate, parserSetupArg); - query = transformStmt(pstate, parsetree); + query = transformTopLevelStmt(pstate, parsetree); free_parsestate(pstate); @@ -975,7 +975,7 @@ exec_simple_query(const char *query_string) * end up being able to do this, keeping the parse/plan snapshot around * until after we start the portal doesn't cost much. */ - PortalStart(portal, NULL, snapshot_set); + PortalStart(portal, NULL, 0, snapshot_set); /* Done with the snapshot used for parsing/planning */ if (snapshot_set) @@ -1709,7 +1709,7 @@ exec_bind_message(StringInfo input_message) * for query execution (currently, reuse will only occur if * PORTAL_ONE_SELECT mode is chosen). */ - PortalStart(portal, params, snapshot_set); + PortalStart(portal, params, 0, snapshot_set); /* Done with the snapshot used for parameter I/O and parsing/planning */ if (snapshot_set) diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c index 42a0fb0f1f2..d0db7ad62c2 100644 --- a/src/backend/tcop/pquery.c +++ b/src/backend/tcop/pquery.c @@ -260,8 +260,7 @@ ChoosePortalStrategy(List *stmts) if (query->canSetTag) { if (query->commandType == CMD_SELECT && - query->utilityStmt == NULL && - query->intoClause == NULL) + query->utilityStmt == NULL) { if (query->hasModifyingCTE) return PORTAL_ONE_MOD_WITH; @@ -285,8 +284,7 @@ ChoosePortalStrategy(List *stmts) if (pstmt->canSetTag) { if (pstmt->commandType == CMD_SELECT && - pstmt->utilityStmt == NULL && - pstmt->intoClause == NULL) + pstmt->utilityStmt == NULL) { if (pstmt->hasModifyingCTE) return PORTAL_ONE_MOD_WITH; @@ -395,8 +393,7 @@ FetchStatementTargetList(Node *stmt) else { if (query->commandType == CMD_SELECT && - query->utilityStmt == NULL && - query->intoClause == NULL) + query->utilityStmt == NULL) return query->targetList; if (query->returningList) return query->returningList; @@ -408,8 +405,7 @@ FetchStatementTargetList(Node *stmt) PlannedStmt *pstmt = (PlannedStmt *) stmt; if (pstmt->commandType == CMD_SELECT && - pstmt->utilityStmt == NULL && - pstmt->intoClause == NULL) + pstmt->utilityStmt == NULL) return pstmt->planTree->targetlist; if (pstmt->hasReturning) return pstmt->planTree->targetlist; @@ -430,7 +426,6 @@ FetchStatementTargetList(Node *stmt) ExecuteStmt *estmt = (ExecuteStmt *) stmt; PreparedStatement *entry; - Assert(!estmt->into); entry = FetchPreparedStatement(estmt->name, true); return FetchPreparedStatementTargetList(entry); } @@ -442,9 +437,15 @@ FetchStatementTargetList(Node *stmt) * Prepare a portal for execution. * * Caller must already have created the portal, done PortalDefineQuery(), - * and adjusted portal options if needed. If parameters are needed by - * the query, they must be passed in here (caller is responsible for - * giving them appropriate lifetime). + * and adjusted portal options if needed. + * + * If parameters are needed by the query, they must be passed in "params" + * (caller is responsible for giving them appropriate lifetime). + * + * The caller can also provide an initial set of "eflags" to be passed to + * ExecutorStart (but note these can be modified internally, and they are + * currently only honored for PORTAL_ONE_SELECT portals). Most callers + * should simply pass zero. * * The use_active_snapshot parameter is currently used only for * PORTAL_ONE_SELECT portals. If it is true, the active snapshot will @@ -456,14 +457,15 @@ FetchStatementTargetList(Node *stmt) * tupdesc (if any) is known. */ void -PortalStart(Portal portal, ParamListInfo params, bool use_active_snapshot) +PortalStart(Portal portal, ParamListInfo params, + int eflags, bool use_active_snapshot) { Portal saveActivePortal; ResourceOwner saveResourceOwner; MemoryContext savePortalContext; MemoryContext oldContext; QueryDesc *queryDesc; - int eflags; + int myeflags; AssertArg(PortalIsValid(portal)); AssertState(portal->status == PORTAL_DEFINED); @@ -517,17 +519,18 @@ PortalStart(Portal portal, ParamListInfo params, bool use_active_snapshot) /* * If it's a scrollable cursor, executor needs to support - * REWIND and backwards scan. + * REWIND and backwards scan, as well as whatever the caller + * might've asked for. */ if (portal->cursorOptions & CURSOR_OPT_SCROLL) - eflags = EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD; + myeflags = eflags | EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD; else - eflags = 0; /* default run-to-completion flags */ + myeflags = eflags; /* * Call ExecutorStart to prepare the plan for execution */ - ExecutorStart(queryDesc, eflags); + ExecutorStart(queryDesc, myeflags); /* * This tells PortalCleanup to shut down the executor diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index 5b81c0bbedc..ea2a6c6a082 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -29,6 +29,7 @@ #include "commands/collationcmds.h" #include "commands/conversioncmds.h" #include "commands/copy.h" +#include "commands/createas.h" #include "commands/dbcommands.h" #include "commands/defrem.h" #include "commands/discard.h" @@ -127,9 +128,7 @@ CommandIsReadOnly(Node *parsetree) switch (stmt->commandType) { case CMD_SELECT: - if (stmt->intoClause != NULL) - return false; /* SELECT INTO */ - else if (stmt->rowMarks != NIL) + if (stmt->rowMarks != NIL) return false; /* SELECT FOR UPDATE/SHARE */ else if (stmt->hasModifyingCTE) return false; /* data-modifying CTE */ @@ -198,6 +197,7 @@ check_xact_readonly(Node *parsetree) case T_CreateSchemaStmt: case T_CreateSeqStmt: case T_CreateStmt: + case T_CreateTableAsStmt: case T_CreateTableSpaceStmt: case T_CreateTrigStmt: case T_CompositeTypeStmt: @@ -673,7 +673,8 @@ standard_ProcessUtility(Node *parsetree, break; case T_ExecuteStmt: - ExecuteQuery((ExecuteStmt *) parsetree, queryString, params, + ExecuteQuery((ExecuteStmt *) parsetree, NULL, + queryString, params, dest, completionTag); break; @@ -1036,6 +1037,11 @@ standard_ProcessUtility(Node *parsetree, ExplainQuery((ExplainStmt *) parsetree, queryString, params, dest); break; + case T_CreateTableAsStmt: + ExecCreateTableAs((CreateTableAsStmt *) parsetree, + queryString, params, completionTag); + break; + case T_VariableSetStmt: ExecSetVariableStmt((VariableSetStmt *) parsetree); break; @@ -1230,8 +1236,6 @@ UtilityReturnsTuples(Node *parsetree) ExecuteStmt *stmt = (ExecuteStmt *) parsetree; PreparedStatement *entry; - if (stmt->into) - return false; entry = FetchPreparedStatement(stmt->name, false); if (!entry) return false; /* not our business to raise error */ @@ -1282,8 +1286,6 @@ UtilityTupleDescriptor(Node *parsetree) ExecuteStmt *stmt = (ExecuteStmt *) parsetree; PreparedStatement *entry; - if (stmt->into) - return NULL; entry = FetchPreparedStatement(stmt->name, false); if (!entry) return NULL; /* not our business to raise error */ @@ -1317,9 +1319,8 @@ QueryReturnsTuples(Query *parsetree) switch (parsetree->commandType) { case CMD_SELECT: - /* returns tuples ... unless it's DECLARE CURSOR or SELECT INTO */ - if (parsetree->utilityStmt == NULL && - parsetree->intoClause == NULL) + /* returns tuples ... unless it's DECLARE CURSOR */ + if (parsetree->utilityStmt == NULL) return true; break; case CMD_INSERT: @@ -1342,6 +1343,37 @@ QueryReturnsTuples(Query *parsetree) /* + * UtilityContainsQuery + * Return the contained Query, or NULL if there is none + * + * Certain utility statements, such as EXPLAIN, contain a Query. + * This function encapsulates knowledge of exactly which ones do. + * We assume it is invoked only on already-parse-analyzed statements + * (else the contained parsetree isn't a Query yet). + */ +Query * +UtilityContainsQuery(Node *parsetree) +{ + switch (nodeTag(parsetree)) + { + case T_ExplainStmt: + Assert(IsA(((ExplainStmt *) parsetree)->query, Query)); + return (Query *) ((ExplainStmt *) parsetree)->query; + + case T_CreateTableAsStmt: + /* might or might not contain a Query ... */ + if (IsA(((CreateTableAsStmt *) parsetree)->query, Query)) + return (Query *) ((CreateTableAsStmt *) parsetree)->query; + Assert(IsA(((CreateTableAsStmt *) parsetree)->query, ExecuteStmt)); + return NULL; + + default: + return NULL; + } +} + + +/* * AlterObjectTypeCommandTag * helper function for CreateCommandTag * @@ -1907,6 +1939,13 @@ CreateCommandTag(Node *parsetree) tag = "EXPLAIN"; break; + case T_CreateTableAsStmt: + if (((CreateTableAsStmt *) parsetree)->is_select_into) + tag = "SELECT INTO"; + else + tag = "CREATE TABLE AS"; + break; + case T_VariableSetStmt: switch (((VariableSetStmt *) parsetree)->kind) { @@ -2060,8 +2099,6 @@ CreateCommandTag(Node *parsetree) Assert(IsA(stmt->utilityStmt, DeclareCursorStmt)); tag = "DECLARE CURSOR"; } - else if (stmt->intoClause != NULL) - tag = "SELECT INTO"; else if (stmt->rowMarks != NIL) { /* not 100% but probably close enough */ @@ -2110,8 +2147,6 @@ CreateCommandTag(Node *parsetree) Assert(IsA(stmt->utilityStmt, DeclareCursorStmt)); tag = "DECLARE CURSOR"; } - else if (stmt->intoClause != NULL) - tag = "SELECT INTO"; else if (stmt->rowMarks != NIL) { /* not 100% but probably close enough */ @@ -2179,7 +2214,7 @@ GetCommandLogLevel(Node *parsetree) case T_SelectStmt: if (((SelectStmt *) parsetree)->intoClause) - lev = LOGSTMT_DDL; /* CREATE AS, SELECT INTO */ + lev = LOGSTMT_DDL; /* SELECT INTO */ else lev = LOGSTMT_ALL; break; @@ -2429,6 +2464,10 @@ GetCommandLogLevel(Node *parsetree) } break; + case T_CreateTableAsStmt: + lev = LOGSTMT_DDL; + break; + case T_VariableSetStmt: lev = LOGSTMT_ALL; break; @@ -2529,10 +2568,7 @@ GetCommandLogLevel(Node *parsetree) switch (stmt->commandType) { case CMD_SELECT: - if (stmt->intoClause != NULL) - lev = LOGSTMT_DDL; /* CREATE AS, SELECT INTO */ - else - lev = LOGSTMT_ALL; /* SELECT or DECLARE CURSOR */ + lev = LOGSTMT_ALL; break; case CMD_UPDATE: @@ -2558,10 +2594,7 @@ GetCommandLogLevel(Node *parsetree) switch (stmt->commandType) { case CMD_SELECT: - if (stmt->intoClause != NULL) - lev = LOGSTMT_DDL; /* CREATE AS, SELECT INTO */ - else - lev = LOGSTMT_ALL; /* SELECT or DECLARE CURSOR */ + lev = LOGSTMT_ALL; break; case CMD_UPDATE: |