Package: shandy-sqlfmt
sqlfmtsqlfmt formats your dbt SQL files so you don't have to. It is similar in nature to black, gofmt,
and rustfmt (but for SQL).sqlfmt promotes collaboration.An auto-formatter makes it easier to collaborate with your team and solicit contributions from new people. You will never have to mention (or argue about) code style in code reviews again.sqlfmt is fast.Forget about formatting your code, and spend your time on business logic instead. sqlfmt processes hundreds of files per second and only operates on files that have changed since the last run.sqlfmt works with Jinja.It formats the code that users look at, and therefore doesn't need to know anything about what happens after the templates are rendered.sqlfmt integrates with your workflow.As a CLI written in Python, it's easy to install locally on any OS and run in CI. Plays well with dbt, pre-commit, SQLFluff, VSCode, and GitHub Actions. sqlfmt powers the dbt Cloud IDE's Format button.sqlfmt is not configurable, except for line length. It enforces a single style. sqlfmt maintains comments and some extra newlines, but largely ignores all indentation and line breaks in the input file.sqlfmt is not a linter. It does not parse your code into an AST; it just lexes it and tracks a small subset of tokens that impact formatting. This lets us "do one thing and do it well:" sqlfmt is very fast, and easier to maintain and extend than linters that need a full SQL grammar.For now, sqlfmt only works onselect,delete,grant,revoke, andcreate functionstatements (which is all you need if you use sqlfmt with a dbt project). It is being extended to additional DDL and DML. Visitthis tracking issuefor more information.DocumentationPlease visitdocs.sqlfmt.comfor more information on Getting Started, Integrations, the sqlfmt Style, and an API Reference. Or keep reading for an excerpt from the full docs.InstallationTry it firstWant to test out sqlfmt on a query before you install it? Go tosqlfmt.comto use the interactive, web-based version.Install Using pipx (recommended)sqlfmt is a pip-installable Python package listed on PyPI under the nameshandy-sqlfmt. You should install it into a virtual environment, whichpipxdoes automatically:pipx install shandy-sqlfmtTo install with the jinjafmt extra (which will also install the Python code formatter,black):pipx install shandy-sqlfmt[jinjafmt]For more installation options,read the docs.Getting StartedOther prerequisitessqlfmt will not always produce the formatted output you might want.It might even break your SQL syntax. It ishighly recommendedto only run sqlfmt on files in a version control system (like git), so that it is easy for you to revert any changes made by sqlfmt. On your first run, be sure to make a commit before running sqlfmt.There are certain situations where sqlfmt can be considered to be in Beta, or even more mature than that. Those are:Using sqlfmt to format select statements for one of the major dialects (PostgresSQL, MySQL, Snowflake, BQ, Redshift).Using sqlfmt to format a dbt project (which may also include jinja and some minimal DDL/DML, like grants, create function, etc.) for one of the major dialects.However, there are other use cases where sqlfmt is very much alpha:Formatting some dialects that deviate from ANSI or Postgres, like T-SQL (SQLServer).Formatting other DDL (create table, insert, etc.) (sqlfmt attempts to be no-op on these statements as much as possible).In these domains sqlfmt is nowhere near "feature complete" and caution is highly advised.Using sqlfmtTo list commands and options:sqlfmt--helpIf you want to format all.sqland.sql.jinjafiles in your current working directory (and all nested directories), simply type:$sqlfmt.If you don't want to format the files you have on disk, you can run sqlfmt with the--checkoption. sqlfmt will exit with code 1 if the files on disk are not properly formatted:$sqlfmt--check.If you want to print a diff of changes that sqlfmt would make to format a file (but not update the file on disk), you can use the--diffoption.--diffalso exits with 1 on changes:$sqlfmt--diff.For more commands, seethe docs.Configuring sqlfmt using pyproject.tomlAny command-line option for sqlfmt can also be set in apyproject.tomlfile, under a[tool.sqlfmt]section header. Options passed at the command line will override the settings in the config file.See the docsfor more information.The jinjafmt extrasqlfmt loves properly-formatted jinja, too.See the docsfor more information about using thejinjafmtextra or disabling jinja formatting.Using sqlfmt with different SQL dialectssqlfmt's rules are simple, which means it does not have to parse every single token in your query. This allows nearly all SQL dialects to be formatted using sqlfmt's default "polyglot" dialect, which requires no configuration.The exception to this isClickHouse, which is case-sensitive where other dialects are not. To prevent the lowercasing of function names, database identifiers, and aliases, use the--dialect clickhouseoption when running sqlfmt. For example,$sqlfmt.--dialectclickhouseThis can also be configured using thepyproject.tomlfile:[tool.sqlfmt]dialect="clickhouse"Note that with this option, sqlfmt will not lowercasemostnon-reserved keywords, even common ones likesumorcount. See (and please join)this discussionfor more on this topic.Integrationssqlfmt plays nicely with other analytics engineering tools. For more information,see the docs.dbtsqlfmt was built for dbt, so onlyminimal configurationis required. We recommend excluding yourtargetanddbt_packagesdirectories from formatting. You can do this with the command-line--excludeoption, or by settingexcludein yourpyproject.tomlfile:[tool.sqlfmt]exclude=["target/**/*","dbt_packages/**/*"]Other IntegrationsConfig for other integrations is detailed in the docs linked below:pre-commitSQLFluffVSCodeThe sqlfmt styleThe only thing you can configure with sqlfmt is the desired line length of the formatted file. You can do this with the--line-lengthor-loptions. The default is 88.sqlfmt borrows elements from well-accepted styles from other programming languages. It places opening brackets on the same line as preceding function names (likeblackfor python and1TBSfor C). It indents closing brackets to the same depth as the opening bracket (this is extended to statements that must be closed, likecaseandend).The sqlfmt style is as simple as possible, with little-to-no special-casing of formatting concerns. While at first blush, this may not create a format that is as "nice" or "expressive" as hand-crafted indentation, over time, as you grow accustomed to the style, formatting becomes transparent and the consistency will allow you to jump between files, projects, and even companies much faster.Read MoreWhy lowercase?Because SQL is code! But there areother good reasons too.Why trailing commas?Using trailing commas follows the convention of every other written language and programming language.But wait, there's more.ContributingProviding FeedbackWe'd love to hear from you!Open an Issueto request new features, report bad formatting, or say hello.Setting up Your Dev Environment and Running TestsInstallPoetryv1.2 or higher if you don't have it already. You may also need or want pyenv, make, and gcc. A complete setup from a fresh install of Ubuntu can be foundhere.Clone this repo into a directory (let's call itsqlfmt), thencd sqlfmt.Usepoetry install --all-extras --syncto install the project (editable) and its dependencies (including thejinjafmtandsqlfmt_primerextras) into a new virtual env.Usepoetry shellto spawn a subshell.Typemaketo run all tests and linters, or runpytest,black,flake8,isort, andmypyindividually.Updating primer repos to reflect formatting changesMake sure all changes are committed to sqlfmt.Check outmainin the repo and make sure youpullchanges locally.Check out theunformattedtag in the repo withgit checkout -b chore/apply-abc123 unformattedwhereabc123is the hash of the most recent sqlfmt commit (from 1).Run sqlfmt against the working tree, thengit add .andgit commit -m "chore: apply sqlfmt abc123".We will have conflicts with main that we want to ignore, so merge main into this branch, ignoring anything on main:git merge -s ours main.Push and open a PR; squash and merge. Grab the commit SHA.Paste the commit SHA as a ref intoprimer.py.Runsqlfmt_primer -kto clear the cache, then update the stats inprimer.pyto match the results.