Showing 3 changed files with 465 additions and 106 deletions
+24 -8
lib/DBIx/Custom.pm
... ...
@@ -196,8 +196,10 @@ sub dbh {
196 196
         
197 197
         # Quote
198 198
         if (!defined $self->reserved_word_quote && !defined $self->quote) {
199
-            my $driver = $self->{dbh}->{Driver}->{Name};
200
-            my $quote = $driver eq 'mysql' ? '`' : '"';
199
+            my $driver = lc $self->{dbh}->{Driver}->{Name};
200
+            my $quote = $driver eq 'odbc' ? '[]'
201
+                       :$driver eq 'mysql' ? '`'
202
+                       : '"';
201 203
             $self->quote($quote);
202 204
         }
203 205
         
... ...
@@ -1393,7 +1395,7 @@ sub _quote {
1393 1395
 }
1394 1396
 
1395 1397
 sub _q {
1396
-    my ($self, $value) = @_;
1398
+    my ($self, $value, $quotemeta) = @_;
1397 1399
     
1398 1400
     my $quote = $self->_quote;
1399 1401
     my $q = substr($quote, 0, 1) || '';
... ...
@@ -1403,6 +1405,11 @@ sub _q {
1403 1405
     }
1404 1406
     else { $p = $q }
1405 1407
     
1408
+    if ($quotemeta) {
1409
+        $q = quotemeta($q);
1410
+        $p = quotemeta($p);
1411
+    }
1412
+    
1406 1413
     return "$q$value$p";
1407 1414
 }
1408 1415
 
... ...
@@ -1429,9 +1436,8 @@ sub _search_tables {
1429 1436
     my $tables = [];
1430 1437
     my $safety_character = $self->safety_character;
1431 1438
     my $q = $self->_quote;
1432
-    my $q_re = quotemeta($q);
1433
-    my $quoted_safety_character_re = $self->_q("?([$safety_character]+)");
1434
-    my $table_re = $q ? qr/(?:^|[^$safety_character])$quoted_safety_character_re?\./
1439
+    my $quoted_safety_character_re = $self->_q("?([$safety_character]+)", 1);
1440
+    my $table_re = $q ? qr/(?:^|[^$safety_character])${quoted_safety_character_re}?\./
1435 1441
                       : qr/(?:^|[^$safety_character])([$safety_character]+)\./;
1436 1442
     while ($source =~ /$table_re/g) {
1437 1443
         push @$tables, $1;
... ...
@@ -1450,8 +1456,18 @@ sub _where_to_obj {
1450 1456
         my $clause = ['and'];
1451 1457
         my $q = $self->_quote;
1452 1458
         foreach my $column (keys %$where) {
1453
-            my $column_quote = $self->_q($column);
1454
-            $column_quote =~ s/\./$self->_q(".")/e;
1459
+            my $table;
1460
+            my $c;
1461
+            if ($column =~ /(?:(.*?)\.)?(.*)/) {
1462
+                $table = $1;
1463
+                $c = $2;
1464
+            }
1465
+            
1466
+            my $table_quote;
1467
+            $table_quote = $self->_q($table) if defined $table;
1468
+            my $column_quote = $self->_q($c);
1469
+            $column_quote = $table_quote . '.' . $column_quote
1470
+              if defined $table_quote;
1455 1471
             push @$clause, "$column_quote = :$column" for keys %$where;
1456 1472
         }
1457 1473
         $obj = $self->where(clause => $clause, param => $where);
+355 -4
t/common-sqlserver.t
... ...
@@ -17,17 +17,368 @@ use DBIx::Custom;
17 17
     sub date_typename { lc $date_typename }
18 18
     sub datetime_typename { lc $datetime_typename }
19 19
 
20
-    my $date_datatype = 91;
21
-    my $datetime_datatype = 11;
20
+    my $date_datatype = -9;
21
+    my $datetime_datatype = 93;
22 22
 
23 23
     sub date_datatype { lc $date_datatype }
24 24
     sub datetime_datatype { lc $datetime_datatype }
25 25
 
26 26
     has datetime_suffix => '.000';
27
-    
27
+    has exclude_table => sub {
28
+        return qr/^(
29
+          CHECK_CONSTRAINTS
30
+          |COLUMN_DOMAIN_USAGE
31
+          |COLUMN_PRIVILEGES
32
+          |COLUMNS
33
+          |CONSTRAINT_COLUMN_USAGE
34
+          |CONSTRAINT_TABLE_USAGE
35
+          |DOMAIN_CONSTRAINTS
36
+          |DOMAINS
37
+          |KEY_COLUMN_USAGE
38
+          |PARAMETERS
39
+          |REFERENTIAL_CONSTRAINTS
40
+          |ROUTINE_COLUMNS
41
+          |ROUTINES
42
+          |SCHEMATA
43
+          |TABLE_CONSTRAINTS
44
+          |TABLE_PRIVILEGES
45
+          |TABLES
46
+          |VIEW_COLUMN_USAGE
47
+          |VIEW_TABLE_USAGE
48
+          |VIEWS
49
+          |all_columns
50
+          |all_objects
51
+          |all_parameters
52
+          |all_sql_modules
53
+          |all_views
54
+          |allocation_units
55
+          |assemblies
56
+          |assembly_files
57
+          |assembly_modules
58
+          |assembly_references
59
+          |assembly_types
60
+          |asymmetric_keys
61
+          |backup_devices
62
+          |certificates
63
+          |change_tracking_databases
64
+          |change_tracking_tables
65
+          |check_constraints
66
+          |column_type_usages
67
+          |column_xml_schema_collection_usages
68
+          |columns
69
+          |computed_columns
70
+          |configurations
71
+          |conversation_endpoints
72
+          |conversation_groups
73
+          |conversation_priorities
74
+          |credentials
75
+          |crypt_properties
76
+          |cryptographic_providers
77
+          |data_spaces
78
+          |database_audit_specification_details
79
+          |database_audit_specifications
80
+          |database_files
81
+          |database_mirroring
82
+          |database_mirroring_endpoints
83
+          |database_permissions
84
+          |database_principal_aliases
85
+          |database_principals
86
+          |database_recovery_status
87
+          |database_role_members
88
+          |databases
89
+          |default_constraints
90
+          |destination_data_spaces
91
+          |dm_audit_actions
92
+          |dm_audit_class_type_map
93
+          |dm_broker_activated_tasks
94
+          |dm_broker_connections
95
+          |dm_broker_forwarded_messages
96
+          |dm_broker_queue_monitors
97
+          |dm_cdc_errors
98
+          |dm_cdc_log_scan_sessions
99
+          |dm_clr_appdomains
100
+          |dm_clr_loaded_assemblies
101
+          |dm_clr_properties
102
+          |dm_clr_tasks
103
+          |dm_cryptographic_provider_properties
104
+          |dm_database_encryption_keys
105
+          |dm_db_file_space_usage
106
+          |dm_db_index_usage_stats
107
+          |dm_db_mirroring_auto_page_repair
108
+          |dm_db_mirroring_connections
109
+          |dm_db_mirroring_past_actions
110
+          |dm_db_missing_index_details
111
+          |dm_db_missing_index_group_stats
112
+          |dm_db_missing_index_groups
113
+          |dm_db_partition_stats
114
+          |dm_db_persisted_sku_features
115
+          |dm_db_script_level
116
+          |dm_db_session_space_usage
117
+          |dm_db_task_space_usage
118
+          |dm_exec_background_job_queue
119
+          |dm_exec_background_job_queue_stats
120
+          |dm_exec_cached_plans
121
+          |dm_exec_connections
122
+          |dm_exec_procedure_stats
123
+          |dm_exec_query_memory_grants
124
+          |dm_exec_query_optimizer_info
125
+          |dm_exec_query_resource_semaphores
126
+          |dm_exec_query_stats
127
+          |dm_exec_query_transformation_stats
128
+          |dm_exec_requests
129
+          |dm_exec_sessions
130
+          |dm_exec_trigger_stats
131
+          |dm_filestream_file_io_handles
132
+          |dm_filestream_file_io_requests
133
+          |dm_fts_active_catalogs
134
+          |dm_fts_fdhosts
135
+          |dm_fts_index_population
136
+          |dm_fts_memory_buffers
137
+          |dm_fts_memory_pools
138
+          |dm_fts_outstanding_batches
139
+          |dm_fts_population_ranges
140
+          |dm_io_backup_tapes
141
+          |dm_io_cluster_shared_drives
142
+          |dm_io_pending_io_requests
143
+          |dm_os_buffer_descriptors
144
+          |dm_os_child_instances
145
+          |dm_os_cluster_nodes
146
+          |dm_os_dispatcher_pools
147
+          |dm_os_dispatchers
148
+          |dm_os_hosts
149
+          |dm_os_latch_stats
150
+          |dm_os_loaded_modules
151
+          |dm_os_memory_allocations
152
+          |dm_os_memory_brokers
153
+          |dm_os_memory_cache_clock_hands
154
+          |dm_os_memory_cache_counters
155
+          |dm_os_memory_cache_entries
156
+          |dm_os_memory_cache_hash_tables
157
+          |dm_os_memory_clerks
158
+          |dm_os_memory_node_access_stats
159
+          |dm_os_memory_nodes
160
+          |dm_os_memory_objects
161
+          |dm_os_memory_pools
162
+          |dm_os_nodes
163
+          |dm_os_performance_counters
164
+          |dm_os_process_memory
165
+          |dm_os_ring_buffers
166
+          |dm_os_schedulers
167
+          |dm_os_spinlock_stats
168
+          |dm_os_stacks
169
+          |dm_os_sublatches
170
+          |dm_os_sys_info
171
+          |dm_os_sys_memory
172
+          |dm_os_tasks
173
+          |dm_os_threads
174
+          |dm_os_virtual_address_dump
175
+          |dm_os_wait_stats
176
+          |dm_os_waiting_tasks
177
+          |dm_os_worker_local_storage
178
+          |dm_os_workers
179
+          |dm_qn_subscriptions
180
+          |dm_repl_articles
181
+          |dm_repl_schemas
182
+          |dm_repl_tranhash
183
+          |dm_repl_traninfo
184
+          |dm_resource_governor_configuration
185
+          |dm_resource_governor_resource_pools
186
+          |dm_resource_governor_workload_groups
187
+          |dm_server_audit_status
188
+          |dm_tran_active_snapshot_database_transactions
189
+          |dm_tran_active_transactions
190
+          |dm_tran_commit_table
191
+          |dm_tran_current_snapshot
192
+          |dm_tran_current_transaction
193
+          |dm_tran_database_transactions
194
+          |dm_tran_locks
195
+          |dm_tran_session_transactions
196
+          |dm_tran_top_version_generators
197
+          |dm_tran_transactions_snapshot
198
+          |dm_tran_version_store
199
+          |dm_xe_map_values
200
+          |dm_xe_object_columns
201
+          |dm_xe_objects
202
+          |dm_xe_packages
203
+          |dm_xe_session_event_actions
204
+          |dm_xe_session_events
205
+          |dm_xe_session_object_columns
206
+          |dm_xe_session_targets
207
+          |dm_xe_sessions
208
+          |endpoint_webmethods
209
+          |endpoints
210
+          |event_notification_event_types
211
+          |event_notifications
212
+          |events
213
+          |extended_procedures
214
+          |extended_properties
215
+          |filegroups
216
+          |foreign_key_columns
217
+          |foreign_keys
218
+          |fulltext_catalogs
219
+          |fulltext_document_types
220
+          |fulltext_index_catalog_usages
221
+          |fulltext_index_columns
222
+          |fulltext_index_fragments
223
+          |fulltext_indexes
224
+          |fulltext_languages
225
+          |fulltext_stoplists
226
+          |fulltext_stopwords
227
+          |fulltext_system_stopwords
228
+          |function_order_columns
229
+          |http_endpoints
230
+          |identity_columns
231
+          |index_columns
232
+          |indexes
233
+          |internal_tables
234
+          |key_constraints
235
+          |key_encryptions
236
+          |linked_logins
237
+          |login_token
238
+          |master_files
239
+          |master_key_passwords
240
+          |message_type_xml_schema_collection_usages
241
+          |messages
242
+          |module_assembly_usages
243
+          |numbered_procedure_parameters
244
+          |numbered_procedures
245
+          |objects
246
+          |openkeys
247
+          |parameter_type_usages
248
+          |parameter_xml_schema_collection_usages
249
+          |parameters
250
+          |partition_functions
251
+          |partition_parameters
252
+          |partition_range_values
253
+          |partition_schemes
254
+          |partitions
255
+          |plan_guides
256
+          |procedures
257
+          |remote_logins
258
+          |remote_service_bindings
259
+          |resource_governor_configuration
260
+          |resource_governor_resource_pools
261
+          |resource_governor_workload_groups
262
+          |routes
263
+          |schemas
264
+          |securable_classes
265
+          |server_assembly_modules
266
+          |server_audit_specification_details
267
+          |server_audit_specifications
268
+          |server_audits
269
+          |server_event_notifications
270
+          |server_event_session_actions
271
+          |server_event_session_events
272
+          |server_event_session_fields
273
+          |server_event_session_targets
274
+          |server_event_sessions
275
+          |server_events
276
+          |server_file_audits
277
+          |server_permissions
278
+          |server_principal_credentials
279
+          |server_principals
280
+          |server_role_members
281
+          |server_sql_modules
282
+          |server_trigger_events
283
+          |server_triggers
284
+          |servers
285
+          |service_broker_endpoints
286
+          |service_contract_message_usages
287
+          |service_contract_usages
288
+          |service_contracts
289
+          |service_message_types
290
+          |service_queue_usages
291
+          |service_queues
292
+          |services
293
+          |soap_endpoints
294
+          |spatial_index_tessellations
295
+          |spatial_indexes
296
+          |spatial_reference_systems
297
+          |sql_dependencies
298
+          |sql_logins
299
+          |sql_modules
300
+          |stats
301
+          |stats_columns
302
+          |symmetric_keys
303
+          |synonyms
304
+          |syscacheobjects
305
+          |syscharsets
306
+          |syscolumns
307
+          |syscomments
308
+          |sysconfigures
309
+          |sysconstraints
310
+          |syscurconfigs
311
+          |syscursorcolumns
312
+          |syscursorrefs
313
+          |syscursors
314
+          |syscursortables
315
+          |sysdatabases
316
+          |sysdepends
317
+          |sysdevices
318
+          |sysfilegroups
319
+          |sysfiles
320
+          |sysforeignkeys
321
+          |sysfulltextcatalogs
322
+          |sysindexes
323
+          |sysindexkeys
324
+          |syslanguages
325
+          |syslockinfo
326
+          |syslogins
327
+          |sysmembers
328
+          |sysmessages
329
+          |sysobjects
330
+          |sysoledbusers
331
+          |sysopentapes
332
+          |sysperfinfo
333
+          |syspermissions
334
+          |sysprocesses
335
+          |sysprotects
336
+          |sysreferences
337
+          |sysremotelogins
338
+          |sysservers
339
+          |system_columns
340
+          |system_components_surface_area_configuration
341
+          |system_objects
342
+          |system_parameters
343
+          |system_sql_modules
344
+          |system_views
345
+          |systypes
346
+          |sysusers
347
+          |table_types
348
+          |tables
349
+          |tcp_endpoints
350
+          |trace_categories
351
+          |trace_columns
352
+          |trace_event_bindings
353
+          |trace_events
354
+          |trace_subclass_values
355
+          |traces
356
+          |transmission_queue
357
+          |trigger_event_types
358
+          |trigger_events
359
+          |triggers
360
+          |type_assembly_usages
361
+          |types
362
+          |user_token
363
+          |via_endpoints
364
+          |views
365
+          |xml_indexes
366
+          |xml_schema_attributes
367
+          |xml_schema_collections
368
+          |xml_schema_component_placements
369
+          |xml_schema_components
370
+          |xml_schema_elements
371
+          |xml_schema_facets
372
+          |xml_schema_model_groups
373
+          |xml_schema_namespaces
374
+          |xml_schema_types
375
+          |xml_schema_wildcard_namespaces
376
+          |xml_schema_wildcards
377
+        )/x
378
+    };
379
+
28 380
     my $dsn = "dbi:ODBC:driver={SQL Server};Server={localhost\\SQLEXPRESS};"
29 381
       . "Trusted_Connection=No;AutoTranslate=No;Database=dbix_custom;";
30
-
31 382
     has dsn => $dsn;
32 383
     has user  => 'dbix_custom';
33 384
     has password => 'dbix_custom';
+86 -94
t/common.t
... ...
@@ -200,20 +200,20 @@ test 'type_rule into';
200 200
 $dbi = DBIx::Custom->connect;
201 201
 eval { $dbi->execute('drop table table1') };
202 202
 $dbi->execute($create_table1_type);
203
-$DB::single = 1;
204 203
 $dbi->type_rule(
205 204
     into1 => {
206 205
         $date_typename => sub { '2010-' . $_[0] }
207 206
     }
208 207
 );
208
+$DB::single = 1;
209 209
 $dbi->insert({key1 => '01-01'}, table => 'table1');
210 210
 $result = $dbi->select(table => 'table1');
211
-is($result->one->{key1}, '2010-01-01');
211
+like($result->one->{key1}, qr/^2010-01-01/);
212 212
 
213
-$DB::single = 1;
214 213
 $dbi = DBIx::Custom->connect;
215 214
 eval { $dbi->execute('drop table table1') };
216 215
 $dbi->execute($create_table1_type);
216
+$DB::single = 1;
217 217
 $dbi->type_rule(
218 218
     into1 => [
219 219
          [$date_typename, $datetime_typename] => sub {
... ...
@@ -226,8 +226,8 @@ $dbi->type_rule(
226 226
 $dbi->insert({key1 => '2010-01-02', key2 => '2010-01-01 01:01:02'}, table => 'table1');
227 227
 $result = $dbi->select(table => 'table1');
228 228
 $row = $result->one;
229
-is($row->{key1}, '2010-01-03');
230
-is($row->{key2}, '2010-01-01 01:01:03' . $datetime_suffix);
229
+like($row->{key1}, qr/^2010-01-03/);
230
+like($row->{key2}, qr/^2010-01-01 01:01:03/);
231 231
 
232 232
 $dbi = DBIx::Custom->connect;
233 233
 eval { $dbi->execute('drop table table1') };
... ...
@@ -247,8 +247,8 @@ $result = $dbi->execute(
247 247
     param => {key1 => '2010-01-03', 'table1.key2' => '2010-01-01 01:01:02'}
248 248
 );
249 249
 $row = $result->one;
250
-is($row->{key1}, '2010-01-03');
251
-is($row->{key2}, '2010-01-01 01:01:03' . $datetime_suffix);
250
+like($row->{key1}, qr/^2010-01-03/);
251
+like($row->{key2}, qr/^2010-01-01 01:01:03/);
252 252
 
253 253
 $dbi = DBIx::Custom->connect;
254 254
 eval { $dbi->execute('drop table table1') };
... ...
@@ -269,14 +269,14 @@ $result = $dbi->execute(
269 269
     table => 'table1'
270 270
 );
271 271
 $row = $result->one;
272
-is($row->{key1}, '2010-01-03');
273
-is($row->{key2}, '2010-01-01 01:01:03' . $datetime_suffix);
272
+like($row->{key1}, qr/^2010-01-03/);
273
+like($row->{key2}, qr/2010-01-01 01:01:03/);
274 274
 
275 275
 $dbi = DBIx::Custom->connect;
276 276
 eval { $dbi->execute('drop table table1') };
277 277
 $dbi->execute($create_table1_type);
278 278
 $dbi->register_filter(convert => sub {
279
-    my $value = shift;
279
+    my $value = shift || '';
280 280
     $value =~ s/02/03/;
281 281
     return $value;
282 282
 });
... ...
@@ -290,16 +290,7 @@ $dbi->type_rule(
290 290
 );
291 291
 $dbi->insert({key1 => '2010-02-02'}, table => 'table1');
292 292
 $result = $dbi->select(table => 'table1');
293
-is($result->fetch->[0], '2010-03-03');
294
-
295
-
296
-
297
-
298
-
299
-
300
-
301
-
302
-
293
+like($result->fetch->[0], qr/^2010-03-03/);
303 294
 
304 295
 test 'type_rule and filter order';
305 296
 $dbi = DBIx::Custom->connect;
... ...
@@ -307,23 +298,23 @@ eval { $dbi->execute('drop table table1') };
307 298
 $dbi->execute($create_table1_type);
308 299
 $dbi->type_rule(
309 300
     into1 => {
310
-        $date_typename => sub { my $v = shift; $v =~ s/4/5/; return $v }
301
+        $date_typename => sub { my $v = shift || ''; $v =~ s/4/5/; return $v }
311 302
     },
312 303
     into2 => {
313
-        $date_typename => sub { my $v = shift; $v =~ s/5/6/; return $v }
304
+        $date_typename => sub { my $v = shift || ''; $v =~ s/5/6/; return $v }
314 305
     },
315 306
     from1 => {
316
-        $date_datatype => sub { my $v = shift; $v =~ s/6/7/; return $v }
307
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/6/7/; return $v }
317 308
     },
318 309
     from2 => {
319
-        $date_datatype => sub { my $v = shift; $v =~ s/7/8/; return $v }
310
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/7/8/; return $v }
320 311
     }
321 312
 );
322 313
 $dbi->insert({key1 => '2010-01-03'}, 
323
-  table => 'table1', filter => {key1 => sub { my $v = shift; $v =~ s/3/4/; return $v }});
314
+  table => 'table1', filter => {key1 => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }});
324 315
 $result = $dbi->select(table => 'table1');
325
-$result->filter(key1 => sub { my $v = shift; $v =~ s/8/9/; return $v });
326
-is($result->fetch_first->[0], '2010-01-09');
316
+$result->filter(key1 => sub { my $v = shift || ''; $v =~ s/8/9/; return $v });
317
+like($result->fetch_first->[0], qr/^2010-01-09/);
327 318
 
328 319
 
329 320
 $dbi = DBIx::Custom->connect;
... ...
@@ -331,24 +322,24 @@ eval { $dbi->execute('drop table table1') };
331 322
 $dbi->execute($create_table1_type);
332 323
 $dbi->type_rule(
333 324
     from1 => {
334
-        $date_datatype => sub { my $v = shift; $v =~ s/3/4/; return $v }
325
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
335 326
     },
336 327
     from2 => {
337
-        $date_datatype => sub { my $v = shift; $v =~ s/4/5/; return $v }
328
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/4/5/; return $v }
338 329
     },
339 330
 );
340 331
 $dbi->insert({key1 => '2010-01-03'}, table => 'table1');
341 332
 $result = $dbi->select(table => 'table1');
342 333
 $result->type_rule(
343 334
     from1 => {
344
-        $date_datatype => sub { my $v = shift; $v =~ s/3/6/; return $v }
335
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/6/; return $v }
345 336
     },
346 337
     from2 => {
347
-        $date_datatype => sub { my $v = shift; $v =~ s/6/8/; return $v }
338
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/6/8/; return $v }
348 339
     }
349 340
 );
350
-$result->filter(key1 => sub { my $v = shift; $v =~ s/8/9/; return $v });
351
-is($result->fetch_first->[0], '2010-01-09');
341
+$result->filter(key1 => sub { my $v = shift || ''; $v =~ s/8/9/; return $v });
342
+like($result->fetch_first->[0], qr/^2010-01-09/);
352 343
 
353 344
 test 'type_rule_off';
354 345
 $dbi = DBIx::Custom->connect;
... ...
@@ -356,65 +347,65 @@ eval { $dbi->execute('drop table table1') };
356 347
 $dbi->execute($create_table1_type);
357 348
 $dbi->type_rule(
358 349
     from1 => {
359
-        $date_datatype => sub { my $v = shift; $v =~ s/3/5/; return $v }
350
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }
360 351
     },
361 352
     into1 => {
362
-        $date_typename => sub { my $v = shift; $v =~ s/3/4/; return $v }
353
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
363 354
     }
364 355
 );
365 356
 $dbi->insert({key1 => '2010-01-03'}, table => 'table1', type_rule_off => 1);
366 357
 $result = $dbi->select(table => 'table1', type_rule_off => 1);
367
-is($result->type_rule_off->fetch->[0], '2010-01-03');
358
+like($result->type_rule_off->fetch->[0], qr/^2010-01-03/);
368 359
 
369 360
 $dbi = DBIx::Custom->connect;
370 361
 eval { $dbi->execute('drop table table1') };
371 362
 $dbi->execute($create_table1_type);
372 363
 $dbi->type_rule(
373 364
     from1 => {
374
-        $date_datatype => sub { my $v = shift; $v =~ s/3/4/; return $v }
365
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
375 366
     },
376 367
     into1 => {
377
-        $date_typename => sub { my $v = shift; $v =~ s/3/5/; return $v }
368
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }
378 369
     }
379 370
 );
380 371
 $dbi->insert({key1 => '2010-01-03'}, table => 'table1', type_rule_off => 1);
381 372
 $result = $dbi->select(table => 'table1', type_rule_off => 1);
382
-is($result->one->{key1}, '2010-01-04');
373
+like($result->one->{key1}, qr/^2010-01-04/);
383 374
 
384 375
 $dbi = DBIx::Custom->connect;
385 376
 eval { $dbi->execute('drop table table1') };
386 377
 $dbi->execute($create_table1_type);
387 378
 $dbi->type_rule(
388 379
     from1 => {
389
-        $date_datatype => sub { my $v = shift; $v =~ s/4/5/; return $v }
380
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/4/5/; return $v }
390 381
     },
391 382
     into1 => {
392
-        $date_typename => sub { my $v = shift; $v =~ s/3/4/; return $v }
383
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
393 384
     }
394 385
 );
395 386
 $dbi->insert({key1 => '2010-01-03'}, table => 'table1');
396 387
 $result = $dbi->select(table => 'table1');
397
-is($result->one->{key1}, '2010-01-05');
388
+like($result->one->{key1}, qr/^2010-01-05/);
398 389
 
399 390
 $dbi = DBIx::Custom->connect;
400 391
 eval { $dbi->execute('drop table table1') };
401 392
 $dbi->execute($create_table1_type);
402 393
 $dbi->type_rule(
403 394
     from1 => {
404
-        $date_datatype => sub { my $v = shift; $v =~ s/4/5/; return $v }
395
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/4/5/; return $v }
405 396
     },
406 397
     into1 => {
407
-        $date_typename => sub { my $v = shift; $v =~ s/3/4/; return $v }
398
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
408 399
     }
409 400
 );
410 401
 $dbi->insert({key1 => '2010-01-03'}, table => 'table1');
411 402
 $result = $dbi->select(table => 'table1');
412
-is($result->fetch->[0], '2010-01-05');
403
+like($result->fetch->[0], qr/2010-01-05/);
413 404
 
414 405
 $dbi = DBIx::Custom->connect;
415 406
 eval { $dbi->execute('drop table table1') };
416 407
 $dbi->execute($create_table1_type);
417
-$dbi->register_filter(ppp => sub { my $v = shift; $v =~ s/3/4/; return $v });
408
+$dbi->register_filter(ppp => sub { my $v = shift || ''; $v =~ s/3/4/; return $v });
418 409
 $dbi->type_rule(
419 410
     into1 => {
420 411
         $date_typename => 'ppp'
... ...
@@ -422,7 +413,7 @@ $dbi->type_rule(
422 413
 );
423 414
 $dbi->insert({key1 => '2010-01-03'}, table => 'table1');
424 415
 $result = $dbi->select(table => 'table1');
425
-is($result->one->{key1}, '2010-01-04');
416
+like($result->one->{key1}, qr/^2010-01-04/);
426 417
 
427 418
 eval{$dbi->type_rule(
428 419
     into1 => {
... ...
@@ -457,176 +448,176 @@ eval { $dbi->execute('drop table table1') };
457 448
 $dbi->execute($create_table1_type);
458 449
 $dbi->type_rule(
459 450
     from1 => {
460
-        $date_datatype => sub { my $v = shift; $v =~ s/4/5/; return $v }
451
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/4/5/; return $v }
461 452
     },
462 453
     into1 => {
463
-        $date_typename => sub { my $v = shift; $v =~ s/3/4/; return $v }
454
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
464 455
     }
465 456
 );
466 457
 $dbi->insert({key1 => '2010-01-03'}, table => 'table1');
467 458
 $result = $dbi->select(table => 'table1');
468 459
 $result->type_rule_off;
469
-is($result->one->{key1}, '2010-01-04');
460
+like($result->one->{key1}, qr/^2010-01-04/);
470 461
 
471 462
 $dbi = DBIx::Custom->connect;
472 463
 eval { $dbi->execute('drop table table1') };
473 464
 $dbi->execute($create_table1_type);
474 465
 $dbi->type_rule(
475 466
     from1 => {
476
-        $date_datatype => sub { my $v = shift; $v =~ s/3/4/; return $v },
477
-        $datetime_datatype => sub { my $v = shift; $v =~ s/3/4/; return $v }
467
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/4/; return $v },
468
+        $datetime_datatype => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
478 469
     },
479 470
 );
480 471
 $dbi->insert({key1 => '2010-01-03', key2 => '2010-01-01 01:01:03'}, table => 'table1');
481 472
 $result = $dbi->select(table => 'table1');
482 473
 $result->type_rule(
483 474
     from1 => {
484
-        $date_datatype => sub { my $v = shift; $v =~ s/3/5/; return $v }
475
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }
485 476
     }
486 477
 );
487 478
 $row = $result->one;
488
-is($row->{key1}, '2010-01-05');
489
-is($row->{key2}, '2010-01-01 01:01:03' . $datetime_suffix);
479
+like($row->{key1}, qr/^2010-01-05/);
480
+like($row->{key2}, qr/^2010-01-01 01:01:03/);
490 481
 
491 482
 $result = $dbi->select(table => 'table1');
492 483
 $result->type_rule(
493 484
     from1 => {
494
-        $date_datatype => sub { my $v = shift; $v =~ s/3/5/; return $v }
485
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }
495 486
     }
496 487
 );
497 488
 $row = $result->one;
498
-is($row->{key1}, '2010-01-05');
499
-is($row->{key2}, '2010-01-01 01:01:03' . $datetime_suffix);
489
+like($row->{key1}, qr/2010-01-05/);
490
+like($row->{key2}, qr/2010-01-01 01:01:03/);
500 491
 
501 492
 $result = $dbi->select(table => 'table1');
502 493
 $result->type_rule(
503 494
     from1 => {
504
-        $date_datatype => sub { my $v = shift; $v =~ s/3/5/; return $v }
495
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }
505 496
     }
506 497
 );
507 498
 $row = $result->one;
508
-is($row->{key1}, '2010-01-05');
509
-is($row->{key2}, '2010-01-01 01:01:03' . $datetime_suffix);
499
+like($row->{key1}, qr/2010-01-05/);
500
+like($row->{key2}, qr/2010-01-01 01:01:03/);
510 501
 
511 502
 $result = $dbi->select(table => 'table1');
512 503
 $result->type_rule(
513
-    from1 => [$date_datatype => sub { my $v = shift; $v =~ s/3/5/; return $v }]
504
+    from1 => [$date_datatype => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }]
514 505
 );
515 506
 $row = $result->one;
516
-is($row->{key1}, '2010-01-05');
517
-is($row->{key2}, '2010-01-01 01:01:03' . $datetime_suffix);
507
+like($row->{key1}, qr/2010-01-05/);
508
+like($row->{key2}, qr/2010-01-01 01:01:03/);
518 509
 
519
-$dbi->register_filter(five => sub { my $v = shift; $v =~ s/3/5/; return $v });
510
+$dbi->register_filter(five => sub { my $v = shift || ''; $v =~ s/3/5/; return $v });
520 511
 $result = $dbi->select(table => 'table1');
521 512
 $result->type_rule(
522 513
     from1 => [$date_datatype => 'five']
523 514
 );
524 515
 $row = $result->one;
525
-is($row->{key1}, '2010-01-05');
526
-is($row->{key2}, '2010-01-01 01:01:03' . $datetime_suffix);
516
+like($row->{key1}, qr/^2010-01-05/);
517
+like($row->{key2}, qr/^2010-01-01 01:01:03/);
527 518
 
528 519
 $result = $dbi->select(table => 'table1');
529 520
 $result->type_rule(
530 521
     from1 => [$date_datatype => undef]
531 522
 );
532 523
 $row = $result->one;
533
-is($row->{key1}, '2010-01-03');
534
-is($row->{key2}, '2010-01-01 01:01:03' . $datetime_suffix);
524
+like($row->{key1}, qr/^2010-01-03/);
525
+like($row->{key2}, qr/^2010-01-01 01:01:03/);
535 526
 
536 527
 $dbi = DBIx::Custom->connect;
537 528
 eval { $dbi->execute('drop table table1') };
538 529
 $dbi->execute($create_table1_type);
539 530
 $dbi->type_rule(
540 531
     from1 => {
541
-        $date_datatype => sub { my $v = shift; $v =~ s/3/4/; return $v },
532
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/4/; return $v },
542 533
     },
543 534
 );
544 535
 $dbi->insert({key1 => '2010-01-03'}, table => 'table1');
545 536
 $result = $dbi->select(table => 'table1');
546
-$result->filter(key1 => sub { my $v = shift; $v =~ s/4/5/; return $v });
547
-is($result->one->{key1}, '2010-01-05');
537
+$result->filter(key1 => sub { my $v = shift || ''; $v =~ s/4/5/; return $v });
538
+like($result->one->{key1}, qr/^2010-01-05/);
548 539
 
549 540
 $dbi = DBIx::Custom->connect;
550 541
 eval { $dbi->execute('drop table table1') };
551 542
 $dbi->execute($create_table1_type);
552 543
 $dbi->type_rule(
553 544
     from1 => {
554
-        $date_datatype => sub { my $v = shift; $v =~ s/3/4/; return $v }
545
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
555 546
     },
556 547
 );
557 548
 $dbi->insert({key1 => '2010-01-03'}, table => 'table1');
558 549
 $result = $dbi->select(table => 'table1');
559
-$result->filter(key1 => sub { my $v = shift; $v =~ s/4/5/; return $v });
560
-is($result->fetch->[0], '2010-01-05');
550
+$result->filter(key1 => sub { my $v = shift || ''; $v =~ s/4/5/; return $v });
551
+like($result->fetch->[0], qr/^2010-01-05/);
561 552
 
562 553
 $dbi = DBIx::Custom->connect;
563 554
 eval { $dbi->execute('drop table table1') };
564 555
 $dbi->execute($create_table1_type);
565 556
 $dbi->type_rule(
566 557
     into1 => {
567
-        $date_typename => sub { my $v = shift; $v =~ s/3/4/; return $v }
558
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
568 559
     },
569 560
     into2 => {
570
-        $date_typename => sub { my $v = shift; $v =~ s/3/5/; return $v }
561
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }
571 562
     },
572 563
     from1 => {
573
-        $date_datatype => sub { my $v = shift; $v =~ s/3/6/; return $v }
564
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/6/; return $v }
574 565
     },
575 566
     from2 => {
576
-        $date_datatype => sub { my $v = shift; $v =~ s/(3|6)/7/; return $v }
567
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/(3|6)/7/; return $v }
577 568
     }
578 569
 );
579 570
 $dbi->insert({key1 => '2010-01-03'}, table => 'table1', type_rule_off => 1);
580 571
 $result = $dbi->select(table => 'table1');
581
-is($result->type_rule_off->fetch_first->[0], '2010-01-03');
572
+like($result->type_rule_off->fetch_first->[0], qr/^2010-01-03/);
582 573
 $result = $dbi->select(table => 'table1');
583
-is($result->type_rule_on->fetch_first->[0], '2010-01-07');
574
+like($result->type_rule_on->fetch_first->[0], qr/^2010-01-07/);
584 575
 
585 576
 $dbi = DBIx::Custom->connect;
586 577
 eval { $dbi->execute('drop table table1') };
587 578
 $dbi->execute($create_table1_type);
588 579
 $dbi->type_rule(
589 580
     into1 => {
590
-        $date_typename => sub { my $v = shift; $v =~ s/3/4/; return $v }
581
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
591 582
     },
592 583
     into2 => {
593
-        $date_typename => sub { my $v = shift; $v =~ s/3/5/; return $v }
584
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }
594 585
     },
595 586
     from1 => {
596
-        $date_datatype => sub { my $v = shift; $v =~ s/(3|5)/6/; return $v }
587
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/(3|5)/6/; return $v }
597 588
     },
598 589
     from2 => {
599
-        $date_datatype => sub { my $v = shift; $v =~ s/6/7/; return $v }
590
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/6/7/; return $v }
600 591
     }
601 592
 );
602 593
 $dbi->insert({key1 => '2010-01-03'}, table => 'table1', type_rule1_off => 1);
603 594
 $result = $dbi->select(table => 'table1');
604
-is($result->type_rule1_off->fetch_first->[0], '2010-01-05');
595
+like($result->type_rule1_off->fetch_first->[0], qr/^2010-01-05/);
605 596
 $result = $dbi->select(table => 'table1');
606
-is($result->type_rule1_on->fetch_first->[0], '2010-01-07');
597
+like($result->type_rule1_on->fetch_first->[0], qr/^2010-01-07/);
607 598
 
608 599
 $dbi = DBIx::Custom->connect;
609 600
 eval { $dbi->execute('drop table table1') };
610 601
 $dbi->execute($create_table1_type);
611 602
 $dbi->type_rule(
612 603
     into1 => {
613
-        $date_typename => sub { my $v = shift; $v =~ s/3/5/; return $v }
604
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }
614 605
     },
615 606
     into2 => {
616
-        $date_typename => sub { my $v = shift; $v =~ s/3/4/; return $v }
607
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
617 608
     },
618 609
     from1 => {
619
-        $date_datatype => sub { my $v = shift; $v =~ s/5/6/; return $v }
610
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/5/6/; return $v }
620 611
     },
621 612
     from2 => {
622
-        $date_datatype => sub { my $v = shift; $v =~ s/(3|6)/7/; return $v }
613
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/(3|6)/7/; return $v }
623 614
     }
624 615
 );
625 616
 $dbi->insert({key1 => '2010-01-03'}, table => 'table1', type_rule2_off => 1);
626 617
 $result = $dbi->select(table => 'table1');
627
-is($result->type_rule2_off->fetch_first->[0], '2010-01-06');
618
+like($result->type_rule2_off->fetch_first->[0], qr/^2010-01-06/);
628 619
 $result = $dbi->select(table => 'table1');
629
-is($result->type_rule2_on->fetch_first->[0], '2010-01-07');
620
+like($result->type_rule2_on->fetch_first->[0], qr/^2010-01-07/);
630 621
 
631 622
 
632 623
 
... ...
@@ -805,7 +796,8 @@ $result = $dbi->execute(
805 796
 );
806 797
 
807 798
 $rows = $result->all;
808
-is_deeply($rows, [{key1 => '2011-10-14 12:19:18' . $datetime_suffix, key2 => 2}]);
799
+like($rows->[0]->{key1}, qr/2011-10-14 12:19:18/);
800
+is($rows->[0]->{key2}, 2);
809 801
 
810 802
 $dbi->delete_all(table => 'table1');
811 803
 $dbi->insert(table => 'table1', param => {key1 => 'a:b c:d', key2 => 2});