Skip to content

fix: SQLDeleteStatement.accept0 missing from/using children (#6563)#6642

Open
daguimu wants to merge 1 commit into
alibaba:masterfrom
daguimu:fix/delete-from-using-accept-6563
Open

fix: SQLDeleteStatement.accept0 missing from/using children (#6563)#6642
daguimu wants to merge 1 commit into
alibaba:masterfrom
daguimu:fix/delete-from-using-accept-6563

Conversation

@daguimu
Copy link
Copy Markdown

@daguimu daguimu commented Apr 29, 2026

Problem

The base SQLDeleteStatement.accept0 walked only with / tableSource / where, silently skipping the from and using sub-trees. As a result, dialects that fall back to the base implementation (DB2, Snowflake, etc.) cannot be fully traversed by visitors that rely on the default tree walk - any AST node reachable only via DELETE ... FROM <ts> or DELETE ... USING <ts> was invisible to AST consumers.

getChildren() had the same omission, and setUsing() failed to wire the parent pointer (setFrom already does), breaking parent-chain traversal for that branch.

Reported in #6563 (DELETE statement visitor cannot reach the FROM sub-tree when modifying table names).

Root Cause

Compare with MySqlDeleteStatement.accept0, which correctly walks with, tableSource, where, from, using, orderBy, limit. The base class - used directly by Snowflake, DB2 and any future dialect that does not override - was missing from and using. Snowflake and PG/Oscar parsers populate the using slot via setUsing(), but no parent was assigned, so even reverse-traversal would not work.

Fix

In SQLDeleteStatement:

  • accept0: walk from and using in addition to the previously-visited children.
  • getChildren: include from and using.
  • setUsing: wire the parent pointer, mirroring setFrom.

No changes to dialect-specific subclasses - they already override accept0 and were unaffected.

Tests Added

core/src/test/java/com/alibaba/druid/sql/issues/Issue6563.java:

  • test_snowflake_delete_using_visited - parses DELETE FROM t1 USING t_using_only WHERE ..., walks the AST with a generic identifier collector, and asserts t_using_only (referenced ONLY through the USING clause) is reached.
  • test_db2_delete_from_visited - parses DELETE FROM t FROM t_from_only WHERE ... for DB2, asserts t_from_only (reachable only through the secondary FROM) is visited.
  • test_getChildren_includes_from_and_using - structural test on the AST API.
  • test_setUsing_sets_parent - verifies the parent pointer is wired so reverse traversal works.

All four tests fail on master (4 failures, no errors) and pass with the fix.

Full mvn test for the core module: 4222 tests, 0 failures, 0 errors.

Fixes #6563

…6563)

The base SQLDeleteStatement.accept0 walked only with/tableSource/where,
silently skipping the from and using sub-trees.  Dialects that fall back
to the base implementation (DB2, Snowflake, etc.) therefore could not be
fully traversed by visitors that rely on the default tree walk - any
identifier reachable only through `DELETE ... FROM <ts>` or
`DELETE ... USING <ts>` was invisible to AST consumers.

`getChildren()` had the same omission, and `setUsing` did not wire the
parent pointer (`setFrom` already did), breaking parent-chain traversal
for that branch.

This commit walks `from` and `using` in accept0, includes them in
getChildren, and sets the parent in setUsing - matching the behaviour
already present in MySqlDeleteStatement.
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.

com.alibaba.druid.sql.ast.statement.SQLDeleteStatement缺少对from节点的accept

1 participant