Repository navigation
feat: format and lint with SQLQuack instead of Polyglot - #38
Merged
Merged
Conversation
Snowflake and DuckDB requests now go to sqlquack-format, pinned by git revision, which lays out SQL on SQLQuack's own tokenizer and parser and checks token identity and idempotency itself. Other dialects still use the Polyglot layout oracle. Work in progress: 6 formatter tests still expect Polyglot's layout.
… the Polyglot AST API SQLClean's corpus check now expects SQLQuack's named departures, listed with their reasons in sqlquack_departures.json: 15 DuckDB and 13 Snowflake queries that SQLQuack lays out or refuses differently. Called names fold to upper case as SQLBuild's query fingerprint folds them, except in unaliased Snowflake select items, whose text names their column. The re-print count test runs on PostgreSQL, which still uses the Polyglot layout. RuleContext.polyglot_ast() and the ast extra are removed. Work in progress: CTE macro placeholders are not laid out yet.
…Polyglot The lint entry points (lint, lint_json, lint_batch_json, parse_sql, catalogue, default_rules, cross_join_subject, fill_finding_path and validate_dialect) now call sqlquack-lint, the port of this lint engine and its quality Rules onto SQLQuack's tokens and trees. The lint request, response and parse types are SQLQuack's, named in sql_lint::types; the format types stay in sql_lint::models. The placeholder constants take sqlquack-lint's values. sql_quality is removed: its Rules run inside sqlquack-lint. sql_facts reads SQLQuack's tokens and trees through parse_sql, with the same collection code. Lint for a dialect SQLQuack does not parse yet, such as T-SQL or MySQL, answers that lint is unavailable rather than reporting findings, so the T-SQL bare UNION test is ignored until that parser lands. The formatter is unchanged and still reads Polyglot; the one lint helper it used, token_depths, stays in sql_lint/_helpers/engine.rs. SQLQuack is pinned at wip/lint-port 4f9ac36d8.
…ith SQLQuack's tokens
SQLQuack's Snowflake parse keeps DATEPART, LAST_DAY and DATE_DIFF as the calls written, so their bare date part, such as day in DATEPART(day, ts), parsed as a column, where Polyglot lowered the call and read it as a unit. Statement facts now leave that argument out of the columns: any bare name for DATEPART and LAST_DAY, and only a known unit name for DATE_DIFF, as Polyglot did. Against SQLClean on Polyglot, the Snowflake facts of 12,313 inputs both parse now differ on 6, all JSON_OBJECTAGG(t.x), whose argument SQLQuack reports as a column and Polyglot dropped; DuckDB's 5,352 are identical.
…ot parse file_facts now answers a dialect SQLQuack does not parse yet, such as MySQL, with no statements and an unavailable reason, the way lint's response does, instead of an error; an unknown dialect is still an error. statement_ends answers None for such a dialect. Both ask lint whether the dialect is unavailable, so facts and lint always agree. The CLI keeps failing those files for now: the custom Rule host turns an unavailable reason into its error, and format_source turns None into one, until the per-file unavailable report replaces them.
… Postgres lint slice SQLQuack is now pinned at the lint slice that parses PostgreSQL and Generic natively (wip/lint-postgres bd308904a), so their lint and facts are available. The native PostgreSQL parser folds unquoted names to lower case, so the facts read table, column, CTE and alias names from the source as written. A column's span now starts at its qualifier when the parser located the name alone, as for a subscripted column. The CREATE and ALTER statements the native tree keeps as a generic object take the kind Polyglot's tree gave them, such as create_index or alter_table. The Rule test harness fails a case whose dialect has no facts, rather than evaluating the Rule over an empty file.
Dialects SQLQuack fingerprints use its shared function; the others keep the Polyglot token stream SQLBuild also uses for them. A comma-less run of CTE macro placeholders is now separated by blank lines like any other CTE.
…QLQuack's integration rev
…atter, and drop the Polyglot oracle Dialects without a native SQLQuack formatter now return their SQL unchanged with an unavailable reason instead of a Polyglot layout, so the oracle formatter and its token layout, printed layout and syntax protection are removed. Fingerprints use SQLQuack's generic tokens for dialects without their own tokenizer, as SQLBuild does; the SQL Server golden changes to the generic digest. The recording demo's custom Rule reads statement facts instead of the removed AST.
…f failing check lists each such file once as a warning, and as unavailable in JSON and SARIF, without counting it as a problem or running custom Rules on it. format and fix leave the file unchanged and do not fail.
… and move the format cases beside the layout rules
Maps the native utility_statement and drop_object kinds back to the statement kinds SQLClean reported before (describe, set_statement, transaction, drop_table and so on). Pins SQLQuack to the lint-postgres landing head provisionally; the shared rev is still to be agreed.
Editors such as SSMS save SQL with a UTF-8 byte order mark. check, format and fix now read the SQL after it, so every dialect lints and formats the file, and format and fix write the mark back unchanged. Not yet built or tested.
The statement-kind mapping builds on the shared SQLQuack rev already pinned here, so the provisional pin bump is dropped.
Not releasable: 19c51fa2 is not on SQLQuack main yet. Two test updates follow SQLQuack's Snowflake grammar checks: the format corpus expects UNNEST refused (Snowflake has no UNNEST), and the no-harness empty-fixture case calls the relation through TABLE( ) as Snowflake requires.
SQLQuack's FormatOptions now takes a FormatDialect; SQLClean keeps its syntax dialect for the CTE macro pass and maps it for the layout.
T-SQL requests go to SQLQuack's SQL Server formatter; the CTE macro pass, which needs the shared tokenizer, is skipped, so a placeholder SQLQuack cannot parse is refused. The corpus test gates T-SQL at 52 formatted and 23 refused, with SQLQuack's named departures.
The native tree keeps a comma relation that follows an explicit join in the FROM list, and a join nested by its ON clauses inside the outer join's relation, so facts lost both. A comma relation after the first explicit join is now an IMPLICIT join, and the joins of an unparenthesized nested join are reported, with the outer join named by its first table. A parenthesized join group still reports only the join to it, as before.
Every SQLQuack crate resolves to the one main commit edfa30b26a0bab86661f96490b86a4f24b92db0a.
Deploying sqlclean with
|
| Latest commit: |
3020a07
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://39d00f6e.sqlclean.pages.dev |
| Branch Preview URL: | https://feat-sqlquack-native-format.sqlclean.pages.dev |
This was referenced Nov 8, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
SQLClean formatted and linted through Polyglot. SQLQuack now has native parsers and a lossless formatter, so SQLClean can drop Polyglot entirely.
Changes
sqlquack-formatfor Snowflake, DuckDB and T-SQL. Other dialects are reported unavailable and left as written.edfa30b2. Polyglot is no longer a dependency.Verification
make check-ci: ruff, ty, fensu (0 faults), docs skill, fmt and clippy pass.cargo test --allanduv run pytest tests(67) pass, including the format corpus for Snowflake, DuckDB and T-SQL and the fingerprint goldens.cargo tree -i polyglot_sqlmatches no package, and Cargo.lock has no polyglot entries.