Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit42599b3

Browse files
committed
Fix SPI cursor support to allow scanning the results of utility commands
that return tuples (such as EXPLAIN). Per gripe from Michael Fuhr.Side effect: fix an old bug that unintentionally disabled backward scansfor all SPI-created cursors.
1 parent5cc8884 commit42599b3

File tree

2 files changed

+54
-15
lines changed

2 files changed

+54
-15
lines changed

‎src/backend/executor/spi.c

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.133 2004/12/31 21:59:45 pgsql Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.134 2005/02/10 20:36:27 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -832,22 +832,35 @@ SPI_cursor_open(const char *name, void *plan,
832832
Portalportal;
833833
intk;
834834

835-
/* Ensure that the plan contains only oneregular SELECTquery */
835+
/* Ensure that the plan contains only one query */
836836
if (list_length(ptlist)!=1||list_length(qtlist)!=1)
837837
ereport(ERROR,
838838
(errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
839839
errmsg("cannot open multi-query plan as cursor")));
840840
queryTree= (Query*)linitial((List*)linitial(qtlist));
841841
planTree= (Plan*)linitial(ptlist);
842842

843-
if (queryTree->commandType!=CMD_SELECT)
844-
ereport(ERROR,
845-
(errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
846-
errmsg("cannot open non-SELECT query as cursor")));
847-
if (queryTree->into!=NULL)
848-
ereport(ERROR,
849-
(errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
850-
errmsg("cannot open SELECT INTO query as cursor")));
843+
/* Must be a query that returns tuples */
844+
switch (queryTree->commandType)
845+
{
846+
caseCMD_SELECT:
847+
if (queryTree->into!=NULL)
848+
ereport(ERROR,
849+
(errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
850+
errmsg("cannot open SELECT INTO query as cursor")));
851+
break;
852+
caseCMD_UTILITY:
853+
if (!UtilityReturnsTuples(queryTree->utilityStmt))
854+
ereport(ERROR,
855+
(errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
856+
errmsg("cannot open non-SELECT query as cursor")));
857+
break;
858+
default:
859+
ereport(ERROR,
860+
(errcode(ERRCODE_INVALID_CURSOR_DEFINITION),
861+
errmsg("cannot open non-SELECT query as cursor")));
862+
break;
863+
}
851864

852865
/* Reset SPI result */
853866
SPI_processed=0;
@@ -911,7 +924,7 @@ SPI_cursor_open(const char *name, void *plan,
911924
*/
912925
PortalDefineQuery(portal,
913926
NULL,/* unfortunately don't have sourceText */
914-
"SELECT",/*cursor's query is always a SELECT */
927+
"SELECT",/*nor the raw parse tree... */
915928
list_make1(queryTree),
916929
list_make1(planTree),
917930
PortalGetHeapMemory(portal));
@@ -922,7 +935,7 @@ SPI_cursor_open(const char *name, void *plan,
922935
* Set up options for portal.
923936
*/
924937
portal->cursorOptions &= ~(CURSOR_OPT_SCROLL |CURSOR_OPT_NO_SCROLL);
925-
if (ExecSupportsBackwardScan(plan))
938+
if (planTree==NULL||ExecSupportsBackwardScan(planTree))
926939
portal->cursorOptions |=CURSOR_OPT_SCROLL;
927940
else
928941
portal->cursorOptions |=CURSOR_OPT_NO_SCROLL;
@@ -944,7 +957,8 @@ SPI_cursor_open(const char *name, void *plan,
944957
*/
945958
PortalStart(portal,paramLI,snapshot);
946959

947-
Assert(portal->strategy==PORTAL_ONE_SELECT);
960+
Assert(portal->strategy==PORTAL_ONE_SELECT||
961+
portal->strategy==PORTAL_UTIL_SELECT);
948962

949963
/* Return the created portal */
950964
returnportal;

‎src/backend/tcop/pquery.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.90 2005/02/01 23:28:40 neilc Exp $
11+
* $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.91 2005/02/10 20:36:28 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1120,6 +1120,30 @@ PortalRunFetch(Portal portal,
11201120
result=DoPortalRunFetch(portal,fdirection,count,dest);
11211121
break;
11221122

1123+
casePORTAL_UTIL_SELECT:
1124+
1125+
/*
1126+
* If we have not yet run the utility statement, do so,
1127+
* storing its results in the portal's tuplestore.
1128+
*/
1129+
if (!portal->portalUtilReady)
1130+
{
1131+
DestReceiver*treceiver;
1132+
1133+
PortalCreateHoldStore(portal);
1134+
treceiver=CreateDestReceiver(Tuplestore,portal);
1135+
PortalRunUtility(portal,linitial(portal->parseTrees),
1136+
treceiver,NULL);
1137+
(*treceiver->rDestroy) (treceiver);
1138+
portal->portalUtilReady= true;
1139+
}
1140+
1141+
/*
1142+
* Now fetch desired portion of results.
1143+
*/
1144+
result=DoPortalRunFetch(portal,fdirection,count,dest);
1145+
break;
1146+
11231147
default:
11241148
elog(ERROR,"unsupported portal strategy");
11251149
result=0;/* keep compiler quiet */
@@ -1170,7 +1194,8 @@ DoPortalRunFetch(Portal portal,
11701194
{
11711195
boolforward;
11721196

1173-
Assert(portal->strategy==PORTAL_ONE_SELECT);
1197+
Assert(portal->strategy==PORTAL_ONE_SELECT||
1198+
portal->strategy==PORTAL_UTIL_SELECT);
11741199

11751200
switch (fdirection)
11761201
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp