コンパイル時のSQLチェック

今日は、Domaコンパイル時におこなっているSQLの検証処理について紹介したいと思います。
Daoには次のメソッドを用意します。

@Select
Emp selectById(Integer id);

このメソッドには、次のようなSQLが対応しテキストファイルとして適切な場所に配置されなければいけません。

select * from EMP where ID = /* id */100

以下では、もし、正しくSQLを記述しなかったらどんなエラーになるのか見てみます。

SQLファイルが見つからない場合

次のようなエラーになります。

[DOMA4019] SQLファイル[META-INF/org/seasar/doma/it/dao/EmpDao/selectById.sql]がクラスパスから見つかりませんでした。

メッセージ中に登場する場所にSQLファイルを置いてねということです。

Daoメソッドのパラメータを参照しない場合

次のようなSQLファイルを用意します。本当は /* id */ という記述でDaoメソッドのパラメータを参照すべきですがそれがありません。

select * from EMP where ID = 100

この場合は、次のようなエラーになります。

[DOMA4122] SQLファイル[META-INF/org/seasar/doma/it/dao/EmpDao/selectById.sql]の妥当検査に失敗しました。
メソッドのパラメータ[id]がSQLファイルで参照されていません。

どのSQLファイルが問題か教えてくれます。

Daoメソッドのパラメータに存在しないパラメータを参照する場合

次のようなSQLファイルを用意します。id2という存在しないパラメータを使っています。

select * from EMP where ID = /* id2 */100

この場合は、次のようなエラーになります。

[DOMA4092] SQLファイル[META-INF/org/seasar/doma/it/dao/EmpDao/selectById.sql]の妥当検査に失敗しました。
SQL[select * from EMP where ID = /* id2 */100]([1]行目[38]番目の文字付近)。詳細は次のものです。
[DOMA4067] SQL内の変数[id2]に対応するパラメータがメソッドに存在しません([3]番目の文字付近)。

まちがっている場所(行や列)も教えてくれます。

テスト用のリテラルが存在しない場合

次のようなSQLファイルを用意します。本当は、/* id */の後ろにテスト用の値が必要です。

select * from EMP where ID = /* id */

この場合は、次のようなエラーになります

[DOMA4069] SQLファイル[META-INF/org/seasar/doma/it/dao/EmpDao/selectById.sql]のパースに失敗しました。原因は次のも
 のです。org.seasar.doma.jdbc.JdbcException: [DOMA2110] SQL[select * from EMP where ID = /* id */]の解析に失敗しました
 ([1]行目[37]番目の文字付近)。バインド変数コメント[/* id */]の直後にテスト用のリテラルもしくは括弧が見つかりません。

S2Daoなどではこういう書き方を認めていますが、SQLのツールで流したときにうまく実行できないのでDomaではエラーにしています。

まとめ

ここにあげたのごく一部の例で、もっと多くの検証をコンパイル時に行っています。実行しなくてもまちがいに気づけるのは、けっこう楽です。