From 6a06b652cce0963e0709dedf1993d0b632b626ee Mon Sep 17 00:00:00 2001 From: akshitj11 <126861164+akshitj11@users.noreply.github.com> Date: Mon, 24 Aug 2026 14:06:55 +0100 Subject: [PATCH] fix(sql): extract CREATE TABLE inside BEGIN/COMMIT blocks (#2953) DDL wrapped in a transaction parses under a `transaction` node the statement walker never descended into, so a CREATE TABLE inside BEGIN/COMMIT was never extracted while a top-level one was. Recurse into transaction blocks; nested statements get the same handling, no double-emit. --- graphify/extractors/sql.py | 4 ++++ tests/fixtures/sample_transaction.sql | 11 +++++++++++ tests/test_multilang.py | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 tests/fixtures/sample_transaction.sql diff --git a/graphify/extractors/sql.py b/graphify/extractors/sql.py index a5dc18c3..162c73fb 100644 --- a/graphify/extractors/sql.py +++ b/graphify/extractors/sql.py @@ -398,6 +398,10 @@ def extract_sql(path: Path, content: str | bytes | None = None) -> dict: if stmt.type == "statement": for child in stmt.children: walk(child) + elif stmt.type == "transaction": + # BEGIN; ... COMMIT; wraps DDL in a transaction node whose children + # are statement nodes, not direct create_table nodes (#2953). + walk(stmt) elif stmt.type in ("fb_proc_or_trigger", "set_term", "declare_external_function", "ERROR"): walk(stmt) diff --git a/tests/fixtures/sample_transaction.sql b/tests/fixtures/sample_transaction.sql new file mode 100644 index 00000000..291ff6e9 --- /dev/null +++ b/tests/fixtures/sample_transaction.sql @@ -0,0 +1,11 @@ +CREATE TABLE alfa (id integer PRIMARY KEY); + +BEGIN; + +CREATE TABLE gamma (id integer PRIMARY KEY); +CREATE TABLE delta ( + id integer PRIMARY KEY, + alfa_id integer REFERENCES alfa(id) +); + +COMMIT; diff --git a/tests/test_multilang.py b/tests/test_multilang.py index db7c0d90..7ff96d3f 100644 --- a/tests/test_multilang.py +++ b/tests/test_multilang.py @@ -461,6 +461,25 @@ def test_sql_finds_tables(): assert any("users" in l for l in labels) assert any("organizations" in l for l in labels) + +def test_sql_create_table_inside_transaction_block(): + """#2953: DDL wrapped in BEGIN; ... COMMIT; must emit table nodes.""" + r = _extract_sql_or_skip("sample_transaction.sql") + labels = [n["label"] for n in r["nodes"]] + assert any("alfa" in l for l in labels) + assert any("gamma" in l for l in labels) + assert any("delta" in l for l in labels) + refs = [ + (e["source"], e["target"]) + for e in r["edges"] + if e["relation"] == "references" + ] + node_by_id = {n["id"]: n["label"] for n in r["nodes"]} + assert any( + "delta" in node_by_id.get(s, "") and "alfa" in node_by_id.get(t, "") + for s, t in refs + ) + def test_sql_finds_view(): r = _extract_sql_or_skip() labels = [n["label"] for n in r["nodes"]]