Skip to content

T-SQL: a bracketed FOREIGN KEY can drop the child table entirely and emit a self-referencing edge tagged EXTRACTED #2713

Description

@YNFM

Summary

For some bracket-quoted T-SQL, a FOREIGN KEY ... REFERENCES clause causes the child table to be
dropped from the graph entirely
and produces a self-referencing edge on the parent, tagged
EXTRACTED
.

EXTRACTED means "explicit in the source". There is no Customer → Customer reference anywhere in
the input. So this is not a missing edge — it is a fabricated edge carrying the highest confidence
grade
, which is worse, because the grade is what a reader uses to decide whether to trust it
without checking.

The identical input with brackets removed is extracted correctly.

Repro

s.sql, alone in a directory:

CREATE TABLE [dbo].[Customer] (
    [CustomerId] INT NOT NULL PRIMARY KEY,
    [Name]       NVARCHAR(100) NULL
);
GO

CREATE TABLE [dbo].[Invoice] (
    [InvoiceId]  INT NOT NULL PRIMARY KEY,
    [CustomerId] INT NOT NULL,
    CONSTRAINT [FK_Invoice_Customer] FOREIGN KEY ([CustomerId])
        REFERENCES [dbo].[Customer] ([CustomerId])
);
GO
graphify . --code-only --force

Actual

labels: ['s.sql', 'dbo].[Customer']
edges : [('s', 'contains',   's_dbo_customer', 'EXTRACTED'),
         ('s_dbo_customer', 'references', 's_dbo_customer', 'EXTRACTED')]

[dbo].[Invoice] is absent from the graph. The FK it declares appears as Customer → Customer.

Expected

The same file with brackets removed gives the right answer, so this is the behaviour to match:

labels: ['s.sql', 'dbo.Customer', 'dbo.Invoice', ...]
edges : [..., ('s_dbo_invoice', 'references', 's_dbo_customer', 'EXTRACTED')]

What I could and could not isolate

Reproduces deterministically, including with --force in a fresh directory, so it is not an
incremental-cache artefact.

I could not isolate the trigger. Four plausible causes were each tested and refuted — nearby
variants all extract correctly:

Hypothesis Test Result
Objects after the first are dropped three bracketed CREATE TABLE, no FK all three extracted — refuted
A bracketed FK breaks extraction generally [dbo].[Beta] FK → [dbo].[Alpha] correct edge — refuted
FK column name matching the referenced column name AlphaIdAlphaId vs AlphaIdId both correct — refuted
A parameterised column type (NVARCHAR(100)) breaks statement boundaries with and without both correct — refuted

So the minimal failing case above is the smallest input I have that fails, and structurally similar
inputs succeed. I did not want to guess further at a mechanism in someone else's parser — the repro
is deterministic, so hopefully it is quicker to bisect from inside.

Why this matters for schema corpora

The stated value of the SQL path is that declared foreign keys become high-confidence edges, and
that is exactly the case failing here. A schema with many FKs is the corpus where the tool should be
strongest; instead some tables vanish silently and some relationships are replaced by self-loops
that look authoritative. Both failures are invisible in the build log — the run exits 0 and reports
a node and edge count that looks reasonable.

For scale, the schema we are indexing declares ~1,365 foreign keys.

Environment

  • graphify 0.9.39, tree_sitter_sql present (confirmed importable)
  • Python 3.14.2, Windows 11
  • --code-only, so this is the local AST path with no LLM involved

Related

The bracket-quoted identifier label mangling (dbo].[Customer) is filed separately. It is visible
in the output above but does not appear to share a trigger with this — every bracketed case mangles
labels, only some drop nodes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions