Adding datetime_undef_if_invalid to squelch errors on DateTime inflation of bogus...
J. Shirley [Fri, 18 Jul 2008 16:48:10 +0000 (16:48 +0000)]
Changes
lib/DBIx/Class/InflateColumn/DateTime.pm
t/89inflate_datetime.t
t/lib/DBICTest/Schema/Event.pm

diff --git a/Changes b/Changes
index e6bd62d..dfa9b22 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,5 +1,7 @@
 Revision history for DBIx::Class
 
+        - Added datetime_undef_if_invalid for InflateColumn::DateTime to
+          return undef on invalid date/time values
         - Added search_related_rs method to ResultSet
         - add a make_column_dirty method to Row to force updates
         - throw a clear exception when user tries multi-has_many prefetch
index a650d69..e1c5de7 100644 (file)
@@ -53,6 +53,18 @@ Chains with the L<DBIx::Class::Row/register_column> method, and sets
 up datetime columns appropriately.  This would not normally be
 directly called by end users.
 
+In the case of an invalid date, L<DateTime> will throw an exception.  To
+bypass these exceptions and just have the inflation return undef, use
+the C<datetime_undef_if_invalid> option in the column info:
+  
+    "broken_date",
+    {
+        data_type => "datetime",
+        default_value => '0000-00-00',
+        is_nullable => 1,
+        datetime_undef_if_invalid => 1
+    }
+
 =cut
 
 sub register_column {
@@ -73,7 +85,8 @@ sub register_column {
         {
           inflate => sub {
             my ($value, $obj) = @_;
-            my $dt = $obj->_datetime_parser->$parse($value);
+            my $dt = eval { $obj->_datetime_parser->$parse($value); };
+            die "Error while inflating ${value} for ${column} on ${self}: $@" if $@ and not $info->{datetime_undef_if_invalid};
             $dt->set_time_zone($timezone) if $timezone;
             return $dt;
           },
index d92340c..2313426 100644 (file)
@@ -10,7 +10,7 @@ my $schema = DBICTest->init_schema();
 eval { require DateTime::Format::MySQL };
 plan skip_all => "Need DateTime::Format::MySQL for inflation tests" if $@;
 
-plan tests => 17;
+plan tests => 21;
 
 # inflation test
 my $event = $schema->resultset("Event")->find(1);
@@ -70,3 +70,25 @@ $created_on = $loaded_event->created_on;
 is("$created_on", '2006-01-31T12:34:56', 'Loaded correct timestamp using timezone');
 is($created_on->time_zone->name, 'America/Chicago', 'Correct timezone');
 
+# This should fail to set
+my $prev_str = "$created_on";
+$loaded_event->update({ created_on => '0000-00-00' });
+is("$created_on", $prev_str, "Don't update invalid dates");
+
+my $invalid = $schema->resultset('Event')->create({
+    starts_at  => '0000-00-00',
+    created_on => $created_on
+});
+
+is( $invalid->get_column('starts_at'), '0000-00-00', "Invalid date stored" );
+is( $invalid->starts_at, undef, "Inflate to undef" );
+
+$invalid->created_on('0000-00-00');
+$invalid->update;
+
+{
+    local $@;
+    eval { $invalid->created_on };
+    like( $@, qr/invalid date format/i, "Invalid date format exception");
+}
+
index bce3e34..ea787f5 100644 (file)
@@ -10,7 +10,7 @@ __PACKAGE__->table('event');
 
 __PACKAGE__->add_columns(
   id => { data_type => 'integer', is_auto_increment => 1 },
-  starts_at => { data_type => 'datetime' },
+  starts_at => { data_type => 'datetime', datetime_undef_if_invalid => 1 },
   created_on => { data_type => 'timestamp' }
 );