aboutsummaryrefslogtreecommitdiff
path: root/src/backend/tcop/utility.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-04-27 22:05:49 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-04-27 22:05:49 +0000
commitbbbe825f5f46d7ead60502f43d3b414719a41aa5 (patch)
treeb4dda033d2ecee0e6ba083621763e058ae0b7ba4 /src/backend/tcop/utility.c
parenta264671116ab9ba45fb20441c16fe0783e52857b (diff)
downloadpostgresql-bbbe825f5f46d7ead60502f43d3b414719a41aa5.tar.gz
postgresql-bbbe825f5f46d7ead60502f43d3b414719a41aa5.zip
Modify processing of DECLARE CURSOR and EXPLAIN so that they can resolve the
types of unspecified parameters when submitted via extended query protocol. This worked in 8.2 but I had broken it during plancache changes. DECLARE CURSOR is now treated almost exactly like a plain SELECT through parse analysis, rewrite, and planning; only just before sending to the executor do we divert it away to ProcessUtility. This requires a special-case check in a number of places, but practically all of them were already special-casing SELECT INTO, so it's not too ugly. (Maybe it would be a good idea to merge the two by treating IntoClause as a form of utility statement? Not going to worry about that now, though.) That approach doesn't work for EXPLAIN, however, so for that I punted and used a klugy solution of running parse analysis an extra time if under extended query protocol.
Diffstat (limited to 'src/backend/tcop/utility.c')
-rw-r--r--src/backend/tcop/utility.c49
1 files changed, 35 insertions, 14 deletions
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 9dd700ffe70..028cb47c7ac 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.278 2007/04/26 16:13:12 neilc Exp $
+ * $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.279 2007/04/27 22:05:49 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -268,7 +268,7 @@ CommandIsReadOnly(Node *parsetree)
switch (stmt->commandType)
{
case CMD_SELECT:
- if (stmt->into != NULL)
+ if (stmt->intoClause != NULL)
return false; /* SELECT INTO */
else if (stmt->rowMarks != NIL)
return false; /* SELECT FOR UPDATE/SHARE */
@@ -505,10 +505,20 @@ ProcessUtility(Node *parsetree,
/*
* Portal (cursor) manipulation
+ *
+ * Note: DECLARE CURSOR is processed mostly as a SELECT, and
+ * therefore what we will get here is a PlannedStmt not a bare
+ * DeclareCursorStmt.
*/
- case T_DeclareCursorStmt:
- PerformCursorOpen((DeclareCursorStmt *) parsetree, params,
- queryString, isTopLevel);
+ case T_PlannedStmt:
+ {
+ PlannedStmt *stmt = (PlannedStmt *) parsetree;
+
+ if (stmt->utilityStmt == NULL ||
+ !IsA(stmt->utilityStmt, DeclareCursorStmt))
+ elog(ERROR, "non-DECLARE CURSOR PlannedStmt passed to ProcessUtility");
+ PerformCursorOpen(stmt, params, queryString, isTopLevel);
+ }
break;
case T_ClosePortalStmt:
@@ -1272,8 +1282,9 @@ QueryReturnsTuples(Query *parsetree)
switch (parsetree->commandType)
{
case CMD_SELECT:
- /* returns tuples ... unless it's SELECT INTO */
- if (parsetree->into == NULL)
+ /* returns tuples ... unless it's DECLARE CURSOR or SELECT INTO */
+ if (parsetree->utilityStmt == NULL &&
+ parsetree->intoClause == NULL)
return true;
break;
case CMD_INSERT:
@@ -1899,7 +1910,12 @@ CreateCommandTag(Node *parsetree)
* will be useful for complaints about read-only
* statements
*/
- if (stmt->into != NULL)
+ if (stmt->utilityStmt != NULL)
+ {
+ Assert(IsA(stmt->utilityStmt, DeclareCursorStmt));
+ tag = "DECLARE CURSOR";
+ }
+ else if (stmt->intoClause != NULL)
tag = "SELECT INTO";
else if (stmt->rowMarks != NIL)
{
@@ -1942,7 +1958,12 @@ CreateCommandTag(Node *parsetree)
* will be useful for complaints about read-only
* statements
*/
- if (stmt->into != NULL)
+ if (stmt->utilityStmt != NULL)
+ {
+ Assert(IsA(stmt->utilityStmt, DeclareCursorStmt));
+ tag = "DECLARE CURSOR";
+ }
+ else if (stmt->intoClause != NULL)
tag = "SELECT INTO";
else if (stmt->rowMarks != NIL)
{
@@ -2009,7 +2030,7 @@ GetCommandLogLevel(Node *parsetree)
break;
case T_SelectStmt:
- if (((SelectStmt *) parsetree)->into)
+ if (((SelectStmt *) parsetree)->intoClause)
lev = LOGSTMT_DDL; /* CREATE AS, SELECT INTO */
else
lev = LOGSTMT_ALL;
@@ -2330,10 +2351,10 @@ GetCommandLogLevel(Node *parsetree)
switch (stmt->commandType)
{
case CMD_SELECT:
- if (stmt->into != NULL)
+ if (stmt->intoClause != NULL)
lev = LOGSTMT_DDL; /* CREATE AS, SELECT INTO */
else
- lev = LOGSTMT_ALL;
+ lev = LOGSTMT_ALL; /* SELECT or DECLARE CURSOR */
break;
case CMD_UPDATE:
@@ -2359,10 +2380,10 @@ GetCommandLogLevel(Node *parsetree)
switch (stmt->commandType)
{
case CMD_SELECT:
- if (stmt->into != NULL)
+ if (stmt->intoClause != NULL)
lev = LOGSTMT_DDL; /* CREATE AS, SELECT INTO */
else
- lev = LOGSTMT_ALL;
+ lev = LOGSTMT_ALL; /* SELECT or DECLARE CURSOR */
break;
case CMD_UPDATE: