diff --git a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java index 0e94b9c9e..b3d1463d0 100644 --- a/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java +++ b/src/main/java/net/sf/jsqlparser/util/TablesNamesFinder.java @@ -154,10 +154,14 @@ import net.sf.jsqlparser.statement.select.FunctionAllColumns; import net.sf.jsqlparser.statement.select.Join; import net.sf.jsqlparser.statement.select.LateralSubSelect; +import net.sf.jsqlparser.statement.select.LateralView; import net.sf.jsqlparser.statement.select.OrderByElement; import net.sf.jsqlparser.statement.select.ParenthesedFromItem; import net.sf.jsqlparser.statement.select.ParenthesedSelect; +import net.sf.jsqlparser.statement.select.Pivot; import net.sf.jsqlparser.statement.select.PivotQuery; +import net.sf.jsqlparser.statement.select.PivotVisitor; +import net.sf.jsqlparser.statement.select.PivotXml; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; import net.sf.jsqlparser.statement.select.SelectItem; @@ -165,6 +169,7 @@ import net.sf.jsqlparser.statement.select.SelectVisitor; import net.sf.jsqlparser.statement.select.SetOperationList; import net.sf.jsqlparser.statement.select.TableFunction; +import net.sf.jsqlparser.statement.select.UnPivot; import net.sf.jsqlparser.statement.select.TableStatement; import net.sf.jsqlparser.statement.select.Values; import net.sf.jsqlparser.statement.select.WithItem; @@ -187,7 +192,7 @@ public class TablesNamesFinder implements SelectVisitor, FromItemVisitor, ExpressionVisitor, SelectItemVisitor, StatementVisitor, MergeOperationVisitor, - PipeOperatorVisitor { + PipeOperatorVisitor, PivotVisitor { private Set tables; private boolean allowColumnProcessing = false; @@ -330,6 +335,20 @@ public Void visit(ParenthesedSelect select, S context) { } } select.getSelect().accept((SelectVisitor) this, context); + visitOrderBy(select.getOrderByElements(), context); + if (select.getPivot() != null) { + select.getPivot().accept(this, context); + } + if (select.getUnPivot() != null) { + select.getUnPivot().accept(this, context); + } + visitLimit(select.getLimit(), context); + if (select.getOffset() != null) { + select.getOffset().getOffset().accept(this, context); + } + if (select.getFetch() != null) { + select.getFetch().getExpression().accept(this, context); + } return null; } @@ -346,6 +365,11 @@ public Void visit(PlainSelect plainSelect, S context) { withItem.accept((SelectVisitor) this, context); } } + if (plainSelect.getDistinct() != null) { + visitSelectItems(plainSelect.getDistinct().getOnSelectItems(), context); + } + visitTables(plainSelect.getIntoTables(), context); + if (plainSelect.getSelectItems() != null) { for (SelectItem item : plainSelect.getSelectItems()) { item.accept(this, context); @@ -356,6 +380,12 @@ public Void visit(PlainSelect plainSelect, S context) { plainSelect.getFromItem().accept(this, context); } + if (plainSelect.getLateralViews() != null) { + for (LateralView lateralView : plainSelect.getLateralViews()) { + lateralView.getGeneratorFunction().accept(this, context); + } + } + visitJoins(plainSelect.getJoins(), context); if (plainSelect.getPreWhere() != null) { plainSelect.getPreWhere().accept(this, context); @@ -364,13 +394,46 @@ public Void visit(PlainSelect plainSelect, S context) { plainSelect.getWhere().accept(this, context); } + visitPreferringClause(plainSelect.getPreferringClause(), context); + visit(plainSelect.getGroupBy(), context); + if (plainSelect.getHaving() != null) { plainSelect.getHaving().accept(this, context); } + if (plainSelect.getQualify() != null) { + plainSelect.getQualify().accept(this, context); + } + if (plainSelect.getOracleHierarchical() != null) { plainSelect.getOracleHierarchical().accept(this, context); } + + if (plainSelect.getWindowDefinitions() != null) { + for (WindowDefinition windowDefinition : plainSelect.getWindowDefinitions()) { + visitExpressions(windowDefinition.getPartitionExpressionList(), context); + visitOrderBy(windowDefinition.getOrderByElements(), context); + } + } + + if (plainSelect.getPivot() != null) { + plainSelect.getPivot().accept(this, context); + } + if (plainSelect.getUnPivot() != null) { + plainSelect.getUnPivot().accept(this, context); + } + + visitOrderBy(plainSelect.getOrderByElements(), context); + visitLimit(plainSelect.getLimit(), context); + visitLimit(plainSelect.getLimitBy(), context); + if (plainSelect.getOffset() != null) { + plainSelect.getOffset().getOffset().accept(this, context); + } + if (plainSelect.getFetch() != null) { + plainSelect.getFetch().getExpression().accept(this, context); + } + visitUpdateSets(plainSelect.getSettings(), context); + visitFromItem(plainSelect.getIntoTempTable(), context); return null; } @@ -431,6 +494,12 @@ public Void visit(Table table, S context) { if (!otherItemNames.contains(tableWholeName)) { tables.add(tableWholeName); } + if (table.getPivot() != null) { + table.getPivot().accept(this, context); + } + if (table.getUnPivot() != null) { + table.getUnPivot().accept(this, context); + } return null; } @@ -883,6 +952,14 @@ public Void visit(SetOperationList list, S context) { for (Select selectBody : list.getSelects()) { selectBody.accept((SelectVisitor) this, context); } + visitOrderBy(list.getOrderByElements(), context); + visitLimit(list.getLimit(), context); + if (list.getOffset() != null) { + list.getOffset().getOffset().accept(this, context); + } + if (list.getFetch() != null) { + list.getFetch().getExpression().accept(this, context); + } return null; } @@ -941,6 +1018,36 @@ public Void visit(FromQuery fromQuery, S context) { return null; } + @Override + public Void visit(Pivot pivot, S context) { + visitSelectItems(pivot.getFunctionItems(), context); + visitExpressions(pivot.getForColumns(), context); + visitSelectItems(pivot.getSingleInItems(), context); + visitSelectItems(pivot.getMultiInItems(), context); + return null; + } + + @Override + public Void visit(PivotXml pivotXml, S context) { + visit((Pivot) pivotXml, context); + if (pivotXml.getInSelect() != null) { + pivotXml.getInSelect().accept((SelectVisitor) this, context); + } + return null; + } + + @Override + public Void visit(UnPivot unpivot, S context) { + for (Column column : unpivot.getUnPivotClause()) { + column.accept(this, context); + } + for (Column column : unpivot.getUnPivotForClause()) { + column.accept(this, context); + } + visitSelectItems(unpivot.getUnPivotInClause(), context); + return null; + } + @Override public Void visit(AggregatePipeOperator aggregate, Void context) { for (SelectItem selectItem : aggregate.getSelectItems()) { @@ -1220,6 +1327,8 @@ public Void visit(Delete delete, S context) { if (delete.getWhere() != null) { delete.getWhere().accept(this, context); } + visitOrderBy(delete.getOrderByElements(), context); + visitLimit(delete.getLimit(), context); visitOutputClause(delete.getOutputClause(), context); visitReturningClause(delete.getReturningClause(), context); return null; @@ -1279,6 +1388,8 @@ public Void visit(Update update, S context) { if (update.getWhere() != null) { update.getWhere().accept(this, context); } + visitOrderBy(update.getOrderByElements(), context); + visitLimit(update.getLimit(), context); visitOutputClause(update.getOutputClause(), context); visitReturningClause(update.getReturningClause(), context); return null; @@ -1790,6 +1901,14 @@ public void visit(Comment comment) { @Override public Void visit(Values values, S context) { values.getExpressions().accept(this, context); + visitOrderBy(values.getOrderByElements(), context); + visitLimit(values.getLimit(), context); + if (values.getOffset() != null) { + values.getOffset().getOffset().accept(this, context); + } + if (values.getFetch() != null) { + values.getFetch().getExpression().accept(this, context); + } return null; } diff --git a/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java b/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java index 53a33e988..e7db44ab9 100644 --- a/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java +++ b/src/test/java/net/sf/jsqlparser/util/TablesNamesFinderTest.java @@ -907,4 +907,163 @@ void testAnalyticFunctionsWithFilterClause() throws JSQLParserException { "MY_TABLE2"); } + @Test + void testSelectIntoTables() throws JSQLParserException { + String sqlStr = "SELECT * INTO MY_TABLE1 FROM MY_TABLE2"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + + @Test + void testSelectIntoTempTable() throws JSQLParserException { + String sqlStr = "SELECT * FROM MY_TABLE2 INTO TEMP MY_TABLE1"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + + @Test + void testGroupBySubquery() throws JSQLParserException { + String sqlStr = + "SELECT A FROM MY_TABLE1 GROUP BY A, (SELECT B FROM MY_TABLE2)"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + + @Test + void testGroupByGroupingSetsSubquery() throws JSQLParserException { + String sqlStr = + "SELECT A FROM MY_TABLE1 GROUP BY GROUPING SETS ((A, (SELECT B FROM MY_TABLE2)), (C))"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + + @Test + void testSelectQualifySubquery() throws JSQLParserException { + String sqlStr = "SELECT * FROM MY_TABLE1 QUALIFY (SELECT B FROM MY_TABLE2) = 1"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + + @Test + void testWindowDefinitionSubquery() throws JSQLParserException { + String sqlStr = + "SELECT * FROM MY_TABLE1 WINDOW W AS (PARTITION BY (SELECT B FROM MY_TABLE2))"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + + @Test + void testSelectOrderBySubquery() throws JSQLParserException { + String sqlStr = "SELECT A FROM MY_TABLE1 ORDER BY A, (SELECT B FROM MY_TABLE2)"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + + @Test + void testSelectLimitSubquery() throws JSQLParserException { + String sqlStr = "SELECT A FROM MY_TABLE1 LIMIT (SELECT B FROM MY_TABLE2)"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + + @Test + void testSelectLimitBySubquery() throws JSQLParserException { + String sqlStr = "SELECT A FROM MY_TABLE1 LIMIT 2 BY (SELECT B FROM MY_TABLE2)"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + + @Test + void testSelectOffsetSubquery() throws JSQLParserException { + String sqlStr = + "SELECT A FROM MY_TABLE1 LIMIT 1 OFFSET (SELECT B FROM MY_TABLE2)"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + + @Test + void testSelectFetchSubquery() throws JSQLParserException { + String sqlStr = + "SELECT A FROM MY_TABLE1 OFFSET 1 ROWS FETCH NEXT (SELECT B FROM MY_TABLE2) ROWS ONLY"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + + @Test + void testSelectDistinctOnSubquery() throws JSQLParserException { + String sqlStr = "SELECT DISTINCT ON ((SELECT B FROM MY_TABLE2)) A FROM MY_TABLE1"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + + @Test + void testLateralViewSubquery() throws JSQLParserException { + String sqlStr = + "SELECT * FROM MY_TABLE1 LATERAL VIEW EXPLODE(ARRAY((SELECT B FROM MY_TABLE2))) V AS X"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + + @Test + void testTablePivotXmlSubquery() throws JSQLParserException { + String sqlStr = + "SELECT * FROM MY_TABLE1 PIVOT XML (SUM(X) FOR Y IN (SELECT Z FROM MY_TABLE2))"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + + @Test + void testTablePivotSimple() throws JSQLParserException { + String sqlStr = "SELECT * FROM MY_TABLE1 PIVOT (SUM(X) FOR Y IN ('a', 'b'))"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1"); + } + + @Test + void testParenthesedOrderByLimitSubquery() throws JSQLParserException { + String sqlStr = + "(SELECT A FROM MY_TABLE1) ORDER BY (SELECT B FROM MY_TABLE2) LIMIT (SELECT C FROM MY_TABLE3)"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2", "MY_TABLE3"); + } + + @Test + void testSetOperationOrderByLimitSubquery() throws JSQLParserException { + String sqlStr = + "SELECT A FROM MY_TABLE1 UNION SELECT B FROM MY_TABLE2 ORDER BY (SELECT C FROM MY_TABLE3) LIMIT (SELECT D FROM MY_TABLE4)"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2", "MY_TABLE3", "MY_TABLE4"); + } + + @Test + void testSelectSettingsSubquery() throws JSQLParserException { + String sqlStr = + "SELECT A FROM MY_TABLE1 SETTINGS X = (SELECT B FROM MY_TABLE2)"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + + @Test + void testValuesOrderByLimitSubquery() throws JSQLParserException { + String sqlStr = + "VALUES (1), (2) ORDER BY (SELECT A FROM MY_TABLE1) LIMIT (SELECT B FROM MY_TABLE2)"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + + @Test + void testDeleteOrderByLimitSubquery() throws JSQLParserException { + String sqlStr = + "DELETE FROM MY_TABLE1 WHERE A = 1 ORDER BY (SELECT B FROM MY_TABLE2) LIMIT 2"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + + @Test + void testUpdateOrderByLimitSubquery() throws JSQLParserException { + String sqlStr = + "UPDATE MY_TABLE1 SET A = 1 ORDER BY (SELECT B FROM MY_TABLE2) LIMIT 2"; + assertThat(TablesNamesFinder.findTables(sqlStr)).containsExactlyInAnyOrder("MY_TABLE1", + "MY_TABLE2"); + } + }