🔍
SQLFluffを使ってSQLをリント(Lint)する
SQLFluffって何?
Fishtown Analytics社(dbtを作っている会社)が作ったSQLのリントツールです。
Dataformやdbt等を活用することで、多人数でのSQLのメンテナンスを実行していく上でコーディング規約の策定やその準拠が出来ているかというのを継続的に保つ必要性がでてくると思います。
このSQLFluffは他のプログラム言語でよくあるリントがある開発を導入することができます。
インストール
$ python --version
Python 3.6.7
3以上が必要
$ brew install pyenv
pythonのバージョンをコントロールすためにpyenvを入れる
$ pyenv install 3.6.7
$ pyenv global 3.6.7
3.6.7を標準で使えるようにする
$ python --version
Python 3.6.7
$ pip install sqlfluff
pipでインストール
利用検証
$ echo " SELECT a + b FROM tbl; " > test.sql
$ sqlfluff lint test.sql
== [test.sql] FAIL
L: 1 | P: 1 | L036 | Select targets should be on a new line unless there is
| only one select target.
L: 1 | P: 8 | L034 | Use wildcards then simple select targets before
| calculations and aggregates.
L: 1 | P: 9 | L006 | Missing whitespace before +
L: 1 | P: 9 | L006 | Missing whitespace after +
L: 1 | P: 11 | L039 | Unnecessary whitespace found.
L: 2 | P: 1 | L003 | Indent expected and not found compared to line #1
L: 2 | P: 10 | L010 | Inconsistent capitalisation of keywords.
L:
は行数、P:
は何文字目かを示しており、L
から始まるのはルール番号(Rules Reference)になり、どこがルールに違反しているのかが表示される
$ sqlfluff lint test.sql --rules L003,L009,L010
== [test.sql] FAIL
L: 2 | P: 3 | L003 | Indentation not hanging or a multiple of 4 spaces
L: 3 | P: 1 | L003 | Indent expected and not found compared to line #1
L: 3 | P: 10 | L010 | Inconsistent capitalisation of keywords.
ルールを指定して実行もできる(上記の場合はL003とL009とL010のルールが実行された
ルールのカスタム
実行する同一階層に.sqlfluff
という設定ファイルを格納することで振る舞いを変更することができる
[sqlfluff:rules]
tab_space_size = 2
[sqlfluff:rules:L010]
capitalisation_policy = lower
ルール例
L001: 不必要なホワイトスペース
🙅🏻♂️ NG
SELECT
a
FROM foo••
👍 OK
SELECT
a
FROM foo
L002: 1行の中にタブとスペースが混ざっている
(→はタブ、•はスペース)
🙅🏻♂️ NG
SELECT
••→a
FROM foo
👍 OK
SELECT
••••a
FROM foo
L010: キーワードの大文字・小文字が統一されていない
🙅🏻♂️ NG
select
a
FROM foo
👍 OK
select
a
from foo
L016: 1行の最大文字数
0から1000で指定できる
L019: カンマの位置(先頭、行末)
[‘leading’, ‘trailing’]
trailing
(行末)を指定した場合以下はエラーになる
🙅🏻♂️ NG
SELECT
a
, b,
c
FROM foo
👍 OK
SELECT
a
, b
, c
FROM foo
L022: WITH句のあとに1行空行をあけているか
🙅🏻♂️ NG
WITH plop AS (
SELECT * FROM foo
)
SELECT a FROM plop
👍 OK
WITH plop AS (
SELECT * FROM foo
)
SELECT a FROM plop
L023: WITH句のasの後ろに空白が入っているか
🙅🏻♂️ NG
WITH plop AS(
SELECT * FROM foo
)
SELECT a FROM plop
👍 OK
WITH plop AS (
SELECT * FROM foo
)
SELECT a FROM plop
L030: 関数の小文字、大文字
L010の設定を継承。
BigQueryを想定したコーディング規約を元にしたリントルールを作ってみる
以下のような定義で設定してみようと思います。
- L001: 不必要なホワイトスペース
- L002: 1行の中にタブとスペースが混ざっている
- L010: 予約語/関数は小文字
capitalisation_policy = lower
- L019: カンマは文頭
- L003: インデントはスペース2つ
tab_space_size = 2
- L016: 1行の行数制限
ignore_comment_lines = True
indent_unit = space
max_line_length = 80
tab_space_size = 2
.sqlfluff
のファイルに書き設定内容を掲載
[sqlfluff:rules]
tab_space_size = 2
[sqlfluff:rules:L010]
capitalisation_policy = lower
[sqlfluff:rules:L016]
ignore_comment_lines = True
indent_unit = space
max_line_length = 80
tab_space_size = 2
[sqlfluff:rules:L019]
comma_style = leading
ドキュメントの通り記載。
上記の設定ファイルを.sqlfluffに書き出し。
SELECT
a+b AS foo,
c AS bar from my_table
検証するSQLはこちら
$ sqlfluff lint test.sql --rules L001,L002,L003,L010,L016,L019
リントを実行する
== [test.sql] FAIL
L: 1 | P: 1 | L010 | Inconsistent capitalisation of keywords.
L: 2 | P: 8 | L010 | Inconsistent capitalisation of keywords.
L: 2 | P: 14 | L019 | Found trailing comma. Expected only leading.
L: 3 | P: 1 | L003 | Indentation not consistent with line #2
L: 3 | P: 3 | L010 | Inconsistent capitalisation of keywords.
エラーが表示される
select
a+b as foo
, c as bar
from my_table
指摘されたポイントを修正し再度実行すると
$ sqlfluff lint test.sql --rules L001,L002,L003,L010,L016,L019
何もエラーが表示されなかったら成功です
Discussion