Skip to content

fix(sql): validate table qualifiers in single-table scope (SQLR-14)#167

Merged
joaoh82 merged 1 commit into
mainfrom
sqlr-14-single-table-qualifier-validation
Jun 11, 2026
Merged

fix(sql): validate table qualifiers in single-table scope (SQLR-14)#167
joaoh82 merged 1 commit into
mainfrom
sqlr-14-single-table-qualifier-validation

Conversation

@joaoh82

@joaoh82 joaoh82 commented Jun 11, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes SQLR-14: SingleTableScope ignored table qualifiers entirely, so SELECT x.id FROM t, ... WHERE bogus.id = 1, and the UPDATE/DELETE equivalents silently resolved anything.col as plain col. JoinedScope already errored on unknown qualifiers; the single-table path now matches it (and SQLite).

Changes

  • SingleTableScope carries a scope_name (FROM alias when declared, else table name) and lookup rejects mismatched qualifiers with JoinedScope's exact wording: unknown table qualifier 'x' in column reference 'x.id'. Matching is ASCII case-insensitive.
  • A shared check_single_scope_qualifier helper also guards the schema-level checks that run before any row is visited: projection list, GROUP BY keys, aggregate args — and the index-probe WHERE shape, where try_extract_equality previously stripped the qualifier via parts.last() (so WHERE bogus.name = 'x' on an indexed column bypassed evaluation entirely).
  • eval_predicate / eval_expr / sort_rowids / select_topk / select_rowids take the scope name; extract_table_name now returns the FROM alias, so UPDATE / DELETE validate too (WHERE and UPDATE SET right-hand sides, including UPDATE t AS a … / DELETE FROM t AS a …).
  • Per SQLite semantics, a declared alias shadows the table name as a qualifier: SELECT t.id FROM t AS a errors — pinned by tests for SELECT, UPDATE, and DELETE.
  • Docs: corrected the "we ignore qualifiers" line in docs/sql-engine.md; added a qualified-references bullet to docs/supported-sql.md.

Acceptance criteria

  • SELECT t.id FROM t and SELECT a.id FROM t AS a keep working (case-insensitive)
  • SELECT x.id FROM t errors with JoinedScope-consistent wording
  • Same enforcement in WHERE / ORDER BY for SELECT, UPDATE, DELETE (UPDATE t SET ... WHERE x.id = 1 errors)
  • Declared alias is the only valid qualifier (SELECT t.id FROM t AS a errors), matching SQLite — pinned with tests
  • Regression matrix covered (14 new tests); audited existing tests for bogus-qualifier usage — none found, zero pre-existing tests broke

Testing

  • 655 tests pass (641 pre-existing + 14 new SQLR-14 regression tests)
  • cargo fmt --check, cargo clippy, cargo doc clean — warning sets identical to main (verified by stash-diff)
  • REPL smoke of the full matrix: bogus qualifiers error on every path (projection, WHERE, indexed WHERE, ORDER BY, GROUP BY, aggregate args, UPDATE SET RHS); valid / alias / case-variant forms return correct rows

Known gaps (follow-ups, not in this PR)

  • fts_match(bogus.col, …) / bm25_score extract their column arg syntactically and still strip a qualifier silently (function args need scope-name access in eval_function)
  • HAVING x.dept … ignores qualifiers via GroupRowScope — shared with the joined path, so single-table and JOIN behavior remain consistent there

🤖 Generated with Claude Code

SingleTableScope now carries the user-visible scope name (FROM alias
when declared, else the table name) and rejects any other qualifier
with the same unknown-table-qualifier error JoinedScope produces.
Validation covers the projection list, WHERE (including the index-probe
shape, which previously stripped the qualifier via parts.last()),
ORDER BY, GROUP BY keys, aggregate args, and UPDATE SET right-hand
sides. UPDATE / DELETE now plumb their FROM alias through
extract_table_name, so alias forms validate too — and per SQLite
semantics a declared alias shadows the table name as a qualifier.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
rust-sqlite Ready Ready Preview, Comment Jun 11, 2026 2:03pm

Request Review

@joaoh82 joaoh82 merged commit 29b5d9a into main Jun 11, 2026
20 checks passed
@joaoh82 joaoh82 deleted the sqlr-14-single-table-qualifier-validation branch June 11, 2026 14:11
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