patch for preventing the specification of conflicting transaction read/write options
Hi,
This is regarding the TODO item:
"Prevent the specification of conflicting transaction read/write options"
listed at:
http://wiki.postgresql.org/wiki/Todo
The issue is :
SET TRANSACTION read only read write read only;
The fix involved iteration over transaction_mode_list and checking for
duplicate entries.
The patch is based on suggestions mentioned in message:
http://archives.postgresql.org/pgsql-hackers/2009-01/msg00692.php
As per this, the patch does not throw any error for the first test case
mentioned above.
It throws error only in case of conflicting modes.
For ex:
postgres=# SET TRANSACTION read only read only;
SET
postgres=# SET TRANSACTION read only read write;
ERROR: conflicting options
LINE 1: SET TRANSACTION read only read write;
^
Below are basic unit test logs:
postgres=# SET TRANSACTION ISOLATION LEVEL serializable ISOLATION LEVEL
serializable;
SET
postgres=# SET TRANSACTION ISOLATION LEVEL serializable ISOLATION LEVEL
repeatable read;
ERROR: conflicting options
LINE 1: SET TRANSACTION ISOLATION LEVEL serializable ISOLATION LEVEL...
postgres=# SET TRANSACTION DEFERRABLE DEFERRABLE;
SET
postgres=# SET TRANSACTION DEFERRABLE NOT DEFERRABLE;
ERROR: conflicting options
LINE 1: SET TRANSACTION DEFERRABLE NOT DEFERRABLE;
^
postgres=# START TRANSACTION read only, read only;
START TRANSACTION
postgres=# rollback;
ROLLBACK
postgres=# START TRANSACTION read only, read write;
ERROR: conflicting options
LINE 1: START TRANSACTION read only, read write;
postgres=# rollback;
ROLLBACK ^
postgres=# BEGIN TRANSACTION ISOLATION LEVEL serializable, ISOLATION LEVEL
serializable;
BEGIN
postgres=# rollback;
ROLLBACK
postgres=# BEGIN TRANSACTION ISOLATION LEVEL serializable, ISOLATION LEVEL
repeatable read;
ERROR: conflicting options
LINE 1: BEGIN TRANSACTION ISOLATION LEVEL serializable, ISOLATION LE...
^
Please pass on any inputs on the patch.
Regards,
Chetan
--
EnterpriseDB Corporation
The Enterprise PostgreSQL Company
Website: www.enterprisedb.com
EnterpriseDB Blog : http://blogs.enterprisedb.com
Follow us on Twitter : http://www.twitter.com/enterprisedb
Attachments:
fix_set_trans_mode.patchtext/x-diff; charset=US-ASCII; name=fix_set_trans_mode.patchDownload
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 62fde67..28c987f 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -146,6 +146,9 @@ static void processCASbits(int cas_bits, int location, const char *constrType,
bool *deferrable, bool *initdeferred, bool *not_valid,
core_yyscan_t yyscanner);
+static void
+check_trans_mode(List *list, DefElem *elem, core_yyscan_t yyscanner);
+
%}
%pure-parser
@@ -7510,9 +7513,16 @@ transaction_mode_list:
transaction_mode_item
{ $$ = list_make1($1); }
| transaction_mode_list ',' transaction_mode_item
- { $$ = lappend($1, $3); }
+ {
+ check_trans_mode((List *)$1, (DefElem *)$3, yyscanner);
+ $$ = lappend($1, $3);
+ }
+
| transaction_mode_list transaction_mode_item
- { $$ = lappend($1, $2); }
+ {
+ check_trans_mode((List *)$1, (DefElem *)$2, yyscanner);
+ $$ = lappend($1, $2);
+ }
;
transaction_mode_list_or_empty:
@@ -13215,6 +13225,57 @@ parser_init(base_yy_extra_type *yyext)
}
/*
+ * checks for conflicting transaction modes by looking up current
+ * element in the given list.
+ */
+static void
+check_trans_mode(List *list, DefElem *elem, core_yyscan_t yyscanner)
+{
+ ListCell *lc;
+ A_Const *elem_arg;
+
+ elem_arg =(A_Const *) elem->arg;
+
+ /* cannot specify conflicting value for transaction mode. */
+ foreach (lc, list)
+ {
+ DefElem *next;
+ A_Const *arg;
+
+ next = (DefElem*)lfirst (lc);
+ arg = (A_Const *)next->arg;
+
+ /* check for duplicate value in remaining list */
+ if (strcmp(elem->defname, next->defname) == 0)
+ {
+ /*
+ * isolation level values are stored
+ * as string whereas other modes are
+ * stored as integer values.
+ */
+ if (strcmp(elem->defname,"transaction_isolation") == 0)
+ {
+ /* check for conflicting values */
+ if (strcmp(elem_arg->val.val.str,arg->val.val.str)!= 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting options"),
+ parser_errposition(arg->location)));
+ }
+ else
+ {
+ /* check for conflicting values */
+ if (elem_arg->val.val.ival != arg->val.val.ival)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting options"),
+ parser_errposition(arg->location)));
+ }
+ }
+ }
+}
+
+/*
* Must undefine this stuff before including scan.c, since it has different
* definitions for these macros.
*/
Chetan Suttraway <chetan.suttraway@enterprisedb.com> wrote:
This is regarding the TODO item:
"Prevent the specification of conflicting transaction read/write
options"listed at:
http://wiki.postgresql.org/wiki/Todo
Thanks for chipping away at items on the list.
Please pass on any inputs on the patch.
Right now we want people focusing on fixing bugs and reviewing
patches submitted by the start of the current CommitFest. Please
add this to the open CF so we don't lose track of it.
-Kevin
On Tue, Feb 7, 2012 at 8:44 PM, Kevin Grittner
<Kevin.Grittner@wicourts.gov>wrote:
Chetan Suttraway <chetan.suttraway@enterprisedb.com> wrote:
This is regarding the TODO item:
"Prevent the specification of conflicting transaction read/write
options"listed at:
http://wiki.postgresql.org/wiki/TodoThanks for chipping away at items on the list.
Please pass on any inputs on the patch.
Right now we want people focusing on fixing bugs and reviewing
patches submitted by the start of the current CommitFest. Please
add this to the open CF so we don't lose track of it.-Kevin
Sure.
Thanks!
-Chetan
--
EnterpriseDB Corporation
The Enterprise PostgreSQL Company
Website: www.enterprisedb.com
EnterpriseDB Blog : http://blogs.enterprisedb.com
Follow us on Twitter : http://www.twitter.com/enterprisedb