aboutsummaryrefslogtreecommitdiff
path: root/src/backend/tcop/utility.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/tcop/utility.c')
-rw-r--r--src/backend/tcop/utility.c310
1 files changed, 182 insertions, 128 deletions
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 5cabec2970b..47051ad1ed2 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.272 2007/02/14 01:58:57 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.273 2007/02/20 17:32:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -248,36 +248,41 @@ CheckRelationOwnership(RangeVar *rel, bool noCatalogs)
/*
- * QueryIsReadOnly: is an analyzed/rewritten query read-only?
+ * CommandIsReadOnly: is an executable query read-only?
*
* This is a much stricter test than we apply for XactReadOnly mode;
* the query must be *in truth* read-only, because the caller wishes
* not to do CommandCounterIncrement for it.
+ *
+ * Note: currently no need to support Query nodes here
*/
bool
-QueryIsReadOnly(Query *parsetree)
+CommandIsReadOnly(Node *parsetree)
{
- switch (parsetree->commandType)
+ if (IsA(parsetree, PlannedStmt))
{
- case CMD_SELECT:
- if (parsetree->into != NULL)
- return false; /* SELECT INTO */
- else if (parsetree->rowMarks != NIL)
- return false; /* SELECT FOR UPDATE/SHARE */
- else
- return true;
- case CMD_UPDATE:
- case CMD_INSERT:
- case CMD_DELETE:
- return false;
- case CMD_UTILITY:
- /* For now, treat all utility commands as read/write */
- return false;
- default:
- elog(WARNING, "unrecognized commandType: %d",
- (int) parsetree->commandType);
- break;
+ PlannedStmt *stmt = (PlannedStmt *) parsetree;
+
+ switch (stmt->commandType)
+ {
+ case CMD_SELECT:
+ if (stmt->into != NULL)
+ return false; /* SELECT INTO */
+ else if (stmt->rowMarks != NIL)
+ return false; /* SELECT FOR UPDATE/SHARE */
+ else
+ return true;
+ case CMD_UPDATE:
+ case CMD_INSERT:
+ case CMD_DELETE:
+ return false;
+ default:
+ elog(WARNING, "unrecognized commandType: %d",
+ (int) stmt->commandType);
+ break;
+ }
}
+ /* For now, treat all utility commands as read/write */
return false;
}
@@ -1161,7 +1166,7 @@ UtilityReturnsTuples(Node *parsetree)
entry = FetchPreparedStatement(stmt->name, false);
if (!entry)
return false; /* not our business to raise error */
- switch (ChoosePortalStrategy(entry->query_list))
+ switch (ChoosePortalStrategy(entry->stmt_list))
{
case PORTAL_ONE_SELECT:
case PORTAL_ONE_RETURNING:
@@ -1244,6 +1249,7 @@ UtilityTupleDescriptor(Node *parsetree)
* QueryReturnsTuples
* Return "true" if this Query will send output to the destination.
*/
+#ifdef NOT_USED
bool
QueryReturnsTuples(Query *parsetree)
{
@@ -1270,14 +1276,15 @@ QueryReturnsTuples(Query *parsetree)
}
return false; /* default */
}
+#endif
/*
* CreateCommandTag
- * utility to get a string representation of the
- * command operation, given a raw (un-analyzed) parsetree.
+ * utility to get a string representation of the command operation,
+ * given either a raw (un-analyzed) parsetree or a planned query.
*
- * This must handle all raw command types, but since the vast majority
+ * This must handle all command types, but since the vast majority
* of 'em are utility commands, it seems sensible to keep it here.
*
* NB: all result strings must be shorter than COMPLETION_TAG_BUFSIZE.
@@ -1290,6 +1297,7 @@ CreateCommandTag(Node *parsetree)
switch (nodeTag(parsetree))
{
+ /* raw plannable queries */
case T_InsertStmt:
tag = "INSERT";
break;
@@ -1306,6 +1314,7 @@ CreateCommandTag(Node *parsetree)
tag = "SELECT";
break;
+ /* utility statements --- same whether raw or cooked */
case T_TransactionStmt:
{
TransactionStmt *stmt = (TransactionStmt *) parsetree;
@@ -1826,65 +1835,98 @@ CreateCommandTag(Node *parsetree)
tag = "DEALLOCATE";
break;
- default:
- elog(WARNING, "unrecognized node type: %d",
- (int) nodeTag(parsetree));
- tag = "???";
- break;
- }
-
- return tag;
-}
-
-/*
- * CreateQueryTag
- * utility to get a string representation of a Query operation.
- *
- * This is exactly like CreateCommandTag, except it works on a Query
- * that has already been through parse analysis (and possibly further).
- */
-const char *
-CreateQueryTag(Query *parsetree)
-{
- const char *tag;
-
- Assert(IsA(parsetree, Query));
+ /* already-planned queries */
+ case T_PlannedStmt:
+ {
+ PlannedStmt *stmt = (PlannedStmt *) parsetree;
- switch (parsetree->commandType)
- {
- case CMD_SELECT:
+ switch (stmt->commandType)
+ {
+ case CMD_SELECT:
+ /*
+ * We take a little extra care here so that the result
+ * will be useful for complaints about read-only
+ * statements
+ */
+ if (stmt->into != NULL)
+ tag = "SELECT INTO";
+ else if (stmt->rowMarks != NIL)
+ {
+ if (((RowMarkClause *) linitial(stmt->rowMarks))->forUpdate)
+ tag = "SELECT FOR UPDATE";
+ else
+ tag = "SELECT FOR SHARE";
+ }
+ else
+ tag = "SELECT";
+ break;
+ case CMD_UPDATE:
+ tag = "UPDATE";
+ break;
+ case CMD_INSERT:
+ tag = "INSERT";
+ break;
+ case CMD_DELETE:
+ tag = "DELETE";
+ break;
+ default:
+ elog(WARNING, "unrecognized commandType: %d",
+ (int) stmt->commandType);
+ tag = "???";
+ break;
+ }
+ }
+ break;
- /*
- * We take a little extra care here so that the result will be
- * useful for complaints about read-only statements
- */
- if (parsetree->into != NULL)
- tag = "SELECT INTO";
- else if (parsetree->rowMarks != NIL)
+ /* parsed-and-rewritten-but-not-planned queries */
+ case T_Query:
{
- if (((RowMarkClause *) linitial(parsetree->rowMarks))->forUpdate)
- tag = "SELECT FOR UPDATE";
- else
- tag = "SELECT FOR SHARE";
+ Query *stmt = (Query *) parsetree;
+
+ switch (stmt->commandType)
+ {
+ case CMD_SELECT:
+ /*
+ * We take a little extra care here so that the result
+ * will be useful for complaints about read-only
+ * statements
+ */
+ if (stmt->into != NULL)
+ tag = "SELECT INTO";
+ else if (stmt->rowMarks != NIL)
+ {
+ if (((RowMarkClause *) linitial(stmt->rowMarks))->forUpdate)
+ tag = "SELECT FOR UPDATE";
+ else
+ tag = "SELECT FOR SHARE";
+ }
+ else
+ tag = "SELECT";
+ break;
+ case CMD_UPDATE:
+ tag = "UPDATE";
+ break;
+ case CMD_INSERT:
+ tag = "INSERT";
+ break;
+ case CMD_DELETE:
+ tag = "DELETE";
+ break;
+ case CMD_UTILITY:
+ tag = CreateCommandTag(stmt->utilityStmt);
+ break;
+ default:
+ elog(WARNING, "unrecognized commandType: %d",
+ (int) stmt->commandType);
+ tag = "???";
+ break;
+ }
}
- else
- tag = "SELECT";
- break;
- case CMD_UPDATE:
- tag = "UPDATE";
- break;
- case CMD_INSERT:
- tag = "INSERT";
- break;
- case CMD_DELETE:
- tag = "DELETE";
- break;
- case CMD_UTILITY:
- tag = CreateCommandTag(parsetree->utilityStmt);
break;
+
default:
- elog(WARNING, "unrecognized commandType: %d",
- (int) parsetree->commandType);
+ elog(WARNING, "unrecognized node type: %d",
+ (int) nodeTag(parsetree));
tag = "???";
break;
}
@@ -1896,9 +1938,9 @@ CreateQueryTag(Query *parsetree)
/*
* GetCommandLogLevel
* utility to get the minimum log_statement level for a command,
- * given a raw (un-analyzed) parsetree.
+ * given either a raw (un-analyzed) parsetree or a planned query.
*
- * This must handle all raw command types, but since the vast majority
+ * This must handle all command types, but since the vast majority
* of 'em are utility commands, it seems sensible to keep it here.
*/
LogStmtLevel
@@ -1908,6 +1950,7 @@ GetCommandLogLevel(Node *parsetree)
switch (nodeTag(parsetree))
{
+ /* raw plannable queries */
case T_InsertStmt:
case T_DeleteStmt:
case T_UpdateStmt:
@@ -1921,6 +1964,7 @@ GetCommandLogLevel(Node *parsetree)
lev = LOGSTMT_ALL;
break;
+ /* utility statements --- same whether raw or cooked */
case T_TransactionStmt:
lev = LOGSTMT_ALL;
break;
@@ -2216,12 +2260,12 @@ GetCommandLogLevel(Node *parsetree)
pstmt = FetchPreparedStatement(stmt->name, false);
if (pstmt)
{
- foreach(l, pstmt->query_list)
+ foreach(l, pstmt->stmt_list)
{
- Query *query = (Query *) lfirst(l);
+ Node *substmt = (Node *) lfirst(l);
LogStmtLevel stmt_lev;
- stmt_lev = GetQueryLogLevel(query);
+ stmt_lev = GetCommandLogLevel(substmt);
lev = Min(lev, stmt_lev);
}
}
@@ -2232,62 +2276,72 @@ GetCommandLogLevel(Node *parsetree)
lev = LOGSTMT_ALL;
break;
- case T_Query:
+ /* already-planned queries */
+ case T_PlannedStmt:
+ {
+ PlannedStmt *stmt = (PlannedStmt *) parsetree;
- /*
- * In complicated situations (eg, EXPLAIN ANALYZE in an extended
- * Query protocol), we might find an already-analyzed query within
- * a utility statement. Cope.
- */
- lev = GetQueryLogLevel((Query *) parsetree);
- break;
+ switch (stmt->commandType)
+ {
+ case CMD_SELECT:
+ if (stmt->into != NULL)
+ lev = LOGSTMT_DDL; /* CREATE AS, SELECT INTO */
+ else
+ lev = LOGSTMT_ALL;
+ break;
- default:
- elog(WARNING, "unrecognized node type: %d",
- (int) nodeTag(parsetree));
- lev = LOGSTMT_ALL;
+ case CMD_UPDATE:
+ case CMD_INSERT:
+ case CMD_DELETE:
+ lev = LOGSTMT_MOD;
+ break;
+
+ default:
+ elog(WARNING, "unrecognized commandType: %d",
+ (int) stmt->commandType);
+ lev = LOGSTMT_ALL;
+ break;
+ }
+ }
break;
- }
- return lev;
-}
+ /* parsed-and-rewritten-but-not-planned queries */
+ case T_Query:
+ {
+ Query *stmt = (Query *) parsetree;
-/*
- * GetQueryLogLevel
- * utility to get the minimum log_statement level for a Query operation.
- *
- * This is exactly like GetCommandLogLevel, except it works on a Query
- * that has already been through parse analysis (and possibly further).
- */
-LogStmtLevel
-GetQueryLogLevel(Query *parsetree)
-{
- LogStmtLevel lev;
+ switch (stmt->commandType)
+ {
+ case CMD_SELECT:
+ if (stmt->into != NULL)
+ lev = LOGSTMT_DDL; /* CREATE AS, SELECT INTO */
+ else
+ lev = LOGSTMT_ALL;
+ break;
- Assert(IsA(parsetree, Query));
+ case CMD_UPDATE:
+ case CMD_INSERT:
+ case CMD_DELETE:
+ lev = LOGSTMT_MOD;
+ break;
- switch (parsetree->commandType)
- {
- case CMD_SELECT:
- if (parsetree->into != NULL)
- lev = LOGSTMT_DDL; /* CREATE AS, SELECT INTO */
- else
- lev = LOGSTMT_ALL;
- break;
+ case CMD_UTILITY:
+ lev = GetCommandLogLevel(stmt->utilityStmt);
+ break;
- case CMD_UPDATE:
- case CMD_INSERT:
- case CMD_DELETE:
- lev = LOGSTMT_MOD;
- break;
+ default:
+ elog(WARNING, "unrecognized commandType: %d",
+ (int) stmt->commandType);
+ lev = LOGSTMT_ALL;
+ break;
+ }
- case CMD_UTILITY:
- lev = GetCommandLogLevel(parsetree->utilityStmt);
+ }
break;
default:
- elog(WARNING, "unrecognized commandType: %d",
- (int) parsetree->commandType);
+ elog(WARNING, "unrecognized node type: %d",
+ (int) nodeTag(parsetree));
lev = LOGSTMT_ALL;
break;
}