... | ... |
@@ -1,7 +1,8 @@ |
1 | 1 |
0.1711 |
2 | 2 |
- renamed EXPERIMENTAL available_type_name to available_typename |
3 | 3 |
- renamed EXPERIMENTAL available_data_type to available_datatype |
4 |
- - added EXPERIMENTAL DBIx::Custom::Where map_if method |
|
4 |
+ - added EXPERIMENTAL DBIx::Custom::Where if method |
|
5 |
+ - added EXPERIMENTAL DBIx::Custom::Where map attribute |
|
5 | 6 |
0.1710 |
6 | 7 |
- use more DBIx::Custom information in sub modules to decrease bugs |
7 | 8 |
(very sorry, this change can't keep backword compatible, |
... | ... |
@@ -10,8 +10,105 @@ use overload '""' => sub { shift->to_string }, fallback => 1; |
10 | 10 |
push @DBIx::Custom::CARP_NOT, __PACKAGE__; |
11 | 11 |
|
12 | 12 |
has [qw/dbi param/], |
13 |
- clause => sub { [] }, |
|
14 |
- map_if => 'exists'; |
|
13 |
+ map => sub { {} }, |
|
14 |
+ clause => sub { [] }; |
|
15 |
+ |
|
16 |
+sub _map_param { |
|
17 |
+ my $self = shift; |
|
18 |
+ my $param = shift; |
|
19 |
+ |
|
20 |
+ return $param if !defined $param; |
|
21 |
+ |
|
22 |
+ my %map = @_; |
|
23 |
+ |
|
24 |
+ # Mapping |
|
25 |
+ my $map_param = {}; |
|
26 |
+ foreach my $key (keys %$param) { |
|
27 |
+ |
|
28 |
+ unless (exists $map{$key}) { |
|
29 |
+ if (ref $param->{$key} eq 'ARRAY') { |
|
30 |
+ $map_param->{$key} = [@{$param->{$key}}]; |
|
31 |
+ } |
|
32 |
+ else { |
|
33 |
+ $map_param->{$key} = $param->{$key}; |
|
34 |
+ } |
|
35 |
+ next; |
|
36 |
+ } |
|
37 |
+ |
|
38 |
+ my $value_cb; |
|
39 |
+ my $condition; |
|
40 |
+ my $map_key; |
|
41 |
+ |
|
42 |
+ # Get mapping information |
|
43 |
+ if (ref $map{$key} eq 'ARRAY') { |
|
44 |
+ foreach my $some (@{$map{$key}}) { |
|
45 |
+ $map_key = $some unless ref $some; |
|
46 |
+ $condition = $some->{if} if ref $some eq 'HASH'; |
|
47 |
+ $value_cb = $some if ref $some eq 'CODE'; |
|
48 |
+ } |
|
49 |
+ } |
|
50 |
+ else { |
|
51 |
+ $map_key = $map{$key}; |
|
52 |
+ } |
|
53 |
+ $value_cb ||= sub { $_[0] }; |
|
54 |
+ $condition ||= $self->if || 'exists'; |
|
55 |
+ |
|
56 |
+ # Map parameter |
|
57 |
+ my $value; |
|
58 |
+ if (ref $condition eq 'CODE') { |
|
59 |
+ if (ref $param->{$key} eq 'ARRAY') { |
|
60 |
+ $map_param->{$map_key} = []; |
|
61 |
+ for (my $i = 0; $i < @{$param->{$key}}; $i++) { |
|
62 |
+ $map_param->{$map_key}->[$i] |
|
63 |
+ = $condition->($param->{$key}->[$i]) ? $param->{$key}->[$i] |
|
64 |
+ : $self->dbi->not_exists; |
|
65 |
+ } |
|
66 |
+ } |
|
67 |
+ else { |
|
68 |
+ $map_param->{$map_key} = $value_cb->($param->{$key}) |
|
69 |
+ if $condition->($param->{$key}); |
|
70 |
+ } |
|
71 |
+ } |
|
72 |
+ elsif ($condition eq 'exists') { |
|
73 |
+ if (ref $param->{$key} eq 'ARRAY') { |
|
74 |
+ $map_param->{$map_key} = []; |
|
75 |
+ for (my $i = 0; $i < @{$param->{$key}}; $i++) { |
|
76 |
+ $map_param->{$map_key}->[$i] |
|
77 |
+ = exists $param->{$key}->[$i] ? $param->{$key}->[$i] |
|
78 |
+ : $self->dbi->not_exists; |
|
79 |
+ } |
|
80 |
+ } |
|
81 |
+ else { |
|
82 |
+ $map_param->{$map_key} = $value_cb->($param->{$key}) |
|
83 |
+ if exists $param->{$key}; |
|
84 |
+ } |
|
85 |
+ } |
|
86 |
+ else { croak qq/Condition must be code reference or "exists" / . _subname } |
|
87 |
+ } |
|
88 |
+ |
|
89 |
+ return $map_param; |
|
90 |
+} |
|
91 |
+ |
|
92 |
+sub if { |
|
93 |
+ my $self = shift; |
|
94 |
+ if (@_) { |
|
95 |
+ my $if = $_[0]; |
|
96 |
+ |
|
97 |
+ $if = $if eq 'exists' ? $if |
|
98 |
+ : $if eq 'defined' ? sub { defined $_[0] } |
|
99 |
+ : $if eq 'length' ? sub { length $_[0] } |
|
100 |
+ : ref $if eq 'CODE' ? $if |
|
101 |
+ : undef; |
|
102 |
+ |
|
103 |
+ croak "You can must specify right value to C<if> " . _subname |
|
104 |
+ unless $if; |
|
105 |
+ |
|
106 |
+ $self->{if} = $if; |
|
107 |
+ return $self; |
|
108 |
+ } |
|
109 |
+ $self->{if} = 'exists' unless exists $self->{if}; |
|
110 |
+ return $self->{if}; |
|
111 |
+} |
|
15 | 112 |
|
16 | 113 |
sub new { |
17 | 114 |
my $self = shift->SUPER::new(@_); |
... | ... |
@@ -43,16 +140,18 @@ sub to_string { |
43 | 140 |
$clause->[0] = 'and' unless @$clause; |
44 | 141 |
|
45 | 142 |
# Map condition |
46 |
- my $map_if = $self->map_if || ''; |
|
47 |
- $map_if = $map_if eq 'exists' ? $map_if |
|
48 |
- : $map_if eq 'defined' ? sub { defined $_[0] } |
|
49 |
- : $map_if eq 'length' ? sub { length $_[0] } |
|
50 |
- : ref $map_if eq 'CODE' ? $map_if |
|
143 |
+ my $if = $self->if || ''; |
|
144 |
+ $if = $if eq 'exists' ? $if |
|
145 |
+ : $if eq 'defined' ? sub { defined $_[0] } |
|
146 |
+ : $if eq 'length' ? sub { length $_[0] } |
|
147 |
+ : ref $if eq 'CODE' ? $if |
|
51 | 148 |
: undef; |
52 | 149 |
|
53 |
- croak "You can must specify right value to C<map_if> " . _subname |
|
54 |
- unless $map_if; |
|
55 |
- $self->{_map_if} = $map_if; |
|
150 |
+ croak "You can must specify right value to C<if> " . _subname |
|
151 |
+ unless $if; |
|
152 |
+ $self->{_if} = $if; |
|
153 |
+ |
|
154 |
+ $self->{_param} = $self->_map_param($self->param, %{$self->map}); |
|
56 | 155 |
|
57 | 156 |
# Parse |
58 | 157 |
my $where = []; |
... | ... |
@@ -133,27 +232,27 @@ sub _parse { |
133 | 232 |
my $count = ++$count->{$column}; |
134 | 233 |
|
135 | 234 |
# Push |
136 |
- my $param = $self->param; |
|
235 |
+ my $param = $self->{_param}; |
|
137 | 236 |
if (ref $param eq 'HASH') { |
138 | 237 |
if (exists $param->{$column}) { |
139 |
- my $map_if = $self->{_map_if}; |
|
238 |
+ my $if = $self->{_if}; |
|
140 | 239 |
|
141 | 240 |
if (ref $param->{$column} eq 'ARRAY') { |
142 | 241 |
unless (ref $param->{$column}->[$count - 1] eq 'DBIx::Custom::NotExists') { |
143 |
- if ($map_if eq 'exists') { |
|
242 |
+ if ($if eq 'exists') { |
|
144 | 243 |
$pushed = 1 if exists $param->{$column}->[$count - 1]; |
145 | 244 |
} |
146 | 245 |
else { |
147 |
- $pushed = 1 if $map_if->($param->{$column}->[$count - 1]); |
|
246 |
+ $pushed = 1 if $if->($param->{$column}->[$count - 1]); |
|
148 | 247 |
} |
149 | 248 |
} |
150 | 249 |
} |
151 | 250 |
elsif ($count == 1) { |
152 |
- if ($map_if eq 'exists') { |
|
153 |
- $pushed = 1 if exists $param->{$column}; |
|
251 |
+ if ($if eq 'exists') { |
|
252 |
+ $pushed = 1 if exists $param->{$column}; |
|
154 | 253 |
} |
155 | 254 |
else { |
156 |
- $pushed = 1 if $map_if->($param->{$column}); |
|
255 |
+ $pushed = 1 if $if->($param->{$column}); |
|
157 | 256 |
} |
158 | 257 |
} |
159 | 258 |
} |
... | ... |
@@ -200,34 +299,43 @@ If all parameter names is exists. |
200 | 299 |
|
201 | 300 |
"where ( title = :title and ( date < :date or date > :date ) )" |
202 | 301 |
|
203 |
-=head2 C<map_if EXPERIMENTAL> |
|
204 |
- |
|
205 |
- my $map_if = $where->map_if($condition); |
|
206 |
- $where->map_if($condition); |
|
302 |
+=head2 C<map EXPERIMENTAL> |
|
303 |
+ |
|
304 |
+Mapping parameter key and value when C<to_stirng> method is executed. |
|
305 |
+ |
|
306 |
+ $where->map({ |
|
307 |
+ 'id' => 'book.id', |
|
308 |
+ 'author' => ['book.author' => sub { '%' . $_[0] . '%' }], |
|
309 |
+ 'price' => [ |
|
310 |
+ 'book.price', {if => sub { length $_[0] } |
|
311 |
+ ] |
|
312 |
+ }); |
|
313 |
+ |
|
314 |
+The following option is available. |
|
207 | 315 |
|
208 |
-If C<clause> contain named placeholder like ':title{=}' |
|
209 |
-and C<param> contain the corresponding key like {title => 'Perl'}, |
|
210 |
-C<to_string> method join the cluase and convert to placeholder |
|
211 |
-like 'title = ?'. |
|
316 |
+=over 4 |
|
212 | 317 |
|
213 |
-C<map_if> method can change this mapping rule. |
|
214 |
-Default is C<exists>. If the key exists, mapping is done. |
|
318 |
+=item * C<if> |
|
319 |
+ |
|
320 |
+By default, if parameter key is exists, mapping is done. |
|
215 | 321 |
|
216 |
- $where->map_if('exists'); |
|
322 |
+ if => 'exists'; |
|
217 | 323 |
|
218 | 324 |
In case C<defined> is specified, if the value is defined, |
219 | 325 |
mapping is done. |
220 | 326 |
|
221 |
- $where->map_if('defined'); |
|
327 |
+ if => 'defined'; |
|
222 | 328 |
|
223 | 329 |
In case C<length> is specified, the value is defined |
224 | 330 |
and the length is bigger than 0, mappting is done. |
225 | 331 |
|
226 |
- $where->map_if('length'); |
|
332 |
+ if => 'length'; |
|
227 | 333 |
|
228 | 334 |
You can also subroutine like C<sub { defined $_[0] }> for mappging. |
229 | 335 |
|
230 |
- $where->map_if(sub { defined $_[0] }); |
|
336 |
+ if => sub { defined $_[0] } |
|
337 |
+ |
|
338 |
+=back |
|
231 | 339 |
|
232 | 340 |
=head2 C<param> |
233 | 341 |
|
... | ... |
@@ -249,6 +357,13 @@ L<DBIx::Custom> object. |
249 | 357 |
L<DBIx::Custom::Where> inherits all methods from L<Object::Simple> |
250 | 358 |
and implements the following new ones. |
251 | 359 |
|
360 |
+=head2 C<if EXPERIMENTAL> |
|
361 |
+ |
|
362 |
+ my $if = $where->if($condition); |
|
363 |
+ $where->if($condition); |
|
364 |
+ |
|
365 |
+C<if> is default of C<map> method C<if> option. |
|
366 |
+ |
|
252 | 367 |
=head2 C<to_string> |
253 | 368 |
|
254 | 369 |
$where->to_string; |
... | ... |
@@ -1060,12 +1060,6 @@ $where = $dbi->where |
1060 | 1060 |
eval{$where->to_string}; |
1061 | 1061 |
like($@, qr/one column/); |
1062 | 1062 |
|
1063 |
-$where = $dbi->where |
|
1064 |
- ->clause('key1 = :key1') |
|
1065 |
- ->param([]); |
|
1066 |
-eval{$where->to_string}; |
|
1067 |
-like($@, qr/Parameter/); |
|
1068 |
- |
|
1069 | 1063 |
$where = $dbi->where |
1070 | 1064 |
->clause(['or', ('key1 = :key1') x 3]) |
1071 | 1065 |
->param({key1 => [$dbi->not_exists, 1, 3]}); |
... | ... |
@@ -1231,7 +1225,7 @@ is_deeply($row, [{key1 => 1, key2 => 2}]); |
1231 | 1225 |
$where = $dbi->where; |
1232 | 1226 |
$where->clause(['and', ':key1{=}']); |
1233 | 1227 |
$where->param({key1 => undef}); |
1234 |
-$where->map_if('defined'); |
|
1228 |
+$where->if('defined'); |
|
1235 | 1229 |
$result = $dbi->execute("select * from table1 $where", {key1 => 1}); |
1236 | 1230 |
$row = $result->all; |
1237 | 1231 |
is_deeply($row, [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}]); |
... | ... |
@@ -1249,7 +1243,7 @@ is_deeply($row, [{key1 => 1, key2 => 2}]); |
1249 | 1243 |
$where = $dbi->where; |
1250 | 1244 |
$where->clause(['and', ':key1{=}']); |
1251 | 1245 |
$where->param({key1 => [undef, undef]}); |
1252 |
-$where->map_if('defined'); |
|
1246 |
+$where->if('defined'); |
|
1253 | 1247 |
$result = $dbi->execute("select * from table1 $where", {key1 => [1, 0]}); |
1254 | 1248 |
$row = $result->all; |
1255 | 1249 |
is_deeply($row, [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}]); |
... | ... |
@@ -1260,7 +1254,7 @@ is_deeply($row, [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}]); |
1260 | 1254 |
$where = $dbi->where; |
1261 | 1255 |
$where->clause(['and', ':key1{=}']); |
1262 | 1256 |
$where->param({key1 => 0}); |
1263 |
-$where->map_if('length'); |
|
1257 |
+$where->if('length'); |
|
1264 | 1258 |
$result = $dbi->execute("select * from table1 $where", {key1 => 1}); |
1265 | 1259 |
$row = $result->all; |
1266 | 1260 |
is_deeply($row, [{key1 => 1, key2 => 2}]); |
... | ... |
@@ -1268,7 +1262,7 @@ is_deeply($row, [{key1 => 1, key2 => 2}]); |
1268 | 1262 |
$where = $dbi->where; |
1269 | 1263 |
$where->clause(['and', ':key1{=}']); |
1270 | 1264 |
$where->param({key1 => ''}); |
1271 |
-$where->map_if('length'); |
|
1265 |
+$where->if('length'); |
|
1272 | 1266 |
$result = $dbi->execute("select * from table1 $where", {key1 => 1}); |
1273 | 1267 |
$row = $result->all; |
1274 | 1268 |
is_deeply($row, [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}]); |
... | ... |
@@ -1276,7 +1270,7 @@ is_deeply($row, [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}]); |
1276 | 1270 |
$where = $dbi->where; |
1277 | 1271 |
$where->clause(['and', ':key1{=}']); |
1278 | 1272 |
$where->param({key1 => 5}); |
1279 |
-$where->map_if(sub { ($_[0] || '') eq 5 }); |
|
1273 |
+$where->if(sub { ($_[0] || '') eq 5 }); |
|
1280 | 1274 |
$result = $dbi->execute("select * from table1 $where", {key1 => 1}); |
1281 | 1275 |
$row = $result->all; |
1282 | 1276 |
is_deeply($row, [{key1 => 1, key2 => 2}]); |
... | ... |
@@ -1284,7 +1278,7 @@ is_deeply($row, [{key1 => 1, key2 => 2}]); |
1284 | 1278 |
$where = $dbi->where; |
1285 | 1279 |
$where->clause(['and', ':key1{=}']); |
1286 | 1280 |
$where->param({key1 => 7}); |
1287 |
-$where->map_if(sub { ($_[0] || '') eq 5 }); |
|
1281 |
+$where->if(sub { ($_[0] || '') eq 5 }); |
|
1288 | 1282 |
$result = $dbi->execute("select * from table1 $where", {key1 => 1}); |
1289 | 1283 |
$row = $result->all; |
1290 | 1284 |
is_deeply($row, [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}]); |