Skip to content

Commit fbec089

Browse files
committed
fix: complete TablesNamesFinder traversal for piped queries, DML side clauses and analytic functions (#2478)
Silently missed tables or threw for: piped queries (visit(FromQuery) was empty, now implements PipeOperatorVisitor), DELETE WITH lists (CTE tables lost, CTE alias leaked as phantom table), MERGE ON condition and WHEN operations (now implements MergeOperationVisitor), INSERT SET / ON DUPLICATE KEY UPDATE / ON CONFLICT actions and OUTPUT / RETURNING clauses of INSERT / UPDATE / DELETE, data modifying CTEs (ClassCastException in WithItem.getSelect(), dispatch any ParenthesedStatement instead) and analytic functions with function level ORDER BY (NPE), window ORDER BY or FILTER clause. Signed-off-by: 付典 <fudianchn@gmail.com>
1 parent f41c0b8 commit fbec089

2 files changed

Lines changed: 402 additions & 5 deletions

File tree

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

Lines changed: 273 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
import net.sf.jsqlparser.statement.PurgeObjectType;
7777
import net.sf.jsqlparser.statement.PurgeStatement;
7878
import net.sf.jsqlparser.statement.ResetStatement;
79+
import net.sf.jsqlparser.statement.ReturningClause;
7980
import net.sf.jsqlparser.statement.RollbackStatement;
8081
import net.sf.jsqlparser.statement.SavepointStatement;
8182
import net.sf.jsqlparser.statement.SessionStatement;
@@ -92,6 +93,7 @@
9293
import net.sf.jsqlparser.statement.alter.AlterSystemStatement;
9394
import net.sf.jsqlparser.statement.alter.RenameTableStatement;
9495
import net.sf.jsqlparser.statement.alter.sequence.AlterSequence;
96+
import net.sf.jsqlparser.statement.OutputClause;
9597
import net.sf.jsqlparser.statement.analyze.Analyze;
9698
import net.sf.jsqlparser.statement.comment.Comment;
9799
import net.sf.jsqlparser.statement.create.database.CreateDatabase;
@@ -111,12 +113,38 @@
111113
import net.sf.jsqlparser.statement.grant.Grant;
112114
import net.sf.jsqlparser.statement.imprt.Import;
113115
import net.sf.jsqlparser.statement.insert.Insert;
116+
import net.sf.jsqlparser.statement.insert.InsertConflictAction;
117+
import net.sf.jsqlparser.statement.insert.InsertDuplicateAction;
114118
import net.sf.jsqlparser.statement.insert.OracleMultiInsertBranch;
115119
import net.sf.jsqlparser.statement.insert.OracleMultiInsertClause;
116120
import net.sf.jsqlparser.statement.insert.ParenthesedInsert;
117121
import net.sf.jsqlparser.statement.lock.LockStatement;
118122
import net.sf.jsqlparser.statement.merge.Merge;
123+
import net.sf.jsqlparser.statement.merge.MergeDelete;
124+
import net.sf.jsqlparser.statement.merge.MergeInsert;
125+
import net.sf.jsqlparser.statement.merge.MergeOperation;
126+
import net.sf.jsqlparser.statement.merge.MergeOperationVisitor;
127+
import net.sf.jsqlparser.statement.merge.MergeUpdate;
128+
import net.sf.jsqlparser.statement.piped.AggregatePipeOperator;
129+
import net.sf.jsqlparser.statement.piped.AsPipeOperator;
130+
import net.sf.jsqlparser.statement.piped.CallPipeOperator;
131+
import net.sf.jsqlparser.statement.piped.DropPipeOperator;
132+
import net.sf.jsqlparser.statement.piped.ExtendPipeOperator;
119133
import net.sf.jsqlparser.statement.piped.FromQuery;
134+
import net.sf.jsqlparser.statement.piped.JoinPipeOperator;
135+
import net.sf.jsqlparser.statement.piped.LimitPipeOperator;
136+
import net.sf.jsqlparser.statement.piped.OrderByPipeOperator;
137+
import net.sf.jsqlparser.statement.piped.PipeOperator;
138+
import net.sf.jsqlparser.statement.piped.PipeOperatorVisitor;
139+
import net.sf.jsqlparser.statement.piped.PivotPipeOperator;
140+
import net.sf.jsqlparser.statement.piped.RenamePipeOperator;
141+
import net.sf.jsqlparser.statement.piped.SelectPipeOperator;
142+
import net.sf.jsqlparser.statement.piped.SetOperationPipeOperator;
143+
import net.sf.jsqlparser.statement.piped.SetPipeOperator;
144+
import net.sf.jsqlparser.statement.piped.TableSamplePipeOperator;
145+
import net.sf.jsqlparser.statement.piped.UnPivotPipeOperator;
146+
import net.sf.jsqlparser.statement.piped.WherePipeOperator;
147+
import net.sf.jsqlparser.statement.piped.WindowPipeOperator;
120148
import net.sf.jsqlparser.statement.refresh.RefreshMaterializedViewStatement;
121149
import net.sf.jsqlparser.statement.select.AllColumns;
122150
import net.sf.jsqlparser.statement.select.AllTableColumns;
@@ -156,7 +184,8 @@
156184
@SuppressWarnings({"PMD.CyclomaticComplexity", "PMD.UncommentedEmptyMethodBody"})
157185
public class TablesNamesFinder<Void>
158186
implements SelectVisitor<Void>, FromItemVisitor<Void>, ExpressionVisitor<Void>,
159-
SelectItemVisitor<Void>, StatementVisitor<Void> {
187+
SelectItemVisitor<Void>, StatementVisitor<Void>, MergeOperationVisitor<Void>,
188+
PipeOperatorVisitor<Void, Void> {
160189

161190
private Set<String> tables;
162191
private boolean allowColumnProcessing = false;
@@ -277,9 +306,8 @@ public <S> Void visit(WithItem<?> withItem, S context) {
277306
if (withItem.getAlias() != null) {
278307
otherItemNames.add(withItem.getAlias().getName());
279308
}
280-
if (withItem.getSelect() != null) {
281-
withItem.getSelect().accept((SelectVisitor<?>) this, context);
282-
}
309+
// dispatch any ParenthesedStatement payload (Select, Delete, Update, Insert)
310+
withItem.accept((StatementVisitor<?>) this, context);
283311
return null;
284312
}
285313

@@ -768,7 +796,15 @@ public <S> Void visit(AnalyticExpression analytic, S context) {
768796
if (analytic.getKeep() != null) {
769797
analytic.getKeep().accept(this, context);
770798
}
799+
if (analytic.getFilterExpression() != null) {
800+
analytic.getFilterExpression().accept(this, context);
801+
}
771802
if (analytic.getFuncOrderBy() != null) {
803+
for (OrderByElement element : analytic.getFuncOrderBy()) {
804+
element.getExpression().accept(this, context);
805+
}
806+
}
807+
if (analytic.getOrderByElements() != null) {
772808
for (OrderByElement element : analytic.getOrderByElements()) {
773809
element.getExpression().accept(this, context);
774810
}
@@ -852,9 +888,143 @@ public void visit(TableStatement tableStatement) {
852888

853889
@Override
854890
public <S> Void visit(FromQuery fromQuery, S context) {
891+
List<WithItem<?>> withItemsList = fromQuery.getWithItemsList();
892+
if (withItemsList != null && !withItemsList.isEmpty()) {
893+
for (WithItem<?> withItem : withItemsList) {
894+
withItem.accept((SelectVisitor<?>) this, context);
895+
}
896+
}
897+
if (fromQuery.getFromItem() != null) {
898+
fromQuery.getFromItem().accept(this, context);
899+
}
900+
for (PipeOperator pipeOperator : fromQuery.getPipeOperators()) {
901+
pipeOperator.accept(this, null);
902+
}
903+
return null;
904+
}
905+
906+
@Override
907+
public Void visit(AggregatePipeOperator aggregate, Void context) {
908+
for (SelectItem<?> selectItem : aggregate.getSelectItems()) {
909+
selectItem.accept(this, context);
910+
}
911+
for (SelectItem<?> groupItem : aggregate.getGroupItems()) {
912+
groupItem.accept(this, context);
913+
}
855914
return null;
856915
}
857916

917+
@Override
918+
public Void visit(AsPipeOperator as, Void context) {
919+
if (as.getAlias() != null) {
920+
otherItemNames.add(as.getAlias().getName());
921+
}
922+
return null;
923+
}
924+
925+
@Override
926+
public Void visit(CallPipeOperator call, Void context) {
927+
visit(call.getTableFunction(), context);
928+
return null;
929+
}
930+
931+
@Override
932+
public Void visit(DropPipeOperator drop, Void context) {
933+
drop.getColumns().accept(this, context);
934+
return null;
935+
}
936+
937+
@Override
938+
public Void visit(ExtendPipeOperator extend, Void context) {
939+
return visit((SelectPipeOperator) extend, context);
940+
}
941+
942+
@Override
943+
public Void visit(JoinPipeOperator joinPipeOperator, Void context) {
944+
visitJoins(List.of(joinPipeOperator.getJoin()), context);
945+
return null;
946+
}
947+
948+
@Override
949+
public Void visit(LimitPipeOperator limit, Void context) {
950+
limit.getLimitExpression().accept(this, context);
951+
if (limit.getOffsetExpression() != null) {
952+
limit.getOffsetExpression().accept(this, context);
953+
}
954+
return null;
955+
}
956+
957+
@Override
958+
public Void visit(OrderByPipeOperator orderBy, Void context) {
959+
for (OrderByElement element : orderBy.getOrderByElements()) {
960+
element.getExpression().accept(this, context);
961+
}
962+
return null;
963+
}
964+
965+
@Override
966+
public Void visit(PivotPipeOperator pivot, Void context) {
967+
pivot.getAggregateExpression().accept(this, context);
968+
for (SelectItem<?> pivotColumn : pivot.getPivotColumns()) {
969+
pivotColumn.accept(this, context);
970+
}
971+
return null;
972+
}
973+
974+
@Override
975+
public Void visit(RenamePipeOperator rename, Void context) {
976+
return visit((SelectPipeOperator) rename, context);
977+
}
978+
979+
@Override
980+
public Void visit(SelectPipeOperator select, Void context) {
981+
for (SelectItem<?> selectItem : select.getSelectItems()) {
982+
selectItem.accept(this, context);
983+
}
984+
return null;
985+
}
986+
987+
@Override
988+
public Void visit(SetPipeOperator set, Void context) {
989+
for (UpdateSet updateSet : set.getUpdateSets()) {
990+
updateSet.getColumns().accept(this, context);
991+
updateSet.getValues().accept(this, context);
992+
}
993+
return null;
994+
}
995+
996+
@Override
997+
public Void visit(TableSamplePipeOperator tableSample, Void context) {
998+
return null;
999+
}
1000+
1001+
@Override
1002+
public Void visit(SetOperationPipeOperator setOperation, Void context) {
1003+
for (ParenthesedSelect select : setOperation.getSelects()) {
1004+
select.accept((SelectVisitor<?>) this, context);
1005+
}
1006+
return null;
1007+
}
1008+
1009+
@Override
1010+
public Void visit(UnPivotPipeOperator unPivot, Void context) {
1011+
for (SelectItem<?> pivotColumn : unPivot.getPivotColumns()) {
1012+
pivotColumn.accept(this, context);
1013+
}
1014+
return null;
1015+
}
1016+
1017+
@Override
1018+
public Void visit(WherePipeOperator where, Void context) {
1019+
where.getExpression().accept(this, context);
1020+
return null;
1021+
}
1022+
1023+
@Override
1024+
public Void visit(WindowPipeOperator window, Void context) {
1025+
return visit((SelectPipeOperator) window, context);
1026+
}
1027+
8581028
@Override
8591029
public <S> Void visit(DateUnitExpression dateUnitExpression, S context) {
8601030
return null;
@@ -988,6 +1158,11 @@ public <S> Void visit(MySQLGroupConcat groupConcat, S context) {
9881158

9891159
@Override
9901160
public <S> Void visit(Delete delete, S context) {
1161+
if (delete.getWithItemsList() != null) {
1162+
for (WithItem<?> withItem : delete.getWithItemsList()) {
1163+
withItem.accept((SelectVisitor<?>) this, context);
1164+
}
1165+
}
9911166
visit(delete.getTable(), context);
9921167

9931168
if (delete.getUsingFromItemList() != null) {
@@ -1001,6 +1176,8 @@ public <S> Void visit(Delete delete, S context) {
10011176
if (delete.getWhere() != null) {
10021177
delete.getWhere().accept(this, context);
10031178
}
1179+
visitOutputClause(delete.getOutputClause(), context);
1180+
visitReturningClause(delete.getReturningClause(), context);
10041181
return null;
10051182
}
10061183

@@ -1058,6 +1235,8 @@ public <S> Void visit(Update update, S context) {
10581235
if (update.getWhere() != null) {
10591236
update.getWhere().accept(this, context);
10601237
}
1238+
visitOutputClause(update.getOutputClause(), context);
1239+
visitReturningClause(update.getReturningClause(), context);
10611240
return null;
10621241
}
10631242

@@ -1096,12 +1275,55 @@ public <S> Void visit(Insert insert, S context) {
10961275
withItem.accept((SelectVisitor<?>) this, context);
10971276
}
10981277
}
1278+
if (insert.getSetUpdateSets() != null) {
1279+
visitUpdateSets(insert.getSetUpdateSets(), context);
1280+
}
1281+
if (insert.getDuplicateAction() != null) {
1282+
visitInsertAction(insert.getDuplicateAction(), context);
1283+
}
1284+
if (insert.getConflictAction() != null) {
1285+
visitInsertAction(insert.getConflictAction(), context);
1286+
}
1287+
visitOutputClause(insert.getOutputClause(), context);
1288+
visitReturningClause(insert.getReturningClause(), context);
10991289
if (insert.getSelect() != null) {
11001290
visit(insert.getSelect(), context);
11011291
}
11021292
return null;
11031293
}
11041294

1295+
private <S> void visitInsertAction(InsertDuplicateAction action, S context) {
1296+
visitUpdateSets(action.getUpdateSets(), context);
1297+
if (action.getWhereExpression() != null) {
1298+
action.getWhereExpression().accept(this, context);
1299+
}
1300+
}
1301+
1302+
private <S> void visitInsertAction(InsertConflictAction action, S context) {
1303+
visitUpdateSets(action.getUpdateSets(), context);
1304+
if (action.getWhereExpression() != null) {
1305+
action.getWhereExpression().accept(this, context);
1306+
}
1307+
}
1308+
1309+
@Override
1310+
public <S> Void visitOutputClause(OutputClause outputClause, S context) {
1311+
if (outputClause != null && outputClause.getSelectItemList() != null) {
1312+
for (SelectItem<?> selectItem : outputClause.getSelectItemList()) {
1313+
selectItem.accept(this, context);
1314+
}
1315+
}
1316+
return null;
1317+
}
1318+
1319+
private <S> void visitReturningClause(ReturningClause returningClause, S context) {
1320+
if (returningClause != null) {
1321+
for (SelectItem<?> selectItem : returningClause) {
1322+
selectItem.accept(this, context);
1323+
}
1324+
}
1325+
}
1326+
11051327
@Override
11061328
public <S> Void visit(ParenthesedInsert insert, S context) {
11071329
return visit(insert.getInsert(), context);
@@ -1315,6 +1537,53 @@ public <S> Void visit(Merge merge, S context) {
13151537
if (merge.getFromItem() != null) {
13161538
merge.getFromItem().accept(this, context);
13171539
}
1540+
1541+
if (merge.getOnCondition() != null) {
1542+
merge.getOnCondition().accept(this, context);
1543+
}
1544+
1545+
if (merge.getOperations() != null) {
1546+
for (MergeOperation operation : merge.getOperations()) {
1547+
operation.accept(this, context);
1548+
}
1549+
}
1550+
return null;
1551+
}
1552+
1553+
@Override
1554+
public <S> Void visit(MergeDelete mergeDelete, S context) {
1555+
if (mergeDelete.getAndPredicate() != null) {
1556+
mergeDelete.getAndPredicate().accept(this, context);
1557+
}
1558+
return null;
1559+
}
1560+
1561+
@Override
1562+
public <S> Void visit(MergeInsert mergeInsert, S context) {
1563+
if (mergeInsert.getAndPredicate() != null) {
1564+
mergeInsert.getAndPredicate().accept(this, context);
1565+
}
1566+
if (mergeInsert.getValues() != null) {
1567+
mergeInsert.getValues().accept(this, context);
1568+
}
1569+
if (mergeInsert.getWhereCondition() != null) {
1570+
mergeInsert.getWhereCondition().accept(this, context);
1571+
}
1572+
return null;
1573+
}
1574+
1575+
@Override
1576+
public <S> Void visit(MergeUpdate mergeUpdate, S context) {
1577+
if (mergeUpdate.getAndPredicate() != null) {
1578+
mergeUpdate.getAndPredicate().accept(this, context);
1579+
}
1580+
visitUpdateSets(mergeUpdate.getUpdateSets(), context);
1581+
if (mergeUpdate.getWhereCondition() != null) {
1582+
mergeUpdate.getWhereCondition().accept(this, context);
1583+
}
1584+
if (mergeUpdate.getDeleteWhereCondition() != null) {
1585+
mergeUpdate.getDeleteWhereCondition().accept(this, context);
1586+
}
13181587
return null;
13191588
}
13201589

0 commit comments

Comments
 (0)