※このエントリはPerl Advent Calendar 2023の3日目の記事です。
※元々は「雑なデータ加工に使える小技5撰」でしたが内容がOtogiriだらけなので、タイトルを変更しました。
Otogiriとは
拙作のPerl製ORM(もどき)です。Otogiri - CPANを参照してください。
特徴として、以下のようなものがあります。
- スキーマ定義がない(DB/テーブルにあるものを正としている)
- データは全てハッシュリファレンスかその配列で表現される
- 端的に言えば DBIx::Sunny + SQL::Maker
MetaCPANに公開されているモジュールですので、cpanm Otogiri
でインストールできます。
Otogiriの基本的な使い方
DB接続
podにも書いてありますが、DB接続は以下のようにして行います。以下の例ではmysqlに接続しています。
1 | use Otogiri; |
strictモード
Otogiriはデフォルトでstrictモードで動作します。strictモードはSQL::Makerのstrictモードそのままの制約がつきます。
strictモードはこちらに記載があるようなSecurity Issue(JSON SQL Injection)への対策として、SQL::Makerに実装されています。もしWebアプリケーションにおいて、ユーザーからの入力をSQLに埋め込む場合はstrictモードを有効にすることを強くお勧めします。
strictモードを解除するには、DB接続時に以下のようにします。
1 | my $db = Otogiri->new( |
これはselectやinsertの際の記述方法に影響があります。別途、selectやinsertの説明の際に触れます。
データ取得
データ取得はselect
メソッドを使います。
1 | ## strictモードが有効の場合 |
単一データを取得する場合はfetch
メソッドを使います。
1 | my $row = $db->fetch(user => { id => 1 }); |
データ挿入
データ挿入はinsert
メソッドを使います。
1 | ## strictモードが有効の場合 |
データ更新
データ更新はupdate
メソッドを使います。
1 | ## strictモードが有効の場合 |
データ削除
データ削除はdelete
メソッドを使います。
1 | ## strictモードが有効の場合 |
トランザクション
トランザクションはtxn_scope
メソッドを使います。
1 | my $txn = $db->txn_scope; |
もっと複雑な使い方
ここから先はさらに複雑な使い方を紹介します。
データ取得時にカラム指定を行う
Otogiriは基本的にテーブルにある全てのカラムを取得します。これは「雑にデータ取得と処理を行うこと」を主目的としているため、そのままではカラム指定を行うことができません。
ですが、Otogiriにはプラグイン機構があります。これはOtogiri::Pluginというモジュールによって実現されています。
カラム指定を行うプラグインはOtogiri::Plugin::SelectWithColumnsです。
使い方は以下のようになります。
1 | use Otogiri; |
select_with_columns
というメソッドが使えるようになり、その第2引数でカラムを指定することができます。
スキーマ定義をしてデータクラスを指定する
Otogiriの特徴には「スキーマ定義がない」というものがありましたが、その気になればスキーマ定義を書くこともできます。
perl-5.38以降であれば class
構文を使うことでスキーマ定義を書くことができます。
1 | class Book { |
実際に単一取得を行う場合、事前にrow_class
メソッドでスキーマ定義を指定することで、スキーマ定義に従ったオブジェクトを取得することができます。
1 | my $book = $db->row_class('Book')->single(book => {id => 1}); |
敢えてrow_classを無効にしたいシーンでは、row_class
メソッドの代わりにno_row_class
メソッドを使います。
1 | my $book = $db->no_row_class->single(book => {id => 1}); |
inflate/deflate
Otogiriの機能で最も複雑なのがinflate/deflateです。これはDBから取得したデータを予め指定した関数に基づいて変換したり、DBに格納するデータを予め指定した関数に基づいて変換したりする機能です。
inflate/deflateは以下のようにして使います。
1 | use JSON; |
inflateはselect(), search_by_sql(), fetch()がコールされた後に呼ばれ、取得データを加工します。
deflateはinsert(), update(), delete()がコールされる前に呼ばれ、格納データを加工します。
直近のOtogiriについて
基本的にはOtogiriのメンテははっきり言ってのんびりしています。ですが、row_class
の機能は最近追加されたばかりです。
また先ほど、DBURLへ対応をさせるためのPull-Requestを作成したところです。
もしこれが取り込まれたら、以下のようにDB接続情報をURLで指定できるようになります。
1 | my $dburl = 'mysql://dbuser:dbpassword@dbhost/mydb?someOption=someValue&otherOption=otherValue'; |
Otogiriの今後
基本的には「雑にデータ取得と処理を行うこと」が主目的なのは変わらずで、そのための機能を追加していく予定です。
ぜひ、Otogiriを使ってみてください。そして、Pluginの作成やPull-Requestの作成など、Otogiriの開発にも参加していただけると嬉しいです。