Perl と Moo で、SQL を組み立てるクエリビルダーを作る全8回の連載です。テーブル名を受け取って SELECT を返すだけのクラスから始め、WHERE・ORDER BY・LIMIT を足すたびにコンストラクタの引数が増えて行き詰まる様子と、値を文字列結合で埋め込んだ SQL が攻撃で全件を返す様子を確かめます。そこから、1句ずつメソッドで足す Builder パターンに組み替え、プレースホルダーで値を分け、JOIN や集計への拡張、定型クエリをまとめる Director、バリデーションとテストまで仕上げます。
各回は前の回のコードに手を足していく作りなので、通して読むなら第1回からが早道です。このページは目次を兼ねた案内板です。入口は「どこから読むか」で、困りごとが決まっているなら「困りごとから探す」で、順に追うなら「全話一覧」で選んでください。
どこから読むか
- 第1回 — 最初から順に作るなら。SELECT を返すだけの Query クラスを作り、SQLite で動かす。前提は Moo のクラス定義の基礎
- 第3回 — 文字列結合の SQL がどう破られるかを先に見たいなら。第2回の Query クラスを使うが、攻撃の筋は1回で追える
- 第4回 — Builder パターンの組み立て方だけ知りたいなら。メソッドチェーンで1句ずつ足す QueryBuilder を作る。第2回の引数7個のコンストラクタと見比べる
困りごとから探す
コンストラクタの引数が増え続けて、どれが必須か分からない
文字列結合の SQL に、入力値がそのまま入っている
句を足したいが、動いているコードは書き換えたくない
- 第6回 — JOIN・GROUP BY・HAVING・OFFSET を、from や where には手を入れず足す
同じ組み立てを何か所にも書いている
- 第7回 — ページ送り付き検索や集計の手順を Director にまとめる
間違った呼び方でも SQL ができてしまう
- 第8回 — 不正な引数を croak で止め、Test::More でテストする
全話一覧
- 最小の SELECT を返す Query クラス(文字列結合)
- WHERE・ORDER BY・LIMIT で引数が7個に(Telescoping Constructor)
- 文字列結合の SQL を攻撃してみる(SQLインジェクション)
- メソッドチェーンで1句ずつ組み立てる(Builder)
- 値を ? と bind 値に分ける(プレースホルダー)
- JOIN・GROUP BY・HAVING・OFFSET を足す(拡張)
- 定型クエリの手順をまとめる(Director)
- バリデーションとテストで完成(Test::More)
前提知識
- Perl v5.36 以降の基本文法(signatures、postfix dereference など)
- Moo によるクラス定義の基礎(has)
- DBI と DBD::SQLite(手元で実行して確かめるときに使う)
- Moo が初めてなら、先に「Mooで覚えるオブジェクト指向プログラミング」シリーズを読むとスムーズに進みます
完成するもの
from・select・join・where・group_by・having・order_by・limit・offset をメソッドチェーンで組み立て、値はプレースホルダーで分けて返す QueryBuilder と、定型クエリをまとめた QueryDirector です。不正な呼び方は croak で止まり、t/query_builder.t のテストで振る舞いを確かめられます。
