From: Peter Rabbitson Date: Thu, 11 Jun 2009 13:02:41 +0000 (+0000) Subject: IC::DT changes: X-Git-Tag: v0.08106~9 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=40f751811e773082d1cc654f15f06ef65749a9e9;p=dbsrgits%2FDBIx-Class.git IC::DT changes: Switch SQLite storage to DT::F::SQLite Fix exception when undef_if_invalid and timezone are both set on a column Split t/89inflate_datetime into separate tests Adjust makefile author dependencies --- diff --git a/Makefile.PL b/Makefile.PL index 826c3bc..3713df1 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -73,12 +73,17 @@ my %force_requires_if_author = ( 'Test::Memory::Cycle' => 0, 'Devel::Cycle' => 1.10, + # t/inflate/datetime*.t + # t/72.pg + # t/36datetime.t # t/60core.t + 'DateTime::Format::SQLite' => 0, 'DateTime::Format::MySQL' => 0, - - # t/89inflate_datetime.t 'DateTime::Format::Pg' => 0, + # t/96_is_deteministic_value.t + 'DateTime::Format::Strptime' => 0, + # t/72pg.t $ENV{DBICTEST_PG_DSN} ? ('Sys::SigAction'=> 0) @@ -92,8 +97,6 @@ my %force_requires_if_author = ( 'namespace::clean' => 0.11, 'Hash::Merge', => 0.11, - # t/96_is_deteministic_value.t - 'DateTime::Format::Strptime' => 0, ); if ($Module::Install::AUTHOR) { diff --git a/lib/DBIx/Class/InflateColumn/DateTime.pm b/lib/DBIx/Class/InflateColumn/DateTime.pm index d006e55..5646768 100644 --- a/lib/DBIx/Class/InflateColumn/DateTime.pm +++ b/lib/DBIx/Class/InflateColumn/DateTime.pm @@ -148,9 +148,13 @@ sub register_column { { inflate => sub { my ($value, $obj) = @_; + my $dt = eval { $obj->_inflate_to_datetime( $value, \%info ) }; - $self->throw_exception ("Error while inflating ${value} for ${column} on ${self}: $@") - if $@ and not $undef_if_invalid; + if (my $err = $@ ) { + return undef if ($undef_if_invalid); + $self->throw_exception ("Error while inflating ${value} for ${column} on ${self}: $err"); + } + $dt->set_time_zone($timezone) if $timezone; $dt->set_locale($locale) if $locale; return $dt; diff --git a/lib/DBIx/Class/Storage/DBI/SQLite.pm b/lib/DBIx/Class/Storage/DBI/SQLite.pm index 5e125c9..7fada30 100644 --- a/lib/DBIx/Class/Storage/DBI/SQLite.pm +++ b/lib/DBIx/Class/Storage/DBI/SQLite.pm @@ -45,6 +45,8 @@ sub backup return $backupfile; } +sub datetime_parser_type { return "DateTime::Format::SQLite"; } + 1; =head1 NAME diff --git a/t/36datetime.t b/t/36datetime.t index d0d6aef..380242d 100644 --- a/t/36datetime.t +++ b/t/36datetime.t @@ -5,9 +5,8 @@ use Test::More; use lib qw(t/lib); use DBICTest; -eval { require DateTime::Format::MySQL }; - -plan $@ ? ( skip_all => 'Requires DateTime::Format::MySQL' ) +eval { require DateTime::Format::SQLite }; +plan $@ ? ( skip_all => 'Requires DateTime::Format::SQLite' ) : ( tests => 3 ); my $schema = DBICTest->init_schema( @@ -24,8 +23,6 @@ is( my $parser = $schema->storage->datetime_parser(); -# We're currently expecting a MySQL parser. May change in future. -is($parser, 'DateTime::Format::MySQL', 'Got expected datetime_parser'); - +is($parser, 'DateTime::Format::SQLite', 'Got expected storage-set datetime_parser'); isa_ok($schema->storage, 'DBIx::Class::Storage::DBI::SQLite', 'storage'); diff --git a/t/89inflate_datetime.t b/t/89inflate_datetime.t deleted file mode 100644 index d165c33..0000000 --- a/t/89inflate_datetime.t +++ /dev/null @@ -1,174 +0,0 @@ -use strict; -use warnings; - -use Test::More; -use lib qw(t/lib); -use DBICTest; - -{ - local $SIG{__WARN__} = sub { warn @_ if $_[0] !~ /extra \=\> .+? has been deprecated/ }; - DBICTest::Schema->load_classes('EventTZDeprecated'); - DBICTest::Schema->load_classes('EventTZPg'); -} - -my $schema = DBICTest->init_schema(); - -plan tests => 57; - -SKIP: { - eval { require DateTime::Format::MySQL }; - skip "Need DateTime::Format::MySQL for inflation tests", 50 if $@; - - -# inflation test -my $event = $schema->resultset("Event")->find(1); - -isa_ok($event->starts_at, 'DateTime', 'DateTime returned'); - -# klunky, but makes older Test::More installs happy -my $starts = $event->starts_at; -is("$starts", '2006-04-25T22:24:33', 'Correct date/time'); - -TODO: { - local $TODO = "We can't do this yet before 0.09" if DBIx::Class->VERSION < 0.09; - - ok(my $row = - $schema->resultset('Event')->search({ starts_at => $starts })->single); - is(eval { $row->id }, 1, 'DT in search'); - - ok($row = - $schema->resultset('Event')->search({ starts_at => { '>=' => $starts } })->single); - is(eval { $row->id }, 1, 'DT in search with condition'); -} - -# create using DateTime -my $created = $schema->resultset('Event')->create({ - starts_at => DateTime->new(year=>2006, month=>6, day=>18), - created_on => DateTime->new(year=>2006, month=>6, day=>23) -}); -my $created_start = $created->starts_at; - -isa_ok($created->starts_at, 'DateTime', 'DateTime returned'); -is("$created_start", '2006-06-18T00:00:00', 'Correct date/time'); - -## timestamp field -isa_ok($event->created_on, 'DateTime', 'DateTime returned'); - -## varchar fields -isa_ok($event->varchar_date, 'DateTime', 'DateTime returned'); -isa_ok($event->varchar_datetime, 'DateTime', 'DateTime returned'); - -## skip inflation field -isnt(ref($event->skip_inflation), 'DateTime', 'No DateTime returned for skip inflation column'); - -# klunky, but makes older Test::More installs happy -my $createo = $event->created_on; -is("$createo", '2006-06-22T21:00:05', 'Correct date/time'); - -my $created_cron = $created->created_on; - -isa_ok($created->created_on, 'DateTime', 'DateTime returned'); -is("$created_cron", '2006-06-23T00:00:00', 'Correct date/time'); - - -# Test "timezone" parameter - -foreach my $tbl (qw/EventTZ EventTZDeprecated/) { - my $event_tz = $schema->resultset($tbl)->create({ - starts_at => DateTime->new(year=>2007, month=>12, day=>31, time_zone => "America/Chicago" ), - created_on => DateTime->new(year=>2006, month=>1, day=>31, - hour => 13, minute => 34, second => 56, time_zone => "America/New_York" ), - }); - - is ($event_tz->starts_at->day_name, "Montag", 'Locale de_DE loaded: day_name'); - is ($event_tz->starts_at->month_name, "Dezember", 'Locale de_DE loaded: month_name'); - is ($event_tz->created_on->day_name, "Tuesday", 'Default locale loaded: day_name'); - is ($event_tz->created_on->month_name, "January", 'Default locale loaded: month_name'); - - my $starts_at = $event_tz->starts_at; - is("$starts_at", '2007-12-31T00:00:00', 'Correct date/time using timezone'); - - my $created_on = $event_tz->created_on; - is("$created_on", '2006-01-31T12:34:56', 'Correct timestamp using timezone'); - is($event_tz->created_on->time_zone->name, "America/Chicago", "Correct timezone"); - - my $loaded_event = $schema->resultset($tbl)->find( $event_tz->id ); - - isa_ok($loaded_event->starts_at, 'DateTime', 'DateTime returned'); - $starts_at = $loaded_event->starts_at; - is("$starts_at", '2007-12-31T00:00:00', 'Loaded correct date/time using timezone'); - is($starts_at->time_zone->name, 'America/Chicago', 'Correct timezone'); - - isa_ok($loaded_event->created_on, 'DateTime', 'DateTime returned'); - $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'); - - # Test floating timezone warning - # We expect one warning - SKIP: { - skip "ENV{DBIC_FLOATING_TZ_OK} was set, skipping", 1 if $ENV{DBIC_FLOATING_TZ_OK}; - local $SIG{__WARN__} = sub { - like( - shift, - qr/You're using a floating timezone, please see the documentation of DBIx::Class::InflateColumn::DateTime for an explanation/, - 'Floating timezone warning' - ); - }; - my $event_tz_floating = $schema->resultset($tbl)->create({ - starts_at => DateTime->new(year=>2007, month=>12, day=>31, ), - created_on => DateTime->new(year=>2006, month=>1, day=>31, - hour => 13, minute => 34, second => 56, ), - }); - delete $SIG{__WARN__}; - }; - - # 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"); - } -} - -## varchar field using inflate_date => 1 -my $varchar_date = $event->varchar_date; -is("$varchar_date", '2006-07-23T00:00:00', 'Correct date/time'); - -## varchar field using inflate_datetime => 1 -my $varchar_datetime = $event->varchar_datetime; -is("$varchar_datetime", '2006-05-22T19:05:07', 'Correct date/time'); - -## skip inflation field -my $skip_inflation = $event->skip_inflation; -is ("$skip_inflation", '2006-04-21 18:04:06', 'Correct date/time'); - -} # Skip if no MySQL DT::Formatter - -SKIP: { - eval { require DateTime::Format::Pg }; - skip ('Need DateTime::Format::Pg for timestamp inflation tests', 3) if $@; - - my $event = $schema->resultset("EventTZPg")->find(1); - $event->update({created_on => '2009-01-15 17:00:00+00'}); - $event->discard_changes; - isa_ok($event->created_on, "DateTime") or diag $event->created_on; - is($event->created_on->time_zone->name, "America/Chicago", "Timezone changed"); - # Time zone difference -> -6hours - is($event->created_on->iso8601, "2009-01-15T11:00:00", "Time with TZ correct"); -} diff --git a/t/inflate/datetime.t b/t/inflate/datetime.t new file mode 100644 index 0000000..ae8fc3b --- /dev/null +++ b/t/inflate/datetime.t @@ -0,0 +1,76 @@ +use strict; +use warnings; + +use Test::More; +use lib qw(t/lib); +use DBICTest; + +my $schema = DBICTest->init_schema(); + +eval { require DateTime::Format::SQLite }; +plan $@ + ? ( skip_all => "Need DateTime::Format::SQLite for DT inflation tests" ) + : ( tests => 18 ) +; + +# inflation test +my $event = $schema->resultset("Event")->find(1); + +isa_ok($event->starts_at, 'DateTime', 'DateTime returned'); + +# klunky, but makes older Test::More installs happy +my $starts = $event->starts_at; +is("$starts", '2006-04-25T22:24:33', 'Correct date/time'); + +TODO: { + local $TODO = "We can't do this yet before 0.09" if DBIx::Class->VERSION < 0.09; + + ok(my $row = + $schema->resultset('Event')->search({ starts_at => $starts })->single); + is(eval { $row->id }, 1, 'DT in search'); + + ok($row = + $schema->resultset('Event')->search({ starts_at => { '>=' => $starts } })->single); + is(eval { $row->id }, 1, 'DT in search with condition'); +} + +# create using DateTime +my $created = $schema->resultset('Event')->create({ + starts_at => DateTime->new(year=>2006, month=>6, day=>18), + created_on => DateTime->new(year=>2006, month=>6, day=>23) +}); +my $created_start = $created->starts_at; + +isa_ok($created->starts_at, 'DateTime', 'DateTime returned'); +is("$created_start", '2006-06-18T00:00:00', 'Correct date/time'); + +## timestamp field +isa_ok($event->created_on, 'DateTime', 'DateTime returned'); + +## varchar fields +isa_ok($event->varchar_date, 'DateTime', 'DateTime returned'); +isa_ok($event->varchar_datetime, 'DateTime', 'DateTime returned'); + +## skip inflation field +isnt(ref($event->skip_inflation), 'DateTime', 'No DateTime returned for skip inflation column'); + +# klunky, but makes older Test::More installs happy +my $createo = $event->created_on; +is("$createo", '2006-06-22T21:00:05', 'Correct date/time'); + +my $created_cron = $created->created_on; + +isa_ok($created->created_on, 'DateTime', 'DateTime returned'); +is("$created_cron", '2006-06-23T00:00:00', 'Correct date/time'); + +## varchar field using inflate_date => 1 +my $varchar_date = $event->varchar_date; +is("$varchar_date", '2006-07-23T00:00:00', 'Correct date/time'); + +## varchar field using inflate_datetime => 1 +my $varchar_datetime = $event->varchar_datetime; +is("$varchar_datetime", '2006-05-22T19:05:07', 'Correct date/time'); + +## skip inflation field +my $skip_inflation = $event->skip_inflation; +is ("$skip_inflation", '2006-04-21 18:04:06', 'Correct date/time'); diff --git a/t/inflate/datetime_mysql.t b/t/inflate/datetime_mysql.t new file mode 100644 index 0000000..51368ad --- /dev/null +++ b/t/inflate/datetime_mysql.t @@ -0,0 +1,97 @@ +use strict; +use warnings; + +use Test::More; +use Test::Exception; +use lib qw(t/lib); +use DBICTest; +use DBICTest::Schema; + +{ + local $SIG{__WARN__} = sub { warn @_ if $_[0] !~ /extra \=\> .+? has been deprecated/ }; + DBICTest::Schema->load_classes('EventTZ'); + DBICTest::Schema->load_classes('EventTZDeprecated'); +} + +eval { require DateTime::Format::MySQL }; +plan $@ + ? ( skip_all => "Need DateTime::Format::MySQL for inflation tests") + : ( tests => 33 ) +; + +my $schema = DBICTest->init_schema(); + +# Test "timezone" parameter +foreach my $tbl (qw/EventTZ EventTZDeprecated/) { + my $event_tz = $schema->resultset($tbl)->create({ + starts_at => DateTime->new(year=>2007, month=>12, day=>31, time_zone => "America/Chicago" ), + created_on => DateTime->new(year=>2006, month=>1, day=>31, + hour => 13, minute => 34, second => 56, time_zone => "America/New_York" ), + }); + + is ($event_tz->starts_at->day_name, "Montag", 'Locale de_DE loaded: day_name'); + is ($event_tz->starts_at->month_name, "Dezember", 'Locale de_DE loaded: month_name'); + is ($event_tz->created_on->day_name, "Tuesday", 'Default locale loaded: day_name'); + is ($event_tz->created_on->month_name, "January", 'Default locale loaded: month_name'); + + my $starts_at = $event_tz->starts_at; + is("$starts_at", '2007-12-31T00:00:00', 'Correct date/time using timezone'); + + my $created_on = $event_tz->created_on; + is("$created_on", '2006-01-31T12:34:56', 'Correct timestamp using timezone'); + is($event_tz->created_on->time_zone->name, "America/Chicago", "Correct timezone"); + + my $loaded_event = $schema->resultset($tbl)->find( $event_tz->id ); + + isa_ok($loaded_event->starts_at, 'DateTime', 'DateTime returned'); + $starts_at = $loaded_event->starts_at; + is("$starts_at", '2007-12-31T00:00:00', 'Loaded correct date/time using timezone'); + is($starts_at->time_zone->name, 'America/Chicago', 'Correct timezone'); + + isa_ok($loaded_event->created_on, 'DateTime', 'DateTime returned'); + $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'); + + # Test floating timezone warning + # We expect one warning + SKIP: { + skip "ENV{DBIC_FLOATING_TZ_OK} was set, skipping", 1 if $ENV{DBIC_FLOATING_TZ_OK}; + local $SIG{__WARN__} = sub { + like( + shift, + qr/You're using a floating timezone, please see the documentation of DBIx::Class::InflateColumn::DateTime for an explanation/, + 'Floating timezone warning' + ); + }; + my $event_tz_floating = $schema->resultset($tbl)->create({ + starts_at => DateTime->new(year=>2007, month=>12, day=>31, ), + created_on => DateTime->new(year=>2006, month=>1, day=>31, + hour => 13, minute => 34, second => 56, ), + }); + delete $SIG{__WARN__}; + }; + + # 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"); +} + +# Test invalid DT +my $invalid = $schema->resultset('EventTZ')->create({ + starts_at => '0000-00-00', + created_on => DateTime->now, +}); + +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; + +throws_ok ( + sub { $invalid->created_on }, + qr/invalid date format/i, + "Invalid date format exception" +); diff --git a/t/inflate/datetime_pg.t b/t/inflate/datetime_pg.t new file mode 100644 index 0000000..054edf1 --- /dev/null +++ b/t/inflate/datetime_pg.t @@ -0,0 +1,30 @@ +use strict; +use warnings; + +use Test::More; +use lib qw(t/lib); +use DBICTest; + +{ + local $SIG{__WARN__} = sub { warn @_ if $_[0] !~ /extra \=\> .+? has been deprecated/ }; + DBICTest::Schema->load_classes('EventTZPg'); +} + +eval { require DateTime::Format::Pg }; +plan $@ + ? ( skip_all => 'Need DateTime::Format::Pg for timestamp inflation tests') + : ( tests => 3 ) +; + + +my $schema = DBICTest->init_schema(); + +{ + my $event = $schema->resultset("EventTZPg")->find(1); + $event->update({created_on => '2009-01-15 17:00:00+00'}); + $event->discard_changes; + isa_ok($event->created_on, "DateTime") or diag $event->created_on; + is($event->created_on->time_zone->name, "America/Chicago", "Timezone changed"); + # Time zone difference -> -6hours + is($event->created_on->iso8601, "2009-01-15T11:00:00", "Time with TZ correct"); +} diff --git a/t/lib/DBICTest/Schema/Event.pm b/t/lib/DBICTest/Schema/Event.pm index caecdc1..c56c1bd 100644 --- a/t/lib/DBICTest/Schema/Event.pm +++ b/t/lib/DBICTest/Schema/Event.pm @@ -10,7 +10,7 @@ __PACKAGE__->table('event'); __PACKAGE__->add_columns( id => { data_type => 'integer', is_auto_increment => 1 }, - starts_at => { data_type => 'datetime', datetime_undef_if_invalid => 1 }, + starts_at => { data_type => 'datetime' }, created_on => { data_type => 'timestamp' }, varchar_date => { data_type => 'varchar', inflate_date => 1, size => 20, is_nullable => 1 }, varchar_datetime => { data_type => 'varchar', inflate_datetime => 1, size => 20, is_nullable => 1 }, diff --git a/t/lib/DBICTest/Schema/EventTZ.pm b/t/lib/DBICTest/Schema/EventTZ.pm index 321b279..2d8df28 100644 --- a/t/lib/DBICTest/Schema/EventTZ.pm +++ b/t/lib/DBICTest/Schema/EventTZ.pm @@ -10,10 +10,15 @@ __PACKAGE__->table('event'); __PACKAGE__->add_columns( id => { data_type => 'integer', is_auto_increment => 1 }, - starts_at => { data_type => 'datetime', timezone => "America/Chicago", locale => 'de_DE' }, + starts_at => { data_type => 'datetime', timezone => "America/Chicago", locale => 'de_DE', datetime_undef_if_invalid => 1 }, created_on => { data_type => 'timestamp', timezone => "America/Chicago", floating_tz_ok => 1 }, ); __PACKAGE__->set_primary_key('id'); +sub _datetime_parser { + require DateTime::Format::MySQL; + DateTime::Format::MySQL->new(); +} + 1; diff --git a/t/lib/DBICTest/Schema/EventTZDeprecated.pm b/t/lib/DBICTest/Schema/EventTZDeprecated.pm index 8a9a11d..a667976 100644 --- a/t/lib/DBICTest/Schema/EventTZDeprecated.pm +++ b/t/lib/DBICTest/Schema/EventTZDeprecated.pm @@ -16,4 +16,10 @@ __PACKAGE__->add_columns( __PACKAGE__->set_primary_key('id'); +sub _datetime_parser { + require DateTime::Format::MySQL; + DateTime::Format::MySQL->new(); +} + + 1;