Skip to content

Commit d3c09cd

Browse files
committed
Reject contradictory MySQL transaction access modes
Signed-off-by: minleejae <mmj9808@gmail.com>
1 parent 672e8dc commit d3c09cd

3 files changed

Lines changed: 42 additions & 0 deletions

File tree

‎src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19052,6 +19052,10 @@ StartTransaction StartTransaction():
1905219052
{
1905319053
requireDdlSyntax(!isMySqlDialect() || statement.getCommand() != StartTransaction.Command.BEGIN
1905419054
|| statement.getModes().isEmpty(), "MySQL BEGIN does not accept transaction characteristics");
19055+
requireDdlSyntax(!Dialect.MYSQL.name().equals(getAsString(Feature.dialect))
19056+
|| !statement.getModes().contains(StartTransaction.Mode.READ_ONLY)
19057+
|| !statement.getModes().contains(StartTransaction.Mode.READ_WRITE),
19058+
"MySQL transactions cannot specify both READ ONLY and READ WRITE");
1905519059
return statement;
1905619060
}
1905719061
}

‎src/site/sphinx/usage.rst‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,6 +1426,8 @@ Transaction statements
14261426
transaction modes. PostgreSQL isolation levels, ``READ ONLY`` / ``READ WRITE``, and
14271427
``[NOT] DEFERRABLE`` are supported, as is MySQL ``WITH CONSISTENT SNAPSHOT``.
14281428
PostgreSQL accepts mode lists with or without commas; output uses commas.
1429+
The explicit MySQL dialect rejects a transaction containing both ``READ ONLY`` and
1430+
``READ WRITE``, while retaining repeated occurrences of the same mode.
14291431

14301432
Choose the dialect explicitly to parse ``BEGIN`` as a transaction command:
14311433

‎src/test/java/net/sf/jsqlparser/statement/TransactionStatementTest.java‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,42 @@ void mysqlStartsAreStructured(String sql) throws Exception {
7979
assertInstanceOf(StartTransaction.class, roundTrip(sql, Dialect.MYSQL));
8080
}
8181

82+
@ParameterizedTest
83+
@ValueSource(strings = {"START TRANSACTION READ ONLY, READ WRITE",
84+
"START TRANSACTION READ WRITE, READ ONLY"})
85+
void contradictoryAccessModesAreRejectedOnlyForMysql(String sql) throws Exception {
86+
JSQLParserException error = assertThrows(JSQLParserException.class,
87+
() -> parse(sql, Dialect.MYSQL));
88+
assertTrue(error.getCause().getMessage()
89+
.contains("cannot specify both READ ONLY and READ WRITE"));
90+
assertThrows(JSQLParserException.class,
91+
() -> parse(sql.replace(", ", ", WITH CONSISTENT SNAPSHOT, "), Dialect.MYSQL));
92+
StartTransaction postgres = assertInstanceOf(StartTransaction.class,
93+
roundTrip(sql, Dialect.POSTGRESQL));
94+
List<StartTransaction.Mode> expected = sql.endsWith("READ WRITE")
95+
? List.of(StartTransaction.Mode.READ_ONLY, StartTransaction.Mode.READ_WRITE)
96+
: List.of(StartTransaction.Mode.READ_WRITE, StartTransaction.Mode.READ_ONLY);
97+
assertEquals(expected, postgres.getModes());
98+
assertEquals(sql, postgres.toString());
99+
StartTransaction permissive = assertInstanceOf(StartTransaction.class,
100+
CCJSqlParserUtil.parse(sql));
101+
assertEquals(expected, permissive.getModes());
102+
assertEquals(sql, permissive.toString());
103+
}
104+
105+
@ParameterizedTest
106+
@ValueSource(strings = {"START TRANSACTION READ ONLY, READ ONLY",
107+
"START TRANSACTION READ WRITE, READ WRITE"})
108+
void mysqlRepeatedAccessModesArePreserved(String sql) throws Exception {
109+
StartTransaction statement = assertInstanceOf(StartTransaction.class,
110+
roundTrip(sql, Dialect.MYSQL));
111+
StartTransaction.Mode mode = sql.endsWith("READ ONLY")
112+
? StartTransaction.Mode.READ_ONLY
113+
: StartTransaction.Mode.READ_WRITE;
114+
assertEquals(List.of(mode, mode), statement.getModes());
115+
assertEquals(sql, statement.toString());
116+
}
117+
82118
@ParameterizedTest
83119
@ValueSource(strings = {"COMMIT", "COMMIT WORK", "COMMIT TRANSACTION", "COMMIT AND CHAIN",
84120
"COMMIT WORK AND NO CHAIN", "COMMIT TRANSACTION AND CHAIN", "ROLLBACK",

0 commit comments

Comments
 (0)