Skip to content

Commit 4dff61a

Browse files
authored
fix: find tables in SET values instead of throwing (#2873)
TablesNamesFinder threw UnsupportedOperationException for every SET statement except SQL Server ON/OFF options. A MySQL trigger whose body is or contains SET, such as FOR EACH ROW SET NEW.a = ..., failed the same way, although its table is known. The finder now visits the value expressions of each assignment, so a subquery in a SET value reports its tables and other SET statements report none. Signed-off-by: minleejae <mmj9808@gmail.com>
1 parent 1e0e858 commit 4dff61a

2 files changed

Lines changed: 28 additions & 2 deletions

File tree

‎src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1950,8 +1950,13 @@ public void visit(Execute execute) {
19501950

19511951
@Override
19521952
public <S> Void visit(SetStatement setStatement, S context) {
1953-
if (setStatement.getOnOffOptions() == null) {
1954-
throwUnsupported(setStatement);
1953+
for (int i = 0; i < setStatement.getCount(); i++) {
1954+
List<Expression> expressions = setStatement.getExpressions(i);
1955+
if (expressions != null) {
1956+
for (Expression expression : expressions) {
1957+
expression.accept(this, context);
1958+
}
1959+
}
19551960
}
19561961
return null;
19571962
}

‎src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java‎

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,27 @@ public void testAlterSequenceHasNoTableReferences() throws JSQLParserException {
392392
assertThat(tablesNamesFinder.getTables(stmt)).isEmpty();
393393
}
394394

395+
@Test
396+
public void testSetStatementFindsTablesInValues() throws JSQLParserException {
397+
assertThat(TablesNamesFinder
398+
.findTables("SET @a = (SELECT MAX(id) FROM MY_TABLE1), @b = 2"))
399+
.containsExactlyInAnyOrder("MY_TABLE1");
400+
assertThat(TablesNamesFinder.findTables("SET search_path TO s1")).isEmpty();
401+
}
402+
403+
@Test
404+
public void testMySqlTriggerWithSetBody() throws JSQLParserException {
405+
String sqlStr = "CREATE TRIGGER trg BEFORE INSERT ON MY_TABLE1 FOR EACH ROW "
406+
+ "SET NEW.a = (SELECT MAX(id) FROM MY_TABLE2)";
407+
assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1",
408+
"MY_TABLE2");
409+
410+
sqlStr = "CREATE TRIGGER trg BEFORE UPDATE ON MY_TABLE1 FOR EACH ROW "
411+
+ "BEGIN SET NEW.updated_at = NOW(); INSERT INTO MY_TABLE2 VALUES (NEW.id); END";
412+
assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1",
413+
"MY_TABLE2");
414+
}
415+
395416
@Test
396417
public void testCreateSynonym_throwsException() throws JSQLParserException {
397418
String sql = "CREATE SYNONYM foo FOR bar";

0 commit comments

Comments
 (0)