SQLFluffというSQLのLinterがあったので、試してみました。

SQLFluff | GitHub
https://github.com/sqlfluff/sqlfluff

SQLFluff | docs.sqlfluff.com
https://docs.sqlfluff.com/en/stable/

現時点(2022年2月)では、open Beta版です。

セットアップ

次のように、SQLFluffをインストールします。

$ pip install sqlfluff

次のコマンドで、インストール出来たかを確認します。

$ sqlfluff --version
sqlfluff, version 0.10.1

簡単な動作確認

以下の「Getting Started」のとおり試してみます。
https://docs.sqlfluff.com/en/stable/

適当なSQLを書いたファイルを用意します。

$ echo "  SELECT a  +  b FROM tbl;  " > test.sql

SQLFluffでチェックを実行します。

$ sqlfluff lint test.sql
== [test.sql] FAIL                                                                                                      
L:   1 | P:   1 | L050 | Files must not begin with newlines or whitespace.
L:   1 | P:   3 | L003 | First line has unexpected indent
L:   1 | P:  11 | L039 | Unnecessary whitespace found.
L:   1 | P:  14 | L039 | Unnecessary whitespace found.
L:   1 | P:  27 | L001 | Unnecessary trailing whitespace.
All Finished 📜 🎉!

以上のように、不自然な空白やインデントが指摘されました。

フォーマット形式の設定例

以下の「Configuration」を参考に、フォーマット形式をカスタマイズ出来ます。 https://docs.sqlfluff.com/en/stable/configuration.html#enabling-and-disabling-rules

確認用に、2つのsqlを用意します。

test2.sql

select
    a,
    b
from tbl
where c = '1'

test3.sql

select tbl1.a, tbl2.b
from tbl1
left join tbl2
  on tbl1.c = tbl2.x
where tbl1.d = '1'

2つのSQLにSQLFluffを実行すると、次のような指摘が表示されます。

$ sqlfluff lint test2.sql
All Finished 📜 🎉!

$ sqlfluff lint test3.sql
== [test3.sql] FAIL                                                                                                     
L:   1 | P:   1 | L036 | Select targets should be on a new line unless there is
                       | only one select target.
L:   4 | P:   3 | L003 | Indentation not hanging or a multiple of 4 spaces
All Finished 📜 🎉!

test3.sqlのような書き方を正としたい場合は、
タブのスペースの数を2に、L036のルールを除外すればよいので、
次のような設定を用意します。

setup.cfg

[sqlfluff:rules]
tab_space_size = 2

[sqlfluff]
exclude_rules = L036

再び2つのSQLにSQLFluffを実行すると、次のように指摘が変わります。

$ sqlfluff lint test2.sql
== [test2.sql] FAIL                                                                                                     
L:   2 | P:   5 | L003 | Line over-indented compared to line #1
L:   3 | P:   5 | L003 | Line over-indented compared to line #1
L:   6 | P:   5 | L003 | Line over-indented compared to line #5
All Finished 📜 🎉!

$ sqlfluff lint test3.sql
All Finished 📜 🎉!

サブコマンドにfixを指定すると、
自動でフォーマット修正をすることも出来ます。

$ sqlfluff fix test2.sql
==== finding fixable violations ====
== [test2.sql] FAIL                                                                                                     
L:   2 | P:   5 | L003 | Line over-indented compared to line #1
L:   3 | P:   5 | L003 | Line over-indented compared to line #1
L:   6 | P:   5 | L003 | Line over-indented compared to line #5
==== fixing violations ====
3 fixable linting violations found
Are you sure you wish to attempt to fix these? [Y/n] ...
Attempting fixes...
Persisting Changes...
== [test2.sql] PASS
Done. Please check your files to confirm.
All Finished 📜 🎉!

フォーマット修正後のファイルは以下の通りです。

test2.sql (自動フォーマット後)

select
  tbl1.a,
  tbl2.b
from tbl1
left join tbl2
  on tbl1.c = tbl2.x
where tbl1.d = '1'

その他のルールのリファレンスは、以下の掲載されています。 https://docs.sqlfluff.com/en/stable/rules.html

その他

pre-commitやGitHub Actionsで利用する場合は、
以下に設定方法が掲載されています。

Production Usage | SQLFluff
https://docs.sqlfluff.com/en/stable/production.html

Jinja2等のテンプレートで変数を埋め込んでSQLをチェックしたい場合は、 以下に設定方法が掲載されています。

Jinja Templating Configuration | SQLFluff
https://docs.sqlfluff.com/en/stable/configuration.html#templateconfig

MySQL, Oracle, PostgreSQL固有のクエリに対応したい場合は、 以下に情報が記載されています。

Dialects | SQLFluff
https://docs.sqlfluff.com/en/stable/dialects.html

例えば、MySQLに対応する場合の設定ファイルは、次のようになります。

setup.cfg

[sqlfluff]
dialect = mysql

類似ツール

類似ツールとして、
sqlparseに含まれる、sqlformatと言うコマンドでも
自動でフォーマット修正することができます。

python-sqlparse https://sqlparse.readthedocs.io/en/latest/

このsqlparseは、Linterではなく、
SQLを構文解析ライブラリなので、ちょっと使い処が違います。

以上。