... | ... |
@@ -1,3 +1,9 @@ |
1 |
+0.1720 |
|
2 |
+ - removed placeholder count check |
|
3 |
+ - added EXPERIMENTAL execute method's id and primary key option. |
|
4 |
+ - added EXPERIMENTAL DBIx::Custom::Model execute method |
|
5 |
+0.1719 |
|
6 |
+ - DBIx::Custom support Microsoft Access through DBD::ODBC |
|
1 | 7 |
0.1718 |
2 | 8 |
- added EXPERIMENTAL DBIx::Custom::Model call_dbi method |
3 | 9 |
- added EXPERIMENTAL count method |
... | ... |
@@ -1,7 +1,7 @@ |
1 | 1 |
package DBIx::Custom; |
2 | 2 |
use Object::Simple -base; |
3 | 3 |
|
4 |
-our $VERSION = '0.1718'; |
|
4 |
+our $VERSION = '0.1720'; |
|
5 | 5 |
use 5.008001; |
6 | 6 |
|
7 | 7 |
use Carp 'croak'; |
... | ... |
@@ -397,6 +397,17 @@ sub execute { |
397 | 397 |
my $query_return = delete $args{query}; |
398 | 398 |
my $table_alias = delete $args{table_alias} || {}; |
399 | 399 |
my $sqlfilter = $args{sqlfilter}; |
400 |
+ my $id = delete $args{id}; |
|
401 |
+ my $primary_key = delete $args{primary_key}; |
|
402 |
+ croak "insert method primary_key option " . |
|
403 |
+ "must be specified when id is specified " . _subname |
|
404 |
+ if defined $id && !defined $primary_key; |
|
405 |
+ $primary_key = [$primary_key] unless ref $primary_key eq 'ARRAY'; |
|
406 |
+ |
|
407 |
+ if (defined $id) { |
|
408 |
+ my $id_param = $self->_create_param_from_id($id, $primary_key); |
|
409 |
+ $param = $self->merge_param($id_param, $param); |
|
410 |
+ } |
|
400 | 411 |
|
401 | 412 |
# Check argument names |
402 | 413 |
foreach my $name (keys %args) { |
... | ... |
@@ -2521,6 +2532,28 @@ registered by by C<register_filter>. |
2521 | 2532 |
This filter is executed before data is saved into database. |
2522 | 2533 |
and before type rule filter is executed. |
2523 | 2534 |
|
2535 |
+=item C<id> |
|
2536 |
+ |
|
2537 |
+ id => 4 |
|
2538 |
+ id => [4, 5] |
|
2539 |
+ |
|
2540 |
+ID corresponding to C<primary_key>. |
|
2541 |
+You can delete rows by C<id> and C<primary_key>. |
|
2542 |
+ |
|
2543 |
+ $dbi->execute( |
|
2544 |
+ "select * from book where id1 = :id1 and id2 = :id2", |
|
2545 |
+ {}, |
|
2546 |
+ parimary_key => ['id1', 'id2'], |
|
2547 |
+ id => [4, 5], |
|
2548 |
+ ); |
|
2549 |
+ |
|
2550 |
+The above is same as the followin one. |
|
2551 |
+ |
|
2552 |
+ $dbi->execute( |
|
2553 |
+ "select * from book where id1 = :id1 and id2 = :id2", |
|
2554 |
+ {id1 => 4, id2 => 5} |
|
2555 |
+ ); |
|
2556 |
+ |
|
2524 | 2557 |
=item C<query> |
2525 | 2558 |
|
2526 | 2559 |
query => 1 |
... | ... |
@@ -2558,6 +2591,10 @@ Note that $row must be simple hash reference, such as |
2558 | 2591 |
{title => 'Perl', author => 'Ken'}. |
2559 | 2592 |
and don't forget to sort $row values by $row key asc order. |
2560 | 2593 |
|
2594 |
+=item C<primary_key> |
|
2595 |
+ |
|
2596 |
+See C<id> option. |
|
2597 |
+ |
|
2561 | 2598 |
=item C<sqlfilter EXPERIMENTAL> |
2562 | 2599 |
|
2563 | 2600 |
SQL filter function. |
... | ... |
@@ -67,6 +67,12 @@ sub call_dbi { |
67 | 67 |
return $self->dbi->$method(@args, @_); |
68 | 68 |
} |
69 | 69 |
|
70 |
+sub execute { |
|
71 |
+ my $self = shift; |
|
72 |
+ push @_, ($_ => $self->$_) for qw/table bind_type primary_key type/; |
|
73 |
+ return $self->dbi->execute(@_); |
|
74 |
+} |
|
75 |
+ |
|
70 | 76 |
sub DESTROY { } |
71 | 77 |
|
72 | 78 |
sub method { |
... | ... |
@@ -116,9 +122,9 @@ DBIx::Custom::Model - Model |
116 | 122 |
|
117 | 123 |
=head1 SYNOPSIS |
118 | 124 |
|
119 |
-use DBIx::Custom::Table; |
|
125 |
+use DBIx::Custom::Model; |
|
120 | 126 |
|
121 |
-my $table = DBIx::Custom::Model->new(table => 'books'); |
|
127 |
+my $model = DBIx::Custom::Model->new(table => 'books'); |
|
122 | 128 |
|
123 | 129 |
=head1 ATTRIBUTES |
124 | 130 |
|
... | ... |
@@ -148,7 +154,7 @@ C<delete>, and C<select> method. |
148 | 154 |
|
149 | 155 |
=head2 C<table> |
150 | 156 |
|
151 |
- my $table = $model->table; |
|
157 |
+ my $model = $model->table; |
|
152 | 158 |
$model = $model->table('book'); |
153 | 159 |
|
154 | 160 |
Table name, this is passed to C<select> method. |
... | ... |
@@ -193,24 +199,31 @@ Options is same as C<select> method's ones. |
193 | 199 |
|
194 | 200 |
=head2 C<delete> |
195 | 201 |
|
196 |
- $table->delete(...); |
|
202 |
+ $model->delete(...); |
|
197 | 203 |
|
198 | 204 |
Same as C<delete> of L<DBIx::Custom> except that |
199 |
-you don't have to specify C<table> option. |
|
205 |
+you don't have to specify C<table> and C<primary_key> option. |
|
200 | 206 |
|
201 | 207 |
=head2 C<delete_all> |
202 | 208 |
|
203 |
- $table->delete_all(...); |
|
209 |
+ $model->delete_all(...); |
|
204 | 210 |
|
205 | 211 |
Same as C<delete_all> of L<DBIx::Custom> except that |
206 |
-you don't have to specify C<table> option. |
|
212 |
+you don't have to specify C<table> and C<primary_key> option. |
|
213 |
+ |
|
214 |
+=head2 C<execute EXPERIMENTAL> |
|
215 |
+ |
|
216 |
+ $model->execute(...); |
|
217 |
+ |
|
218 |
+Same as C<execute> of L<DBIx::Custom> except that |
|
219 |
+you don't have to specify C<table> and C<primary_key> option. |
|
207 | 220 |
|
208 | 221 |
=head2 C<insert> |
209 | 222 |
|
210 |
- $table->insert(...); |
|
223 |
+ $model->insert(...); |
|
211 | 224 |
|
212 | 225 |
Same as C<insert> of L<DBIx::Custom> except that |
213 |
-you don't have to specify C<table> option. |
|
226 |
+you don't have to specify C<table> and C<primary_key> option. |
|
214 | 227 |
|
215 | 228 |
=head2 C<method> |
216 | 229 |
|
... | ... |
@@ -247,29 +260,29 @@ If column names is omitted, C<columns> attribute of the model is used. |
247 | 260 |
|
248 | 261 |
=head2 C<new> |
249 | 262 |
|
250 |
- my $table = DBIx::Custom::Table->new; |
|
263 |
+ my $model = DBIx::Custom::Model->new; |
|
251 | 264 |
|
252 |
-Create a L<DBIx::Custom::Table> object. |
|
265 |
+Create a L<DBIx::Custom::Model> object. |
|
253 | 266 |
|
254 | 267 |
=head2 C<select> |
255 | 268 |
|
256 |
- $table->select(...); |
|
269 |
+ $model->select(...); |
|
257 | 270 |
|
258 | 271 |
Same as C<select> of L<DBIx::Custom> except that |
259 |
-you don't have to specify C<table> option. |
|
272 |
+you don't have to specify C<table>, C<primary_key> and C<jon> option. |
|
260 | 273 |
|
261 | 274 |
=head2 C<update> |
262 | 275 |
|
263 |
- $table->update(...); |
|
276 |
+ $model->update(...); |
|
264 | 277 |
|
265 | 278 |
Same as C<update> of L<DBIx::Custom> except that |
266 |
-you don't have to specify C<table> option. |
|
279 |
+you don't have to specify C<table> and C<primary_key> option. |
|
267 | 280 |
|
268 | 281 |
=head2 C<update_all> |
269 | 282 |
|
270 |
- $table->update_all(param => \%param); |
|
283 |
+ $model->update_all(param => \%param); |
|
271 | 284 |
|
272 | 285 |
Same as C<update_all> of L<DBIx::Custom> except that |
273 |
-you don't have to specify table name. |
|
286 |
+you don't have to specify C<table> and C<primary_key> option. |
|
274 | 287 |
|
275 | 288 |
=cut |
... | ... |
@@ -42,28 +42,10 @@ sub build_query { |
42 | 42 |
|
43 | 43 |
my $sql = $query->sql; |
44 | 44 |
$query->sql($sql); |
45 |
- |
|
46 |
- # Check placeholder count |
|
47 |
- croak qq{Placeholder count in "$sql" must be same as column count} |
|
48 |
- . _subname |
|
49 |
- unless $self->_placeholder_count($sql) eq @{$query->columns}; |
|
50 | 45 |
|
51 | 46 |
return $query; |
52 | 47 |
} |
53 | 48 |
|
54 |
-sub _placeholder_count { |
|
55 |
- my ($self, $sql) = @_; |
|
56 |
- |
|
57 |
- # Count |
|
58 |
- $sql ||= ''; |
|
59 |
- my $count = 0; |
|
60 |
- my $pos = -1; |
|
61 |
- while (($pos = index($sql, '?', $pos + 1)) != -1) { |
|
62 |
- $count++; |
|
63 |
- } |
|
64 |
- return $count; |
|
65 |
-} |
|
66 |
- |
|
67 | 49 |
sub _parse_parameter { |
68 | 50 |
my ($self, $source) = @_; |
69 | 51 |
|
... | ... |
@@ -2767,6 +2767,27 @@ $rows = [ |
2767 | 2767 |
); |
2768 | 2768 |
} |
2769 | 2769 |
|
2770 |
+$dbi->execute("drop table $table1"); |
|
2771 |
+$dbi->execute($create_table1_highperformance); |
|
2772 |
+$rows = [ |
|
2773 |
+ {$key7 => 10, $key6 => 2, $key5 => 3, $key4 => 4, $key3 => 5, $key2 => 5}, |
|
2774 |
+ {$key7 => 11, $key6 => 2, $key5 => 3, $key4 => 4, $key3 => 5, $key2 => 6}, |
|
2775 |
+]; |
|
2776 |
+{ |
|
2777 |
+ $model = $dbi->create_model(table => $table1, primary_key => $key1); |
|
2778 |
+ my $query; |
|
2779 |
+ foreach my $row (@$rows) { |
|
2780 |
+ $query ||= $model->insert($row, id => 1, query => 1); |
|
2781 |
+ $model->execute($query, $row, id => 1, filter => {$key7 => sub { $_[0] * 2 }}); |
|
2782 |
+ } |
|
2783 |
+ is_deeply($dbi->select(table => $table1, append => 'order by key2')->all, |
|
2784 |
+ [ |
|
2785 |
+ {$key7 => 20, $key6 => 2, $key5 => 3, $key4 => 4, $key3 => 5, $key2 => 5, $key1 => 1}, |
|
2786 |
+ {$key7 => 22, $key6 => 2, $key5 => 3, $key4 => 4, $key3 => 5, $key2 => 6, $key1 => 1}, |
|
2787 |
+ ] |
|
2788 |
+ ); |
|
2789 |
+} |
|
2790 |
+ |
|
2770 | 2791 |
test 'result'; |
2771 | 2792 |
$dbi = DBIx::Custom->connect; |
2772 | 2793 |
eval { $dbi->execute("drop table $table1") }; |
... | ... |
@@ -2909,15 +2930,6 @@ $dbi->register_tag( |
2909 | 2930 |
); |
2910 | 2931 |
|
2911 | 2932 |
|
2912 |
-$dbi->register_tag( |
|
2913 |
- a => sub { |
|
2914 |
- return ["? ? ?", ['']]; |
|
2915 |
- } |
|
2916 |
-); |
|
2917 |
-eval{$builder->build_query("{a}")}; |
|
2918 |
-like($@, qr/\QPlaceholder count/, "placeholder count is invalid"); |
|
2919 |
- |
|
2920 |
- |
|
2921 | 2933 |
test 'Default tag Error case'; |
2922 | 2934 |
eval{$builder->build_query("{= }")}; |
2923 | 2935 |
like($@, qr/Column name must be specified in tag "{= }"/, "basic '=' : key not exist"); |