diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/commands/portalcmds.c | 7 | ||||
-rw-r--r-- | src/backend/executor/spi.c | 19 | ||||
-rw-r--r-- | src/backend/parser/analyze.c | 16 |
3 files changed, 37 insertions, 5 deletions
diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c index 939452650d0..e8f21d4f083 100644 --- a/src/backend/commands/portalcmds.c +++ b/src/backend/commands/portalcmds.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.65 2007/04/27 22:05:47 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.66 2007/10/24 23:27:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -102,12 +102,13 @@ PerformCursorOpen(PlannedStmt *stmt, ParamListInfo params, * * If the user didn't specify a SCROLL type, allow or disallow scrolling * based on whether it would require any additional runtime overhead to do - * so. + * so. Also, we disallow scrolling for FOR UPDATE cursors. */ portal->cursorOptions = cstmt->options; if (!(portal->cursorOptions & (CURSOR_OPT_SCROLL | CURSOR_OPT_NO_SCROLL))) { - if (ExecSupportsBackwardScan(stmt->planTree)) + if (stmt->rowMarks == NIL && + ExecSupportsBackwardScan(stmt->planTree)) portal->cursorOptions |= CURSOR_OPT_SCROLL; else portal->cursorOptions |= CURSOR_OPT_NO_SCROLL; diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 875e4da2914..6d59401d0fb 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.181 2007/09/20 17:56:31 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.182 2007/10/24 23:27:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -975,6 +975,7 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan, { if (list_length(stmt_list) == 1 && IsA((Node *) linitial(stmt_list), PlannedStmt) && + ((PlannedStmt *) linitial(stmt_list))->rowMarks == NIL && ExecSupportsBackwardScan(((PlannedStmt *) linitial(stmt_list))->planTree)) portal->cursorOptions |= CURSOR_OPT_SCROLL; else @@ -982,6 +983,22 @@ SPI_cursor_open(const char *name, SPIPlanPtr plan, } /* + * Disallow SCROLL with SELECT FOR UPDATE. This is not redundant with + * the check in transformDeclareCursorStmt because the cursor options + * might not have come through there. + */ + if (portal->cursorOptions & CURSOR_OPT_SCROLL) + { + if (list_length(stmt_list) == 1 && + IsA((Node *) linitial(stmt_list), PlannedStmt) && + ((PlannedStmt *) linitial(stmt_list))->rowMarks != NIL) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("DECLARE CURSOR SCROLL ... FOR UPDATE/SHARE is not supported"), + errdetail("Scrollable cursors must be READ ONLY."))); + } + + /* * If told to be read-only, we'd better check for read-only queries. * This can't be done earlier because we need to look at the finished, * planned queries. (In particular, we don't want to do it between diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 3135d852467..567130b18db 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -17,7 +17,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.367 2007/06/23 22:12:51 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.368 2007/10/24 23:27:08 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1623,6 +1623,20 @@ transformDeclareCursorStmt(ParseState *pstate, DeclareCursorStmt *stmt) errmsg("DECLARE CURSOR WITH HOLD ... FOR UPDATE/SHARE is not supported"), errdetail("Holdable cursors must be READ ONLY."))); + /* FOR UPDATE and SCROLL are not compatible */ + if (result->rowMarks != NIL && (stmt->options & CURSOR_OPT_SCROLL)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("DECLARE CURSOR SCROLL ... FOR UPDATE/SHARE is not supported"), + errdetail("Scrollable cursors must be READ ONLY."))); + + /* FOR UPDATE and INSENSITIVE are not compatible */ + if (result->rowMarks != NIL && (stmt->options & CURSOR_OPT_INSENSITIVE)) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("DECLARE CURSOR INSENSITIVE ... FOR UPDATE/SHARE is not supported"), + errdetail("Insensitive cursors must be READ ONLY."))); + /* We won't need the raw querytree any more */ stmt->query = NULL; |