Skip to content

fix: complete TablesNamesFinder traversal for piped queries, DML side clauses and analytic functions (#2478) - #2479

Merged
manticore-projects merged 1 commit into
JSQLParser:masterfrom
fudianchn:fix/tables-names-finder-coverage
Aug 17, 2026
Merged

fix: complete TablesNamesFinder traversal for piped queries, DML side clauses and analytic functions (#2478)#2479
manticore-projects merged 1 commit into
JSQLParser:masterfrom
fudianchn:fix/tables-names-finder-coverage

Conversation

@fudianchn

Copy link
Copy Markdown
Contributor

What

Completes the visitor traversal of TablesNamesFinder for piped queries (FromQuery + all pipe operators), the WITH list of DELETE, the ON condition and WHEN operations of MERGE, the SET list, ON DUPLICATE KEY UPDATE / ON CONFLICT ... DO UPDATE actions and OUTPUT / RETURNING clauses of the DML statements, data modifying CTE payloads and the ORDER BY / FILTER parts of analytic functions.

Why

TablesNamesFinder is the documented entry point for SQL auditing / firewall use cases; four of the gaps silently return an incomplete table list and two throw. Fixes #2478.

How

  • visit(FromQuery) traverses the WITH list, the from item and all pipe operators; TablesNamesFinder now implements PipeOperatorVisitor (mirroring SelectDeParser).
  • visit(Delete) traverses withItemsList like visit(Update) / visit(Insert) already do.
  • visit(Merge) traverses onCondition and all operations; TablesNamesFinder now implements MergeOperationVisitor.
  • visit(Insert) traverses setUpdateSets, duplicateAction, conflictAction (via the existing ExpressionVisitor.visitUpdateSets default); all three DML visits traverse outputClause (overriding the SelectVisitor default) and returningClause.
  • visit(WithItem) dispatches the payload as any ParenthesedStatement instead of casting via getSelect(), which fixes data modifying CTEs.
  • visit(AnalyticExpression) traverses funcOrderBy and orderByElements independently and adds filterExpression.

The parser, grammar and deparser are untouched, so there is no impact on parsing performance.

Root cause

Visitor coverage in TablesNamesFinder was incomplete: newer AST families (piped queries, merge operations, insert actions, output / returning clauses) were never wired up, and two pre-existing guards were wrong (getSelect() cast, getFuncOrderBy() checked but getOrderByElements() iterated).

Testing

  • 14 new tests in TablesNamesFinderTest; all 14 fail on master f41c0b8 (missing tables, ClassCastException, NullPointerException) and pass with this change: ./gradlew test --tests net.sf.jsqlparser.util.TablesNamesFinderTest -> 85 tests, 0 failures.
  • Full local gate ./gradlew spotlessApply check -> 4854 tests, 0 failures.

Verification of the original issue

Case from #2478 master f41c0b8 with this change
piped query (4 tables) [] all 4 tables
DELETE with WITH [cte, MY_TABLE1] [MY_TABLE1, MY_TABLE2]
MERGE with subqueries [src, MY_TABLE1] all 5 tables
INSERT ... ON DUPLICATE KEY UPDATE [MY_TABLE1] [MY_TABLE1, MY_TABLE2]
WITH del AS (DELETE ...) ClassCastException [MY_TABLE1, MY_TABLE2]
string_agg(...) OVER (...) NullPointerException [MY_TABLE1]

Fixes #2478

… clauses and analytic functions (JSQLParser#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>
@manticore-projects

Copy link
Copy Markdown
Contributor

Great work, thank you much for fixing this!

@manticore-projects
manticore-projects merged commit ad69ecc into JSQLParser:master Aug 17, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] TablesNamesFinder misses tables or throws for piped queries, DML statements and analytic clauses

2 participants