Add datetime adding and now to MSSQL
Arthur Axel 'fREW' Schmidt [Thu, 3 Feb 2011 20:40:06 +0000 (14:40 -0600)]
lib/DBIx/Class/SQLMaker/DateOps.pm
lib/DBIx/Class/SQLMaker/MSSQL.pm
t/sqlmaker/op_dt.t

index 40e7514..4224e53 100644 (file)
@@ -196,6 +196,12 @@ sub _where_op_ADD_DATETIME {
   return $self->_datetime_add_sql($part, $all_sql[0], $all_sql[1]), @all_bind
 }
 
+sub _reorder_diff_datetime_vars {
+   my ($self, $d1, $d2) = @_;
+
+   return ($d1, $d2);
+}
+
 sub _where_op_DIFF_DATETIME {
   my ($self) = @_;
 
@@ -218,6 +224,7 @@ sub _where_op_DIFF_DATETIME {
   my ($part, @val) = @$vals;
   my $placeholder = $self->_convert('?');
 
+  @val = $self->_reorder_diff_datetime_vars(@val);
   my (@all_sql, @all_bind);
   foreach my $val (@val) {
     my ($sql, @bind) = $self->_SWITCH_refkind($val, {
index 9800945..96f0993 100644 (file)
@@ -10,6 +10,8 @@ sub _rno_default_order {
   return \ '(SELECT(1))';
 }
 
+sub _datetime_now_sql { 'NOW()' }
+
 {
   my %part_map = (
      year         => 'year',
@@ -23,6 +25,7 @@ sub _rno_default_order {
      minute       => 'minute',
      second       => 'second',
      millisecond  => 'millisecond',
+     nanosecond   => 'nanosecond',
   );
 
   my %diff_part_map = %part_map;
@@ -33,12 +36,28 @@ sub _rno_default_order {
   sub _datetime_sql {
     die $_[0]->_unsupported_date_extraction($_[1], 'Microsoft SQL Server')
        unless exists $part_map{$_[1]};
-    "DATEPART('$part_map{$_[1]}', $_[2])"
+    "DATEPART($part_map{$_[1]}, $_[2])"
   }
   sub _datetime_diff_sql {
     die $_[0]->_unsupported_date_diff($_[1], 'Microsoft SQL Server')
        unless exists $diff_part_map{$_[1]};
-    "DATEDIFF('$diff_part_map{$_[1]}', $_[2], $_[3])"
+    "DATEDIFF($diff_part_map{$_[1]}, $_[2], $_[3])"
+  }
+
+  sub _reorder_diff_datetime_vars {
+    my ($self, $d1, $d2) = @_;
+
+    return ($d2, $d1);
+  }
+
+  sub _datetime_add_sql {
+    my ($self, $part, $amount, $date) = @_;
+
+    die $self->_unsupported_date_adding($part, 'Microsoft SQL Server')
+      unless exists $diff_part_map{$part};
+
+    my $placeholder = $self->_convert('?');
+    return "(DATEADD($diff_part_map{$part}, $amount, $date))"
   }
 }
 
index 2bf4615..2060ddf 100644 (file)
@@ -7,15 +7,65 @@ use Test::Exception;
 use lib qw(t/lib);
 use DBIC::SqlMakerTest;
 use DateTime;
+use DBIx::Class::SQLMaker::MSSQL;
+use Try::Tiny;
 
-use_ok('DBICTest');
+use DBICTest;
 
-my $schema = DBICTest->init_schema();
+my %dbs_to_test = (
+   sqlite => 1,
+   mssql  => 0,
+);
+
+my %schema = (
+   sqlite => DBICTest->init_schema( no_populate => 1 ),
+   mssql => do {
+      my ($dsn, $user, $pass) = @ENV{map { "DBICTEST_MSSQL_ODBC_${_}" } qw/DSN USER PASS/};
+      if ($dsn && $user) {
+         my $s = DBICTest::Schema->connect($dsn, $user, $pass);
+         try { $s->storage->ensure_connected };
 
-my %sql_maker = (
-   sqlite => $schema->storage->sql_maker,
+         $s->storage->dbh_do (sub {
+             my ($storage, $dbh) = @_;
+             eval { $dbh->do("DROP TABLE event") };
+             $dbh->do(<<'SQL');
+CREATE TABLE event (
+   id INT IDENTITY NOT NULL,
+   starts_at DATE NOT NULL,
+   created_on DATETIME NOT NULL,
+   varchar_date VARCHAR(20),
+   varchar_datetime VARCHAR(20),
+   skip_inflation DATETIME,
+   ts_without_tz DATETIME,
+
+   primary key(id)
+)
+SQL
+        $dbs_to_test{mssql} = 1;
+});
+$s;
+      } else {
+         DBICTest->init_schema( no_deploy=> 1, storage_type => '::DBI::MSSQL' )
+      }
+   },
 );
 
+my %rs = map { $_ => $schema{$_}->resultset('Event') } keys %schema;
+
+$rs{sqlite}->populate([
+ [qw(starts_at created_on skip_inflation)],
+ ['2010-12-12', '2010-12-14 12:12:12', '2019-12-12 12:12:12'],
+ ['2010-12-12', '2011-12-14 12:12:12', '2011-12-12 12:12:12'],
+]);
+
+$rs{mssql}->populate([
+ [qw(starts_at created_on skip_inflation)],
+ ['2010-12-12', '2010-12-14 12:12:12.000', '2019-12-12 12:12:12.000'],
+ ['2010-12-12', '2011-12-14 12:12:12.000', '2011-12-12 12:12:12.000'],
+]) if $schema{mssql}->storage->connected;
+
+#my %sql_maker = map { $_ => $schema{$_}->storage->sql_maker } keys %schema;
+
 my $date = DateTime->new(
    year => 2010,
    month => 12,
@@ -25,183 +75,361 @@ my $date = DateTime->new(
    second => 12,
 );
 
+sub hri_thing {
+   return {
+      starts_at => $_[0],
+      created_on => $_[1],
+      skip_inflation => $_[2]
+   }
+}
+
 my $date2 = $date->clone->set_day(16);
 
 my @tests = (
   {
-    func   => 'select',
-    args   => ['artist', '*', { 'artist.when_began' => { -dt => $date } }],
+    search => { 'me.created_on' => { -dt => $date } },
     sqlite => {
-       stmt   => 'SELECT * FROM artist WHERE artist.when_began = ?',
-       bind   => [[ 'artist.when_began', '2010-12-14 12:12:12' ]],
+      select => 'me.starts_at, me.created_on, me.skip_inflation',
+      where  => 'me.created_on = ?',
+      bind   => [[ 'me.created_on', '2010-12-14 12:12:12' ]],
+      hri    => [hri_thing('2010-12-12', '2010-12-14 12:12:12', '2019-12-12 12:12:12')],
     },
-    msg => '-dt_now works',
-  },
-  {
-    func   => 'update',
-    args   => ['artist',
-      { 'artist.when_began' => { -dt => $date } },
-      { 'artist.when_ended' => { '<' => { -dt => $date2 } } }
-    ],
-    sqlite => {
-       stmt   => 'UPDATE artist SET artist.when_began = ?  WHERE artist.when_ended < ?  ',
-       bind   => [
-         [ 'artist.when_began', '2010-12-14 12:12:12' ],
-         [ 'artist.when_ended', '2010-12-16 12:12:12' ],
-       ],
+    mssql => {
+      select => 'me.starts_at, me.created_on, me.skip_inflation',
+      where  => 'me.created_on = ?',
+      bind   => [[ 'me.created_on', '2010-12-14 12:12:12.000' ]],
+      hri    => [hri_thing('2010-12-12', '2010-12-14 12:12:12.000', '2019-12-12 12:12:12.000')],
     },
     msg => '-dt_now works',
   },
+
   {
-    func   => 'select',
-    args   => ['artist', [ [ -dt_year => { -ident => 'artist.when_began' } ] ]],
+    search => { 'me.id' => 1 },
+    select => [ [ -dt_year => { -ident => 'me.created_on' } ] ],
+    as     => [ 'year' ],
+    mssql => {
+      select => "DATEPART(year, me.created_on)",
+      where => "me.id = ?",
+      bind   => [['me.id' => 1 ]],
+      hri    => [{ year => 2010 }],
+    },
     sqlite => {
-      stmt   => "SELECT STRFTIME('%Y', artist.when_began) FROM artist",
-       bind   => [],
+      select => "STRFTIME('%Y', me.created_on)",
+      where => "me.id = ?",
+      bind   => [['me.id' => 1 ]],
+      hri    => [{ year => 2010 }],
     },
     msg    => '-dt_year works',
   },
+
   {
-    func   => 'select',
-    args   => ['artist', [ [ -dt_month => { -ident => 'artist.when_began' } ] ]],
+    search => { 'me.id' => 1 },
+    select   => [ [ -dt_month => { -ident => 'me.created_on' } ] ],
+    as       => [ 'month' ],
     sqlite => {
-      stmt   => "SELECT STRFTIME('%m', artist.when_began) FROM artist",
-      bind   => [],
+      select   => "STRFTIME('%m', me.created_on)",
+      where => "me.id = ?",
+      bind   => [['me.id' => 1 ]],
+      hri    => [{ month => 12 }],
+    },
+    mssql => {
+      select => "DATEPART(month, me.created_on)",
+      where => "me.id = ?",
+      bind   => [['me.id' => 1 ]],
+      hri    => [{ month => 12 }],
     },
     msg    => '-dt_month works',
   },
+
   {
-    func   => 'select',
-    args   => ['artist', [ [ -dt_day => { -ident => 'artist.when_began' } ] ]],
+    search => { 'me.id' => 1 },
+    select   => [ [ -dt_day => { -ident => 'me.created_on' } ] ],
+    as       => [ 'day' ],
     sqlite => {
-      stmt   => "SELECT STRFTIME('%d', artist.when_began) FROM artist",
-      bind   => [],
+      select   => "STRFTIME('%d', me.created_on)",
+      where => "me.id = ?",
+      bind   => [['me.id' => 1 ]],
+      hri    => [{ day => 14 }],
+    },
+    mssql => {
+      select => "DATEPART(day, me.created_on)",
+      where => "me.id = ?",
+      bind   => [['me.id' => 1 ]],
+      hri    => [{ day => 14 }],
     },
     msg    => '-dt_day works',
   },
+
   {
-    func   => 'select',
-    args   => ['artist', [ [ -dt_hour => { -ident => 'artist.when_began' } ] ]],
+    search => { 'me.id' => 1 },
+    select   => [ [ -dt_hour => { -ident => 'me.created_on' } ] ],
+    as       => [ 'hour' ],
     sqlite => {
-      stmt   => "SELECT STRFTIME('%H', artist.when_began) FROM artist",
-      bind   => [],
+      select   => "STRFTIME('%H', me.created_on)",
+      where => "me.id = ?",
+      bind   => [['me.id' => 1 ]],
+      hri    => [{ hour => 12 }],
+    },
+    mssql => {
+      select => "DATEPART(hour, me.created_on)",
+      where => "me.id = ?",
+      bind   => [['me.id' => 1 ]],
+      hri    => [{ hour => 12 }],
     },
     msg    => '-dt_hour works',
   },
+
   {
-    func   => 'select',
-    args   => ['artist', [ [ -dt_minute => { -ident => 'artist.when_began' } ] ]],
+    search => { 'me.id' => 1 },
+    select   => [ [ -dt_minute => { -ident => 'me.created_on' } ] ],
+    as       => [ 'minute' ],
     sqlite => {
-      stmt   => "SELECT STRFTIME('%M', artist.when_began) FROM artist",
-      bind   => [],
+      select   => "STRFTIME('%M', me.created_on)",
+      where => "me.id = ?",
+      bind   => [['me.id' => 1 ]],
+      hri    => [{ minute => 12 }],
+    },
+    mssql => {
+      select => "DATEPART(minute, me.created_on)",
+      where => "me.id = ?",
+      bind   => [['me.id' => 1 ]],
+      hri    => [{ minute => 12 }],
     },
     msg    => '-dt_minute works',
   },
+
   {
-    func   => 'select',
-    args   => ['artist', [ [ -dt_second => { -ident => 'artist.when_began' } ] ]],
+    search => { 'me.id' => 1 },
+    select   => [ [ -dt_second => { -ident => 'me.created_on' } ] ],
+    as       => [ 'second' ],
     sqlite => {
-      stmt   => "SELECT STRFTIME('%s', artist.when_began) FROM artist",
-      bind   => [],
+      select   => "STRFTIME('%S', me.created_on)",
+      where => "me.id = ?",
+      bind   => [['me.id' => 1 ]],
+      hri    => [{ second => 12 }],
+    },
+    mssql => {
+      select => "DATEPART(second, me.created_on)",
+      where => "me.id = ?",
+      bind   => [['me.id' => 1 ]],
+      hri    => [{ second => 12 }],
     },
     msg    => '-dt_second works',
   },
+
   {
-    func   => 'select',
-    args   => ['artist', [ [ -dt_diff => [second => { -ident => 'artist.when_ended' }, \'artist.when_began' ] ] ]],
+    search => { 'me.id' => 2 },
+    select   => [ [ -dt_diff => [second => { -ident => 'me.created_on' }, \'me.skip_inflation' ] ] ],
+    as => [ 'sec_diff' ],
     sqlite => {
-      stmt   => "SELECT (STRFTIME('%s', artist.when_ended) - STRFTIME('%s', artist.when_began)) FROM artist",
-      bind   => [],
+      select   => "(STRFTIME('%s', me.created_on) - STRFTIME('%s', me.skip_inflation))",
+      where => "me.id = ?",
+      bind   => [['me.id' => 2 ]],
+      hri => [{ sec_diff => 2*24*60*60 }],
+    },
+    mssql => {
+      select   => "DATEDIFF(second, me.skip_inflation, me.created_on)",
+      where => "me.id = ?",
+      bind   => [['me.id' => 2 ]],
+      hri => [{ sec_diff => 2*24*60*60 }],
     },
     msg    => '-dt_diff (second) works',
   },
+
   {
-    func   => 'select',
-    args   => ['artist', [ [ -dt_diff => [day => { -ident => 'artist.when_ended' }, \'artist.when_began' ] ] ]],
+    search => { 'me.id' => 2 },
+    select   => [ [ -dt_diff => [day => { -ident => 'me.created_on' }, \'me.skip_inflation' ] ] ],
+    as => [ 'day_diff' ],
     sqlite => {
-      stmt   => "SELECT (JULIANDAY(artist.when_ended) - JULIANDAY(artist.when_began)) FROM artist",
-      bind   => [],
+      select   => "(JULIANDAY(me.created_on) - JULIANDAY(me.skip_inflation))",
+      where => "me.id = ?",
+      bind   => [['me.id' => 2 ]],
+      hri => [{ day_diff => 2 }],
+    },
+    mssql => {
+      select   => "DATEDIFF(dayofyear, me.skip_inflation, me.created_on)",
+      where => "me.id = ?",
+      bind   => [['me.id' => 2 ]],
+      hri => [{ day_diff => 2 }],
     },
     msg    => '-dt_diff (day) works',
   },
+
   {
-    func   => 'select',
-    args   => ['artist', [ [ -dt_add => [year => 3, { -ident => 'artist.when_ended' } ] ] ]],
+    search => { 'me.id' => 2 },
+    select   => [ [ -dt_add => [year => 3, { -ident => 'me.created_on' } ] ] ],
+    as   => [ 'date' ],
     sqlite => {
-      stmt   => "SELECT (datetime(artist.when_ended, ? || ' years')) FROM artist",
-      bind   => [[ '', 3 ]],
+      select => "(datetime(me.created_on, ? || ' years'))",
+      where => "me.id = ?",
+      bind   => [['', 3], ['me.id' => 2 ]],
+      hri    => [{ date => '2014-12-14 12:12:12' }],
+    },
+    mssql => {
+      select => "(DATEADD(year, ?, me.created_on))",
+      where => "me.id = ?",
+      bind   => [['', 3], ['me.id' => 2 ]],
+      hri    => [{ date => '2014-12-14 12:12:12.000' }],
+      skip   => 'need working bindtypes',
     },
     msg    => '-dt_add (year) works',
   },
+
   {
-    func   => 'select',
-    args   => ['artist', [ [ -dt_add => [month => 3, { -ident => 'artist.when_ended' } ] ] ]],
+    search => { 'me.id' => 2 },
+    select   => [ [ -dt_add => [month => 3, { -ident => 'me.created_on' } ] ] ],
+    as   => [ 'date' ],
     sqlite => {
-      stmt   => "SELECT (datetime(artist.when_ended, ? || ' months')) FROM artist",
-      bind   => [[ '', 3 ]],
+      select => "(datetime(me.created_on, ? || ' months'))",
+      where => "me.id = ?",
+      bind   => [['', 3], ['me.id' => 2 ]],
+      hri    => [{ date => '2012-03-14 12:12:12' }],
+    },
+    mssql => {
+      select => "(DATEADD(month, ?, me.created_on))",
+      where => "me.id = ?",
+      bind   => [['', 3], ['me.id' => 2 ]],
+      hri    => [{ date => '2012-03-14 12:12:12.000' }],
+      skip   => 'need working bindtypes',
     },
     msg    => '-dt_add (month) works',
   },
+
   {
-    func   => 'select',
-    args   => ['artist', [ [ -dt_add => [day => 3, { -ident => 'artist.when_ended' } ] ] ]],
+    search => { 'me.id' => 2 },
+    select   => [ [ -dt_add => [day => 3, { -ident => 'me.created_on' } ] ] ],
+    as   => [ 'date' ],
     sqlite => {
-      stmt   => "SELECT (datetime(artist.when_ended, ? || ' days')) FROM artist",
-      bind   => [[ '', 3 ]],
+      select => "(datetime(me.created_on, ? || ' days'))",
+      where => "me.id = ?",
+      bind   => [['', 3], ['me.id' => 2 ]],
+      hri    => [{ date => '2011-12-17 12:12:12' }],
+    },
+    mssql => {
+      select => "(DATEADD(dayofyear, ?, me.created_on))",
+      where => "me.id = ?",
+      bind   => [['', 3], ['me.id' => 2 ]],
+      hri    => [{ date => '2011-12-17 12:12:12.000' }],
+      skip   => 'need working bindtypes',
     },
     msg    => '-dt_add (day) works',
   },
+
   {
-    func   => 'select',
-    args   => ['artist', [ [ -dt_add => [hour => 3, { -ident => 'artist.when_ended' } ] ] ]],
+    search => { 'me.id' => 2 },
+    select   => [ [ -dt_add => [hour => 3, { -ident => 'me.created_on' } ] ] ],
+    as   => [ 'date' ],
     sqlite => {
-      stmt   => "SELECT (datetime(artist.when_ended, ? || ' hours')) FROM artist",
-      bind   => [[ '', 3 ]],
+      select => "(datetime(me.created_on, ? || ' hours'))",
+      where => "me.id = ?",
+      bind   => [['', 3], ['me.id' => 2 ]],
+      hri    => [{ date => '2011-12-14 15:12:12' }],
+    },
+    mssql => {
+      select => "(DATEADD(hour, ?, me.created_on))",
+      where => "me.id = ?",
+      bind   => [['', 3], ['me.id' => 2 ]],
+      hri    => [{ date => '2011-12-14 15:12:12.000' }],
+      skip   => 'need working bindtypes',
     },
     msg    => '-dt_add (hour) works',
   },
+
   {
-    func   => 'select',
-    args   => ['artist', [ [ -dt_add => [minute => 3, { -ident => 'artist.when_ended' } ] ] ]],
+    search => { 'me.id' => 2 },
+    select   => [ [ -dt_add => [minute => 3, { -ident => 'me.created_on' } ] ] ],
+    as   => [ 'date' ],
     sqlite => {
-      stmt   => "SELECT (datetime(artist.when_ended, ? || ' minutes')) FROM artist",
-      bind   => [[ '', 3 ]],
+      select => "(datetime(me.created_on, ? || ' minutes'))",
+      where => "me.id = ?",
+      bind   => [['', 3], ['me.id' => 2 ]],
+      hri    => [{ date => '2011-12-14 12:15:12' }],
+    },
+    mssql => {
+      select => "(DATEADD(minute, ?, me.created_on))",
+      where => "me.id = ?",
+      bind   => [['', 3], ['me.id' => 2 ]],
+      hri    => [{ date => '2011-12-14 12:15:12.000' }],
+      skip   => 'need working bindtypes',
     },
     msg    => '-dt_add (minute) works',
   },
+
   {
-    func   => 'select',
-    args   => ['artist', [ [ -dt_add => [second => 3, { -ident => 'artist.when_ended' } ] ] ]],
+    search => { 'me.id' => 2 },
+    select   => [ [ -dt_add => [second => 3, { -ident => 'me.created_on' } ] ] ],
+    as   => [ 'date' ],
     sqlite => {
-      stmt   => "SELECT (datetime(artist.when_ended, ? || ' seconds')) FROM artist",
-      bind   => [[ '', 3 ]],
+      select => "(datetime(me.created_on, ? || ' seconds'))",
+      where => "me.id = ?",
+      bind   => [['', 3], ['me.id' => 2 ]],
+      hri    => [{ date => '2011-12-14 12:12:15' }],
+    },
+    mssql => {
+      select => "(DATEADD(second, ?, me.created_on))",
+      where => "me.id = ?",
+      bind   => [['', 3], ['me.id' => 2 ]],
+      hri    => [{ date => '2011-12-14 12:12:15.000' }],
+      skip   => 'need working bindtypes',
     },
     msg    => '-dt_add (second) works',
   },
+
   {
-    func   => 'select',
-    args   => ['artist', [ [ -dt_diff => [year => \'artist.when_started', { -ident => 'artist.when_ended' } ] ] ]],
+    search => { 'me.id' => 2 },
+    select   => [ [ -dt_add => [second => 3, { -dt_add => [ day => 1, { -ident => 'me.created_on' } ] } ] ] ],
+    as       => [ 'date' ],
+    sqlite => {
+      select   => "(datetime((datetime(me.created_on, ? || ' days')), ? || ' seconds'))",
+      where => "me.id = ?",
+      bind   => [['', 1], [ '', 3 ], ['me.id', 2]],
+      hri    => [{ date => '2011-12-15 12:12:15' }],
+    },
+    mssql => {
+      select => "(DATEADD(second, ?, (DATEADD(dayofyear, ?, me.created_on))))",
+      where => "me.id = ?",
+      bind   => [['', 3], [ '', 1 ], ['me.id', 2]],
+      hri    => [{ date => '2011-12-15 12:12:15.000' }],
+      skip   => 'need working bindtypes',
+    },
+    msg    => 'nested -dt_add works',
+  },
+
+  {
+    search => { 'me.id' => 2 },
+    select   => [ [ -dt_diff => [year => \'me.starts_at', { -ident => 'me.created_on' } ] ] ],
+    as       => [ 'year' ],
     sqlite => {
       exception_like => qr/date diff not supported for part "year" with database "SQLite"/,
     },
+    mssql => {
+      select   => "DATEDIFF(year, me.created_on, me.starts_at)",
+      where => "me.id = ?",
+      bind   => [['me.id', 2]],
+      hri    => [{ year => -1 }],
+    },
+    msg => '-dt_diff (year) works',
   },
 );
 
 for my $t (@tests) {
-  local $"=', ';
 
   DB_TEST:
-  for my $db (keys %sql_maker) {
-     my $maker = $sql_maker{$db};
-
+  for my $db (keys %rs) {
      my $db_test = $t->{$db};
      next DB_TEST unless $db_test;
 
-     my($stmt, @bind);
+     my ($r, $my_rs);
 
      my $cref = sub {
-       my $op = $t->{func};
-       ($stmt, @bind) = $maker->$op (@ { $t->{args} } );
+       my $stuff = {
+         ( exists $t->{select}
+           ? ( select => $t->{select}, as => $t->{as} )
+           : ( columns => [qw(starts_at created_on skip_inflation)] )
+         )
+       };
+       $my_rs = $rs{$db}->search($t->{search}, $stuff);
+       $r = $my_rs->as_query
      };
 
      if ($db_test->{exception_like}) {
@@ -222,12 +450,24 @@ for my $t (@tests) {
          $cref->();
        }
        is_same_sql_bind(
-         $stmt,
-         \@bind,
-         $db_test->{stmt},
+         $r,
+         "(SELECT $db_test->{select} FROM event me WHERE $db_test->{where})",
          $db_test->{bind},
-         ($t->{msg} ? $t->{msg} : ())
+         ($t->{msg} ? "$t->{msg} ($db)" : ())
        );
+
+       SKIP: {
+       if (my $hri = $db_test->{hri}) {
+          skip "Cannot test database we are not connected to ($db)", 1 unless $dbs_to_test{$db};
+          skip $db_test->{skip} . " ($db)", 1 if $db_test->{skip};
+
+          my $msg = ($t->{msg} ? "$t->{msg} ($db actually pulls expected data)" : '');
+          try {
+             is_deeply [ $my_rs->hri_dump->all ], $hri, $msg;
+          } catch {
+             ok 0, $msg . " $_";
+          }
+        } }
      }
   }
 }