mirror of
https://github.com/postgres/postgres.git
synced 2025-11-10 17:42:29 +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:
@@ -15,7 +15,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.245 2003/03/05 20:01:01 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.246 2003/03/10 03:53:49 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1465,8 +1465,6 @@ _copyQuery(Query *from)
|
||||
COPY_NODE_FIELD(utilityStmt);
|
||||
COPY_SCALAR_FIELD(resultRelation);
|
||||
COPY_NODE_FIELD(into);
|
||||
COPY_SCALAR_FIELD(isPortal);
|
||||
COPY_SCALAR_FIELD(isBinary);
|
||||
COPY_SCALAR_FIELD(hasAggs);
|
||||
COPY_SCALAR_FIELD(hasSubLinks);
|
||||
COPY_NODE_FIELD(rtable);
|
||||
@@ -1547,8 +1545,6 @@ _copySelectStmt(SelectStmt *from)
|
||||
COPY_NODE_FIELD(groupClause);
|
||||
COPY_NODE_FIELD(havingClause);
|
||||
COPY_NODE_FIELD(sortClause);
|
||||
COPY_STRING_FIELD(portalname);
|
||||
COPY_SCALAR_FIELD(binary);
|
||||
COPY_NODE_FIELD(limitOffset);
|
||||
COPY_NODE_FIELD(limitCount);
|
||||
COPY_NODE_FIELD(forUpdate);
|
||||
@@ -1648,6 +1644,17 @@ _copyInsertDefault(InsertDefault *from)
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static DeclareCursorStmt *
|
||||
_copyDeclareCursorStmt(DeclareCursorStmt *from)
|
||||
{
|
||||
DeclareCursorStmt *newnode = makeNode(DeclareCursorStmt);
|
||||
|
||||
COPY_STRING_FIELD(portalname);
|
||||
COPY_SCALAR_FIELD(options);
|
||||
COPY_NODE_FIELD(query);
|
||||
|
||||
return newnode;
|
||||
}
|
||||
|
||||
static ClosePortalStmt *
|
||||
_copyClosePortalStmt(ClosePortalStmt *from)
|
||||
@@ -2632,6 +2639,9 @@ copyObject(void *from)
|
||||
case T_GrantStmt:
|
||||
retval = _copyGrantStmt(from);
|
||||
break;
|
||||
case T_DeclareCursorStmt:
|
||||
retval = _copyDeclareCursorStmt(from);
|
||||
break;
|
||||
case T_ClosePortalStmt:
|
||||
retval = _copyClosePortalStmt(from);
|
||||
break;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.188 2003/03/05 20:01:02 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.189 2003/03/10 03:53:49 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -560,8 +560,6 @@ _equalQuery(Query *a, Query *b)
|
||||
COMPARE_NODE_FIELD(utilityStmt);
|
||||
COMPARE_SCALAR_FIELD(resultRelation);
|
||||
COMPARE_NODE_FIELD(into);
|
||||
COMPARE_SCALAR_FIELD(isPortal);
|
||||
COMPARE_SCALAR_FIELD(isBinary);
|
||||
COMPARE_SCALAR_FIELD(hasAggs);
|
||||
COMPARE_SCALAR_FIELD(hasSubLinks);
|
||||
COMPARE_NODE_FIELD(rtable);
|
||||
@@ -631,8 +629,6 @@ _equalSelectStmt(SelectStmt *a, SelectStmt *b)
|
||||
COMPARE_NODE_FIELD(groupClause);
|
||||
COMPARE_NODE_FIELD(havingClause);
|
||||
COMPARE_NODE_FIELD(sortClause);
|
||||
COMPARE_STRING_FIELD(portalname);
|
||||
COMPARE_SCALAR_FIELD(binary);
|
||||
COMPARE_NODE_FIELD(limitOffset);
|
||||
COMPARE_NODE_FIELD(limitCount);
|
||||
COMPARE_NODE_FIELD(forUpdate);
|
||||
@@ -718,6 +714,16 @@ _equalInsertDefault(InsertDefault *a, InsertDefault *b)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalDeclareCursorStmt(DeclareCursorStmt *a, DeclareCursorStmt *b)
|
||||
{
|
||||
COMPARE_STRING_FIELD(portalname);
|
||||
COMPARE_SCALAR_FIELD(options);
|
||||
COMPARE_NODE_FIELD(query);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
_equalClosePortalStmt(ClosePortalStmt *a, ClosePortalStmt *b)
|
||||
{
|
||||
@@ -1756,6 +1762,9 @@ equal(void *a, void *b)
|
||||
case T_GrantStmt:
|
||||
retval = _equalGrantStmt(a, b);
|
||||
break;
|
||||
case T_DeclareCursorStmt:
|
||||
retval = _equalDeclareCursorStmt(a, b);
|
||||
break;
|
||||
case T_ClosePortalStmt:
|
||||
retval = _equalClosePortalStmt(a, b);
|
||||
break;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.200 2003/02/16 02:30:37 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.201 2003/03/10 03:53:49 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Every node type that can appear in stored rules' parsetrees *must*
|
||||
@@ -1081,6 +1081,16 @@ _outNotifyStmt(StringInfo str, NotifyStmt *node)
|
||||
WRITE_NODE_FIELD(relation);
|
||||
}
|
||||
|
||||
static void
|
||||
_outDeclareCursorStmt(StringInfo str, DeclareCursorStmt *node)
|
||||
{
|
||||
WRITE_NODE_TYPE("DECLARECURSOR");
|
||||
|
||||
WRITE_STRING_FIELD(portalname);
|
||||
WRITE_INT_FIELD(options);
|
||||
WRITE_NODE_FIELD(query);
|
||||
}
|
||||
|
||||
static void
|
||||
_outSelectStmt(StringInfo str, SelectStmt *node)
|
||||
{
|
||||
@@ -1173,6 +1183,7 @@ _outQuery(StringInfo str, Query *node)
|
||||
case T_CreateStmt:
|
||||
case T_IndexStmt:
|
||||
case T_NotifyStmt:
|
||||
case T_DeclareCursorStmt:
|
||||
WRITE_NODE_FIELD(utilityStmt);
|
||||
break;
|
||||
default:
|
||||
@@ -1185,8 +1196,6 @@ _outQuery(StringInfo str, Query *node)
|
||||
|
||||
WRITE_INT_FIELD(resultRelation);
|
||||
WRITE_NODE_FIELD(into);
|
||||
WRITE_BOOL_FIELD(isPortal);
|
||||
WRITE_BOOL_FIELD(isBinary);
|
||||
WRITE_BOOL_FIELD(hasAggs);
|
||||
WRITE_BOOL_FIELD(hasSubLinks);
|
||||
WRITE_NODE_FIELD(rtable);
|
||||
@@ -1684,6 +1693,9 @@ _outNode(StringInfo str, void *obj)
|
||||
case T_NotifyStmt:
|
||||
_outNotifyStmt(str, obj);
|
||||
break;
|
||||
case T_DeclareCursorStmt:
|
||||
_outDeclareCursorStmt(str, obj);
|
||||
break;
|
||||
case T_SelectStmt:
|
||||
_outSelectStmt(str, obj);
|
||||
break;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.149 2003/02/16 02:30:37 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.150 2003/03/10 03:53:49 tgl Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Path and Plan nodes do not have any readfuncs support, because we
|
||||
@@ -198,8 +198,6 @@ _readQuery(void)
|
||||
READ_NODE_FIELD(utilityStmt);
|
||||
READ_INT_FIELD(resultRelation);
|
||||
READ_NODE_FIELD(into);
|
||||
READ_BOOL_FIELD(isPortal);
|
||||
READ_BOOL_FIELD(isBinary);
|
||||
READ_BOOL_FIELD(hasAggs);
|
||||
READ_BOOL_FIELD(hasSubLinks);
|
||||
READ_NODE_FIELD(rtable);
|
||||
@@ -233,6 +231,21 @@ _readNotifyStmt(void)
|
||||
READ_DONE();
|
||||
}
|
||||
|
||||
/*
|
||||
* _readDeclareCursorStmt
|
||||
*/
|
||||
static DeclareCursorStmt *
|
||||
_readDeclareCursorStmt(void)
|
||||
{
|
||||
READ_LOCALS(DeclareCursorStmt);
|
||||
|
||||
READ_STRING_FIELD(portalname);
|
||||
READ_INT_FIELD(options);
|
||||
READ_NODE_FIELD(query);
|
||||
|
||||
READ_DONE();
|
||||
}
|
||||
|
||||
/*
|
||||
* _readSortClause
|
||||
*/
|
||||
@@ -894,8 +907,6 @@ parseNodeString(void)
|
||||
|
||||
if (MATCH("QUERY", 5))
|
||||
return_value = _readQuery();
|
||||
else if (MATCH("NOTIFY", 6))
|
||||
return_value = _readNotifyStmt();
|
||||
else if (MATCH("SORTCLAUSE", 10))
|
||||
return_value = _readSortClause();
|
||||
else if (MATCH("GROUPCLAUSE", 11))
|
||||
@@ -966,6 +977,10 @@ parseNodeString(void)
|
||||
return_value = _readExprFieldSelect();
|
||||
else if (MATCH("RTE", 3))
|
||||
return_value = _readRangeTblEntry();
|
||||
else if (MATCH("NOTIFY", 6))
|
||||
return_value = _readNotifyStmt();
|
||||
else if (MATCH("DECLARECURSOR", 13))
|
||||
return_value = _readDeclareCursorStmt();
|
||||
else
|
||||
{
|
||||
elog(ERROR, "badly formatted node string \"%.32s\"...", token);
|
||||
|
||||
Reference in New Issue
Block a user