🎉

SQLFluffでDocker越しにSQLのフォーマットチェック

2023/10/23に公開

SQLのLinterなんてあったのか

データベースのデプロイする際、
migrationに任せたり、
SQLを書いたりと各社環境はまちまちで、
甲乙つけがたい状況。

lintに関してmigrationであればその言語側に任せればいいが、
SQLについては考えたことがなかった。

ふと他の人のSQLを調整する作業をしたときに、
SQL文のlinterってないのか気になったので調べてみたらあった。

SQLFluff

SQLFluff is a dialect-flexible and configurable SQL linter. Designed with ELT applications in mind, SQLFluff also works with Jinja templating and dbt. SQLFluff will auto-fix most linting errors, allowing you to focus your time on what matters.
SQLFluff は方言に柔軟で設定可能な SQL リンターです。ELTアプリケーションを念頭に設計されたSQLFluffは、Jinjaテンプレートやdbtでも動作します。SQLFluff はほとんどのリンティングエラーを自動修正してくれます。

Pythonのパッケージでコマンドライン実行型のSQLLinter
結構いろんなデータベースに対応しているので、
使いこなせればこれ一本でSQLは解決かも

Podmanを使うようになってからなんでもかんでもコンテナでやるようになった。
今回もSQLFluff公式のコンテナを使ってSQLを整形してみよう

ヾ(・ω<)ノ" 三三三● ⅱⅲ コロコロ♪

------------------- ↓ 本題はここから ↓-------------------

SQLFluffをpull

podman pull sqlfluff/sqlfluff

SQLのフォーマットチェック

まずはマニュアル通りテストファイルを作ってチェックする
データベースはMySQLとすると

echo "  SELECT a  +  b from tbl;  " > test.sql
podman run -it --rm -v $PWD:/sql sqlfluff/sqlfluff lint --dialect mysql test.sql
== [test.sql] FAIL
L:   1 | P:   1 | LT01 | Expected only single space before 'SELECT' keyword.
                       | Found '  '. [layout.spacing]
L:   1 | P:   1 | LT02 | First line should not be indented.
                       | [layout.indent]
L:   1 | P:   1 | LT13 | Files must not begin with newlines or whitespace.
                       | [layout.start_of_file]
L:   1 | P:  11 | LT01 | Expected only single space before binary operator '+'.
                       | Found '  '. [layout.spacing]
L:   1 | P:  14 | LT01 | Expected only single space before naked identifier.
                       | Found '  '. [layout.spacing]
L:   1 | P:  27 | LT01 | Unnecessary trailing whitespace.
                       | [layout.spacing]

(「・ω・)「 チェックできてる

LTxx っていうのはルールの番号でカスタマイズの際に使う

https://docs.sqlfluff.com/en/stable/rules.html

基本的には全部適用して該当しないものを外していくホワイトリスト方式にしたいので
オプションのexclude-rulesを使う
また、rootlessユーザーだとfixコマンドがうまく動かないので、
rootfull運用をする方が良い

# linter
sudo -E podman run -it --rm -u 1000:1000 -v $PWD:/sql sqlfluff/sqlfluff lint --dialect mysql --exclude-rules LT05 test.sql
# fixer
sudo -E podman run -it --rm -u 1000:1000 -v $PWD:/sql sqlfluff/sqlfluff fix --dialect mysql --exclude-rules LT05 test.sql

設定ファイル使用

コマンドラインでルール設定も可能だが、
全部を網羅することはできないようだ
その場合設定ファイル.sqlfluffを使う

SQLでは特に気になる大文字小文字の自動調整などはここで行う

.sqlfluff
[sqlfluff]
dialect = mysql
exclude_rules = LT05

[sqlfluff:indentation]
tab_space_size = 4

[sqlfluff:rules:capitalisation.keywords]
capitalisation_policy = upper
[sqlfluff:rules:capitalisation.identifiers]
capitalisation_policy = upper
[sqlfluff:rules:capitalisation.functions]
extended_capitalisation_policy = upper
[sqlfluff:rules:capitalisation.literals]
capitalisation_policy = upper
[sqlfluff:rules:capitalisation.types]
extended_capitalisation_policy = upper

実行結果は

echo "  SELECT a  +  b from tbl;  " > test.sql
sudo -E podman run -it --rm -u 1000:1000 -v $PWD:/sql sqlfluff/sqlfluff fix test.sql
==== finding fixable violations ====
== [test.sql] FAIL
L:   1 | P:  18 | CP01 | Keywords must be upper case.
                       | [capitalisation.keywords]
==== fixing violations ====

(^o^) 大文字が必須に変わっている

------------------- ↓ 後書きはここから ↓-------------------

PHPCSやeslintのように昔から使っていたわけではないので、
こんな感じかなと言うのがなんとなく掴めた

Discussion