Microsoft
C#
SQLServer

TransactSql.ScriptDomを使ってTransact-SQLのコーディング規約をチェックする

More than 5 years have passed since last update.

JOINをしているのにテーブル名を書いていない場所を見つける

テーブル名の宣言無しに列名が使われるとわかりづらいため、
「joinを行ったらテーブル名を書かなくてはならない」というコーディング規約が現場にある。
しかし、この規約違反を目でチェックするのが面倒なので自動化する。

つまり、

good.sql
SELECT
   book.title
FROM
   book
   INNER JOIN shelf ON boo.id_shelf = shelf.id
WHERE
   shelf.name = 'mine'

というのを、

bad.sql
SELECT
   title
FROM
   book
   INNER JOIN shelf ON boo.id_shelf = shelf.id
WHERE
   shelf.name = 'mine'

のように書いている場所を発見したい。(下のSELECT句にはbookが抜けている)

道具の用意

静的にTransact-SQLを解析するのは自分の力ではできそうになかったので、ライブラリを使用した。
使用したのは、Microsoftが提供しているTransact-SQLのパーサー兼ジェネレータ
TransactSql.ScriptDom

使い方はT-SQL の パーサーとジェネレーター(ScriptDom)の紹介が参考になる。

これはVisitorを使用していて、動きに合わせて全ての部分に行けるのでパース結果から静的な解析が楽にできる。
が、ドキュメントが皆無なので、どんな時に何のメソッドが呼ばれるのかは実験する必要がある。

解析する

目的は「joinを行ったのにテーブル名を書いていない場所を見つける」こと

テーブルの列名が宣言されるべき場所はSELECT, WHERE, ORDERなど色々あるが、パースした結果では共通してExplicitVisit(ColumnReferenceExpression)が呼ばれている。
そのため、

  • SELECT,INSERT,UPDATE,DELETE文内でExplicitVisit(..)が呼ばれている
  • 宣言されている列名にテーブル名がついていない
  • JOINが呼ばれている

以上を満たせば「joinがあるのにテーブル名が宣言されていない」ということがわかる。

これを利用して、T-SQL文字列から規約違反を発見することが出来る。
実際に使用しているプログラムはGithubにおいている。
SQLChecker内が実際にT-SQLをチェックしている部分