SQLFluffではじめるお手軽コーディング規約導入

はじめに

こんにちは。株式会社High Link データエンジニアの谷口祐太郎(@ytaniguchi811)です。

私たちのチームは全社的にデータの利活用を推進できるよう、分析基盤の開発に日々取り組んでいます。

Data WarehouseとしてはBigQueryを採用しており、分析用のテーブルはdbtとGitHubを連携させてコードで管理しています。 dbtを用いることで分析テーブルをコード管理できるようになり、私たちのような小規模チームでも管理・運用が非常に楽になりました。詳しくは本テックブログの別記事で説明していますので、よろしければご参照ください。

tech.high-link.co.jp

しかしながら、「実装者によってSQLの記法がバラバラで見通しが悪い」、「レビューのコストが増大する」という課題にぶつかり、SQLのコーディング規約の導入を検討し始めました。 コーディング規約を導入する際には、「規約の定義」、「規約の運用」の2つが重要になってきますが、私たちは、SQLFluffというツールを活用することでこの2ステップを同時に満たすことができました。

今回は、SQLFluffを用いてどのようにコーディング規約を定義し、運用しているのかについてご紹介したいと思います。 コーディング規約をどう決めたらよいか?Linter/Formatterは何を選べばいいか?など迷っている方のご参考になれば幸いです。

SQLコーディング規約とは?

SQLコーディング規約とは、SQLコードの品質を保つために表記を統一するルールです。

例えば、以下のようなものがあります。

  • SELECTやFROMなどの予約語は必ず大文字にする
  • GROUP BYの中身は列番号(1, 2, …)ではなく必ずカラム名を用いる
  • カンマは行末ではなく必ず行頭におく

このような表記方法のぶれを統一するルールをみんなで決めておくことで、「レビューしやすくなる」、「改修しやすくなる」、「知見としてキャッチアップしやすくなる」といった利点があり、開発や改善が高速になることが期待できます。

具体的な事例については、クックパッドさんやマネーフォワードさん、他多数のチームが公開されていますので、ご参照ください。

SQLFluffを利用したコーディング規約の定義

私たちはSQLFluffで提供されたルールセットをもとにコーディング規約の定義を決めました。SQLFluffとは、さまざまな書式・オプションに対応しているSQL Linter/Formatterです。

www.sqlfluff.com

SQLFluffは、適用可能なルールセットが用意されており、チームのポリシーに応じて適用するルールを適宜カスタマイズして利用することが可能となっています。

当初は、一からコーディング規約を定義しようとしていたのですが、網羅的に決めることのコストや、決めた規約をどうやって浸透させるかという点で課題を感じていました。 そこで、「コーディング規約を決めてからLinterを導入する」のではなく、「SQLFluff(Linter)に合わせてコーディング規約を決める」ようにすることで、「定義」と「運用」を同時にカバーしようと考えました。

SQLFluffで利用可能なルールは L001 から L068 までの68種類があります。(ルールに関する公式ドキュメントはこちら)

私たちは基本的にはSQLFluffが提供しているルールをそのまま取り入れつつ、一部カスタマイズをしています。

具体的には、以下の4つのルールは無効に設定しました。このあたりはチームごとで要不要を判断していただければよいかと思います。

SQLFluffルール番号 ルール 無効にした理由
L029 予約語カラム名に使わない すでに分析に活用されているテーブルのカラム名に source などの予約語が含まれており、私たちの場合は依存テーブルなどを含めた修正コストが大きかったため。
L031 テーブル名のエイリアスを許容しない 長いテーブル名など、エイリアスを使ったほうが読み書きしやすいと考えたため。
L034 SELECT文では * が最初で、関数を使うものは最後にする 各カラムの意味ごとにまとまっていたほうが読み書きしやすいと考えたため。
L042 サブクエリではなくWITHクエリを使う クエリが短い場合など、場合によってはサブクエリを使ったほうが読みやすいと考えたため。

また、「カンマは先頭か末尾か」、「COUNT(*)とCOUNT(1)、どちらを使うか」など各ルールの設定もコンフィグで設定することができます。これらに関しても、メンバーのコーディングスタイルを考慮した設定を行いました。

このように適宜、状況に合わせてカスタマイズして使うのがおすすめです。

チームでの運用

実行環境・コンフィグの統一

SQLFluffをチームで運用していくうえで、誰もが簡単に環境を揃えてフォーマット・エラー検出できれば楽になります。そこで、メンバー間での実行環境・コンフィグを簡単に統一できる仕組みを作りました。

実行環境の統一のために、Pythonのパッケージマネージャーpoetryでインストールするようにしました。以下のように pyproject.tomlpoetry.lock を設定しています。

[tool.poetry.dependencies]
python = "^3.9"
sqlfluff = "1.3.0"
name = "sqlfluff"
version = "1.3.0"
description = "The SQL Linter for Humans"
category = "main"
optional = false
python-versions = ">=3.7"

また、コンフィグの統一のために、SQLFluffのconfigファイルをリポジトリ内に用意しています。このファイルに記述することで、前節で述べた各オプションを設定しています。以下に私たちのconfigファイルの内容の一部を記載します。

[sqlfluff]
rules = all
exclude_rules = L029, L031, L034, L042,
templater = jinja

[sqlfluff:rules]
max_line_length = 120
tab_space_size = 2

[sqlfluff:indentation]
# JOINではインデントしない
indented_joins = False
# ONではインデントしない
indented_using_on = False

[sqlfluff:rules:L010]
# 予約語は大文字
capitalisation_policy = upper

GitHub Actionsによるエラー検出・自動修正

さらに運用を楽にするために、GitHub Actionsを設定してCIでエラー検出・自動修正コミットができるようにしました。ブランチプッシュをトリガーとしてSQLFluffのコマンドを実行し、以下の2つの処理を行うようにしています。参考までに、それぞれの処理を行うGitHub Actionsの記述も一緒に記載しておきます。

  • fixable violations(自動修正可能なエラー)については修正コミットをプッシュする
- name: Fix With Sqlfluff
      continue-on-error: true
      run: poetry run sqlfluff fix ./models/* --dialect bigquery --config .sqlfluff -f
- name: Check Diff
      id: check_diff
      run: |
        git add -N .
        git diff --name-only --exit-code
      continue-on-error: true
    - name: Commit & Push
      run: |
        git config --local user.email "action@github.com"
        git config --local user.name "GitHub Action"
        git commit -m "Auto Fix with SQLFluff" -a
        git push
      if:
        steps.check_diff.outcome == 'failure'
  • unfixable violations(検出はできるが手動で修正する必要があるエラー)についてはエラーを出す
- name: Lint With Sqlfluff
      run: poetry run sqlfluff lint ./models/* --dialect bigquery --config .sqlfluff

このようなCIへの組み込みによって、「GitHubにコミットされたコードは規約を遵守している」ということが保証されます。実際私は、うっかり手元での確認を忘れてプッシュしてしまうことが多々あるのですが、ここでキャッチしてくれるのでとても助かっています。

おわりに

今回は、私たちのチームにおけるSQLFluffを用いたSQLのコーディング規約の導入とその運用方法についてお話しました。

SQLFluffの活用によって「規約の定義」、「規約の運用」を同時に満たすことができ、簡単に規約の導入ができました。

SQLコーディング規約の事例調査でさまざまな流派や考え方に触れ、このような定義を一から作るのは大変そうだと思っていたのですが、SQLFluffが提供してるルールに準拠する道を選んだことで、定義から運用までを比較的簡単にカバーすることができてよかったです。

さらにCIへの組み込みにより、決めたルールをほぼ自動で準拠させることが可能となったので運用は非常に楽になりました。

High Linkではデータ基盤の整備やデータマネジメントを通して、一緒に全社的なデータ利活用レベルを引き上げていけるエンジニアを募集しております!

https://herp.careers/v1/highlink/RIGo8XhyyCPQ?utm_source=hatena&utm_medium=highlinktechblog&utm_campaign=sqlfluff-coding-styleherp.careers

https://herp.careers/v1/highlink/-0mpTggpwsjk?utm_source=hatena&utm_medium=highlinktechblog&utm_campaign=sqlfluff-coding-styleherp.careers