Skip to content

Add studio relation click-through#128

Open
mmkal wants to merge 3 commits into
mainfrom
ui-relations
Open

Add studio relation click-through#128
mmkal wants to merge 3 commits into
mainfrom
ui-relations

Conversation

@mmkal
Copy link
Copy Markdown
Collaborator

@mmkal mmkal commented May 16, 2026

Summary

Adds clickable relation previews to the studio table grid. Cells backed by a single-column foreign key now show a relation action that opens the referenced parent row, and referenced key cells show reverse actions for matching child rows.

The schema endpoint now returns relation metadata for both directions:

relation.foreignKeys // child table -> parent table
relation.referencedBy // parent table -> child tables

SQLite and Postgres both implement the new dialect hook. The UI intentionally limits the first visible click-through pass to single-column relationships, while the metadata shape can carry composite keys for a later UI pass.

Media

Forward relation preview from order_details.product_id to the referenced products row:

https://github.com/user-attachments/assets/a2105fef-0ffb-44b8-9132-e267fb2465bd

Reverse relation preview from products.product_id to matching order_details rows:

https://github.com/user-attachments/assets/745a4d6e-dd48-441b-a3cd-e8a4ac8d0791

Relation click-through walkthrough video:

pr-128-relation-click-through.mp4

Before / After

Before, an order_details.product_id cell was just a scalar value. The user had to manually know and type the follow-up query.

After, hovering/clicking the relation action previews the generated filtered query and matching rows:

select * from "products" where "product_id" = ? limit 100

Reverse relations work the same way from the parent row, for example products.product_id = 1 can preview matching order_details rows:

select * from "order_details" where "product_id" = ? limit 100

Verification

  • pnpm --filter sqlfu exec vitest run test/ui-server.test.ts --testNamePattern "schema.get exposes forward"
  • SQLFU_UI_TEST_PORT=3228 pnpm --filter @sqlfu/ui exec playwright test test/demo.spec.ts --grep "child rows|referenced parent"
  • pnpm typecheck
  • pnpm --filter @sqlfu/ui build
Package size — packed 240.2 kB (+844 B, +0.3%)

Package size

main this PR Δ
packed 239.4 kB 240.2 kB +0.3%
unpacked 991.8 kB 995.5 kB +0.4%
files 185 185 0

dist/vendor/*.js bundles

main this PR Δ
vendor/sha256.js 4.3 kB 4.3 kB 0
vendor/sql-formatter/*.js 58.3 kB 58.3 kB 0
vendor/sqlfu-sqlite-parser/*.js 17.2 kB 17.2 kB 0
vendor/standard-schema/*.js 2.8 kB 2.8 kB 0
vendor/typesql/*.js 134.6 kB 134.6 kB 0

Measured with npm pack --dry-run --json on sqlfu (0.0.3-7 on main vs 0.0.3-7 on this PR).

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 16, 2026

Open in StackBlitz

npm i https://pkg.pr.new/sqlfu@128

commit: 3caefca

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3caefca. Configure here.

existing.columns.push(column);
if (referencedColumn) {
existing.referencedColumns.push(referencedColumn);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conditional push misaligns parallel arrays in foreign key grouping

Medium Severity

groupSqliteForeignKeys conditionally skips pushing to referencedColumns when referencedColumn is falsy (SQLite's to is NULL for implicit-PK references), but always pushes to columns and seq. The ordering step then indexes into referencedColumns using the same positional index as seq/columns, causing misaligned column associations for composite FKs and empty referencedColumns for single-column implicit-PK references — hiding those relation actions from the UI.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3caefca. Configure here.

mmkal added a commit that referenced this pull request May 21, 2026
## Summary

Runs the 2026-05-17 evergreen task cleanup pass.

- Files the completed nightly architecture task from merged PR #125 into
`tasks/complete/2026-05-16-architecture-2026-05-15.md`
- Updates `tasks/cleanup-tasks.md` with the pass status, PR/task survey,
removed local worktrees, and skipped candidates
- Removes clean local worktree checkouts for merged or stale compare
branches while preserving local/remote branches

## Task filing

Moved:

- `tasks/architecture-2026-05-15.md` ->
`tasks/complete/2026-05-16-architecture-2026-05-15.md`

Left open intentionally:

- Evergreen logs: `tasks/cleanup-tasks.md`, `tasks/improve-docs.md`
- Broad or deferred follow-up tasks touched by recent PRs:
`tasks/landing-demo-maintainability.md`, `tasks/pg.md`
- Open PR task files, including `tasks/ui-relations.md` while PR #128
remains open

## Local worktree cleanup

Removed clean local checkouts only:

- `bedtime-2026-05-14-generate-preflight`
- `bedtime-2026-05-14-query-identity-manifest`
- `bedtime-2026-05-15-architecture`
- `bedtime-2026-05-15-cleanup-tasks`
- `bedtime-2026-05-15-db-base-directory`
- `bedtime-2026-05-15-default-db-gitignore`
- `bedtime-2026-05-15-improve-docs`
- `bedtime-2026-05-15-landing-trace`
- `bedtime-2026-05-15-pg-docs-followup`
- `compat-existing-tools`
- `query-identity-refresh-pr-114`

Left dirty, ahead, active, ambiguous, or out-of-scope worktrees in place
and recorded the reason in the task log.

## Verification

- `gh pr list --state open --limit 50 --json
number,title,headRefName,baseRefName,isDraft,updatedAt,url`
- `gh pr list --state merged --limit 30 --json
number,title,headRefName,baseRefName,mergedAt,url`
- `gh pr list --state closed --limit 30 --json
number,title,headRefName,baseRefName,closedAt,url`
- `gh pr view` for PRs #120 through #129
- `find tasks -maxdepth 2 -type f | sort`
- `git worktree list --porcelain`
- `git status --short`
- `git diff --check`

<!-- package-size:start -->
<details>
<summary>Package size — packed 239.4 kB (no change)</summary>

## Package size

|  | main | this PR | Δ |
| - | - | - | - |
| packed | 239.4 kB | 239.4 kB | 0 |
| unpacked | 991.8 kB | 991.8 kB | 0 |
| files | 185 | 185 | 0 |

### `dist/vendor/*.js` bundles

|  | main | this PR | Δ |
| - | - | - | - |
| `vendor/sha256.js` | 4.3 kB | 4.3 kB | 0 |
| `vendor/sql-formatter/*.js` | 58.3 kB | 58.3 kB | 0 |
| `vendor/sqlfu-sqlite-parser/*.js` | 17.2 kB | 17.2 kB | 0 |
| `vendor/standard-schema/*.js` | 2.8 kB | 2.8 kB | 0 |
| `vendor/typesql/*.js` | 134.6 kB | 134.6 kB | 0 |

_Measured with `npm pack --dry-run --json` on `sqlfu` (0.0.3-7 on main
vs 0.0.3-7 on this PR)._

</details>
<!-- package-size:end -->

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Low risk: documentation-only changes that move a task file to `done`
status and append cleanup notes; no runtime or build logic is modified.
> 
> **Overview**
> Records the **2026-05-17 cleanup pass** in `tasks/cleanup-tasks.md`,
including what was inspected, which worktrees were removed, and which
candidates were intentionally left in place.
> 
> Files the merged nightly architecture task into
`tasks/complete/2026-05-16-architecture-2026-05-15.md` and updates its
frontmatter/status summary to reflect **done/merged in PR #125**.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
c3d0672. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
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