Repository navigation
feat(BREAKING): replace sqlformat with our own SQL formatter - #14
Merged
Merged
Conversation
Formats SQL with a dialect-aware lexer, a tolerant parser and dprint-core's IR instead of wrapping sqlformat-rs. - Dialects: generic (default), postgresql, mysql, sqlserver, sqlite, oracle, bigquery and snowflake, selected with the new `dialect` option. - Procedural code: BEGIN/END blocks, exception handlers, IF/ELSIF, T-SQL IF/WHILE, loops, CASE statements, labels, declaration sections, Oracle packages and type bodies, PL/pgSQL `$$` bodies, MySQL DELIMITER, T-SQL GO batches, SQL*Plus `/` and psql meta-commands. - New `lineWidth` option. Lists, conditions and brackets break only when they don't fit. - Output is checked to differ from the input only in whitespace (and keyword casing when it's changed). Otherwise the file is left as it is and an error is reported. - Range formatting. BREAKING CHANGE: `format_text` returns a `Result` and the formatted output differs from sqlformat's. The update workflow that followed sqlformat releases is removed. Closes #3 Closes #12
- run clippy, rustfmt and the tracing tests in CI - give linesBetweenQueries a minimum of 1 in the schema - mark Dialect and FormatError as non-exhaustive - drop the dprint-core-macros dependency - mention the deprecated uppercase option in the readme
- end a variable's name at `#` where it starts a comment (MySQL, BigQuery) - keep Snowflake stage paths and `file://` URLs as one token - keep BigQuery project and table names holding dashes - treat whitespace beyond ASCII as part of a name rather than as a space - only let PostgreSQL operators end in `+` or `-` - end BigQuery raw strings and backticked names after an escaped quote - don't read a column named like a clause in a list as that clause - keep the case of reserved words that name a table (ex. `FROM view`) - look up the last token that isn't a comment without scanning back
…eep nesting quickly - split an INSERT, UPDATE, DELETE or MERGE after a CREATE or ALTER that isn't a routine - end an UPDATE or MERGE at a SET after its own, and a T-SQL RETURN at the end of its line - don't read a view's or routine's WITH option as a common table expression - tell a routine by the first word naming a kind of object (not `CREATE VIEW v AS SELECT event`) - keep more SQL*Plus commands (SHOW, EXEC, COLUMN, DESC, ...) on their lines - don't parse a CASE that failed to parse again, which took exponential time when nested - always break deeply nested values onto lines, since fitting them took exponential time
- don't move a comma across a template tag, and check where template tags are in the code - write a list with a template tag on its own line or against a comma as it flows - keep the line break between strings that PostgreSQL joins - indent a clause's body beneath a comment on a line of its own after its keyword, which was unstable - only accept a word's case changing to the configured one
…ations stable - only treat ASCII whitespace as space wherever the lexer trims or splits a line - keep an UPDATE or DELETE after an ALTER in it (ex. ClickHouse's ALTER TABLE t UPDATE) - continue a SQL*Plus command onto the next line after a trailing ` -`
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.
Replaces the sqlformat-rs wrapper with our own SQL formatter: a dialect-aware lexer, a tolerant parser and dprint-core's IR, following what was done in dprint-plugin-toml and dprint-plugin-markdown.
Closes #3
Closes #12
What it does
generic(the default),postgresql,mysql,sqlserver,sqlite,oracle,bigqueryandsnowflake, chosen with thedialectoption. The dialect decides how comments, quotes, strings, variables and operators are read.BEGIN/ENDblocks and exception handlersIF/ELSIF, T-SQLIF/WHILE, loops,CASEstatements and labels$$bodies, which are formatted as SQL tooDELIMITER, T-SQLGObatches, SQL*Plus/and its commands, psql meta-commandslineWidth: lists, conditions and brackets break only when they don't fit (Expose a config formaxInlineBlock/ VALUES tuple wrapping #12).EXCEPTandMINUSgo on their own line likeUNIONandINTERSECT(set operations inconsistently formatted #3).{{ }},{% %},{# #}) are kept as they are.casingchanges it, and so must the line breaks that matter (between joined strings, and template tags in place). If anything else changed, the file is left as it is and an error is reported, so a formatter bug can't silently change code.Breaking changes
lineWidth(default 120) now affects SQL output. It was ignored before.linesBetweenQueriesis now a minimum: existing blank lines between statements are kept.format_textreturns aResult.DialectandFormatErrorare#[non_exhaustive].All existing options are still accepted, including the deprecated
uppercase.Testing
cargo fmt --checkand thetracingfeature's tests.Review
Four reviews (lexer, parser, generator, packaging) were done before opening this, and their findings are fixed in the follow-up commits:
#in MySQL variables, unicode whitespaceKnown follow-ups, none of which change code:
ALTER TABLE ... ADD COLUMNis too long, its type's brackets get broken (varchar(\n 255\n)). It should get theALTER TABLE x\n ADD ...layout instead.||chains, a trigger'sEXECUTE FUNCTION, andGRANT ... TO a, b, c.casing: upper:CAST(a AS text)buta::TEXT.#variable_conflictRETURN SELF AS RESULTEND LOOP label, and T-SQLEND CONVERSATIONMERGEinside an exception handler that has a comment before itsWHENBEGIN,linesBetweenQueries: 2puts a blank line afterAS.{% endif %}at the end of a list loses its indentation./* dprint-ignore */at the start of a line moves onto a line of its own.newLineKind, like the rest of the file.