mirror of
https://github.com/postgres/postgres.git
synced 2025-06-30 21:42:05 +03:00
Restructure parsetree representation of DECLARE CURSOR: now it's a
utility statement (DeclareCursorStmt) with a SELECT query dangling from it, rather than a SELECT query with a few unusual fields in it. Add code to determine whether a planned query can safely be run backwards. If DECLARE CURSOR specifies SCROLL, ensure that the plan can be run backwards by adding a Materialize plan node if it can't. Without SCROLL, you get an error if you try to fetch backwards from a cursor that can't handle it. (There is still some discussion about what the exact behavior should be, but this is necessary infrastructure in any case.) Along the way, make EXPLAIN DECLARE CURSOR work.
This commit is contained in:
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1994-5, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.103 2003/02/10 17:06:23 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/explain.c,v 1.104 2003/03/10 03:53:49 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -85,7 +85,9 @@ ExplainQuery(ExplainStmt *stmt, CommandDest dest)
|
||||
if (query->commandType == CMD_UTILITY)
|
||||
{
|
||||
/* Rewriter will not cope with utility statements */
|
||||
if (query->utilityStmt && IsA(query->utilityStmt, ExecuteStmt))
|
||||
if (query->utilityStmt && IsA(query->utilityStmt, DeclareCursorStmt))
|
||||
ExplainOneQuery(query, stmt, tstate);
|
||||
else if (query->utilityStmt && IsA(query->utilityStmt, ExecuteStmt))
|
||||
ExplainExecuteQuery(stmt, tstate);
|
||||
else
|
||||
do_text_output_oneline(tstate, "Utility statements have no plan structure");
|
||||
@ -125,30 +127,45 @@ ExplainOneQuery(Query *query, ExplainStmt *stmt, TupOutputState *tstate)
|
||||
{
|
||||
Plan *plan;
|
||||
QueryDesc *queryDesc;
|
||||
bool isCursor = false;
|
||||
int cursorOptions = 0;
|
||||
|
||||
/* planner will not cope with utility statements */
|
||||
if (query->commandType == CMD_UTILITY)
|
||||
{
|
||||
if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
|
||||
if (query->utilityStmt && IsA(query->utilityStmt, DeclareCursorStmt))
|
||||
{
|
||||
DeclareCursorStmt *dcstmt;
|
||||
List *rewritten;
|
||||
|
||||
dcstmt = (DeclareCursorStmt *) query->utilityStmt;
|
||||
query = (Query *) dcstmt->query;
|
||||
isCursor = true;
|
||||
cursorOptions = dcstmt->options;
|
||||
/* Still need to rewrite cursor command */
|
||||
Assert(query->commandType == CMD_SELECT);
|
||||
rewritten = QueryRewrite(query);
|
||||
if (length(rewritten) != 1)
|
||||
elog(ERROR, "ExplainOneQuery: unexpected rewrite result");
|
||||
query = (Query *) lfirst(rewritten);
|
||||
Assert(query->commandType == CMD_SELECT);
|
||||
/* do not actually execute the underlying query! */
|
||||
stmt->analyze = false;
|
||||
}
|
||||
else if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt))
|
||||
{
|
||||
do_text_output_oneline(tstate, "NOTIFY");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
do_text_output_oneline(tstate, "UTILITY");
|
||||
return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't support DECLARE CURSOR in EXPLAIN, but parser will take it
|
||||
* because it's an OptimizableStmt
|
||||
*/
|
||||
if (query->isPortal)
|
||||
elog(ERROR, "EXPLAIN / DECLARE CURSOR is not supported");
|
||||
|
||||
/* plan the query */
|
||||
plan = planner(query);
|
||||
|
||||
/* pg_plan could have failed */
|
||||
if (plan == NULL)
|
||||
return;
|
||||
plan = planner(query, isCursor, cursorOptions);
|
||||
|
||||
/* Create a QueryDesc requesting no output */
|
||||
queryDesc = CreateQueryDesc(query, plan, None, NULL, NULL,
|
||||
|
Reference in New Issue
Block a user