Showing 3 changed files with 154 additions and 44 deletions
+2 -1
Changes
... ...
@@ -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,
+146 -31
lib/DBIx/Custom/Where.pm
... ...
@@ -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;
+6 -12
t/sqlite.t
... ...
@@ -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}]);