Skip to main content

SQLFluff入門:SQLコードをクリーンかつエラーフリーに

cover photo

コードを書いた後に実行したとき、エラーが発生するとイライラします。さらに厄介なのは、そのエラーの原因が分からないときです。また、複数のメンバーがいる大規模なプロジェクトでは、メンバーごとにコードの書き方が異なる傾向があり、その結果、コードレビューが難しくなり、ソースコードに不整合が生じます。コードを実行する前にエラーを検出できた方が良いと思いませんか?さらに、チームメンバー全員が同じフォーマットでコードを書けば、もっと効率的になるでしょう。

SQLFluffと言うツールがこの全ての事を実現させます。

SQLFluffは何でしょう?

SQLFluffは、SQLファイル用の最も人気のあるリンターです。構文エラーを検出すると、そのエラーが発生した行番号や位置、エラーの原因が表示されます。SQLFluffはエラーの検出だけでなく、SQLコードのフォーマットや構文エラーの修正も可能です。PostgreSQL、MySQL、Google BigQuery、Snowflakeなど、複数のSQL 言語をサポートしています。つまり、SQLコードを実行する前に構文エラーを検出・修正できるので、非常に役立ち、重要な作業に集中することができます。また、SQLFluffは非常に設定が簡単で、コンマの位置、文字の大文字小文字、インデントなどのルールを簡単に設定できます。

エンジニアは自分のパソコンにSQLFluffをインストールし、SQLFluffを利用してコードのエラーを検出・修正した後にGitにコミットし、GitLabやGitHubなどにプッシュすることをお勧めします。
全てのドキュメントはこちらにあります: Docs

インストール

SQLFluff は以下のようにインストールできます

  • VSCode エクステンション
  • プリコミットフック
  • コマンドラインツール
  • CI/CDパイプラインツール

SQLFluffをコマンドラインツールとして設定し、実行してくださいのが一番簡単です。また、この記事でプレコミットフックとしての使い方も説明します。

SQLFluffをコマンドラインツールとしてインストール

注意点: SQLFluffをインストールするにはPythonとpip (またはpoetryやpipenvなどのパッケージマネージャ)が必要です。このマニュアルではpipを使用します。

ターミナルで以下のコマンドを実行して SQLFluff をインストールする:

pip install sqlfluff

インストールを確認する為に、以下のコマンドを実行してください:

sqlfluff version
# 3.2.4

使う方

SQLFluffには3つの主要なコマンドがあります: lint : 構文エラーを表示します。 format : コードを整形する(主に改行、インデテーション、空白を修正する)。 fix: カンマ、セミコロン、順番、改行などの構文エラーを修正します。

test.sqlというファイルをlintする為に、以下のコマンドを実行してください:

sqlfluff lint test.sql --dialect snowflake

上のコマンドの結果:

== [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 at end of file.
                       | [layout.spacing]
L:   1 | P:  27 | LT12 | Files must end with a single trailing newline.
                       | [layout.end_of_file]
All Finished 📜 🎉!

リント出力の説明:

リント出力には、エラーの原因となったL(行番号)と P(位置)、そしてエラーを見つけたルール・インデックス(この場合はLT01)が表示される。ルール・インデックスの後には、何が問題なのかについての短い説明がある。
すべてのルールとその定義は、こちらをご覧ください:Rule Index

SQLFluff にはデフォルトのルールが用意されています。これらのルールはコマンドラインでもすぐに確認出来ます:

sqlfluff rules

チェックするルールを指定したり、特定のルールを除外したりすることが出来ます。 ルールを指定する方法:

sqlfluff lint test.sql --rules LT02,LT12,CP01,ST06,LT09,LT01

ルールを除外する方法:

sqlfluff fix test.sql --exclude-rules LT01

SQLFluffはあるSQL言語が使用するいくつかのキーワードを理解出来ない場合があります。 このような場合、parsing errorが発生します。この問題を回避する為に、SQLFluffにparsing errorを無視するように指示する事が出来ます。

sqlfluff fix test.sql --ignore parsing

全てのコマンドライン設定はこちらをご覧ください: CLI Config

設定ファイル

SQLFluffがデフォルトの設定があり、デフォルトの設定を上書きすることも可能です。SQLFluffをcliで設定したくない場合は、設定ファイルを書く事が出来ます。
SQLFluffデフォルトの設定をファイルとしてこちらでご確認出来ま: Config File

SQLFluff は以下の設定ファイルをサポートします:

  • setup.cfg
  • tox.ini
  • pep8.ini
  • .sqlfluff
  • pyproject.toml

以下の例では、7つのコンフィギュレーション ルールを変更します。残りのルールはデフォルトのままです。

.sqlfluff ファイルとして

[sqlfluff]

dialect = snowflake

exclude_rules = ST06

runaway_limit = 2

large_file_skip_byte_limit = 2000000

[sqlfluff:layout:type:comma]
line_position = leading

同じ設定は、TOMLファイルでは次のようになります:

[tool.sqlfluff]

dialect = snowflake

exclude_rules = ST06

runaway_limit = 2

large_file_skip_byte_limit = 2000000

[tool.sqlfluff.layout.type.comma]
line_position = leading

記の設定の説明:

dialect = snowflake SQLFluff の方言を Snowflake 構文に設定します。exclude_rules = ST06 はルール ST06を除外する設定です。ST06ルールはselect対象を複雑さの昇順に並べます。例えば、ST06ルールが*を他のselect項目の上に置きます:

select
    *,
    a,
    b,
    row_number() over (partition by id order by date) as y
from my_table

でも、僕は列の順番を変わったくないので、ST06ルールを除外する設定を書いています。

runaway_limit = 2 次コードブロックに進む前に、SQLFluff が、コードブロックからエラー探し、改善を試み回数の制限。large_file_skip_byte_limit = 2000000, SQLファイルが2000000バイト(2MB)を超える場合、SQLFluffはそのファイルを無視します。line_position = leading は各行の先頭にカンマを置きます。 line_position = leadingルールの結果:

Select
    a
    ,b
    ,c
From my_table;

プレコミット

Git はすべての開発者にとって欠かせないツールです。バージョン管理とコラボレーションに役立ちます。Gitが通常の作業を行う際にいくつかの関数を呼び出すことができます。たとえば、変更をリポジトリにコミットする前に、git は特定の関数を呼び出すことができます。これらの関数は、プレコミットフックと呼ばれます。これらの関数(pre-commit hooks)の設定や構成を支援するpre-commitと言うツールがあります。

プレコミットの設定

$ pip install pre-commit

# check installation
$ pre-commit --version
# pre-commit v4.0.1

レポジトリのルートフォルダーに.pre-commit-config.yamlというファイルを作成します。 中に以下のコードを書きます:

repos:
  - repo: https://github.com/sqlfluff/sqlfluff
    rev: 2.1.4
    hooks:
      - id: sqlfluff-lint
      - id: sqlfluff-fix

pre-commit.sqlfluffの設定を使うことができます。しかし、.sqlfluffファイルを使用したくない場合は、以下のように.pre-commit-config.yamlファイルに直接設定を記述することができます。

repos:
  - repo: https://github.com/sqlfluff/sqlfluff
    rev: 2.1.4
    hooks:
      - id: sqlfluff-lint
        args:
            - '--dialect'
            - 'snowflake'
            - '--exclude-rules'
            - 'ST06'
            - '--runaway-limit'
            - '2'
            - '--layout-type'
            - 'comma'
            - '--line-position'
            - 'leading'

      - id: sqlfluff-fix
            args:
            - '--dialect'
            - 'snowflake'
            - '--exclude-rules'
            - 'ST06'
            - '--runaway-limit'
            - '2'
            - '--layout-type'
            - 'comma'
            - '--line-position'
            - 'leading'

SQLFluffのpre-commit関数をセットアップする為に、pre-commit install を実行してください。これで、git commit を実行するたびに、コミット前に SQLFluff の linting コマンドと修正コマンドが実行されます。SQLFluff がエラーを見つけなければコミットされますが、エラーが見つかった場合はコミットされません。SQlFluff はエラーをターミナルに出力し、可能な限り修正します。その後、git add コマンドと git commit コマンドをもう一度実行する必要があります。

Comments

Popular posts from this blog

Introduction to SQLFluff: How to make your SQL code clean and error-free

Image by Jake Aldridge from Pixabay You know oftentimes, the cause of runtime or compile errors and hours of debugging agony is all due to simply a missing semicolon. Have you ever had such experience? If you had, you are not alone. There are two ways to avoid these unfortunate situations: either become a perfect developer who never makes mistakes, or use helpful tools such as linters that can catch these errors early on. I am nowhere near being a perfect developer who never makes a mistake. In fact, I'm probably the opposite of a perfect developer, so even if I wanted to, I wouldn’t be able to teach you how to become a perfect developer. But what I can teach you is using linters. A Wikipedia defines a linter as a "static code analysis tool used to flag programming errors, bugs, stylistic errors and suspicious constructs." If you're not convinced yet on using linters, consider this scenario: in a large project with multiple members, different people tend to ...

WinMerge のセットアップと使う方

WinMerge は、Windows 用のオープン ソースの差分およびマージ ツールです。WinMerge は、フォルダーとファイルの両方を比較し、違いを理解して扱いやすい視覚的なテキスト形式で表示します。この記事でWinMerge のセットアップと使う方を教えます。 source: https://winmerge.org WinMerge をダウンロード WinMerge のウェブサイト に行って、「WinMerge-2.16.44-x64-Setup.exe」ボタンを押し、WinMerge 2.16 をダウンロードしてください。 WinMerge をインストール ダウンロードされたソフトウェアをクリックし、ポップアップ画面で「Next」を押してください 「Languages」部分をスクロールダウンし、「Japanese menus and dialogs」を選択し、「Next」ボタンを押してください ターミナル等からも WinMerge をアクセス出来ようにする為に「Add WinMerge folder to your system path」オプションを選択し、希望によって他のオプション選択してください 「Enable Explorer context menu Integration」オプションを選択したら、フォルダ/ファイルを右キリックし、コンテクストメニューから WinMerge を開くようになります。 「Install」ボタンを押し、「Next」ボタンを押し、その後、「Finish」ボタンを押してください 言語を日本語にする もし WinMerge の言語が日本語じゃなくて、英語なら、「Edit」タブから「Options」を押してください。 ポップアップ画面で右側の下にある「Languages」と言うドロップダウンメニューから日本語を選択し、「OK」ボタンを押してください WinMerge を使う方 「ファイル」タッブから「開く」を押し 参照ボタンを押し、比較したいフォルダ・ファイルを指定 比較したいフォルダを指定する方法: ポップアップ画面から対象のフォルダーを選択し、「Open」を押してくだい 何も選択しないで、「Open」を押してくだい 右側下にある「比較」ボタンを押し ...

Git squash merge explained

There are many ways to integrate changes in git: regular / normal git merge, git squash merge, git rebase etc. This article explains git squash merge by comparing it to regular merge. Let’s use below example: In the repository with default main branch, after two commits, a new feature branch is created. Some work happened in feature branch. feature branch now has 2 commits that it shares with main branch, and three exclusive commits (exists only in feature branch). In the meantime, others worked on main branch and added two new commits (exists only in main branch). git log output of the main branch: c72d4a9 ( HEAD - > main ) fourth commit on main 2c3dd61 third commit on main 0c2eec3 second commit on main 9b968e8 first commit on main git log output of the feature branch: 786650f ( HEAD - > feature ) third commit on feature 21cbaf1 second commit on feature 677bc7f first commit on feature 0c2eec3 second commit on main 9b968e8 first commit on mai...