diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2007-04-27 22:05:49 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2007-04-27 22:05:49 +0000 |
commit | bbbe825f5f46d7ead60502f43d3b414719a41aa5 (patch) | |
tree | b4dda033d2ecee0e6ba083621763e058ae0b7ba4 /src/backend/tcop/utility.c | |
parent | a264671116ab9ba45fb20441c16fe0783e52857b (diff) | |
download | postgresql-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.c | 49 |
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: |