Showing 5 changed files with 147 additions and 18 deletions
+4
Changes
... ...
@@ -1,3 +1,7 @@
1
+0.1711
2
+    - renamed EXPERIMENTAL available_type_name to available_typename
3
+    - renamed EXPERIMENTAL available_data_type to available_datatype
4
+    - added EXPERIMENTAL DBIx::Custom::Where map_if method
1 5
 0.1710
2 6
     - use more DBIx::Custom information in sub modules to decrease bugs
3 7
       (very sorry, this change can't keep backword compatible,
+10 -10
lib/DBIx/Custom.pm
... ...
@@ -905,7 +905,7 @@ sub setup_model {
905 905
     return $self;
906 906
 }
907 907
 
908
-sub available_data_type {
908
+sub available_datatype {
909 909
     my $self = shift;
910 910
     
911 911
     my $data_types = '';
... ...
@@ -921,7 +921,7 @@ sub available_data_type {
921 921
     return $data_types;
922 922
 }
923 923
 
924
-sub available_type_name {
924
+sub available_typename {
925 925
     my $self = shift;
926 926
     
927 927
     # Type Names
... ...
@@ -2004,16 +2004,16 @@ L<DBIx::Custom> inherits all methods from L<Object::Simple>
2004 2004
 and use all methods of L<DBI>
2005 2005
 and implements the following new ones.
2006 2006
 
2007
-=head2 C<available_data_type> EXPERIMENTAL
2007
+=head2 C<available_datatype> EXPERIMENTAL
2008 2008
 
2009
-    print $dbi->available_data_type;
2009
+    print $dbi->available_datatype;
2010 2010
 
2011 2011
 Get available data types. You can use these data types
2012 2012
 in C<type rule>'s C<from1> and C<from2> section.
2013 2013
 
2014
-=head2 C<available_type_name> EXPERIMENTAL
2014
+=head2 C<available_typename> EXPERIMENTAL
2015 2015
 
2016
-    print $dbi->available_type_name;
2016
+    print $dbi->available_typename;
2017 2017
 
2018 2018
 Get available type names. You can use these type names in
2019 2019
 C<type_rule>'s C<into1> and C<into2> section.
... ...
@@ -2709,15 +2709,15 @@ This need C<table> option in each method.
2709 2709
 
2710 2710
 =back
2711 2711
 
2712
-You get all type name used in database by C<available_type_name>.
2712
+You get all type name used in database by C<available_typename>.
2713 2713
 
2714
-    print $dbi->available_type_name;
2714
+    print $dbi->available_typename;
2715 2715
 
2716 2716
 In C<from1> and C<from2> you specify data type, not type name.
2717 2717
 C<from2> is executed after C<from1>.
2718
-You get all data type by C<available_data_type>.
2718
+You get all data type by C<available_datatype>.
2719 2719
 
2720
-    print $dbi->available_data_type;
2720
+    print $dbi->available_datatype;
2721 2721
 
2722 2722
 You can also specify multiple types at once.
2723 2723
 
+60 -6
lib/DBIx/Custom/Where.pm
... ...
@@ -10,7 +10,8 @@ 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 { [] };
13
+    clause => sub { [] },
14
+    map_if => 'exists';
14 15
 
15 16
 sub new {
16 17
     my $self = shift->SUPER::new(@_);
... ...
@@ -40,7 +41,19 @@ sub to_string {
40 41
     my $clause = $self->clause;
41 42
     $clause = ['and', $clause] unless ref $clause eq 'ARRAY';
42 43
     $clause->[0] = 'and' unless @$clause;
43
-
44
+    
45
+    # 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
51
+            : undef;
52
+    
53
+    croak "You can must specify right value to C<map_if> " . _subname
54
+      unless $map_if;
55
+    $self->{_map_if} = $map_if;
56
+    
44 57
     # Parse
45 58
     my $where = [];
46 59
     my $count = {};
... ...
@@ -123,13 +136,25 @@ sub _parse {
123 136
         my $param = $self->param;
124 137
         if (ref $param eq 'HASH') {
125 138
             if (exists $param->{$column}) {
139
+                my $map_if = $self->{_map_if};
140
+                
126 141
                 if (ref $param->{$column} eq 'ARRAY') {
127
-                    $pushed = 1
128
-                      if  exists $param->{$column}->[$count - 1]
129
-                       && ref $param->{$column}->[$count - 1] ne 'DBIx::Custom::NotExists';
142
+                    unless (ref $param->{$column}->[$count - 1] eq 'DBIx::Custom::NotExists') {
143
+                        if ($map_if eq 'exists') {
144
+                            $pushed = 1 if exists $param->{$column}->[$count - 1];
145
+                        }
146
+                        else {
147
+                            $pushed = 1 if $map_if->($param->{$column}->[$count - 1]);
148
+                        }
149
+                    }
130 150
                 } 
131 151
                 elsif ($count == 1) {
132
-                    $pushed = 1;
152
+                    if ($map_if eq 'exists') {
153
+                        $pushed = 1 if  exists $param->{$column};
154
+                    }
155
+                    else {
156
+                        $pushed = 1 if $map_if->($param->{$column});
157
+                    }
133 158
                 }
134 159
             }
135 160
             push @$where, $clause if $pushed;
... ...
@@ -175,6 +200,35 @@ If all parameter names is exists.
175 200
 
176 201
     "where ( title = :title and ( date < :date or date > :date ) )"
177 202
 
203
+=head2 C<map_if EXPERIMENTAL>
204
+    
205
+    my $map_if = $where->map_if($condition);
206
+    $where->map_if($condition);
207
+
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 = ?'.
212
+
213
+C<map_if> method can change this mapping rule.
214
+Default is C<exists>. If the key exists, mapping is done.
215
+    
216
+    $where->map_if('exists');
217
+
218
+In case C<defined> is specified, if the value is defined,
219
+mapping is done.
220
+
221
+    $where->map_if('defined');
222
+
223
+In case C<length> is specified, the value is defined
224
+and the length is bigger than 0, mappting is done.
225
+
226
+    $where->map_if('length');
227
+
228
+You can also subroutine like C<sub { defined $_[0] }> for mappging.
229
+
230
+    $where->map_if(sub { defined $_[0] });
231
+
178 232
 =head2 C<param>
179 233
 
180 234
     my $param = $where->param;
+2
t/common.t
... ...
@@ -238,4 +238,6 @@ $result = $dbi->execute(
238 238
 $rows = $result->all;
239 239
 is_deeply($rows, [{key1 => 'a:b c:d', key2 => 2}]);
240 240
 
241
+
242
+
241 243
 1;
+71 -2
t/sqlite.t
... ...
@@ -1221,6 +1221,74 @@ $result = $dbi->select(
1221 1221
 $row = $result->all;
1222 1222
 is_deeply($row, [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}]);
1223 1223
 
1224
+$where = $dbi->where;
1225
+$where->clause(['and', ':key1{=}']);
1226
+$where->param({key1 => undef});
1227
+$result = $dbi->execute("select * from table1 $where", {key1 => 1});
1228
+$row = $result->all;
1229
+is_deeply($row, [{key1 => 1, key2 => 2}]);
1230
+
1231
+$where = $dbi->where;
1232
+$where->clause(['and', ':key1{=}']);
1233
+$where->param({key1 => undef});
1234
+$where->map_if('defined');
1235
+$result = $dbi->execute("select * from table1 $where", {key1 => 1});
1236
+$row = $result->all;
1237
+is_deeply($row, [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}]);
1238
+
1239
+$where = $dbi->where;
1240
+$where->clause(['or', ':key1{=}', ':key1{=}']);
1241
+$where->param({key1 => [undef, undef]});
1242
+$result = $dbi->execute("select * from table1 $where", {key1 => [1, 0]});
1243
+$row = $result->all;
1244
+is_deeply($row, [{key1 => 1, key2 => 2}]);
1245
+$result = $dbi->execute("select * from table1 $where", {key1 => [0, 1]});
1246
+$row = $result->all;
1247
+is_deeply($row, [{key1 => 1, key2 => 2}]);
1248
+
1249
+$where = $dbi->where;
1250
+$where->clause(['and', ':key1{=}']);
1251
+$where->param({key1 => [undef, undef]});
1252
+$where->map_if('defined');
1253
+$result = $dbi->execute("select * from table1 $where", {key1 => [1, 0]});
1254
+$row = $result->all;
1255
+is_deeply($row, [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}]);
1256
+$result = $dbi->execute("select * from table1 $where", {key1 => [0, 1]});
1257
+$row = $result->all;
1258
+is_deeply($row, [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}]);
1259
+
1260
+$where = $dbi->where;
1261
+$where->clause(['and', ':key1{=}']);
1262
+$where->param({key1 => 0});
1263
+$where->map_if('length');
1264
+$result = $dbi->execute("select * from table1 $where", {key1 => 1});
1265
+$row = $result->all;
1266
+is_deeply($row, [{key1 => 1, key2 => 2}]);
1267
+
1268
+$where = $dbi->where;
1269
+$where->clause(['and', ':key1{=}']);
1270
+$where->param({key1 => ''});
1271
+$where->map_if('length');
1272
+$result = $dbi->execute("select * from table1 $where", {key1 => 1});
1273
+$row = $result->all;
1274
+is_deeply($row, [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}]);
1275
+
1276
+$where = $dbi->where;
1277
+$where->clause(['and', ':key1{=}']);
1278
+$where->param({key1 => 5});
1279
+$where->map_if(sub { ($_[0] || '') eq 5 });
1280
+$result = $dbi->execute("select * from table1 $where", {key1 => 1});
1281
+$row = $result->all;
1282
+is_deeply($row, [{key1 => 1, key2 => 2}]);
1283
+
1284
+$where = $dbi->where;
1285
+$where->clause(['and', ':key1{=}']);
1286
+$where->param({key1 => 7});
1287
+$where->map_if(sub { ($_[0] || '') eq 5 });
1288
+$result = $dbi->execute("select * from table1 $where", {key1 => 1});
1289
+$row = $result->all;
1290
+is_deeply($row, [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}]);
1291
+
1224 1292
 
1225 1293
 test 'dbi_option default';
1226 1294
 $dbi = DBIx::Custom->new;
... ...
@@ -3108,9 +3176,9 @@ $result = $model->select(column => 'key1');
3108 3176
 $result->filter(key1 => sub { $_[0] * 2 });
3109 3177
 is_deeply($result->one, {key1 => 2});
3110 3178
 
3111
-test 'available_date_type';
3179
+test 'available_datetype';
3112 3180
 $dbi = DBIx::Custom->connect(%memory);
3113
-ok($dbi->can('available_data_type'));
3181
+ok($dbi->can('available_datatype'));
3114 3182
 
3115 3183
 
3116 3184
 test 'select prefix option';
... ...
@@ -3560,3 +3628,4 @@ like($@, qr/unexpected "}"/, "error : 1");
3560 3628
 $source = "a {= {}";
3561 3629
 eval{$builder->build_query($source)};
3562 3630
 like($@, qr/unexpected "{"/, "error : 2");
3631
+