aboutsummaryrefslogtreecommitdiff
path: root/src/backend/tcop
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/tcop')
-rw-r--r--src/backend/tcop/dest.c4
-rw-r--r--src/backend/tcop/postgres.c6
-rw-r--r--src/backend/tcop/pquery.c39
-rw-r--r--src/backend/tcop/utility.c81
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: