SQLのLinter「SQLFluff」を使ってみた
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を構文解析ライブラリなので、ちょっと使い処が違います。
以上。