Retire DBIC::DebugObj, replace with $dbictest_schema->is_executed_sql_bind()
Peter Rabbitson [Tue, 27 May 2014 17:17:26 +0000 (19:17 +0200)]
This cuts down on a lot of the silliness with debugcb/debugobj, and makes
for more precise tests as a whole. Went through great pains to not disturb
any existing tests, fingercross this is indeed the case

Read under -w for sanity

17 files changed:
Makefile.PL
t/18insert_default.t
t/80unique.t
t/85utf8.t
t/93autocast.t
t/count/count_rs.t
t/lib/DBIC/DebugObj.pm [deleted file]
t/lib/DBICTest/BaseSchema.pm
t/lib/DBICTest/Stats.pm [deleted file]
t/resultset/update_delete.t
t/row/find_one_has_many.t
t/search/preserve_original_rs.t
t/sqlmaker/mysql.t
t/sqlmaker/quotes.t
t/storage/debug.t
t/storage/nobindvars.t
t/storage/savepoints.t

index 492368e..108624a 100644 (file)
@@ -84,7 +84,7 @@ my $runtime_requires = {
   'namespace::clean'         => '0.24',
   'Path::Class'              => '0.18',
   'Scope::Guard'             => '0.03',
-  'SQL::Abstract'            => '1.77',
+  'SQL::Abstract'            => '1.78',
   'Try::Tiny'                => '0.07',
 
   # Technically this is not a core dependency - it is only required
index cd49cec..17657cc 100644 (file)
@@ -2,11 +2,8 @@ use strict;
 use warnings;
 
 use Test::More;
-use Test::Exception;
 use lib qw(t/lib);
 use DBICTest;
-use DBIC::DebugObj;
-use DBIC::SqlMakerTest;
 
 my $schema = DBICTest->init_schema();
 $schema->storage->sql_maker->quote_char('"');
@@ -15,27 +12,12 @@ my $rs = $schema->resultset ('Artist');
 my $last_obj = $rs->search ({}, { order_by => { -desc => 'artistid' }, rows => 1})->single;
 my $last_id = $last_obj ? $last_obj->artistid : 0;
 
-
-my ($sql, @bind);
-my $orig_debugobj = $schema->storage->debugobj;
-my $orig_debug = $schema->storage->debug;
-
-$schema->storage->debugobj (DBIC::DebugObj->new (\$sql, \@bind) );
-$schema->storage->debug (1);
-
 my $obj;
-lives_ok { $obj = $rs->create ({}) } 'Default insert successful';
-
-$schema->storage->debugobj ($orig_debugobj);
-$schema->storage->debug ($orig_debug);
-
-is_same_sql_bind (
-  $sql,
-  \@bind,
-  'INSERT INTO "artist" DEFAULT VALUES',
-  [],
-  'Default-value insert correct SQL',
-);
+$schema->is_executed_sql_bind( sub {
+  $obj = $rs->create ({})
+}, [[
+  'INSERT INTO "artist" DEFAULT VALUES'
+]], 'Default-value insert correct SQL' );
 
 ok ($obj, 'Insert defaults ( $rs->create ({}) )' );
 
index ba5a181..b380225 100644 (file)
@@ -6,8 +6,6 @@ use Test::Exception;
 use Test::Warn;
 use lib qw(t/lib);
 use DBICTest;
-use DBIC::SqlMakerTest;
-use DBIC::DebugObj;
 
 my $schema = DBICTest->init_schema();
 
@@ -228,23 +226,12 @@ is($row->baz, 3, 'baz is correct');
 {
   my $artist = $schema->resultset('Artist')->find(1);
 
-  my ($sql, @bind);
-  my $old_debugobj = $schema->storage->debugobj;
-  my $old_debug = $schema->storage->debug;
-  $schema->storage->debugobj(DBIC::DebugObj->new(\$sql, \@bind)),
-  $schema->storage->debug(1);
-
-  $artist->discard_changes;
-
-  is_same_sql_bind (
-    $sql,
-    \@bind,
-    'SELECT me.artistid, me.name, me.rank, me.charfield FROM artist me WHERE me.artistid = ?',
-    [qw/'1'/],
-  );
-
-  $schema->storage->debug($old_debug);
-  $schema->storage->debugobj($old_debugobj);
+  $schema->is_executed_sql_bind( sub { $artist->discard_changes }, [
+    [
+      'SELECT me.artistid, me.name, me.rank, me.charfield FROM artist me WHERE me.artistid = ?',
+      [ { dbic_colname => "me.artistid", sqlt_datatype => "integer" } => 1 ],
+    ]
+  ], 'Expected query on discard_changes');
 }
 
 {
index a07e42a..64b4994 100644 (file)
@@ -5,7 +5,6 @@ use Test::More;
 use Test::Warn;
 use lib qw(t/lib);
 use DBICTest;
-use DBIC::DebugObj;
 
 {
   package A::Comp;
@@ -97,24 +96,22 @@ my $bytestream_title = my $utf8_title = "weird \x{466} stuff";
 utf8::encode($bytestream_title);
 cmp_ok ($bytestream_title, 'ne', $utf8_title, 'unicode/raw differ (sanity check)');
 
-my $storage = $schema->storage;
-my ($sql, @bind);
-my $debugobj = DBIC::DebugObj->new (\$sql, \@bind);
-my ($orig_debug, $orig_debugobj) = ($storage->debug, $storage->debugobj);
-$storage->debugobj ($debugobj);
-$storage->debug (1);
-
-my $cd = $schema->resultset('CD')->create( { artist => 1, title => $utf8_title, year => '2048' } );
-
-$storage->debugobj ($orig_debugobj);
-$storage->debug ($orig_debug);
-
-# bind values are always alphabetically ordered by column, thus [1]
-# the single quotes are an artefact of the debug-system
+my $cd;
 {
   local $TODO = "This has been broken since rev 1191, Mar 2006";
-  is ($bind[1], "'$bytestream_title'", 'INSERT: raw bytes sent to the database');
-}
+
+  $schema->is_executed_sql_bind( sub {
+    $cd = $schema->resultset('CD')->create( { artist => 1, title => $utf8_title, year => '2048' } )
+  }, [[
+    'INSERT INTO cd ( artist, title, year) VALUES ( ?, ?, ? )',
+     [ { dbic_colname => "artist", sqlt_datatype => "integer" }
+        => 1 ],
+     [ { dbic_colname => "title", sqlt_datatype => "varchar", sqlt_size => 100 }
+        => $bytestream_title ],
+     [ { dbic_colname => "year", sqlt_datatype => "varchar", sqlt_size => 100 }
+        => 2048 ],
+  ]], 'INSERT: raw bytes sent to the database' );
+};
 
 # this should be using the cursor directly, no inflation/processing of any sort
 my ($raw_db_title) = $schema->resultset('CD')
@@ -149,16 +146,20 @@ ok(! utf8::is_utf8( $cd->{_column_data}{title} ), 'reloaded utf8-less title' );
 $bytestream_title = $utf8_title = "something \x{219} else";
 utf8::encode($bytestream_title);
 
+$schema->is_executed_sql_bind( sub {
+  $cd->update ({ title => $utf8_title });
+}, [
+  [ 'BEGIN' ],
+  [
+    'UPDATE cd SET title = ? WHERE cdid = ?',
+    [ { dbic_colname => "title", sqlt_datatype => "varchar", sqlt_size => 100 }
+      => $bytestream_title ],
+    [ { dbic_colname => "cdid", sqlt_datatype => "integer" }
+      => 6 ],
+  ],
+  [ 'COMMIT' ],
+], 'UPDATE: raw bytes sent to the database');
 
-$storage->debugobj ($debugobj);
-$storage->debug (1);
-
-$cd->update ({ title => $utf8_title });
-
-$storage->debugobj ($orig_debugobj);
-$storage->debug ($orig_debug);
-
-is ($bind[0], "'$bytestream_title'", 'UPDATE: raw bytes sent to the database');
 ($raw_db_title) = $schema->resultset('CD')
                              ->search ($cd->ident_condition)
                                ->get_column('title')
index 95d2b92..49c1f57 100644 (file)
@@ -4,8 +4,6 @@ use warnings;
 use Test::More;
 use lib qw(t/lib);
 use DBICTest;
-use DBIC::SqlMakerTest;
-use DBIC::DebugObj;
 
 { # Fake storage driver for sqlite with autocast
     package DBICTest::SQLite::AutoCast;
@@ -37,22 +35,18 @@ my $rs = $schema->resultset ('CD')->search ({
   'me.single_track' => \[ '= ?', [ single_track => 1 ] ],
 }, { join => 'tracks' });
 
-my ($sql, @bind);
-my $debugobj = DBIC::DebugObj->new (\$sql, \@bind);
-my $storage = $schema->storage;
-my ($orig_debug, $orig_debugobj) = ($storage->debug, $storage->debugobj);
-$storage->debugobj ($debugobj);
-$storage->debug (1);
-
-# the quoting is a debugobj thing, not dbic-internals
-my $bind = [ map { "'$_'" } qw/
-  5 1 2009 4
-/];
+my @bind = (
+  [ { dbic_colname => "cdid", sqlt_datatype => "integer" }
+      => 5 ],
+  [ { dbic_colname => "single_track", sqlt_datatype => "integer" }
+      => 1 ],
+  [ { dbic_colname => "tracks.last_updated_on", sqlt_datatype => "datetime" }
+      => 2009 ],
+  [ { dbic_colname => "tracks.position", sqlt_datatype => "int" }
+      => 4 ],
+);
 
-$rs->all;
-is_same_sql_bind (
-  $sql,
-  \@bind,
+$schema->is_executed_sql_bind( sub { $rs->all }, [[
   '
     SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track
       FROM cd me
@@ -64,16 +58,12 @@ is_same_sql_bind (
       AND tracks.last_updated_on < ?
       AND tracks.position = ?
   ',
-  $bind,
-  'expected sql with casting off',
-);
+  @bind,
+]], 'expected sql with casting off' );
 
 $schema->storage->auto_cast (1);
 
-$rs->all;
-is_same_sql_bind (
-  $sql,
-  \@bind,
+$schema->is_executed_sql_bind( sub { $rs->all }, [[
   '
     SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track
       FROM cd me
@@ -85,11 +75,7 @@ is_same_sql_bind (
       AND tracks.last_updated_on < CAST (? AS DateTime)
       AND tracks.position = ?
   ',
-  $bind,
-  'expected sql with casting on',
-);
-
-$storage->debugobj ($orig_debugobj);
-$storage->debug ($orig_debug);
+  @bind,
+]], 'expected sql with casting on' );
 
 done_testing;
index 83b6257..5883daf 100644 (file)
@@ -6,7 +6,6 @@ use lib qw(t/lib);
 use Test::More;
 use DBICTest;
 use DBIC::SqlMakerTest;
-use DBIC::DebugObj;
 use DBIx::Class::SQLMaker::LimitDialects;
 
 my ($ROWS, $OFFSET) = (
@@ -23,27 +22,25 @@ my $schema = DBICTest->init_schema();
                 { position => [1,2] },
                 { prefetch => [qw/disc lyrics/], rows => 3, offset => 8 },
             );
-  is ($rs->all, 2, 'Correct number of objects');
-
-
-  my ($sql, @bind);
-  $schema->storage->debugobj(DBIC::DebugObj->new(\$sql, \@bind));
-  $schema->storage->debug(1);
+  my @wherebind = (
+    [ { sqlt_datatype => 'int', dbic_colname => 'position' }
+      => 1 ],
+    [ { sqlt_datatype => 'int', dbic_colname => 'position' }
+      => 2 ],
+  );
 
-  is ($rs->count, 2, 'Correct count via count()');
+  is ($rs->all, 2, 'Correct number of objects');
 
-  is_same_sql_bind (
-    $sql,
-    \@bind,
+  $schema->is_executed_sql_bind( sub {
+    is ($rs->count, 2, 'Correct count via count()');
+  }, [[
     'SELECT COUNT( * )
       FROM cd me
       JOIN track tracks ON tracks.cd = me.cdid
       JOIN cd disc ON disc.cdid = tracks.cd
      WHERE ( ( position = ? OR position = ? ) )
-    ',
-    [ qw/'1' '2'/ ],
-    'count softlimit applied',
-  );
+    ', @wherebind
+  ]], 'count softlimit applied');
 
   my $crs = $rs->count_rs;
   is ($crs->next, 2, 'Correct count via count_rs()');
@@ -60,14 +57,7 @@ my $schema = DBICTest->init_schema();
         LIMIT ? OFFSET ?
        ) tracks
     )',
-    [
-      [ { sqlt_datatype => 'int', dbic_colname => 'position' }
-        => 1 ],
-      [ { sqlt_datatype => 'int', dbic_colname => 'position' }
-        => 2 ],
-      [$ROWS => 3],
-      [$OFFSET => 8],
-    ],
+    [ @wherebind, [$ROWS => 3], [$OFFSET => 8] ],
     'count_rs db-side limit applied',
   );
 }
@@ -79,17 +69,18 @@ my $schema = DBICTest->init_schema();
                 { 'tracks.position' => [1,2] },
                 { prefetch => [qw/tracks artist/], rows => 3, offset => 4 },
             );
-  is ($rs->all, 1, 'Correct number of objects');
-
-  my ($sql, @bind);
-  $schema->storage->debugobj(DBIC::DebugObj->new(\$sql, \@bind));
-  $schema->storage->debug(1);
+  my @wherebind = (
+    [ { sqlt_datatype => 'int', dbic_colname => 'tracks.position' }
+      => 1 ],
+    [ { sqlt_datatype => 'int', dbic_colname => 'tracks.position' }
+      => 2 ],
+  );
 
-  is ($rs->count, 1, 'Correct count via count()');
+  is ($rs->all, 1, 'Correct number of objects');
 
-  is_same_sql_bind (
-    $sql,
-    \@bind,
+  $schema->is_executed_sql_bind( sub {
+    is ($rs->count, 1, 'Correct count via count()');
+  }, [ [
     'SELECT COUNT( * )
       FROM (
         SELECT cds.cdid
@@ -100,10 +91,8 @@ my $schema = DBICTest->init_schema();
         WHERE tracks.position = ? OR tracks.position = ?
         GROUP BY cds.cdid
       ) cds
-    ',
-    [ qw/'1' '2'/ ],
-    'count softlimit applied',
-  );
+    ', @wherebind
+  ]], 'count softlimit applied' );
 
   my $crs = $rs->count_rs;
   is ($crs->next, 1, 'Correct count via count_rs()');
@@ -122,14 +111,7 @@ my $schema = DBICTest->init_schema();
         LIMIT ? OFFSET ?
       ) cds
     )',
-    [
-      [ { sqlt_datatype => 'int', dbic_colname => 'tracks.position' }
-        => 1 ],
-      [ { sqlt_datatype => 'int', dbic_colname => 'tracks.position' }
-        => 2 ],
-      [ $ROWS => 3],
-      [$OFFSET => 4],
-    ],
+    [ @wherebind, [$ROWS => 3], [$OFFSET => 4], ],
     'count_rs db-side limit applied',
   );
 }
diff --git a/t/lib/DBIC/DebugObj.pm b/t/lib/DBIC/DebugObj.pm
deleted file mode 100644 (file)
index c43bae9..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-package DBIC::DebugObj;
-
-use strict;
-use warnings;
-
-use Class::C3;
-
-use base qw/DBIx::Class::Storage::Statistics Exporter Class::Accessor::Fast/;
-
-__PACKAGE__->mk_accessors( qw/dbictest_sql_ref dbictest_bind_ref/ );
-
-
-=head2 new(PKG, SQL_REF, BIND_REF, ...)
-
-Creates a new instance that on subsequent queries will store
-the generated SQL to the scalar pointed to by SQL_REF and bind
-values to the array pointed to by BIND_REF.
-
-=cut
-
-sub new {
-  my $pkg = shift;
-  my $sql_ref = shift;
-  my $bind_ref = shift;
-
-  my $self = $pkg->SUPER::new(@_);
-
-  $self->debugfh(undef);
-
-  $self->dbictest_sql_ref($sql_ref);
-  $self->dbictest_bind_ref($bind_ref || []);
-
-  return $self;
-}
-
-sub query_start {
-  my $self = shift;
-
-  (${$self->dbictest_sql_ref}, @{$self->dbictest_bind_ref}) = @_;
-}
-
-sub query_end { }
-
-sub txn_begin { }
-
-sub txn_commit { }
-
-sub txn_rollback { }
-
-1;
index 0e1e5e2..ae8d74a 100644 (file)
@@ -3,7 +3,6 @@ package #hide from pause
 
 use strict;
 use warnings;
-
 use base qw(DBICTest::Base DBIx::Class::Schema);
 
 use Fcntl qw(:DEFAULT :seek :flock);
@@ -12,6 +11,92 @@ use DBICTest::Util::LeakTracer qw(populate_weakregistry assert_empty_weakregistr
 use DBICTest::Util 'local_umask';
 use namespace::clean;
 
+{
+  package # moar hide
+    DBICTest::SQLTracerObj;
+  use base 'DBIx::Class::Storage::Statistics';
+
+  sub query_start { push @{$_[0]{sqlbinds}}, [ ($_[1] =~ /^\s*(\S+)/)[0], [ $_[1], @{ $_[2]||[] } ] ] }
+
+  # who the hell came up with this API >:(
+  for my $txn (qw(begin rollback commit)) {
+    no strict 'refs';
+    *{"txn_$txn"} = sub { push @{$_[0]{sqlbinds}}, [ uc $txn => [ uc $txn ] ] };
+  }
+
+  sub svp_begin { push @{$_[0]{sqlbinds}}, [ SAVEPOINT => [ "SAVEPOINT $_[1]" ] ] }
+  sub svp_release { push @{$_[0]{sqlbinds}}, [ RELEASE_SAVEPOINT => [ "RELEASE $_[1]" ] ] }
+  sub svp_rollback { push @{$_[0]{sqlbinds}}, [ ROLLBACK_TO_SAVEPOINT => [ "ROLLBACK TO $_[1]" ] ] }
+
+}
+
+sub capture_executed_sql_bind {
+  my ($self, $cref) = @_;
+
+  $self->throw_exception("Expecting a coderef to run") unless ref $cref eq 'CODE';
+
+  # hack around stupid, stupid API
+  no warnings 'redefine';
+  local *DBIx::Class::Storage::DBI::_format_for_trace = sub { $_[1] };
+  Class::C3->reinitialize if DBIx::Class::_ENV_::OLD_MRO;
+
+  local $self->storage->{debugcb};
+  local $self->storage->{debugobj} = my $tracer_obj = DBICTest::SQLTracerObj->new;
+  local $self->storage->{debug} = 1;
+
+
+  $cref->();
+
+  return $tracer_obj->{sqlbinds} || [];
+}
+
+sub is_executed_sql_bind {
+  my ($self, $cref, $sqlbinds, $msg) = @_;
+
+  local $Test::Builder::Level = $Test::Builder::Level + 1;
+
+  $self->throw_exception("Expecting an arrayref of SQL/Bind pairs") unless ref $sqlbinds eq 'ARRAY';
+
+  my @expected = @$sqlbinds;
+
+  my @got = map { $_->[1] } @{ $self->capture_executed_sql_bind($cref) };
+
+
+  return Test::Builder->new->ok(1, $msg || "No queries executed while running $cref")
+    if !@got and !@expected;
+
+  require SQL::Abstract::Test;
+  my $ret = 1;
+  while (@expected or @got) {
+    my $left = shift @got;
+    my $right = shift @expected;
+
+    # allow the right side to "simplify" the entire shebang
+    if ($left and $right) {
+      $left = [ @$left ];
+      for my $i (1..$#$right) {
+        if (
+          ! ref $right->[$i]
+            and
+          ref $left->[$i] eq 'ARRAY'
+            and
+          @{$left->[$i]} == 2
+        ) {
+          $left->[$i] = $left->[$i][1]
+        }
+      }
+    }
+
+    $ret &= SQL::Abstract::Test::is_same_sql_bind(
+      \( $left || [] ),
+      \( $right || [] ),
+      $msg,
+    );
+  }
+
+  return $ret;
+}
+
 our $locker;
 END {
   # we need the $locker to be referenced here for delayed destruction
diff --git a/t/lib/DBICTest/Stats.pm b/t/lib/DBICTest/Stats.pm
deleted file mode 100644 (file)
index 5a4544f..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-package DBICTest::Stats;
-use strict;
-use warnings;
-
-use base qw/DBIx::Class::Storage::Statistics/;
-
-sub txn_begin {
-  my $self = shift;
-
-  $self->{'TXN_BEGIN'}++;
-  return $self->{'TXN_BEGIN'};
-}
-
-sub txn_rollback {
-  my $self = shift;
-
-  $self->{'TXN_ROLLBACK'}++;
-  return $self->{'TXN_ROLLBACK'};
-}
-
-sub txn_commit {
-  my $self = shift;
-
-  $self->{'TXN_COMMIT'}++;
-  return $self->{'TXN_COMMIT'};
-}
-
-sub svp_begin {
-  my ($self, $name) = @_;
-
-  $self->{'SVP_BEGIN'}++;
-  return $self->{'SVP_BEGIN'};
-}
-
-sub svp_release {
-  my ($self, $name) = @_;
-
-  $self->{'SVP_RELEASE'}++;
-  return $self->{'SVP_RELEASE'};
-}
-
-sub svp_rollback {
-  my ($self, $name) = @_;
-
-  $self->{'SVP_ROLLBACK'}++;
-  return $self->{'SVP_ROLLBACK'};
-}
-
-sub query_start {
-  my ($self, $string, @bind) = @_;
-
-  $self->{'QUERY_START'}++;
-  return $self->{'QUERY_START'};
-}
-
-sub query_end {
-  my ($self, $string) = @_;
-
-  $self->{'QUERY_END'}++;
-  return $self->{'QUERY_START'};
-}
-
-1;
index 917e12f..ee32717 100644 (file)
@@ -12,16 +12,9 @@ BEGIN {
 }
 
 use DBICTest;
-use DBIC::DebugObj;
-use DBIC::SqlMakerTest;
 
 my $schema = DBICTest->init_schema;
 
-my ($sql, @bind);
-my $debugobj = DBIC::DebugObj->new (\$sql, \@bind);
-my $orig_debugobj = $schema->storage->debugobj;
-my $orig_debug = $schema->storage->debug;
-
 my $tkfks = $schema->resultset('FourKeys_to_TwoKeys');
 
 my ($fa, $fb, $fc) = $tkfks->related_resultset ('fourkeys')->populate ([
@@ -64,23 +57,16 @@ my $fks = $schema->resultset ('FourKeys')->search (
 );
 
 is ($fks->count, 4, 'Joined FourKey count correct (2x2)');
-
-$schema->storage->debugobj ($debugobj);
-$schema->storage->debug (1);
-$fks->update ({ read_count => \ 'read_count + 1' });
-$schema->storage->debugobj ($orig_debugobj);
-$schema->storage->debug ($orig_debug);
-
-is_same_sql_bind (
-  $sql,
-  \@bind,
+$schema->is_executed_sql_bind( sub {
+  $fks->update ({ read_count => \ 'read_count + 1' })
+}, [[
   'UPDATE fourkeys
    SET read_count = read_count + 1
    WHERE ( ( ( bar = ? OR bar = ? ) AND ( foo = ? OR foo = ? ) AND ( goodbye = ? OR goodbye = ? ) AND ( hello = ? OR hello = ? ) AND sensors != ? ) )
   ',
-  [ ("'1'", "'2'") x 4, "'c'" ],
-  'Correct update-SQL with multijoin with pruning',
-);
+  (1, 2) x 4,
+  'c',
+]], 'Correct update-SQL with multijoin with pruning' );
 
 is ($fa->discard_changes->read_count, 11, 'Update ran only once on discard-join resultset');
 is ($fb->discard_changes->read_count, 21, 'Update ran only once on discard-join resultset');
@@ -88,40 +74,44 @@ is ($fc->discard_changes->read_count, 30, 'Update did not touch outlier');
 
 # make the multi-join stick
 my $fks_multi = $fks->search({ 'fourkeys_to_twokeys.pilot_sequence' => { '!=' => 666 } });
-
-$schema->storage->debugobj ($debugobj);
-$schema->storage->debug (1);
-$fks_multi->update ({ read_count => \ 'read_count + 1' });
-$schema->storage->debugobj ($orig_debugobj);
-$schema->storage->debug ($orig_debug);
-
-is_same_sql_bind (
-  $sql,
-  \@bind,
-  'UPDATE fourkeys
-   SET read_count = read_count + 1
-   WHERE ( bar = ? AND foo = ? AND goodbye = ? AND hello = ? ) OR ( bar = ? AND foo = ? AND goodbye = ? AND hello = ? )',
-  [ map { "'$_'" } ( (1) x 4, (2) x 4 ) ],
-  'Correct update-SQL with multijoin without pruning',
-);
+$schema->is_executed_sql_bind( sub {
+  $fks_multi->update ({ read_count => \ 'read_count + 1' })
+}, [
+  [ 'BEGIN' ],
+  [
+    'SELECT me.foo, me.bar, me.hello, me.goodbye
+      FROM fourkeys me
+      LEFT JOIN fourkeys_to_twokeys fourkeys_to_twokeys
+        ON fourkeys_to_twokeys.f_bar = me.bar AND fourkeys_to_twokeys.f_foo = me.foo AND fourkeys_to_twokeys.f_goodbye = me.goodbye AND fourkeys_to_twokeys.f_hello = me.hello
+      WHERE ( bar = ? OR bar = ? ) AND ( foo = ? OR foo = ? ) AND fourkeys_to_twokeys.pilot_sequence != ? AND ( goodbye = ? OR goodbye = ? ) AND ( hello = ? OR hello = ? ) AND sensors != ?
+      GROUP BY me.foo, me.bar, me.hello, me.goodbye
+    ',
+    (1, 2) x 2,
+    666,
+    (1, 2) x 2,
+    'c',
+  ],
+  [
+    'UPDATE fourkeys
+     SET read_count = read_count + 1
+     WHERE ( bar = ? AND foo = ? AND goodbye = ? AND hello = ? ) OR ( bar = ? AND foo = ? AND goodbye = ? AND hello = ? )
+    ',
+    ( (1) x 4, (2) x 4 ),
+  ],
+  [ 'COMMIT' ],
+], 'Correct update-SQL with multijoin without pruning' );
 
 is ($fa->discard_changes->read_count, 12, 'Update ran only once on joined resultset');
 is ($fb->discard_changes->read_count, 22, 'Update ran only once on joined resultset');
 is ($fc->discard_changes->read_count, 30, 'Update did not touch outlier');
 
 # try the same sql with forced multicolumn in
-$schema->storage->_use_multicolumn_in (1);
-$schema->storage->debugobj ($debugobj);
-$schema->storage->debug (1);
-throws_ok { $fks_multi->update ({ read_count => \ 'read_count + 1' }) } # this can't actually execute, we just need the "as_query"
-  qr/\QDBI Exception:/ or do { $sql = ''; @bind = () };
-$schema->storage->_use_multicolumn_in (undef);
-$schema->storage->debugobj ($orig_debugobj);
-$schema->storage->debug ($orig_debug);
-
-is_same_sql_bind (
-  $sql,
-  \@bind,
+$schema->is_executed_sql_bind( sub {
+  local $schema->storage->{_use_multicolumn_in} = 1;
+
+  # this can't actually execute on sqlite
+  eval { $fks_multi->update ({ read_count => \ 'read_count + 1' }) };
+}, [[
   'UPDATE fourkeys
     SET read_count = read_count + 1
     WHERE (
@@ -137,39 +127,44 @@ is_same_sql_bind (
       )
     )
   ',
+  ( 1, 2) x 2,
+  666,
+  ( 1, 2) x 2,
+  'c',
+]], 'Correct update-SQL with multicolumn in support' );
+
+$schema->is_executed_sql_bind( sub {
+  $fks->search({ 'twokeys.artist' => { '!=' => 666 } })->update({ read_count => \ 'read_count + 1' });
+}, [
+  [ 'BEGIN' ],
   [
-    ("'1'", "'2'") x 2,
-    "'666'",
-    ("'1'", "'2'") x 2,
-    "'c'",
+    'SELECT me.foo, me.bar, me.hello, me.goodbye
+      FROM fourkeys me
+      LEFT JOIN fourkeys_to_twokeys fourkeys_to_twokeys
+        ON fourkeys_to_twokeys.f_bar = me.bar AND fourkeys_to_twokeys.f_foo = me.foo AND fourkeys_to_twokeys.f_goodbye = me.goodbye AND fourkeys_to_twokeys.f_hello = me.hello
+      LEFT JOIN twokeys twokeys
+        ON twokeys.artist = fourkeys_to_twokeys.t_artist AND twokeys.cd = fourkeys_to_twokeys.t_cd
+      WHERE ( bar = ? OR bar = ? ) AND ( foo = ? OR foo = ? ) AND ( goodbye = ? OR goodbye = ? ) AND ( hello = ? OR hello = ? ) AND sensors != ? AND twokeys.artist != ?
+      GROUP BY me.foo, me.bar, me.hello, me.goodbye
+    ',
+    (1, 2) x 4,
+    'c',
+    666,
   ],
-  'Correct update-SQL with multicolumn in support',
-);
-
-# make a *premultiplied* join stick
-my $fks_premulti = $fks->search({ 'twokeys.artist' => { '!=' => 666 } });
-
-$schema->storage->debugobj ($debugobj);
-$schema->storage->debug (1);
-$fks_premulti->update ({ read_count => \ 'read_count + 1' });
-$schema->storage->debugobj ($orig_debugobj);
-$schema->storage->debug ($orig_debug);
-
-is_same_sql_bind (
-  $sql,
-  \@bind,
-  'UPDATE fourkeys
-   SET read_count = read_count + 1
-   WHERE ( bar = ? AND foo = ? AND goodbye = ? AND hello = ? ) OR ( bar = ? AND foo = ? AND goodbye = ? AND hello = ? )',
-  [ map { "'$_'" } ( (1) x 4, (2) x 4 ) ],
-  'Correct update-SQL with premultiplied restricting join without pruning',
-);
+  [
+    'UPDATE fourkeys
+     SET read_count = read_count + 1
+     WHERE ( bar = ? AND foo = ? AND goodbye = ? AND hello = ? ) OR ( bar = ? AND foo = ? AND goodbye = ? AND hello = ? )
+    ',
+    ( (1) x 4, (2) x 4 ),
+  ],
+  [ 'COMMIT' ],
+], 'Correct update-SQL with premultiplied restricting join without pruning' );
 
 is ($fa->discard_changes->read_count, 13, 'Update ran only once on joined resultset');
 is ($fb->discard_changes->read_count, 23, 'Update ran only once on joined resultset');
 is ($fc->discard_changes->read_count, 30, 'Update did not touch outlier');
 
-
 #
 # Make sure multicolumn in or the equivalent functions correctly
 #
@@ -253,43 +248,34 @@ is ($tkfks->count, $tkfk_cnt -= 1, 'Only one row deleted');
 
 
 # check with sql-equality, as sqlite will accept most bad sql just fine
-$schema->storage->debugobj ($debugobj);
-$schema->storage->debug (1);
-
 {
   my $rs = $schema->resultset('CD')->search(
     { 'me.year' => { '!=' => 2010 } },
   );
 
-  $rs->search({}, { join => 'liner_notes' })->delete;
-  is_same_sql_bind (
-    $sql,
-    \@bind,
+  $schema->is_executed_sql_bind( sub {
+    $rs->search({}, { join => 'liner_notes' })->delete;
+  }, [[
     'DELETE FROM cd WHERE ( year != ? )',
-    ["'2010'"],
-    'Non-restricting multijoins properly thrown out'
-  );
+    2010,
+  ]], 'Non-restricting multijoins properly thrown out' );
 
-  $rs->search({}, { prefetch => 'liner_notes' })->delete;
-  is_same_sql_bind (
-    $sql,
-    \@bind,
+  $schema->is_executed_sql_bind( sub {
+    $rs->search({}, { prefetch => 'liner_notes' })->delete;
+  }, [[
     'DELETE FROM cd WHERE ( year != ? )',
-    ["'2010'"],
-    'Non-restricting multiprefetch thrown out'
-  );
+    2010,
+  ]], 'Non-restricting multiprefetch thrown out' );
 
-  $rs->search({}, { prefetch => 'artist' })->delete;
-  is_same_sql_bind (
-    $sql,
-    \@bind,
+  $schema->is_executed_sql_bind( sub {
+    $rs->search({}, { prefetch => 'artist' })->delete;
+  }, [[
     'DELETE FROM cd WHERE ( cdid IN ( SELECT me.cdid FROM cd me JOIN artist artist ON artist.artistid = me.artist WHERE ( me.year != ? ) ) )',
-    ["'2010'"],
-    'Restricting prefetch left in, selector thrown out'
-  );
+    2010,
+  ]], 'Restricting prefetch left in, selector thrown out');
 
-  # switch artist and cd to fully qualified table names
-  # make sure nothing is stripped out
+### switch artist and cd to fully qualified table names
+### make sure nothing is stripped out
   my $cd_rsrc = $schema->source('CD');
   $cd_rsrc->name('main.cd');
   $cd_rsrc->relationship_info($_)->{attrs}{cascade_delete} = 0
@@ -300,85 +286,80 @@ $schema->storage->debug (1);
   $art_rsrc->relationship_info($_)->{attrs}{cascade_delete} = 0
     for $art_rsrc->relationships;
 
-  $rs->delete;
-  is_same_sql_bind (
-    $sql,
-    \@bind,
-    'DELETE FROM main.cd WHERE ( year != ? )',
-    ["'2010'"],
-    'delete with fully qualified table name'
-  );
+  $schema->is_executed_sql_bind( sub {
+    $rs->delete
+  }, [[
+    'DELETE FROM main.cd WHERE year != ?',
+    2010,
+  ]], 'delete with fully qualified table name' );
 
   $rs->create({ title => 'foo', artist => 1, year => 2000 });
-  $rs->delete_all;
-  is_same_sql_bind (
-    $sql,
-    \@bind,
-    'DELETE FROM main.cd WHERE ( cdid = ? )',
-    ["'1'"],
-    'delete_all with fully qualified table name'
-  );
-
-  $rs->create({ cdid => 42, title => 'foo', artist => 2, year => 2000 });
-  $rs->find(42)->delete;
-  is_same_sql_bind (
-    $sql,
-    \@bind,
-    'DELETE FROM main.cd WHERE ( cdid = ? )',
-    ["'42'"],
-    'delete of object from table with fully qualified name'
-  );
+  $schema->is_executed_sql_bind( sub {
+    $rs->delete_all
+  }, [
+    [ 'BEGIN' ],
+    [
+      'SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track FROM main.cd me WHERE me.year != ?',
+      2010,
+    ],
+    [
+      'DELETE FROM main.cd WHERE ( cdid = ? )',
+      1,
+    ],
+    [ 'COMMIT' ],
+  ], 'delete_all with fully qualified table name' );
 
   $rs->create({ cdid => 42, title => 'foo', artist => 2, year => 2000 });
-  $rs->find(42)->related_resultset('artist')->delete;
-  is_same_sql_bind (
-    $sql,
-    \@bind,
+  my $cd42 = $rs->find(42);
+
+  $schema->is_executed_sql_bind( sub {
+    $cd42->delete
+  }, [[
+    'DELETE FROM main.cd WHERE cdid = ?',
+    42,
+  ]], 'delete of object from table with fully qualified name' );
+
+  $schema->is_executed_sql_bind( sub {
+    $cd42->related_resultset('artist')->delete
+  }, [[
     'DELETE FROM main.artist WHERE ( artistid IN ( SELECT me.artistid FROM main.artist me WHERE ( me.artistid = ? ) ) )',
-    ["'2'"],
-    'delete of related object from scalarref fully qualified named table',
-  );
+    2,
+  ]], 'delete of related object from scalarref fully qualified named table' );
+
+  my $art3 = $schema->resultset('Artist')->find(3);
 
-  $schema->resultset('Artist')->find(3)->related_resultset('cds')->delete;
-  is_same_sql_bind (
-    $sql,
-    \@bind,
+  $schema->is_executed_sql_bind( sub {
+    $art3->related_resultset('cds')->delete;
+  }, [[
     'DELETE FROM main.cd WHERE ( artist = ? )',
-    ["'3'"],
-    'delete of related object from fully qualified named table',
-  );
+    3,
+  ]], 'delete of related object from fully qualified named table' );
 
-  $schema->resultset('Artist')->find(3)->cds_unordered->delete;
-  is_same_sql_bind (
-    $sql,
-    \@bind,
+  $schema->is_executed_sql_bind( sub {
+    $art3->cds_unordered->delete;
+  }, [[
     'DELETE FROM main.cd WHERE ( artist = ? )',
-    ["'3'"],
-    'delete of related object from fully qualified named table via relaccessor',
-  );
+    3,
+  ]], 'delete of related object from fully qualified named table via relaccessor' );
 
-  $rs->search({}, { prefetch => 'artist' })->delete;
-  is_same_sql_bind (
-    $sql,
-    \@bind,
+  $schema->is_executed_sql_bind( sub {
+    $rs->search({}, { prefetch => 'artist' })->delete;
+  }, [[
     'DELETE FROM main.cd WHERE ( cdid IN ( SELECT me.cdid FROM main.cd me JOIN main.artist artist ON artist.artistid = me.artist WHERE ( me.year != ? ) ) )',
-    ["'2010'"],
-    'delete with fully qualified table name and subquery correct'
-  );
+    2010,
+  ]], 'delete with fully qualified table name and subquery correct' );
 
   # check that as_subselect_rs works ok
   # inner query is untouched, then a selector
   # and an IN condition
-  $schema->resultset('CD')->search({
-    'me.cdid' => 1,
-    'artist.name' => 'partytimecity',
-  }, {
-    join => 'artist',
-  })->as_subselect_rs->delete;
-
-  is_same_sql_bind (
-    $sql,
-    \@bind,
+  $schema->is_executed_sql_bind( sub {
+    $schema->resultset('CD')->search({
+      'me.cdid' => 1,
+      'artist.name' => 'partytimecity',
+    }, {
+      join => 'artist',
+    })->as_subselect_rs->delete;
+  }, [[
     '
       DELETE FROM main.cd
       WHERE (
@@ -393,12 +374,9 @@ $schema->storage->debug (1);
         )
       )
     ',
-    ["'partytimecity'", "'1'"],
-    'Delete from as_subselect_rs works correctly'
-  );
+    'partytimecity',
+    1,
+  ]], 'Delete from as_subselect_rs works correctly' );
 }
 
-$schema->storage->debugobj ($orig_debugobj);
-$schema->storage->debug ($orig_debug);
-
 done_testing;
index 5e1e953..ea7767f 100644 (file)
@@ -4,8 +4,6 @@ use warnings;
 use Test::More;
 use lib qw(t/lib);
 use DBICTest;
-use DBIC::DebugObj;
-use DBIC::SqlMakerTest;
 
 my $schema = DBICTest->init_schema();
 
@@ -15,20 +13,20 @@ $schema->resultset('CD')->delete;
 my $artist  = $schema->resultset("Artist")->create({ artistid => 21, name => 'Michael Jackson', rank => 20 });
 my $cd = $artist->create_related('cds', { year => 1975, title => 'Compilation from 1975' });
 
-my ($sql, @bind);
-local $schema->storage->{debug} = 1;
-local $schema->storage->{debugobj} = DBIC::DebugObj->new(\$sql, \@bind);
-
-my $find_cd = $artist->find_related('cds',{title => 'Compilation from 1975'});
-
-s/^'//, s/'\z// for @bind; # why does DBIC::DebugObj not do this?
-
-is_same_sql_bind (
-  $sql,
-  \@bind,
-  'SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track FROM cd me WHERE ( ( me.artist = ? AND me.title = ? ) ) ORDER BY year ASC',
-  [21, 'Compilation from 1975'],
-  'find_related only uses foreign key condition once',
-);
+$schema->is_executed_sql_bind(sub {
+  my $find_cd = $artist->find_related('cds',{title => 'Compilation from 1975'});
+}, [
+  [
+    ' SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track
+        FROM cd me
+      WHERE me.artist = ? AND me.title = ?
+      ORDER BY year ASC
+    ',
+    [ { dbic_colname => "me.artist", sqlt_datatype => "integer" }
+      => 21 ],
+    [ { dbic_colname => "me.title",  sqlt_datatype => "varchar", sqlt_size => 100 }
+      => "Compilation from 1975" ],
+  ]
+], 'find_related only uses foreign key condition once' );
 
 done_testing;
index cb9a306..04dc9a8 100644 (file)
@@ -7,9 +7,8 @@ use Test::Exception;
 use lib qw(t/lib);
 use DBICTest;
 use DBIC::SqlMakerTest;
-use DBIC::DebugObj;
 
-use Storable qw/dclone/;
+use Storable 'dclone';
 
 my $schema = DBICTest->init_schema();
 
index b5ce8a5..5b3f330 100644 (file)
@@ -7,7 +7,6 @@ use lib qw(t/lib);
 use DBICTest;
 use DBICTest::Schema;
 use DBIC::SqlMakerTest;
-use DBIC::DebugObj;
 
 my $schema = DBICTest::Schema->connect (DBICTest->_database, { quote_char => '`' });
 # cheat
@@ -17,54 +16,39 @@ bless ( $schema->storage, 'DBIx::Class::Storage::DBI::mysql' );
 
 # check that double-subqueries are properly wrapped
 {
-  my ($sql, @bind);
-  my $debugobj = DBIC::DebugObj->new (\$sql, \@bind);
-  my $orig_debugobj = $schema->storage->debugobj;
-  my $orig_debug = $schema->storage->debug;
-
-  $schema->storage->debugobj ($debugobj);
-  $schema->storage->debug (1);
-
   # the expected SQL may seem wastefully nonsensical - this is due to
   # CD's tablename being \'cd', which triggers the "this can be anything"
   # mode, and forces a subquery. This in turn forces *another* subquery
   # because mysql is being mysql
   # Also we know it will fail - never deployed. All we care about is the
-  # SQL to compare
-  eval { $schema->resultset ('CD')->update({ genreid => undef }) };
-  is_same_sql_bind (
-    $sql,
-    \@bind,
+  # SQL to compare, hence the eval
+  $schema->is_executed_sql_bind( sub {
+    eval { $schema->resultset ('CD')->update({ genreid => undef }) }
+  },[[
     'UPDATE cd SET `genreid` = ? WHERE `cdid` IN ( SELECT * FROM ( SELECT `me`.`cdid` FROM cd `me` ) `_forced_double_subquery` )',
-    [ 'NULL' ],
-    'Correct update-SQL with double-wrapped subquery',
-  );
+    [ { dbic_colname => "genreid", sqlt_datatype => "integer" }  => undef ],
+  ]], 'Correct update-SQL with double-wrapped subquery' );
 
   # same comment as above
-  eval { $schema->resultset ('CD')->delete };
-  is_same_sql_bind (
-    $sql,
-    \@bind,
+  $schema->is_executed_sql_bind( sub {
+    eval { $schema->resultset ('CD')->delete }
+  }, [[
     'DELETE FROM cd WHERE `cdid` IN ( SELECT * FROM ( SELECT `me`.`cdid` FROM cd `me` ) `_forced_double_subquery` )',
-    [],
-    'Correct delete-SQL with double-wrapped subquery',
-  );
+  ]], 'Correct delete-SQL with double-wrapped subquery' );
 
   # and a couple of really contrived examples (we test them live in t/71mysql.t)
   my $rs = $schema->resultset('Artist')->search({ name => { -like => 'baby_%' } });
   my ($count_sql, @count_bind) = @${$rs->count_rs->as_query};
-  eval {
-    $schema->resultset('Artist')->search(
-      { artistid => {
-        -in => $rs->get_column('artistid')
-                    ->as_query
-      } },
-    )->update({ name => \[ "CONCAT( `name`, '_bell_out_of_', $count_sql )", @count_bind ] });
-  };
-
-  is_same_sql_bind (
-    $sql,
-    \@bind,
+  $schema->is_executed_sql_bind( sub {
+    eval {
+      $schema->resultset('Artist')->search(
+        { artistid => {
+          -in => $rs->get_column('artistid')
+                      ->as_query
+        } },
+      )->update({ name => \[ "CONCAT( `name`, '_bell_out_of_', $count_sql )", @count_bind ] });
+    }
+  }, [[
     q(
       UPDATE `artist`
         SET `name` = CONCAT(`name`, '_bell_out_of_', (
@@ -84,18 +68,18 @@ bless ( $schema->storage, 'DBIx::Class::Storage::DBI::mysql' );
               WHERE `name` LIKE ?
             ) `_forced_double_subquery` )
     ),
-    [ ("'baby_%'") x 2 ],
-  );
-
-  eval {
-    $schema->resultset('CD')->search_related('artist',
-      { 'artist.name' => { -like => 'baby_with_%' } }
-    )->delete
-  };
-
-  is_same_sql_bind (
-    $sql,
-    \@bind,
+    ( [ { dbic_colname => "name", sqlt_datatype => "varchar", sqlt_size => 100 }
+        => 'baby_%' ]
+    ) x 2
+  ]]);
+
+  $schema->is_executed_sql_bind( sub {
+    eval {
+      $schema->resultset('CD')->search_related('artist',
+        { 'artist.name' => { -like => 'baby_with_%' } }
+      )->delete
+    }
+  }, [[
     q(
       DELETE FROM `artist`
       WHERE `artistid` IN (
@@ -109,11 +93,9 @@ bless ( $schema->storage, 'DBIx::Class::Storage::DBI::mysql' );
           ) `_forced_double_subquery`
       )
     ),
-    [ "'baby_with_%'" ],
-  );
-
-  $schema->storage->debugobj ($orig_debugobj);
-  $schema->storage->debug ($orig_debug);
+    [ { dbic_colname => "artist.name", sqlt_datatype => "varchar", sqlt_size => 100 }
+        => 'baby_with_%' ],
+  ]] );
 }
 
 # Test support for straight joins
index 84f2a3f..d3a8c8f 100644 (file)
@@ -6,27 +6,29 @@ use Test::More;
 use lib qw(t/lib);
 use DBICTest;
 use DBIC::SqlMakerTest;
-use DBIC::DebugObj;
 
-my $schema = DBICTest->init_schema();
+my $schema = DBICTest->init_schema( no_deploy => 1 );
 
 $schema->connection(
   @{ $schema->storage->_dbi_connect_info },
   { AutoCommit => 1, quote_char => [qw/[ ]/] }
 );
 
-my ($sql, @bind);
-$schema->storage->debugobj(DBIC::DebugObj->new(\$sql, \@bind));
-$schema->storage->debug(1);
+my $rs =  $schema->resultset('CD')->search(
+  { 'me.year' => 2001, 'artist.name' => 'Caterwauler McCrae' },
+  { join => 'artist' }
+)->count_rs;
+
+my $expected_bind = [
+  [ { dbic_colname => "artist.name", sqlt_datatype => "varchar", sqlt_size => 100 }
+    => 'Caterwauler McCrae' ],
+  [ { dbic_colname => "me.year", sqlt_datatype => "varchar", sqlt_size => 100 }
+    => 2001 ],
+];
 
-my $rs = $schema->resultset('CD')->search(
-           { 'me.year' => 2001, 'artist.name' => 'Caterwauler McCrae' },
-           { join => 'artist' });
-my $expected_bind =   ["'Caterwauler McCrae'", "'2001'"];
-eval { $rs->count };
 is_same_sql_bind(
-  $sql, \@bind,
-  "SELECT COUNT( * ) FROM cd [me]  JOIN [artist] [artist] ON ( [artist].[artistid] = [me].[artist] ) WHERE ( [artist].[name] = ? AND [me].[year] = ? )",
+  $rs->as_query,
+  "(SELECT COUNT( * ) FROM cd [me] JOIN [artist] [artist] ON [artist].[artistid] = [me].[artist] WHERE ( [artist].[name] = ? AND [me].[year] = ? ))",
   $expected_bind,
   'got correct SQL for count query with bracket quoting'
 );
@@ -34,27 +36,32 @@ is_same_sql_bind(
 $schema->storage->sql_maker->quote_char('`');
 $schema->storage->sql_maker->name_sep('.');
 
-eval { $rs->count };
-is_same_sql_bind(
-  $sql, \@bind,
-  "SELECT COUNT( * ) FROM cd `me`  JOIN `artist` `artist` ON ( `artist`.`artistid` = `me`.`artist` ) WHERE ( `artist`.`name` = ? AND `me`.`year` = ? )",
+is_same_sql_bind (
+  $rs->as_query,
+  "(SELECT COUNT( * ) FROM cd `me`  JOIN `artist` `artist` ON ( `artist`.`artistid` = `me`.`artist` ) WHERE ( `artist`.`name` = ? AND `me`.`year` = ? ))",
   $expected_bind,
-  'got correct SQL for count query with quoting'
+  'got correct SQL for count query with mysql quoting'
 );
 
-my $order = 'year DESC';
-$rs = $schema->resultset('CD')->search({},
-            { 'order_by' => $order });
-eval { $rs->first };
-like($sql, qr/ORDER BY `\Q${order}\E`/, 'quoted ORDER BY with DESC (should use a scalarref anyway)');
+# !!! talk to ribasushi *explicitly* before modfying these tests !!!
+{
+  is_same_sql_bind(
+    $schema->resultset('CD')->search({}, { order_by => 'year DESC', columns => 'cdid' })->as_query,
+    '(SELECT `me`.`cdid` FROM cd `me` ORDER BY `year DESC`)',
+    [],
+    'quoted ORDER BY with DESC (should use a scalarref anyway)'
+  );
 
-$rs = $schema->resultset('CD')->search({},
-            { 'order_by' => \$order });
-eval { $rs->first };
-like($sql, qr/ORDER BY \Q${order}\E/, 'did not quote ORDER BY with scalarref');
+  is_same_sql_bind(
+    $schema->resultset('CD')->search({}, { order_by => \'year DESC', columns => 'cdid' })->as_query,
+    '(SELECT `me`.`cdid` FROM cd `me` ORDER BY year DESC)',
+    [],
+    'did not quote ORDER BY with scalarref',
+  );
+}
 
-is(
-  $schema->storage->sql_maker->update('group', { name => 'Bill', order => 12 }),
+is_same_sql(
+  scalar $schema->storage->sql_maker->update('group', { order => 12, name => 'Bill' }),
   'UPDATE `group` SET `name` = ?, `order` = ?',
   'quoted table names for UPDATE' );
 
index 6d8e94c..514b43b 100644 (file)
@@ -6,7 +6,6 @@ use Test::More;
 use Test::Exception;
 use lib qw(t/lib);
 use DBICTest;
-use DBIC::DebugObj;
 use DBIC::SqlMakerTest;
 use Path::Class qw/file/;
 
@@ -19,6 +18,7 @@ unlink $lfn or die $!
   if -e $lfn;
 
 # make sure we are testing the vanilla debugger and not ::PrettyPrint
+require DBIx::Class::Storage::Statistics;
 $schema->storage->debugobj(DBIx::Class::Storage::Statistics->new);
 
 ok ( $schema->storage->debug(1), 'debug' );
@@ -61,25 +61,45 @@ dies_ok {
 
 open(STDERR, '>&STDERRCOPY');
 
-# test trace output correctness for bind params
+# test debugcb and debugobj protocol
 {
-    my ($sql, @bind);
-    $schema->storage->debugobj(DBIC::DebugObj->new(\$sql, \@bind));
-
-    my @cds = $schema->resultset('CD')->search( { artist => 1, cdid => { -between => [ 1, 3 ] }, } );
-    is_same_sql_bind(
-        $sql, \@bind,
-        "SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track FROM cd me WHERE ( artist = ? AND (cdid BETWEEN ? AND ?) )",
-        [qw/'1' '1' '3'/],
-        'got correct SQL with all bind parameters (debugcb)'
-    );
-
-    @cds = $schema->resultset('CD')->search( { artist => 1, cdid => { -between => [ 1, 3 ] }, } );
-    is_same_sql_bind(
-        $sql, \@bind,
-        "SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track FROM cd me WHERE ( artist = ? AND (cdid BETWEEN ? AND ?) )", ["'1'", "'1'", "'3'"],
-        'got correct SQL with all bind parameters (debugobj)'
-    );
+  my $rs = $schema->resultset('CD')->search( {
+    artist => 1,
+    cdid => { -between => [ 1, 3 ] },
+    title => { '!=' => \[ '?', undef ] }
+  });
+
+  my $sql_trace = 'SELECT me.cdid, me.artist, me.title, me.year, me.genreid, me.single_track FROM cd me WHERE ( ( artist = ? AND ( cdid BETWEEN ? AND ? ) AND title != ? ) )';
+  my @bind_trace = qw( '1' '1' '3' NULL );  # quotes are in fact part of the trace </facepalm>
+
+
+  my @args;
+  $schema->storage->debugcb(sub { push @args, @_ } );
+
+  $rs->all;
+
+  is_deeply( \@args, [
+    "SELECT",
+    sprintf( "%s: %s\n", $sql_trace, join ', ', @bind_trace ),
+  ]);
+
+  {
+    package DBICTest::DebugObj;
+    our @ISA = 'DBIx::Class::Storage::Statistics';
+
+    sub query_start {
+      my $self = shift;
+      ( $self->{_traced_sql}, @{$self->{_traced_bind}} ) = @_;
+    }
+  }
+
+  my $do = $schema->storage->debugobj(DBICTest::DebugObj->new);
+
+  $rs->all;
+
+  is( $do->{_traced_sql}, $sql_trace );
+
+  is_deeply ( $do->{_traced_bind}, \@bind_trace );
 }
 
 done_testing;
index d2dd840..b229756 100644 (file)
@@ -4,17 +4,14 @@ use warnings;
 use Test::More;
 use lib qw(t/lib);
 use DBICTest;
-use DBIC::DebugObj;
-use DBIC::SqlMakerTest;
-use DBI::Const::GetInfoType;
 
 { # Fake storage driver for SQLite + no bind variables
   package DBICTest::SQLite::NoBindVars;
-    use Class::C3;
-    use base qw/
-        DBIx::Class::Storage::DBI::NoBindVars
-        DBIx::Class::Storage::DBI::SQLite
-    /;
+  use base qw(
+    DBIx::Class::Storage::DBI::NoBindVars
+    DBIx::Class::Storage::DBI::SQLite
+  );
+  use mro 'c3';
 }
 
 my $schema = DBICTest->init_schema (storage_type => 'DBICTest::SQLite::NoBindVars', no_populate => 1);
@@ -35,26 +32,13 @@ my $it = $schema->resultset('Artist')->search( {},
 
 is( $it->count, 3, "LIMIT count ok" );  # ask for 3 rows out of 7 artists
 
-my ($sql, @bind);
-my $orig_debugobj = $schema->storage->debugobj;
-my $orig_debug = $schema->storage->debug;
-$schema->storage->debugobj (DBIC::DebugObj->new (\$sql, \@bind) );
-$schema->storage->debug (1);
-
-is( $it->next->name, "Artist 2", "iterator->next ok" );
-$it->next;
-$it->next;
-is( $it->next, undef, "next past end of resultset ok" );
-
-$schema->storage->debugobj ($orig_debugobj);
-$schema->storage->debug ($orig_debug);
-
-is_same_sql_bind (
-  $sql,
-  \@bind,
-  'SELECT me.artistid, me.name, me.rank, me.charfield FROM artist me ORDER BY artistid LIMIT 3 OFFSET 2',
-  [],
-  'Correctly interpolated SQL'
-);
+$schema->is_executed_sql_bind( sub {
+  is( $it->next->name, "Artist 2", "iterator->next ok" );
+  $it->next;
+  $it->next;
+  is( $it->next, undef, "next past end of resultset ok" );
+}, [
+  [ 'SELECT me.artistid, me.name, me.rank, me.charfield FROM artist me ORDER BY artistid LIMIT 3 OFFSET 2' ],
+], 'Correctly interpolated SQL' );
 
 done_testing;
index fab7036..0c56afc 100644 (file)
@@ -3,17 +3,30 @@ use warnings;
 
 use Test::More;
 use Test::Exception;
-use DBIx::Class::Optional::Dependencies ();
+
+use lib qw(t/lib);
+use DBICTest;
+
+{
+  package # moar hide
+    DBICTest::SVPTracerObj;
+
+  use base 'DBIx::Class::Storage::Statistics';
+
+  sub query_start { 'do notning'}
+  sub callback { 'dummy '}
+
+  for my $svpcall (map { "svp_$_" } qw(begin rollback release)) {
+    no strict 'refs';
+    *$svpcall = sub { $_[0]{uc $svpcall}++ };
+  }
+}
 
 my $env2optdep = {
   DBICTEST_PG => 'test_rdbms_pg',
   DBICTEST_MYSQL => 'test_rdbms_mysql',
 };
 
-use lib qw(t/lib);
-use DBICTest;
-use DBICTest::Stats;
-
 my $schema;
 
 for ('', keys %$env2optdep) { SKIP: {
@@ -56,9 +69,8 @@ for ('', keys %$env2optdep) { SKIP: {
 
   note "Testing $prefix";
 
-  my $stats = DBICTest::Stats->new;
-  $schema->storage->debugobj($stats);
-  $schema->storage->debug(1);
+  local $schema->storage->{debugobj} = my $stats = DBICTest::SVPTracerObj->new;
+  local $schema->storage->{debug} = 1;
 
   $schema->resultset('Artist')->create({ name => 'foo' });