Skip to content

fix(schema): clear empty-state for a DB with no lineage (was invisible/empty output)#46

Merged
BorisTyshkevich merged 1 commit into
mainfrom
fix/schema-graph-empty-state
Jun 26, 2026
Merged

fix(schema): clear empty-state for a DB with no lineage (was invisible/empty output)#46
BorisTyshkevich merged 1 commit into
mainfrom
fix/schema-graph-empty-state

Conversation

@BorisTyshkevich

Copy link
Copy Markdown
Collaborator

Bug (reported)

Dragging database target_all on github.demo (201 tables, all URL engine, zero relationships) produced empty output.

Diagnosed live: buildSchemaGraph returned 201 nodes / 0 edges; dagre laid them out in a ~127621px × 58px single row; fit-to-view shrank every node to sub-pixel → a blank-looking pane.

Root cause

buildSchemaGraph pruned isolated nodes only inside else if (edges.length), so a DB with no relationships skipped pruning and dumped every table as a disconnected node. The only empty-state placeholder was keyed on nodeCount === 0 — unreachable for any real DB (≥1 table ⇒ ≥1 node) — so the degenerate case fell through to the unreadable strip.

Fixes (from a high-effort /code-review of the schema-graph feature, #41)

The bug

  • schema-graph.js — whole-DB lineage now always keeps only connected (degree>0) nodes. A lineage view shows lineage; a relationless DB yields an empty graph.
  • explain-graph.js — informative empty-state via schemaEmptyMessage: "No object relationships in <db> — its N tables aren't linked by a view, materialized view, dictionary, or Distributed/Buffer/Merge engine." (table focus: "<db.table> has no lineage relationships."). app.js carries tableCount.
  • results.js — hide Expand when there's nothing to draw.
  • attachPanZoomminW = min(width/8, 600) so a wide graph can still be zoomed to a legible scale.

Also surfaced by the review

  • ch-client.jsloadSchemaLineage used a local SQL quoter that dropped backslash-escaping; now uses core/format.js sqlString.
  • schema-graph.js — index system.dictionaries by db.name (was O(D) find per dict); removed the dead void uuid.
  • explain-graph.js — single placeholder() helper (was triplicated markup).
  • README + tests — the doc promised unconditional pruning and a test ("keeps all tables when a DB has no lineage") certified the buggy behavior; both corrected.

Tests

New: no-relationship DB (50 URL tables → empty graph), the db/table empty-state messages, hidden Expand. 883 tests pass; per-file coverage gate holds.

Verified live

github.demo target_all now shows the message (not a strip); no Expand button. Deployed to otel / antalya / github.demo (sha 867ea3a).

Deferred (noted, not in this PR)

  • A node cap / "graph is large — open fullscreen" guard for a genuinely large connected lineage (this PR resolves the degenerate edgeless case).
  • Merge-engine O(K×N) scan and conditional fetch of create_table_query/as_select (payload) — minor at current scale.
  • EXPLAIN-AST fan-out cap (already tracked in Schema lineage: cap the EXPLAIN AST fan-out on large schemas #42).

🤖 Generated with Claude Code

…e strip)

Reported: dragging db `target_all` on github.demo (201 tables, all URL engine,
zero relationships) produced "empty output". Diagnosed live: buildSchemaGraph
returned 201 nodes / 0 edges, dagre laid them in a ~127000px-wide × 58px single
row, and fit-to-view shrank every node to sub-pixel — a blank-looking pane.

Root cause + fixes (from a high-effort review of the schema-graph feature, #41):
- schema-graph.js: whole-DB lineage now ALWAYS keeps only connected (degree>0)
  nodes — a lineage view shows lineage. The old `else if (edges.length)` kept all
  tables when there were no edges, which is exactly the degenerate dump. A DB with
  no relationships now yields an empty graph.
- explain-graph.js: the empty-state was keyed on nodeCount===0 (unreachable for a
  real DB). renderSchemaGraph/openSchemaFullscreen now show an informative
  message via schemaEmptyMessage ("No object relationships in <db> — its N tables
  aren't linked by …" / "<db.table> has no lineage relationships"). app.js carries
  tableCount for the message.
- results.js: hide Expand when there's nothing to draw.
- attachPanZoom: minW floor `min(width/8, 600)` so a wide graph can still be
  zoomed to a legible scale (was width/8 ≈ unusable on huge graphs).

Also from the review:
- ch-client.js: loadSchemaLineage used a local SQL quoter that dropped
  backslash-escaping — use core/format.js sqlString.
- schema-graph.js: index system.dictionaries by db.name (was O(D) find per dict);
  drop the dead `void uuid` in the inner-label pass.
- explain-graph.js: single `placeholder()` helper (was triplicated markup).
- README + tests: the doc and a test ("keeps all tables when a DB has no lineage")
  previously certified the buggy behavior — both updated; new tests cover the
  no-relationship DB (50 URL tables → empty), the empty-state messages, and the
  hidden Expand.

Verified live on github.demo: target_all now shows the message, not a strip.
883 tests pass; per-file coverage gate holds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QGBS74oUsXarGkCRQKEFLu
@BorisTyshkevich BorisTyshkevich merged commit 37ac404 into main Jun 26, 2026
4 checks passed
@BorisTyshkevich BorisTyshkevich deleted the fix/schema-graph-empty-state branch June 26, 2026 05:40
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.

1 participant