8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -832,22 +832,35 @@ SPI_cursor_open(const char *name, void *plan,
832
832
Portal portal ;
833
833
int k ;
834
834
835
- /* Ensure that the plan contains only one regular SELECT query */
835
+ /* Ensure that the plan contains only one query */
836
836
if (list_length (ptlist ) != 1 || list_length (qtlist ) != 1 )
837
837
ereport (ERROR ,
838
838
(errcode (ERRCODE_INVALID_CURSOR_DEFINITION ),
839
839
errmsg ("cannot open multi-query plan as cursor" )));
840
840
queryTree = (Query * ) linitial ((List * ) linitial (qtlist ));
841
841
planTree = (Plan * ) linitial (ptlist );
842
842
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
+ case CMD_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
+ case CMD_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
+ }
851
864
852
865
/* Reset SPI result */
853
866
SPI_processed = 0 ;
@@ -911,7 +924,7 @@ SPI_cursor_open(const char *name, void *plan,
911
924
*/
912
925
PortalDefineQuery (portal ,
913
926
NULL , /* unfortunately don't have sourceText */
914
- "SELECT" , /* cursor's query is always a SELECT */
927
+ "SELECT" , /* nor the raw parse tree... */
915
928
list_make1 (queryTree ),
916
929
list_make1 (planTree ),
917
930
PortalGetHeapMemory (portal ));
@@ -922,7 +935,7 @@ SPI_cursor_open(const char *name, void *plan,
922
935
* Set up options for portal.
923
936
*/
924
937
portal -> cursorOptions &= ~(CURSOR_OPT_SCROLL | CURSOR_OPT_NO_SCROLL );
925
- if (ExecSupportsBackwardScan (plan ))
938
+ if (planTree == NULL || ExecSupportsBackwardScan (planTree ))
926
939
portal -> cursorOptions |= CURSOR_OPT_SCROLL ;
927
940
else
928
941
portal -> cursorOptions |= CURSOR_OPT_NO_SCROLL ;
@@ -944,7 +957,8 @@ SPI_cursor_open(const char *name, void *plan,
944
957
*/
945
958
PortalStart (portal , paramLI , snapshot );
946
959
947
- Assert (portal -> strategy == PORTAL_ONE_SELECT );
960
+ Assert (portal -> strategy == PORTAL_ONE_SELECT ||
961
+ portal -> strategy == PORTAL_UTIL_SELECT );
948
962
949
963
/* Return the created portal */
950
964
return portal ;
0 commit comments