Skip to content

perf: evaluate built-in rules over Polyglot query facts and drop sqlparser - #1143

Merged
kvlonge merged 9 commits into
mainfrom
perf/rules-on-polyglot
Oct 18, 2026
Merged

kvlonge merged 9 commits into
mainfrom
perf/rules-on-polyglot

Conversation

@kvlonge

@kvlonge kvlonge commented Oct 18, 2026 •

Copy link
Copy Markdown
Contributor

Why

Built-in model rules re-parsed every model with a second SQL parser (sqlparser), about 80% of built-in rules CPU on the dense 10k project, while the compiler already uses Polyglot. Keeping two parsers also meant rules and the compiler could disagree about what parses.

Changes

  • Built-in model rules and SQL-test rules evaluate compact facts from one Polyglot parse per distinct stubbed query shape (references replaced by numbered stubs, per-dialect comment and quoting rules); positions map back to each model's own SQL. Shapes are shared only for byte-identical stubbed SQL, and findings order is unchanged.
  • sqlparser is removed from the workspace.
  • Accepted finding changes: models the old parser rejected but the compiler accepts are now evaluated; unevaluated reasons carry Polyglot's error; SQBRDECLARATION101/102 quote the authored source text; a doubled-quote reference argument no longer gives a spurious SQBRMODEL101; DuckDB FROM-first queries are treated as SELECT *.
  • Known difference outside DuckDB: SELECT * FROM (subquery) UNION ALL ... follows a Polyglot parse bug (CHI-627).

Verification

  • Ordered rules run SQBR findings identical between base and candidate on every corpus compared (600-model project: 7,794; examples, fixtures and synthetic DuckDB/Snowflake edge-case projects).
  • Compiled SQL and compile JSON identical on dense 1k and 10k; 1k cold/warm/edit cache counters identical.
  • Dense 10k cold: instructions 386 G to 341 G (-11.9%), about -8.8 CPU-s.
  • New tests for comments, literals, cast and CONVERT types, TOP, FROM-first positions and previously unevaluated models; rules cargo, focused Python and rules E2E tests pass; make test passed.
  • Independent review and one follow-up; findings fixed. Set-operation shapes added to the comparison corpus; rules and contract E2E files pass locally (312).
  • make check-ci and compiler differential pass.

Rules need analysis's Snowflake variant normalization together with the
character map back to the authored SQL, so positions survive the rewrite.
Built-in model and SQL-test rules re-parsed every model with sqlparser.
They now read compact facts from one Polyglot parse per stubbed query
shape: dependency calls are stubbed by occurrence, shapes are shared by
the rules workers when their stubbed SQL is byte-identical, and positions
map back to each model's own SQL.

Models sqlparser rejected but Polyglot parses are now evaluated;
SQBRDECLARATION101/102 quote the comparison's source text and follow its
source position. Unparseable SQL keeps the unevaluated result with
Polyglot's error.
The rules quote policy is a static dialect table, so no crate needs
sqlparser any more.
The stub scanner only knew -- and /* */ comments, so a Snowflake // or a
Snowflake/BigQuery # comment could hold a phantom __ref call, or an
apostrophe in it could open a fake string that swallowed real calls.
Scan with the comment and quoting syntax the rules parser used per
dialect, and blank comments before normalization and parsing.
…ar facts

- SQBRDECLARATION101 compares each string literal's own source text with
  the authored SQL and covers double-quoted, triple-quoted, escape and
  Unicode strings again.
- SQBRTEST203 no longer treats a parameterized cast type such as
  DECIMAL(18, 2) as a function call.
- A T-SQL TOP (n), TOP n PERCENT or WITH TIES clause is not projection.
- Stars in dependency import CTEs are exempt from SQBRMODEL102 by CTE
  classification, not by having a recovered source position.
A DuckDB FROM-first query has an implicit star but no SELECT token, so
its star finding fell back to 1:1. Anchor that star on the FROM keyword.
A SELECT whose only located part is an unaliased subquery is now matched
to its own SELECT keyword through the subquery's opening parenthesis, so
its star keeps its source position too.
SQBRTEST203 counted the leading parameterized type of a T-SQL
CONVERT(VARCHAR(10), x) or TRY_CONVERT(DECIMAL(18, 2), x) as a function
call, so an empty SQL Server mock or bare existence assertion was not
flagged. Skip that type argument, as sqlparser's conversion parse did;
function calls in the value argument still count.
@kvlonge
kvlonge enabled auto-merge (squash) October 18, 2026 11:34
…okens

A set-operation branch whose items carry no Polyglot span, such as
SELECT CAST(1 AS INTEGER), CAST('games' AS VARCHAR) after an aliased
first branch, found no SELECT token region. Its SQBRCONTRACT105 cast
types then fell back to Polyglot's spelling and its findings to 1:1,
producing false contract findings. Such a select now takes the next
unclaimed SELECT region after the previous branch, since branches and
CTEs are read in source order.
@kvlonge
kvlonge merged commit bfaff24 into main Oct 18, 2026
43 checks passed
@kvlonge
kvlonge deleted the perf/rules-on-polyglot branch October 18, 2026 12:41
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