added experimental expand me...
|
1 |
=encoding utf8 |
2 | ||
updated document
|
3 |
=head1 NAME |
added experimental expand me...
|
4 | |
update pod
|
5 |
DBIx::Custom::Guide::Ja - DBIx::Customのガイドブック |
added experimental expand me...
|
6 | |
7 |
=head1 ガイド |
|
8 | ||
selection can contain where ...
|
9 |
(このモジュールはまだ実験的な機能を多く含んでいます |
10 |
モジュールのドキュメントにexperimentalがついているものは、 |
|
11 |
予告なしに変更されることがあります。) |
|
12 | ||
update pod
|
13 |
L<DBIx::Custom>はSQLの実行を簡単に行うためのクラスです。 |
14 |
L<DBIx::Class>やL<DBIx::Simple>と同じように |
|
updated document
|
15 |
L<DBI>のラッパクラスになっています。L<DBIx::Class>よりも簡単に、 |
16 |
L<DBIx::Simple>よりもはるかに柔軟なことを行うことができます。 |
|
added experimental expand me...
|
17 | |
18 |
L<DBIx::Custom>はO/Rマッパーではありません。O/Rマッパーは |
|
19 |
便利ですが、O/Rマッパのたくさんの文法を覚える必要があります。 |
|
updated document
|
20 |
また、O/Rマッパによって生成されたSQLは非効率なことがありますし、 |
21 |
複雑なSQLを生成することができないので、 |
|
update pod
|
22 |
生のSQLを実行しなければならない場合がたくさんあります。 |
added experimental expand me...
|
23 | |
updated document
|
24 |
L<DBIx::Custom>はO/Rマッパとは対照的な設計が行われています。 |
updated document
|
25 |
L<DBIx::Custom>の主な目的は、SQLを尊重しつつ、L<DBI>だけでは |
updated document
|
26 |
とてもめんどうな作業を簡単にすることです。もしSQLについて |
27 |
多くの知識を持っているならば、L<DBIx::Custom>でそのまま |
|
updated document
|
28 |
活用することができます。 |
updated document
|
29 | |
update pod
|
30 |
L<DBIx::Custom>の仕組みを少しだけ説明しておきます。 |
updated document
|
31 |
L<DBIx::Custom>では、タグと呼ばれるものを |
32 |
SQLの中に埋め込むことができます。 |
|
33 | ||
34 |
select * from book where {= title} and {=author}; |
|
35 | ||
36 |
{}で囲まれた部分がタグです。このSQLは実際に実行されるときには |
|
37 |
次のようにプレースホルダに展開されます。 |
|
38 | ||
updated document
|
39 |
select * from book where title = ? and author = ?; |
updated document
|
40 | |
41 |
これらの展開にはどのような意味があるのでしょうかと質問 |
|
update pod
|
42 |
されるかもしれません。この簡単な仕組みの上に |
43 |
便利な機能が実装されます。それは以下のようなものです。 |
|
updated document
|
44 | |
updated document
|
45 |
=over 4 |
updated document
|
46 | |
update pod
|
47 |
=item 1. プレースホルダにバインドする値をハッシュリファレンスで指定 |
updated document
|
48 | |
update pod
|
49 |
L<DBI>を使うのであればプレースホルダにバインドする値は配列 |
updated document
|
50 |
で指定する必要があります。 |
updated document
|
51 | |
updated document
|
52 |
$sth->execute(@bind); |
53 | ||
54 |
L<DBIx::Custom>を利用するのであればハッシュリファレンスで指定すること |
|
55 |
できます。 |
|
56 |
|
|
57 |
my $param = {title => 'Perl', author => 'Ken'}; |
|
58 |
$dbi->execute($sql, $param); |
|
59 | ||
update pod
|
60 |
=item 2. 値のフィルタリング |
updated document
|
61 | |
update pod
|
62 |
L<DBIx::Custom>はフィルタリングの機能を提供します。 |
updated document
|
63 |
たとえば、日付の列は、Perlで扱うときにはC<Time::Piece>などの日付オブジェクト |
64 |
で扱い、データベースに格納するときはデータベースの日付型に変換したい |
|
65 |
と思うのではないでしょうか。またデータベースから取り出すときは |
|
66 |
データベースの日付型から日付オブジェクトに変換したと思うのでは |
|
67 |
ないでしょうか。 |
|
68 | ||
69 |
このようなときはフィルタ機能を使うことができます。 |
|
70 | ||
71 |
まずフィルタを登録します。 |
|
72 | ||
73 |
$dbi->register_filter( |
|
74 |
tp_to_date => sub { |
|
75 |
... |
|
76 |
}, |
|
77 |
date_to_tp => sub { |
|
78 |
... |
|
79 |
} |
|
80 |
); |
|
81 | ||
82 |
次にテーブルの各列にこのフィルタを適用します。 |
|
83 | ||
84 |
$dbi->apply_filter('book', |
|
renamed dbi_options to dbi_o...
|
85 |
'issue_date' => {out => 'tp_to_date', in => 'date_to_tp'} |
updated document
|
86 |
); |
87 | ||
88 |
outはPerlからデータベースに保存する方向、inはデータベースからPerlに取得する方向です。 |
|
89 | ||
update pod
|
90 |
多くのメソッドで自動的にこのフィルタが有効になります。 |
updated document
|
91 | |
update pod
|
92 |
$dbi->insert(table => 'book', param => {issue_date => $tp}); |
updated document
|
93 | |
94 |
=item 3. 選択的な検索条件 |
|
95 | ||
update pod
|
96 |
L<DBI>では選択的に検索条件を作成することは難しいです。 |
updated document
|
97 | |
98 |
たとえば、検索条件にtitleとauthorが指定された場合は次のSQLを |
|
99 | ||
100 |
select * from book where title = ? and author = ?; |
|
101 | ||
102 |
titleだけの場合は次のSQLを |
|
103 | ||
104 |
select * from book where title = ?; |
|
105 |
|
|
update pod
|
106 |
authorだけの場合は次のSQLを実行した場合を考えましょう。 |
updated document
|
107 | |
108 |
select * from book where author = ?; |
|
109 | ||
110 |
これはとても大変な作業なので、通常はL<SQL::Abstract>を動的に生成してくれる |
|
111 |
モジュールを利用することになります。 |
|
112 | ||
113 |
L<DBIx::Custom>はさらに簡単で便利な方法を用意しています。 |
|
114 | ||
update pod
|
115 |
# Whereオブジェクト |
updated document
|
116 |
my $where = $dbi->where; |
update pod
|
117 |
|
118 |
# 検索条件 |
|
updated document
|
119 |
$where->clause( |
120 |
['and', '{= title}', {'= author'}] |
|
121 |
); |
|
update pod
|
122 |
|
123 |
# 必要な列を自動的に選択するための設定 |
|
124 |
$where->param({title => 'Perl'}); |
|
updated document
|
125 | |
update pod
|
126 |
# SQLへのWhere句の埋め込み |
updated document
|
127 |
my $sql = "select * from book $where"; |
128 | ||
129 |
詳しい説明は後ほど行いますが、上記のように記述すれば、 |
|
130 |
L<DBIx::Custom>では選択的な検索条件を持つWhere句を生成することができます。 |
|
131 |
検索条件が入れ子になった構造やorについても対応しています。 |
|
132 | ||
133 |
=item 4. 挿入、更新、削除、選択を行うためのメソッド |
|
134 | ||
update pod
|
135 |
L<DBIx::Custom>では挿入、更新、削除、選択を行うための |
136 |
メソッドを提供しています。 |
|
137 |
C<insert()>, C<update()>, C<delete()>,C<select()>などがあります。 |
|
updated document
|
138 | |
139 |
my $param = {title => 'Perl', author => 'Ken'}; |
|
140 |
$dbi->insert(table => 'book', param => $param); |
|
141 | ||
update pod
|
142 |
=item 5. テーブルのためのメソッドの登録 |
updated document
|
143 | |
update pod
|
144 |
テーブルのためにメソッドを登録することができます。 |
updated document
|
145 | |
update pod
|
146 |
$dbi->table('book')->method( |
updated document
|
147 |
list => sub { |
148 |
... |
|
149 |
}, |
|
update pod
|
150 |
something => sub { |
151 |
... |
|
updated document
|
152 |
} |
153 |
); |
|
154 | ||
update pod
|
155 |
メソッドの利用です。 |
updated document
|
156 | |
157 |
$dbi->table('book')->list; |
|
added experimental expand me...
|
158 | |
update pod
|
159 |
多くのO/Rマッパではテーブルのためのクラスを作成する必要がありますが、 |
160 |
L<DBIx::Custom>では簡単です。 |
|
added experimental expand me...
|
161 | |
updated document
|
162 |
=back |
163 | ||
update pod
|
164 |
L<DBIx::Custom>はとても便利です。 |
165 |
興味をもたれた方は、続きをご覧になってみてください。 |
|
added experimental expand me...
|
166 | |
167 |
=head2 1. データベースへの接続 |
|
168 | ||
update pod
|
169 |
L<DBIx::Custom>を読み込みます。 |
updated document
|
170 | |
171 |
use DBIx::Custom; |
|
172 | ||
update pod
|
173 |
データベースに接続するにはC<connect()>メソッドを使用します。 |
174 |
戻り値はL<DBIx::Custom>オブジェクトです。 |
|
added experimental expand me...
|
175 | |
updated document
|
176 |
my $dbi = DBIx::Custom->connect( |
update pod
|
177 |
data_source => "dbi:mysql:database=bookstore", |
updated document
|
178 |
user => 'ken', |
179 |
password => '!LFKD%$&', |
|
180 |
dbi_options => {mysql_enable_utf8 => 1} |
|
181 |
); |
|
added experimental expand me...
|
182 | |
update pod
|
183 |
C<data_source>はデータベースシステムに応じたものである必要があります。 |
184 |
以下はデータソースのサンプルです。 |
|
added experimental expand me...
|
185 | |
updated document
|
186 |
B<MySQL> |
added experimental expand me...
|
187 | |
deprecated DBIx::Custom::MyS...
|
188 |
"dbi:mysql:database=$database" |
189 |
"dbi:mysql:database=$database;host=$hostname;port=$port" |
|
added experimental expand me...
|
190 | |
updated document
|
191 |
B<SQLite> |
deprecated DBIx::Custom::MyS...
|
192 | |
193 |
"dbi:SQLite:dbname=$database" |
|
194 |
"dbi:SQLite:dbname=:memory:" |
|
195 | ||
updated document
|
196 |
B<PostgreSQL> |
deprecated DBIx::Custom::MyS...
|
197 | |
198 |
"dbi:Pg:dbname=$dbname" |
|
199 | ||
updated document
|
200 |
B<Oracle> |
deprecated DBIx::Custom::MyS...
|
201 | |
202 |
"dbi:Oracle:$dbname" |
|
203 |
"dbi:Oracle:host=$host;sid=$sid" |
|
204 | ||
updated document
|
205 |
B<ODBC(Microsoft Access)> |
deprecated DBIx::Custom::MyS...
|
206 | |
207 |
"dbi:ODBC:driver=Microsoft Access Driver (*.mdb);dbq=hoge.mdb" |
|
208 | ||
updated document
|
209 |
B<ODBC(SQL Server)> |
deprecated DBIx::Custom::MyS...
|
210 | |
211 |
"dbi:ODBC:driver={SQL Server};Server=(local);database=test;Trusted_Connection=yes;AutoTranslate=No;" |
|
added experimental expand me...
|
212 | |
update pod
|
213 |
認証が必要な場合は、C<user>とC<password>を指定できます。 |
updated document
|
214 | |
update pod
|
215 |
L<DBIx::Custom>はL<DBI>のラッパークラスです。 |
216 |
L<DBI>のデータベースハンドルは取得するにあhC<dbh()>を使用します。 |
|
added experimental expand me...
|
217 | |
218 |
my $dbh = $dbi->dbh; |
|
219 | ||
updated document
|
220 |
L<DBIx::Custom>ではデータベースハンドル属性にはデフォルトで次のものが設定されます。 |
added experimental expand me...
|
221 |
|
222 |
$dbi->dbh->{RaiseError} = 1; |
|
223 |
$dbi->dbh->{PrintError} = 0; |
|
224 |
$dbi->dbh->{AutoCommit} = 1; |
|
225 | ||
update pod
|
226 |
致命的なエラーが起こるとプログラムは終了します。 |
227 |
SQLが実行されると自動的にコミットされます。 |
|
added experimental expand me...
|
228 | |
updated document
|
229 |
=head2 2. 挿入、更新、削除、選択のためのメソッド |
added experimental expand me...
|
230 | |
update pod
|
231 |
下記のメソッドがあります。 |
added experimental expand me...
|
232 | |
update pod
|
233 |
=head3 行の挿入 C<insert()> |
added experimental expand me...
|
234 | |
update pod
|
235 |
データベースに行を挿入するにはC<insert()>を使用します。 |
added experimental expand me...
|
236 | |
remove DBIx::Custom::Model
|
237 |
$dbi->insert(table => 'book', |
added experimental expand me...
|
238 |
param => {title => 'Perl', author => 'Ken'}); |
239 | ||
update pod
|
240 |
C<table>はテーブル名、C<param>は挿入する行のデータです。 |
added experimental expand me...
|
241 | |
update pod
|
242 |
次のSQLが実行されます。 |
updated document
|
243 | |
244 |
insert into (title, author) values (?, ?); |
|
added experimental expand me...
|
245 | |
update pod
|
246 |
=head3 データの更新 C<update()> |
added experimental expand me...
|
247 | |
update pod
|
248 |
データベースの行を更新するには、C<update()>を使用します。 |
added experimental expand me...
|
249 | |
remove DBIx::Custom::Model
|
250 |
$dbi->update(table => 'book', |
added experimental expand me...
|
251 |
param => {title => 'Perl', author => 'Ken'}, |
252 |
where => {id => 5}); |
|
253 | ||
update pod
|
254 |
C<table>はテーブル名、C<param>は更新データ、C<where>は |
255 |
条件です。 |
|
added experimental expand me...
|
256 | |
update pod
|
257 |
次のSQLが実行されます。 |
updated document
|
258 | |
259 |
update book set title = ?, author = ?; |
|
added experimental expand me...
|
260 | |
update pod
|
261 |
安全のためC<where>のないupdate()を実効することはできません。 |
added experimental expand me...
|
262 |
もしすべての行を更新したい場合は |
updated document
|
263 |
C<update_all()>を使用してください。 |
added experimental expand me...
|
264 | |
remove DBIx::Custom::Model
|
265 |
$dbi->update_all(table => 'book', |
added experimental expand me...
|
266 |
param => {title => 'Perl', author => 'Ken'}); |
267 | ||
update pod
|
268 |
=head3 データの削除 C<delete()> |
added experimental expand me...
|
269 | |
update pod
|
270 |
データベースの行を1件削除するには、C<delete()>を使用します。 |
added experimental expand me...
|
271 | |
remove DBIx::Custom::Model
|
272 |
$dbi->delete(table => 'book', |
added experimental expand me...
|
273 |
where => {author => 'Ken'}); |
274 | ||
update pod
|
275 |
C<table>はテーブル名、C<where>は条件です。 |
added experimental expand me...
|
276 | |
update pod
|
277 |
次のSQLが実行されます。 |
updated document
|
278 | |
279 |
delete from book where id = ?; |
|
added experimental expand me...
|
280 | |
update pod
|
281 |
安全のためC<where>のないC<delete()>を実効することはできません。 |
added experimental expand me...
|
282 |
もしすべての行を削除したい場合は |
updated document
|
283 |
C<delete_all()>を使用してください。 |
added experimental expand me...
|
284 | |
remove DBIx::Custom::Model
|
285 |
$dbi->delete_all(table => 'book'); |
added experimental expand me...
|
286 | |
update pod
|
287 |
=head3 データの選択 C<select()> |
added experimental expand me...
|
288 | |
updated document
|
289 |
行を選択するにはC<select()>を使用します。 |
added experimental expand me...
|
290 | |
remove DBIx::Custom::Model
|
291 |
my $result = $dbi->select(table => 'book'); |
added experimental expand me...
|
292 | |
update pod
|
293 |
次のSQLが実行されます。 |
added experimental expand me...
|
294 | |
updated document
|
295 |
select * from book; |
added experimental expand me...
|
296 | |
update pod
|
297 |
戻り値はL<DBIx::Custom::Result> |
updated document
|
298 |
オブジェクトです。行をフェッチするにはC<fetch()>を使用します。 |
added experimental expand me...
|
299 | |
300 |
while (my $row = $result->fetch) { |
|
301 |
my $title = $row->[0]; |
|
302 |
my $author = $row->[1]; |
|
303 |
} |
|
304 | ||
update pod
|
305 |
L<DBIx::Custom::Result>についてはL<3. 行のフェッチ/"3. 行のフェッチ">を見てください。 |
updated document
|
306 | |
update pod
|
307 |
サンプルを続けます。 |
added experimental expand me...
|
308 | |
309 |
my $result = $dbi->select( |
|
remove DBIx::Custom::Model
|
310 |
table => 'book', |
updated document
|
311 |
column => ['author', 'title'], |
added experimental expand me...
|
312 |
where => {author => 'Ken'} |
313 |
); |
|
314 | ||
update pod
|
315 |
C<column>は列名、C<where>は条件です。 |
316 | ||
317 |
次のSQLが実行されます。 |
|
updated document
|
318 | |
319 |
select author, title from book where author = ?; |
|
added experimental expand me...
|
320 | |
update pod
|
321 |
次のサンプルです。 |
added experimental expand me...
|
322 | |
323 |
my $result = $dbi->select( |
|
DBIx::Custom::Model select()...
|
324 |
table => 'book', |
updated document
|
325 |
where => {book.name => 'Perl'}, |
remove DBIx::Custom::Model
|
326 |
relation => {'book.id' => 'rental.book_id'} |
added experimental expand me...
|
327 |
); |
328 | ||
update pod
|
329 |
C<relation>テーブル間の関係です。これは内部結合です。 |
330 | ||
331 |
次のSQLが実行されます。 |
|
332 | ||
updated document
|
333 |
bookテーブルのid列とrentalテーブルのbook_idが関連付けられます。 |
update pod
|
334 |
次のSQLが実行されます。 |
added experimental expand me...
|
335 | |
updated document
|
336 |
select * from book, rental where book.name = ? and book.id = rental.book_id; |
added experimental expand me...
|
337 | |
update pod
|
338 |
次のサンプルです。 |
added experimental expand me...
|
339 | |
340 |
my $result = $dbi->select( |
|
remove DBIx::Custom::Model
|
341 |
table => 'book', |
added experimental expand me...
|
342 |
where => {author => 'Ken'}, |
updated document
|
343 |
append => 'for update', |
added experimental expand me...
|
344 |
); |
345 | ||
update pod
|
346 |
C<append>はSQLの末尾に追加される文字列です。 |
347 | ||
348 |
次のSQLが実行されます。 |
|
updated document
|
349 | |
updated document
|
350 |
select * book where author = ? for update; |
updated document
|
351 | |
updated document
|
352 |
またC<append>は、C<select>だけでなくC<insert()>、C<update()>、C<update_all()> |
353 |
C<delete()>、C<delete_all()>、C<select()>で使用することもできます。 |
|
updated document
|
354 | |
update pod
|
355 |
C<column>とC<table>を使用する代わりに、C<selection>を使用することも |
356 |
できます。列名とテーブル名をまとめて指定する場合に利用します。 |
|
357 |
|
|
358 |
my $selection = <<"EOS"; |
|
359 |
title, author, company_name |
|
360 |
from book inner join company on book.company_id = company.id |
|
361 |
EOS |
|
362 | ||
363 |
$dbi->select(selection => $selection); |
|
364 | ||
365 |
C<selection>においてはwhere句を利用できないということに注意してください。 |
|
366 |
"inner join"などの句を利用してください。 |
|
367 | ||
update pod
|
368 |
=head3 SQLの実行 C<execute()> |
removed experimental txn_sco...
|
369 | |
update pod
|
370 |
SQLを実行するにはC<execute()>を使用します。 |
removed experimental txn_sco...
|
371 | |
372 |
$dbi->execute("select * from book;"); |
|
373 | ||
update pod
|
374 |
タグを処理してSQLを実行します。 |
removed experimental txn_sco...
|
375 | |
376 |
$dbi->execute( |
|
377 |
"select * from book {= title} and {= author};" |
|
378 |
param => {title => 'Perl', author => 'Ken'} |
|
379 |
); |
|
380 | ||
update pod
|
381 |
次のSQLが実行されます。 |
removed experimental txn_sco...
|
382 | |
383 |
select * from book title = ? and author = ?; |
|
384 | ||
update pod
|
385 |
プレースホルダにtitleとauthorの値が埋め込まれます。 |
removed experimental txn_sco...
|
386 | |
update pod
|
387 |
タグについてはL<5. タグ/"5. タグ">を見てください。 |
removed experimental txn_sco...
|
388 | |
update pod
|
389 |
またC<execute()>のSQLの末尾にはセミコロンを置く必要はありません。 |
removed experimental txn_sco...
|
390 | |
391 |
$dbi->execute('select * from book'); |
|
392 | ||
update pod
|
393 |
=head3 プライマリーキーを利用した行の挿入 C<insert_at()> |
394 | ||
395 |
プライマリーを使用して行を更新するにはC<insert_at()>を使用します。 |
|
396 | ||
397 |
$dbi->insert_at( |
|
398 |
table => 'book', primary_key => ['id'], |
|
399 |
where => ['123'], param => {name => 'Ken'} |
|
400 |
); |
|
401 | ||
402 |
この例ではidの列が123の行に挿入されます。C<where>には、配列の |
|
403 |
リファレンスを渡す必要があることに注意してください。 |
|
404 |
なおC<param>にプライマリーキーが含まれていた場合は、そのキーが削除されます。 |
|
405 | ||
add experimental update_at()...
|
406 |
=head3 プライマリーキーを利用した行の更新 C<update_at()> |
407 | ||
408 |
プライマリーを使用して行を更新するにはC<update_at()>を使用します。 |
|
409 | ||
410 |
$dbi->update_at( |
|
411 |
table => 'book', primary_key => ['id'], |
|
412 |
where => ['123'], param => {name => 'Ken'} |
|
413 |
); |
|
414 | ||
415 |
この例ではidの列が123の行が更新されます。C<where>には、配列の |
|
416 |
リファレンスを渡す必要があることに注意してください。 |
|
update pod
|
417 |
なおC<param>にプライマリーキーが含まれていた場合は、そのキーが削除されます。 |
add experimental update_at()...
|
418 | |
419 |
=head3 プライマリーキーを利用した行の削除 C<delete_at()> |
|
420 | ||
421 |
プライマリーを使用して行を削除するにはC<delete_at()>を使用します。 |
|
422 | ||
423 |
$dbi->delete_at(table => 'book', primary_key => ['id'], where => ['123']); |
|
424 | ||
425 |
この例ではidの列が123の行が削除されます。C<where>には、配列の |
|
426 |
リファレンスを渡す必要があることに注意してください。 |
|
427 | ||
428 |
また下のような記述方法も許されています。 |
|
429 | ||
430 |
$dbi->delete_at(table => 'book', primary_key => ['id'], param => {id => '123'}); |
|
431 | ||
432 |
=head3 プライマリーキーを利用した行の選択 C<select_at()> |
|
433 | ||
434 |
プライマリーを使用して行を選択するにはC<select_at()>を使用します。 |
|
435 | ||
436 |
$dbi->select_at(table => 'book', primary_key => ['id'], where => ['123']); |
|
437 | ||
438 |
この例ではidの列が123の行が選択されます。C<where>には、配列の |
|
439 |
リファレンスを渡す必要があることに注意してください。 |
|
440 | ||
441 |
また下のような記述方法も許されています。 |
|
442 | ||
443 |
$dbi->select_at(table => 'book', primary_key => ['id'], param => {id => '123'}); |
|
444 | ||
updated document
|
445 |
=head2 3. 行のフェッチ |
446 | ||
updated document
|
447 |
C<select()>メソッドの戻り値はL<DBIx::Custom::Result>オブジェクトです。 |
update pod
|
448 |
行をフェッチするためのさまざまなメソッドがあります。 |
updated document
|
449 | |
update pod
|
450 |
=head3 1行づつフェッチ(配列) C<fetch()> |
updated document
|
451 | |
updated document
|
452 |
一行フェッチして配列のリファレンスに格納するにはC<fetch()>を使用します。 |
updated document
|
453 | |
update pod
|
454 |
my $row = $result->fetch; |
455 | ||
456 |
以下のようにすべての行を取得することができます。 |
|
457 | ||
updated document
|
458 |
while (my $row = $result->fetch) { |
updated document
|
459 |
my $title = $row->[0]; |
460 |
my $author = $row->[1]; |
|
updated document
|
461 |
} |
462 | ||
update pod
|
463 |
=head3 最初の行だけフェッチ(配列) C<fetch_first()> |
updated document
|
464 | |
updated document
|
465 |
一行だけフェッチして配列のリファレンスに格納するにはC<fetch_first()> |
466 |
を使用します。 |
|
updated document
|
467 | |
468 |
my $row = $result->fetch_first; |
|
469 | ||
update pod
|
470 |
ステートメントハンドルのC<finish()>が実行される |
471 |
ので残りの行をフェッチできません。 |
|
updated document
|
472 | |
update pod
|
473 |
=head3 複数行を順にフェッチ(配列) C<fetch_multi()> |
updated document
|
474 | |
updated document
|
475 |
複数行をフェッチして配列のリファレンスを要素に持つ |
476 |
配列のリファレンスに格納するにはC<fetch_multi()>を使用します。 |
|
updated document
|
477 | |
updated document
|
478 |
while (my $rows = $result->fetch_multi(2)) { |
479 |
my $title0 = $rows->[0][0]; |
|
480 |
my $author0 = $rows->[0][1]; |
|
481 |
|
|
482 |
my $title1 = $rows->[1][0]; |
|
483 |
my $author1 = $rows->[1][1]; |
|
updated document
|
484 |
} |
485 | ||
update pod
|
486 |
取り出したい行数を引数に指定します。 |
updated document
|
487 | |
update pod
|
488 |
次のようなデータを取得できます。 |
updated document
|
489 | |
490 |
[ |
|
491 |
['Perl', 'Ken'], |
|
492 |
['Ruby', 'Mark'] |
|
493 |
] |
|
494 | ||
update pod
|
495 |
=head3 すべての行をフェッチ(配列) C<fetch_all> |
updated document
|
496 | |
updated document
|
497 |
すべての行をフェッチして配列のリファレンスを要素に持つ |
498 |
配列のリファレンスに格納するにはC<fetch_all()>を使用します。 |
|
updated document
|
499 | |
500 |
my $rows = $result->fetch_all; |
|
501 | ||
updated document
|
502 |
すべての行を格納した次のようなデータを取得できます。 |
503 | ||
504 |
[ |
|
505 |
['Perl', 'Ken'], |
|
506 |
['Ruby', 'Mark'] |
|
507 |
] |
|
508 | ||
update pod
|
509 |
=head3 1行づつフェッチ(ハッシュ) C<fetch_hash()> |
updated document
|
510 | |
updated document
|
511 |
一行フェッチしてハッシュのリファレンスに格納するにはC<fetch_hash()>を使用します。 |
updated document
|
512 | |
513 |
while (my $row = $result->fetch_hash) { |
|
514 |
my $title = $row->{title}; |
|
515 |
my $author = $row->{author}; |
|
516 |
} |
|
517 | ||
update pod
|
518 |
=head3 最初の行だけフェッチ(ハッシュ) C<fetch_hash_first()> |
updated document
|
519 | |
updated document
|
520 |
一行だけフェッチしてハッシュのリファレンスに格納するには |
521 |
C<fetch_hash_first()>を使用します。 |
|
updated document
|
522 | |
523 |
my $row = $result->fetch_hash_first; |
|
524 | ||
update pod
|
525 |
ステートメントハンドルのC<finish()>が実行される |
526 |
ので残りの行をフェッチできません。 |
|
updated document
|
527 | |
update pod
|
528 |
=head3 複数行をフェッチ(ハッシュ) C<fetch_hash_multi()> |
updated document
|
529 | |
updated document
|
530 |
複数行をフェッチしてハッシュのリファレンスを要素に持つ |
531 |
配列のリファレンスに格納するにはC<fetch_hash_multi()> |
|
532 |
を使用します。 |
|
updated document
|
533 | |
534 |
while (my $rows = $result->fetch_hash_multi(5)) { |
|
updated document
|
535 |
my $title0 = $rows->[0]{title}; |
536 |
my $author0 = $rows->[0]{author}; |
|
537 |
my $title1 = $rows->[1]{title}; |
|
538 |
my $author1 = $rows->[1]{author}; |
|
updated document
|
539 |
} |
540 | ||
updated document
|
541 |
引数には取り出したい行数を指定します。 |
542 | ||
update pod
|
543 |
次のようなデータを取得できます。 |
updated document
|
544 | |
545 |
[ |
|
546 |
{title => 'Perl', author => 'Ken'}, |
|
547 |
{title => 'Ruby', author => 'Mark'} |
|
548 |
] |
|
549 | ||
update pod
|
550 |
=head3 すべての行をフェッチ(ハッシュ) C<fetch_hash_all()> |
updated document
|
551 | |
updated document
|
552 |
すべての行をフェッチしてハッシュのリファレンスを要素に持つ |
553 |
配列のリファレンスに格納するにはC<fetch_hash_all()> |
|
554 |
を使用します。 |
|
updated document
|
555 | |
556 |
my $rows = $result->fetch_hash_all; |
|
557 | ||
update pod
|
558 |
次のようなデータを取得できます。 |
updated document
|
559 | |
560 |
[ |
|
561 |
{title => 'Perl', author => 'Ken'}, |
|
562 |
{title => 'Ruby', author => 'Mark'} |
|
563 |
] |
|
564 | ||
update pod
|
565 |
=head3 ステートメントハンドル C<sth()> |
updated document
|
566 | |
update pod
|
567 |
ステートメントハンドル取得したい場合は |
568 |
<sth()>を使用します。 |
|
updated document
|
569 | |
570 |
my $sth = $result->sth; |
|
571 | ||
renamed dbi_options to dbi_o...
|
572 |
=head2 4. フィルタリング |
573 | ||
update pod
|
574 |
L<DBIx::Custom>は値のフィルタリング機能を提供します。 |
575 | ||
576 |
たとえば、データをデータベースに登録するときは |
|
577 |
L<Time::Piece>オブジェクトからデータベースの日付のフォーマットに、 |
|
578 |
データベースからデータを取得するときは、 |
|
579 |
データベースの日付のフォーマットからL<Time::Piece>オブジェクト |
|
580 |
に変換を行いたいと思うことでしょう。 |
|
renamed dbi_options to dbi_o...
|
581 | |
update pod
|
582 |
=head3 フィルタの登録 C<register_filter()> |
renamed dbi_options to dbi_o...
|
583 | |
584 |
フィルタを登録するにはC<register_filter()>を使用します。 |
|
585 | ||
586 |
$dbi->register_filter( |
|
587 |
# Time::Piece object to DATE format |
|
588 |
tp_to_date => sub { |
|
589 |
my $date = shift; |
|
590 | ||
591 |
return '0000-00-00' unless $tp; |
|
592 |
return $tp->strftime('%Y-%m-%d'); |
|
593 |
}, |
|
594 |
|
|
595 |
# DATE to Time::Piece object |
|
596 |
date_to_tp => sub { |
|
597 |
my $date = shift; |
|
598 | ||
599 |
return if $date eq '0000-00-00'; |
|
600 |
return Time::Piece->strptime($date, '%Y-%m-%d'); |
|
601 |
}, |
|
602 |
); |
|
603 | ||
604 |
登録したフィルタはC<apply_filter()>などで利用することができます。 |
|
605 | ||
update pod
|
606 |
=head3 フィルタの適用 C<apply_filter()> |
renamed dbi_options to dbi_o...
|
607 | |
608 |
作成したフィルタを適用するには、C<apply_filter()>を使用します。 |
|
609 | ||
610 |
$dbi->apply_filter('book', |
|
611 |
issue_date => {out => 'tp_to_date', in => 'date_to_tp'}, |
|
612 |
first_issue_date => {out => 'tp_to_date', in => 'date_to_tp'} |
|
613 |
); |
|
614 | ||
update pod
|
615 |
第一引数はテーブル名です。第1引数より後の引数は、列名とフィルタルールのペアを記述します。 |
renamed dbi_options to dbi_o...
|
616 |
フィルタルールのoutには、データベースにデータを送信するときに適用するフィルタを、 |
617 |
フィルタルールのinには、データベースからデータを取得するときに適用するフィルタを |
|
update pod
|
618 |
記述します。 |
619 | ||
620 |
フィルタとしてコードリファレンスを |
|
renamed dbi_options to dbi_o...
|
621 |
指定することもできます。 |
622 | ||
623 |
issue_date => {out => sub { ... }, in => sub { ... }} |
|
624 | ||
625 |
適用されたフィルタはC<insert()>、C<update()>、C<update_all()>、C<delete()>、 |
|
626 |
C<delete_all()>、C<select()>で有効になります。 |
|
627 | ||
628 |
my $tp = Time::Piece->strptime('2010/10/14', '%Y/%m/%d'); |
|
629 |
my $result = $dbi->select(table => 'book', where => {issu_date => $tp}); |
|
630 | ||
631 |
データベースにデータが送信されるときに、L<Time::Piece>オブジェクトは |
|
632 |
データベースの日付のフォーマット「2010-10-14」に変換されます。 |
|
633 | ||
update pod
|
634 |
データをフェッチするときには、データベースの日付のフォーマットは |
635 |
L<Time::Piece>オブジェクトに変換されます。 |
|
renamed dbi_options to dbi_o...
|
636 | |
637 |
my $row = $resutl->fetch_hash_first; |
|
638 |
my $tp = $row->{issue_date}; |
|
639 | ||
update pod
|
640 |
テーブル名を含む列名を使用することもできます。 |
removed experimental expand
|
641 | |
642 |
$dbi->select( |
|
643 |
table => 'book', |
|
644 |
where => {'book.title' => 'Perl', 'book.author' => 'Ken'} |
|
645 |
); |
|
646 | ||
update pod
|
647 |
フェッチを行う場合に"TABLE__COLUMN"という名前を使用した場合もフィルタは |
648 |
有効になります。 |
|
649 | ||
650 |
my $result = $dbi->execute( |
|
651 |
"select issue_date as book__issue_date from book"); |
|
652 | ||
653 |
C<in>フィルタの後に実行されるC<end>フィルタを適用することもできます。 |
|
654 | ||
655 |
$dbi->apply_filter('book', |
|
656 |
issue_date => {out => 'tp_to_date', in => 'date_to_tp', |
|
657 |
end => 'tp_to_displaydate'}, |
|
658 |
); |
|
659 | ||
update pod
|
660 |
=head3 個別のフィルタ C<filter> |
renamed dbi_options to dbi_o...
|
661 | |
removed experimental txn_sco...
|
662 |
個別にフィルタを適用することもできます。 |
renamed dbi_options to dbi_o...
|
663 |
個別のフィルタはC<apply_filter()>で適用したフィルタを上書きます。 |
removed experimental txn_sco...
|
664 | |
update pod
|
665 |
データを送信する場合に個別のフィルタを適用するには、C<filter>オプションを使用します。 |
666 |
このオプションはC<insert()>、C<update()>、 |
|
removed experimental txn_sco...
|
667 |
C<update_all()>、C<delete()>、C<delete_all()>、C<select()>、C<execute()> |
668 |
で使用することができます。 |
|
renamed dbi_options to dbi_o...
|
669 | |
removed experimental txn_sco...
|
670 |
$dbi->insert( |
671 |
table => 'book', |
|
672 |
param => {issue_date => $tp, first_issue_date => $tp}, |
|
673 |
filter => {issue_date => 'tp_to_date', first_issue_date => 'tp_to_date'} |
|
674 |
); |
|
675 | ||
676 |
C<execute()>の例を示します。 |
|
677 | ||
678 |
my $sql = <<"EOS"; |
|
679 |
select YEAR(issue_date) as issue_year |
|
680 |
from book |
|
681 |
where YEAR(issue_date) = {? issue_year} |
|
682 |
EOS |
|
683 |
|
|
684 |
my $result = $dbi->execute( |
|
685 |
$sql, |
|
686 |
param => {issue_year => '2010'}, |
|
687 |
filter => {issue_year => 'tp_to_year'} |
|
688 |
); |
|
689 | ||
update pod
|
690 |
行をフェッチするときにも個別のフィルタを適用することができます。 |
691 |
C<DBIx::Custom::Result>のC<filter()>を使用します。 |
|
renamed dbi_options to dbi_o...
|
692 | |
removed experimental txn_sco...
|
693 |
$result->filter(issue_year => 'year_to_tp'); |
694 | ||
selection can contain where ...
|
695 |
C<remove_filter()>でフィルタを取り除くこともできます。 |
696 | ||
697 |
$result->remove_filter |
|
698 | ||
update pod
|
699 |
=head3 最後のフィルタリング : C<end_filter()> |
removed experimental txn_sco...
|
700 | |
update pod
|
701 |
最後にもうひとつフィルタを追加することができます。 |
702 |
最終的な出力を作成する場合に便利です。 |
|
703 |
最後のフィルタを登録するにはC<end_filter()>を使用します。 |
|
removed experimental txn_sco...
|
704 | |
705 |
$result->end_filter(issue_date => sub { |
|
706 |
my $tp = shift; |
|
707 |
|
|
708 |
return '' unless $tp; |
|
709 |
return $tp->strftime('%Y/%m/%d %h:%m:%s (%a)'); |
|
710 |
}); |
|
711 | ||
update pod
|
712 |
この例ではL<Time::Piece>オブジェクトを読みやすい書式に変換しています。 |
removed experimental txn_sco...
|
713 | |
added experimental DBIx::Cus...
|
714 |
最後のフィルタリングをC<remove_filter()>で取り除くこともできます。 |
715 | ||
716 |
$result->remove_end_filter; |
|
717 | ||
update pod
|
718 |
=head3 フィルタの適用の自動化 C<each_column()> |
removed experimental txn_sco...
|
719 | |
update pod
|
720 |
日付型の列は自動的にフィルタを適用できると便利です。 |
721 |
列のすべての情報を処理するためのC<each_column()>を利用することができます。 |
|
removed experimental txn_sco...
|
722 | |
723 |
$dbi->each_column( |
|
724 |
sub { |
|
725 |
my ($self, $table, $column, $info) = @_; |
|
726 |
|
|
727 |
my $type = $info->{TYPE_NAME}; |
|
728 |
|
|
729 |
my $filter = $type eq 'DATE' ? {out => 'tp_to_date', in => 'date_to_tp'} |
|
730 |
: $type eq 'DATETIME' ? {out => 'tp_to_datetime', in => 'datetime_to_tp'} |
|
731 |
: undef; |
|
732 |
|
|
733 |
$self->apply_filter($table, $column, $filter) |
|
734 |
if $filter; |
|
735 |
} |
|
736 |
); |
|
renamed dbi_options to dbi_o...
|
737 | |
removed experimental txn_sco...
|
738 |
each_columnはコールバックを受け取ります。コールバックの引数は |
update pod
|
739 |
L<DBIx::Custom>オブジェクト、テーブル名、列名、列の情報です。 |
removed experimental txn_sco...
|
740 |
列の型名の情報をもとに自動的に、フィルタを適用しています。 |
741 | ||
renamed dbi_options to dbi_o...
|
742 |
=head2 5. タグ |
updated document
|
743 | |
update pod
|
744 |
=head3 タグの基本 |
updated document
|
745 | |
update pod
|
746 |
SQLの中にタグを埋め込むことができます。 |
updated document
|
747 | |
update pod
|
748 |
select * from book where {= title} and {like author}; |
updated document
|
749 | |
update pod
|
750 |
{= title}と{like author}の部分がタグです。タグは次のような形式 |
751 |
を持ちます。 |
|
updated document
|
752 | |
update pod
|
753 |
{タグ名 引数1 引数2 ...} |
754 |
|
|
755 |
タグはC<{>で始まり、C<}>で終わります。最初のC<{>とタグ名の間 |
|
756 |
には空白を挿入しないよう注意してください。 |
|
updated document
|
757 | |
update pod
|
758 |
C<{>とC<}>は予約語になっています。 |
759 |
もし利用したい場合は\でエスケープを行う必要があります。 |
|
updated document
|
760 | |
update pod
|
761 |
select from book \\{ ... \\} |
762 | ||
763 |
C<\>自体がPerlのエスケープ文字ですので、 |
|
update pod
|
764 |
C<\>は二つ必要になります。 |
update pod
|
765 | |
update pod
|
766 |
タグはSQLが実行される前に展開されます。 |
update pod
|
767 | |
768 |
select * from book where title = ? and author like ?; |
|
updated document
|
769 | |
update pod
|
770 |
タグを含むSQLを実行するにはC<execute()>を使用します。 |
updated document
|
771 | |
update pod
|
772 |
my $sql = "select * from book where {= author} and {like title};" |
773 |
$dbi->execute($sql, param => {title => 'Perl', author => '%Ken%'}); |
|
updated document
|
774 | |
update pod
|
775 |
C<param>オプションを使って、プレースホルダに埋め込みたい値を |
776 |
ハッシュリファレンスで指定することができます。 |
|
updated document
|
777 | |
update pod
|
778 |
C<execute()>においてもC<filter>を指定することができます。 |
update pod
|
779 | |
780 |
$dbi->execute($sql, param => {title => 'Perl', author => '%Ken%'} |
|
781 |
filter => {title => 'to_something'); |
|
782 | ||
update pod
|
783 |
C<execute>ではC<apply_filter()>で適用されたフィルタ |
784 |
は有効ではないということに注意してください。 |
|
update pod
|
785 |
C<apply_filter()>で適用されたフィルタを有効にするには、 |
update pod
|
786 |
C<table>タグを利用します。 |
update pod
|
787 | |
update pod
|
788 |
my $sql = "select * from {table book} where {= author} and {like title};" |
update pod
|
789 | |
update pod
|
790 |
=head3 タグ一覧 |
update pod
|
791 | |
update pod
|
792 |
=head4 C<table> |
793 | ||
794 |
{table NAME} -> NAME |
|
795 | ||
796 |
これはSQLの中でテーブル名を指定する場合に利用します。 |
|
797 |
テーブル名を指定することによって、C<apply_filter()> |
|
798 |
によるフィルタリングが有効になります。 |
|
799 | ||
update pod
|
800 |
=head4 C<?> |
update pod
|
801 | |
802 |
{? NAME} -> ? |
|
803 | ||
update pod
|
804 |
=head4 C<=> |
update pod
|
805 | |
806 |
{= NAME} -> NAME = ? |
|
807 | ||
update pod
|
808 |
=head4 C<E<lt>E<gt>> |
update pod
|
809 | |
810 |
{<> NAME} -> NAME <> ? |
|
811 | ||
update pod
|
812 |
=head4 C<E<lt>> |
update pod
|
813 | |
814 |
{< NAME} -> NAME < ? |
|
815 | ||
update pod
|
816 |
=head4 C<E<gt>> |
update pod
|
817 | |
818 |
{> NAME} -> NAME > ? |
|
819 | ||
update pod
|
820 |
=head4 C<E<gt>=> |
update pod
|
821 | |
822 |
{>= NAME} -> NAME >= ? |
|
823 | ||
update pod
|
824 |
=head4 C<E<lt>=> |
update pod
|
825 | |
826 |
{<= NAME} -> NAME <= ? |
|
827 | ||
update pod
|
828 |
=head4 C<like> |
update pod
|
829 | |
830 |
{like NAME} -> NAME like ? |
|
831 | ||
update pod
|
832 |
=head4 C<in> |
update pod
|
833 | |
834 |
{in NAME COUNT} -> NAME in [?, ?, ..] |
|
835 | ||
update pod
|
836 |
=head4 C<insert_param> |
update pod
|
837 | |
updated document
|
838 |
{insert_param NAME1 NAME2} -> (NAME1, NAME2) values (?, ?) |
update pod
|
839 | |
update pod
|
840 |
=head4 C<update_param> |
update pod
|
841 | |
updated document
|
842 |
{update_param NAME1 NAME2} -> set NAME1 = ?, NAME2 = ? |
843 | ||
update pod
|
844 |
=head3 同名の列の扱い |
updated document
|
845 | |
update pod
|
846 |
同名の列を含むタグがある場合でも大丈夫です。 |
847 |
二つの日付で比較しなければならない場合を |
|
update pod
|
848 |
考えて見ましょう。 |
updated document
|
849 | |
update pod
|
850 |
my $sql = "select * from table where {> date} and {< date};"; |
updated document
|
851 | |
update pod
|
852 |
このような場合はパラメータの値を配列のリファレンスで指定します。 |
removed experimental txn_sco...
|
853 | |
update pod
|
854 |
my $dbi->execute($sql, param => {date => ['2010-10-01', '2012-02-10']}); |
855 | ||
update pod
|
856 |
=head3 タグの登録 C<register_tag()> |
update pod
|
857 | |
update pod
|
858 |
独自のタグを登録することができます。 |
update pod
|
859 |
タグを追加するにはC<register_tag()>を使用します。 |
removed experimental txn_sco...
|
860 | |
861 |
$dbi->register_tag( |
|
update pod
|
862 |
'=' => sub { |
863 |
my $column = shift; |
|
864 |
|
|
865 |
return ["$column = ?", [$column]]; |
|
removed experimental txn_sco...
|
866 |
} |
867 |
); |
|
868 | ||
update pod
|
869 |
ここではデフォルトのC<=>タグがどのように実装されているかを示しています。 |
update pod
|
870 |
タグの形式は次のようになっています。 |
update pod
|
871 | |
update pod
|
872 |
{タグ名 引数1 引数2 ...} |
update pod
|
873 | |
874 |
C<=>タグの場合は |
|
875 | ||
876 |
{= title} |
|
877 | ||
878 |
という形式ですから、サブルーチンにはtitleというひとつの列名がわたってきます。 |
|
879 | ||
880 |
サブルーチンの戻り値には次の形式の配列のリファレンスを返す必要があります。 |
|
881 | ||
882 |
[ |
|
883 |
展開後の文字列, |
|
884 |
[プレースホルダに埋め込みに利用する列名1, 列名2, ...] |
|
885 |
] |
|
886 | ||
887 |
一つ目の要素は展開後の文字列です。この例では |
|
888 | ||
889 |
'title = ?' |
|
890 | ||
891 |
を返す必要があります。 |
|
892 | ||
893 |
二つ目の要素はプレースホルダに埋め込みに利用する列名を含む配列の |
|
894 |
リファレンスです。今回の例では |
|
895 | ||
896 |
['title'] |
|
897 | ||
898 |
を返す必要があります。複数のプレースホルダを含む場合は、この部分が |
|
update pod
|
899 |
複数になります。 |
update pod
|
900 | |
901 |
上記を合わせると |
|
902 | ||
903 |
['title = ?', ['title']] |
|
904 |
|
|
905 |
を返す必要があるということです。 |
|
906 | ||
added experimental not_exist...
|
907 |
タグの実装の他のサンプルはL<DBIx::Custom::Tag>のソースコード |
908 |
をご覧になってみてください。 |
|
909 | ||
removed experimental txn_sco...
|
910 |
=head2 6. Where句の動的な生成 |
911 | ||
added experimental not_exist...
|
912 |
=head3 Where句の動的な生成 where() |
913 | ||
914 |
複数の検索条件を指定して、検索を行いたい場合があります。 |
|
915 |
次の3つのケースのwhere句を考えてみましょう。 |
|
916 | ||
917 |
titleの値だけで検索したい場合 |
|
918 | ||
919 |
where {= title} |
|
920 | ||
921 |
authorの値だけで検索したい場合 |
|
922 | ||
923 |
where {= author} |
|
924 | ||
925 |
titleとauthorの両方の値で検索したい場合 |
|
926 | ||
927 |
where {= title} and {=author} |
|
928 | ||
929 |
L<DBIx::Custom>では動的なWhere句の生成をサポートしています。 |
|
930 |
まずC<where()>でL<DBIx::Custom::Where>オブジェクトを生成します。 |
|
931 | ||
932 |
my $where = $dbi->where; |
|
933 | ||
934 |
次にC<clause()>を使用してwhere句を記述します。 |
|
935 | ||
936 |
$where->clause( |
|
937 |
['and', '{= title'}, '{= author}'] |
|
938 |
); |
|
939 | ||
940 |
clauseの指定方法は次のようになります。 |
|
941 | ||
942 |
['or' あるいは 'and', タグ1, タグ2, タグ3] |
|
943 | ||
944 |
第一引数にはorあるいはandを指定します。第二引数以降には |
|
945 |
検索条件をタグを使って記述します。 |
|
946 | ||
947 |
C<clause>の指定は入れ子にすることもでき、さらに複雑な条件 |
|
948 |
を記述することもできます。 |
|
949 | ||
950 |
['and', |
|
951 |
'{= title}', |
|
952 |
['or', '{= author}', '{like date}'] |
|
953 |
] |
|
954 | ||
update pod
|
955 |
これは "{=title} and ( {=author} or {like date} )" 意味しています。 |
956 | ||
957 |
C<clause>を設定した後にC<param>にパラメータを指定します。 |
|
added experimental not_exist...
|
958 |
|
update pod
|
959 |
$where->param({title => 'Perl'}); |
added experimental not_exist...
|
960 | |
961 |
この例ではtitleだけがパラメータに含まれています。 |
|
962 | ||
963 |
この後C<to_string()>を実行すると$paramに含まれるパラメータを満たす |
|
964 |
where句を生成することができます。 |
|
965 | ||
966 |
my $where_clause = $where->to_string; |
|
967 | ||
968 |
パラメータはtitleだけですので、次のようなwhere句が生成されます。 |
|
969 | ||
970 |
where {= title} |
|
971 | ||
cleanup
|
972 |
またL<DBIx::Custom>は文字列の評価をオーバーロードして、C<to_string()> |
added experimental not_exist...
|
973 |
を呼び出すようにしていますので、次のようにしてwhere句を生成することも |
974 |
できます。 |
|
975 | ||
976 |
my $where_clause = "$where"; |
|
977 | ||
978 |
これはSQLの中にwhere句を埋め込むときにとても役立つ機能です。 |
|
979 | ||
make delete() using where ob...
|
980 |
=head3 同一の列名を含む場合 |
added experimental not_exist...
|
981 | |
make delete() using where ob...
|
982 |
タグの中に同一の名前を持つものが存在した場合でも動的に |
983 |
where句を作成することができます。 |
|
added experimental not_exist...
|
984 | |
make delete() using where ob...
|
985 |
たとえば、パラメータとして開始日付と終了日付を受け取ったことを |
986 |
考えてみてください。 |
|
added experimental not_exist...
|
987 | |
make delete() using where ob...
|
988 |
my $param = {start_date => '2010-11-15', end_date => '2011-11-21'}; |
added experimental not_exist...
|
989 | |
update pod
|
990 |
この場合はパラメータの値を配列のリファレンスにしてください。 |
added experimental not_exist...
|
991 | |
make delete() using where ob...
|
992 |
my $p = {date => ['2010-11-15', '2011-11-21']}; |
added experimental not_exist...
|
993 | |
make delete() using where ob...
|
994 |
同名の列を含むタグに順番に埋め込むことができます。 |
added experimental not_exist...
|
995 | |
make delete() using where ob...
|
996 |
$where->clause( |
997 |
['and', '{> date}', '{< date}'] |
|
998 |
); |
|
999 |
$where->param($p); |
|
1000 | ||
1001 |
また開始日付が存在しない場合は次のようなデータを作成します。 |
|
1002 | ||
1003 |
my $p = {date => [$dbi->not_exists, '2011-11-21']}; |
|
1004 | ||
update pod
|
1005 |
C<not_exists()>でDBIx::Custom::NotExistsオブジェクトを |
make delete() using where ob...
|
1006 |
取得できます。これは対応する値が存在しないことを示すためのものです。 |
1007 | ||
1008 |
また終了日付が存在しない場合は次のようなデータを作成します。 |
|
1009 | ||
1010 |
my $p = {date => ['2010-11-15']}; |
|
added experimental not_exist...
|
1011 | |
make delete() using where ob...
|
1012 |
どちらも存在しない場合は次のようなデータを作成します。 |
1013 | ||
1014 |
my $p = {date => []}; |
|
1015 | ||
1016 |
少し難しいので一番簡単に作成できるロジックを示しておきます。 |
|
1017 | ||
1018 |
my @date; |
|
1019 |
push @date, exists $param->{start_date} ? $param->{start_date} |
|
1020 |
: $dbi->not_exists; |
|
1021 |
push @date, $param->{end_date} if exists $param->{end_date}; |
|
1022 |
my $p = {date => \@date}; |
|
1023 | ||
1024 |
=head3 C<select()>との連携 |
|
1025 | ||
update pod
|
1026 |
L<DBIx::Custom::Where>オブジェクトは |
1027 |
C<select()>のC<where>に直接渡すことが |
|
make delete() using where ob...
|
1028 |
できます。 |
1029 |
|
|
1030 |
my $where = $dbi->where; |
|
1031 |
$where->clause(...); |
|
1032 |
$where->param($param); |
|
1033 |
my $result = $dbi->select(table => 'book', where => $where); |
|
1034 | ||
update pod
|
1035 |
あるいはC<update()>、C<delete()>のwhereに指定することも可能です。 |
make delete() using where ob...
|
1036 | |
1037 |
=head3 C<execute()>との連携 |
|
1038 | ||
1039 |
C<execute()>との連携です。SQLを作成するときに埋め込むことができます。 |
|
1040 | ||
1041 | ||
1042 |
my $where = $dbi->where; |
|
1043 |
$where->clause(...); |
|
1044 |
$where->param($param); |
|
1045 | ||
update pod
|
1046 |
my $sql = <<"EOS"; |
make delete() using where ob...
|
1047 |
select * from book; |
1048 |
$where |
|
1049 |
EOS |
|
added experimental not_exist...
|
1050 | |
make delete() using where ob...
|
1051 |
$dbi->execute($sql, param => $param); |
added experimental not_exist...
|
1052 | |
add feture. all model class ...
|
1053 |
=head2 7. モデル |
update pod
|
1054 | |
add feture. all model class ...
|
1055 |
=head3 モデル |
update pod
|
1056 | |
removed experimental base_ta...
|
1057 |
ソースコードの見通しをよくするために、 |
add feture. all model class ...
|
1058 |
L<DBIx::Custom::Model>を継承してモデルを作成することができます。 |
update pod
|
1059 | |
add experimental DBIx::Custo...
|
1060 |
まず最初にモデルの元になるクラスを<DBIx::Custom::Model> |
1061 |
を継承して作成します。 |
|
update pod
|
1062 | |
add experimental DBIx::Custo...
|
1063 |
package MyModel; |
1064 |
|
|
1065 |
use base 'DBIx::Custom::Model'; |
|
update pod
|
1066 | |
add experimental DBIx::Custo...
|
1067 |
次に個々のモデルクラスを作成します。 |
update pod
|
1068 | |
add experimental DBIx::Custo...
|
1069 |
MyModel::book |
update pod
|
1070 | |
add experimental DBIx::Custo...
|
1071 |
package MyModel::book; |
1072 |
|
|
1073 |
use base 'MyModel'; |
|
1074 |
|
|
1075 |
sub insert { ... } |
|
1076 |
sub list { ... } |
|
update pod
|
1077 | |
add experimental DBIx::Custo...
|
1078 |
MyModel::company |
add feture. all model class ...
|
1079 | |
add experimental DBIx::Custo...
|
1080 |
package MyModel::company; |
add feture. all model class ...
|
1081 |
|
add experimental DBIx::Custo...
|
1082 |
use base 'MyModel'; |
1083 |
|
|
1084 |
sub insert { ... } |
|
1085 |
sub list { ... } |
|
add feture. all model class ...
|
1086 | |
add experimental DBIx::Custo...
|
1087 |
このように作成したモジュールを次のように配置してください。 |
add feture. all model class ...
|
1088 | |
1089 |
MyModel.pm |
|
1090 |
MyModel / book.pm |
|
1091 |
/ company.pm |
|
add experimental DBIx::Custo...
|
1092 | |
1093 |
このように作成したモデルはC<include_model()>で取り込むことができます。 |
|
1094 | ||
1095 |
$dbi->include_model('MyModel'); |
|
1096 | ||
1097 |
第一引数は、モデルの名前空間になります。 |
|
1098 | ||
add feture. all model class ...
|
1099 |
モデルは次のように利用することができます。 |
1100 | ||
1101 |
my $result = $dbi->model('book')->list; |
|
1102 | ||
1103 |
モデルではテーブル名を指定することなしに |
|
removed experimental base_ta...
|
1104 |
C<insert()>, C<update()>, C<update_all()>, |
1105 |
C<delete()>, C<delete_all()>, C<select()>などのメソッドを |
|
add feture. all model class ...
|
1106 |
利用できます。 |
update pod
|
1107 | |
add feture. all model class ...
|
1108 |
$dbi->model('book')->insert(param => $param); |
update pod
|
1109 | |
add experimental DBIx::Custo...
|
1110 |
またモデルクラスでC<primary_key>の設定がなされていれば、 |
1111 |
プライマリキーを指定することなしに |
|
update pod
|
1112 |
C<insert_at>, C<update_at()>, C<delete_at()>, C<select_at()>のメソッドを |
add experimental DBIx::Custo...
|
1113 |
利用できます。 |
1114 | ||
1115 |
$dbi->model('book')->delete_at(where => 123); |
|
1116 | ||
add feture. all model class ...
|
1117 |
モデルはL<DBIx::Custom::Model>です。 |
update pod
|
1118 | |
add feture. all model class ...
|
1119 |
必要であれば、C<table()>でテーブル名を取得することができます。 |
update pod
|
1120 | |
add feture. all model class ...
|
1121 |
my $table = $model->table; |
removed experimental base_ta...
|
1122 | |
1123 |
L<DBIx::Custom>オブジェクトを取得することもできます。 |
|
1124 | ||
add feture. all model class ...
|
1125 |
my $dbi = $model->dbi; |
removed experimental base_ta...
|
1126 | |
1127 |
L<DBIx::Custom>とL<DBI>のすべてのメソッドを呼び出すこともできます。 |
|
update pod
|
1128 | |
update pod
|
1129 |
# DBIx::Custom method |
add feture. all model class ...
|
1130 |
$model->execute($sql); |
update pod
|
1131 |
|
1132 |
# DBI method |
|
add feture. all model class ...
|
1133 |
$model->begin_work; |
1134 |
$model->commit; |
|
update pod
|
1135 | |
add models() attribute
|
1136 |
すべてのモデル名を取得したい場合はC<models()>のキーを取得してください。 |
1137 | ||
1138 |
my @models = keys %{$self->models}; |
|
1139 | ||
add DBIx::Custom::Model fore...
|
1140 |
モデルにはプライマリーキーを設定することもできます。 |
1141 | ||
1142 |
$model->primary_key(['id', 'number_id']); |
|
1143 | ||
update pod
|
1144 |
ここで設定したプライマリーキーはC<insert_at>, C<update_at()>, C<delete_at()>, |
add DBIx::Custom::Model fore...
|
1145 |
C<select_at()>で利用されます。 |
1146 | ||
add experimental DBIx::Custo...
|
1147 |
C<filter>でC<apply_filter()>で適用されるフィルタを定義しておくこともできます。 |
1148 | ||
1149 |
$model->filter({ |
|
1150 |
title => {out => ..., in => ..., end => ...}, |
|
1151 |
author => {out => ..., in => ..., end => ...} |
|
1152 |
}); |
|
1153 | ||
1154 |
このフィルタはC<include_model()>を呼び出したときに自動的に適用されます。 |
|
1155 | ||
add DBIx::Custom::Model colu...
|
1156 |
モデルには列名を設定することもできます。 |
1157 | ||
1158 |
$model->columns(['id', 'number_id']); |
|
1159 | ||
add experimental setup_model...
|
1160 |
列名はC<setup_model()>で自動的に設定することができます。 |
1161 |
このメソッドはC<include_model()>の後で呼び出してください。 |
|
1162 | ||
1163 |
$dbi->setup_model; |
|
1164 | ||
cleanup
|
1165 |
モデルにはリレーションを設定することもできます。 |
1166 | ||
1167 |
$model->relation({'book.company_id' => 'company.id'}); |
|
1168 | ||
1169 |
ここで設定したリレーションはC<select()>, C<select_at()>で利用されます。 |
|
1170 | ||
add experimental DBIx::Custo...
|
1171 | |
add experimental DBIx::Custo...
|
1172 |
=head2 クラス名、モデル名、テーブル名 |
1173 | ||
1174 |
クラス名とモデル名とテーブル名の関係について書いておきます。 |
|
1175 |
通常はクラス名がモデル名に利用され、テーブル名にはモデル名が利用されます。 |
|
1176 | ||
1177 |
クラス名 モデル名 テーブル名 |
|
1178 |
book (クラス名) -> book (モデル名) -> book |
|
1179 | ||
1180 |
モデル名を変更することもできます。 |
|
1181 | ||
1182 |
package MyModel::book; |
|
1183 |
|
|
add experimental DBIx::Custo...
|
1184 |
use base 'MyModel'; |
1185 |
|
|
add experimental DBIx::Custo...
|
1186 |
__PACAKGE__->attr(name => 'book_model'); |
1187 | ||
1188 |
クラス名 モデル名 テーブル名 |
|
1189 |
book book_model (モデル名) -> book_model |
|
1190 | ||
1191 |
モデル名というのは、L<DBIx::Custom>のL<model()>で利用される名前です。 |
|
1192 | ||
1193 |
$dbi->model('book_model'); |
|
1194 | ||
1195 |
テーブル名を変更することもできます。 |
|
1196 | ||
1197 |
package MyModel::book; |
|
add experimental DBIx::Custo...
|
1198 | |
1199 |
use base 'MyModel'; |
|
add experimental DBIx::Custo...
|
1200 |
|
1201 |
__PACAKGE__->attr(table => 'book_table'); |
|
add experimental DBIx::Custo...
|
1202 |
|
add experimental DBIx::Custo...
|
1203 |
クラス名 モデル名 テーブル名 |
1204 |
book (クラス名) -> book book_table |
|
1205 | ||
1206 |
テーブル名というのは、実際にアクセスされるテーブルです。 |
|
1207 | ||
1208 |
$dbi->model('book')->insert(...); # book_tableにアクセス |
|
1209 | ||
add experimental DBIx::Custo...
|
1210 |
=head2 列名の自動生成 : column_clause() |
1211 | ||
1212 |
列名の節を自動生成するにはC<column_clause()>を使用します。 |
|
1213 |
C<table>とC<columns>の値が利用されます。 |
|
1214 | ||
1215 |
my $column_clause = $model->column_clause; |
|
1216 | ||
1217 |
C<table>の値が'book'、C<column>の値が['id', 'name']で |
|
1218 |
あった場合は次のような列名の節が生成されます。 |
|
1219 | ||
1220 |
book.id as id, book.name as name |
|
1221 | ||
1222 |
このように列名の節を生成するのは、列名のあいまいさをなくすためです。 |
|
1223 | ||
1224 |
不必要な列がある場合はC<remove>オプションで指定することができます。 |
|
1225 | ||
1226 |
my $column_clause = $model->column_clause(remove => ['id']); |
|
1227 | ||
1228 |
追加したい列がある場合は、C<add>オプションで追加することができます。 |
|
1229 | ||
1230 |
my $column_clause = $model->column_clause(add => ['company.id as company__id']); |
|
1231 | ||
add feture. all model class ...
|
1232 |
=head2 モデルのサンプル |
update pod
|
1233 | |
add feture. all model class ...
|
1234 |
モデルのサンプルです。 |
update pod
|
1235 | |
1236 |
package MyDBI; |
|
1237 |
|
|
1238 |
use base 'DBIx::Custom'; |
|
1239 |
|
|
1240 |
sub connect { |
|
1241 |
my $self = shift->SUPER::connect(@_); |
|
1242 |
|
|
add feture. all model class ...
|
1243 |
$self->include_model( |
1244 |
MyModel => [ |
|
removed experimental base_ta...
|
1245 |
'book', |
1246 |
'company' |
|
1247 |
] |
|
update pod
|
1248 |
); |
1249 |
} |
|
removed experimental base_ta...
|
1250 |
|
add feture. all model class ...
|
1251 |
package MyModel::book; |
1252 |
use base 'DBIx::Custom::Model'; |
|
removed experimental base_ta...
|
1253 |
|
add experimental update_at()...
|
1254 |
__PACKAGE__->attr('primary_key' => sub { ['id'] }; |
1255 |
|
|
removed experimental base_ta...
|
1256 |
sub insert { ... } |
1257 |
sub list { ... } |
|
1258 |
|
|
add feture. all model class ...
|
1259 |
package MyModel::company; |
1260 |
use base 'DBIx::Custom::Model'; |
|
add experimental update_at()...
|
1261 | |
1262 |
__PACKAGE__->attr('primary_key' => sub { ['id'] }; |
|
removed experimental base_ta...
|
1263 |
|
1264 |
sub insert { ... } |
|
1265 |
sub list { ... } |
|
update pod
|
1266 | |
1267 |
=head2 8. パフォーマンスの改善 |
|
updated document
|
1268 | |
update pod
|
1269 |
=head3 クエリの作成 |
updated document
|
1270 | |
update pod
|
1271 |
パフォーマンスが得られない場合はC<query>オプションを使って |
1272 |
クエリを作成してみてください。 |
|
update pod
|
1273 | |
update pod
|
1274 |
my $params = [ |
1275 |
{title => 'Perl', author => 'Ken'}, |
|
1276 |
{title => 'Good day', author => 'Tom'} |
|
1277 |
] |
|
1278 |
my $query = $dbi->insert(table => 'book', param => $params->[0], query => 1); |
|
update pod
|
1279 | |
update pod
|
1280 |
戻り値はL<DBIx::Custom::Query>オブジェクトです。 |
1281 |
作成したクエリはC<execute()>で実行することができます。 |
|
update pod
|
1282 | |
update pod
|
1283 |
foreach my $param (@$params) { |
1284 |
$dbi->execute($query, $param); |
|
1285 |
} |
|
1286 | ||
1287 |
ステートメントハンドルが再利用されるので、パフォーマンスが |
|
1288 |
改善されます。 |
|
1289 |
C<query>オプションはC<insert()>, C<update()>, C<update_all()>, |
|
1290 |
C<delete()>, C<delete_all()>で利用することができます. |
|
1291 | ||
1292 |
クエリを作成するメソッドに渡すパラメータと |
|
1293 |
C<execute()>に渡すパラメータの個数は同じでなければならない |
|
1294 |
ことに注意してください。 |
|
1295 | ||
1296 |
C<create_query()>を使って任意のSQLのクエリを作成 |
|
update pod
|
1297 |
することもできます。 |
updated document
|
1298 | |
1299 |
my $query = $dbi->create_query( |
|
update pod
|
1300 |
"insert into book {insert_param title author};"; |
updated document
|
1301 |
); |
1302 | ||
1303 | ||
update pod
|
1304 |
=head2 9. その他の機能 |
updated document
|
1305 | |
update pod
|
1306 |
=head3 メソッドの登録 |
updated document
|
1307 | |
update pod
|
1308 |
L<DBIx::Custom>オブジェクトにメソッドを追加することができます。 |
update pod
|
1309 |
C<method()>を使用します。 |
updated document
|
1310 | |
update pod
|
1311 |
$dbi->method( |
updated document
|
1312 |
update_or_insert => sub { |
1313 |
my $self = shift; |
|
update pod
|
1314 |
# something |
updated document
|
1315 |
}, |
1316 |
find_or_create => sub { |
|
1317 |
my $self = shift; |
|
update pod
|
1318 |
# something |
updated document
|
1319 |
} |
1320 |
); |
|
1321 | ||
update pod
|
1322 |
これらのメソッドは |
1323 |
L<DBIx::Custom>オブジェクトから呼び出すことができます。 |
|
updated document
|
1324 | |
1325 |
$dbi->update_or_insert; |
|
1326 |
$dbi->find_or_create; |
|
1327 | ||
removed experimental expand
|
1328 |
=head3 結果クラスの変更 |
1329 | ||
update pod
|
1330 |
結果クラスを変更することができます。 |
1331 |
デフォルトはL<DBIx::Custom::Result>です。 |
|
removed experimental expand
|
1332 | |
1333 |
package MyResult; |
|
1334 |
use base 'DBIx::Custom::Result'; |
|
1335 |
|
|
1336 |
sub some_method { ... } |
|
updated document
|
1337 | |
removed experimental expand
|
1338 |
1; |
1339 |
|
|
1340 |
package main; |
|
1341 |
|
|
1342 |
use MyResult; |
|
1343 |
|
|
1344 |
my $dbi = DBIx::Custom->connect(...); |
|
1345 |
$dbi->result_class('MyResult'); |
|
updated document
|
1346 | |
removed experimental expand
|
1347 |
=head3 キャッシング |
updated document
|
1348 | |
update pod
|
1349 |
タグの解析後のSQLはパフォーマンスの理由のためにキャッシュされます。 |
removed experimental expand
|
1350 |
これはC<chace>で設定でき、デフォルトではキャッシュを行う設定です。 |
updated document
|
1351 | |
removed experimental expand
|
1352 |
$dbi->cache(1); |
updated document
|
1353 | |
update pod
|
1354 |
キャッシュ方法はC<cache_method>で変更することができます。 |
1355 |
デフォルトのメソッドは以下のようになっていて、 |
|
1356 |
メモリ上にキャッシュが保存されます。 |
|
updated document
|
1357 | |
removed experimental expand
|
1358 |
$dbi->cache_method(sub { |
1359 |
sub { |
|
1360 |
my $self = shift; |
|
1361 |
|
|
1362 |
$self->{_cached} ||= {}; |
|
1363 |
|
|
1364 |
if (@_ > 1) { |
|
update pod
|
1365 |
# キャッシュの保存 |
removed experimental expand
|
1366 |
$self->{_cached}{$_[0]} = $_[1] |
1367 |
} |
|
1368 |
else { |
|
update pod
|
1369 |
# キャッシュの取得 |
removed experimental expand
|
1370 |
return $self->{_cached}{$_[0]} |
1371 |
} |
|
1372 |
} |
|
1373 |
}); |
|
1374 |
|
|
1375 |
第一はL<DBIx::Custom>オブジェクトです。 |
|
update pod
|
1376 |
第二引数はタグが解析される前のSQLです。 |
1377 |
第三引数はタグの解析後のSQLの情報です。これはハッシュのリファレンスです。 |
|
updated document
|
1378 | |
update pod
|
1379 |
第三引数が存在した場合はキャッシュを設定し、 |
removed experimental expand
|
1380 |
存在しなかった場合はキャッシュを取得する実装に |
1381 |
してください。 |
|
updated document
|
1382 | |
update pod
|
1383 |
=head1 サンプル |
1384 | ||
1385 |
以下のWikiでサンプルを見ることができます。 |
|
1386 | ||
1387 |
L<DBIx::Custom Wiki|https://github.com/yuki-kimoto/DBIx-Custom/wiki> |
|
1388 | ||
updated document
|
1389 |
=cut |