add test for IDENTITY_INSERT
[dbsrgits/DBIx-Class.git] / t / 746sybase.t
index 7c9e56b..6f6f3aa 100644 (file)
@@ -9,7 +9,7 @@ use DBICTest;
 
 my ($dsn, $user, $pass) = @ENV{map { "DBICTEST_SYBASE_${_}" } qw/DSN USER PASS/};
 
-my $TESTS = 29 + 2;
+my $TESTS = 37 + 2;
 
 if (not ($dsn && $user)) {
   plan skip_all =>
@@ -27,21 +27,22 @@ my @storage_types = (
 my $schema;
 my $storage_idx = -1;
 
+sub get_schema {
+  DBICTest::Schema->connect($dsn, $user, $pass, {
+    on_connect_call => [
+      [ blob_setup => log_on_update => 1 ], # this is a safer option
+    ],
+  });
+}
+
 for my $storage_type (@storage_types) {
   $storage_idx++;
-# this is so we can set ->storage_type before connecting
-  my $schema = DBICTest::Schema->clone;
 
   unless ($storage_type eq 'DBI::Sybase') { # autodetect
-    $schema->storage_type("::$storage_type");
+    DBICTest::Schema->storage_type("::$storage_type");
   }
 
-  $schema->connection($dsn, $user, $pass, {
-    AutoCommit => 1,
-    on_connect_call => [
-      [ blob_setup => log_on_update => 1 ], # this is a safer option
-    ],
-  });
+  $schema = get_schema();
 
   $schema->storage->ensure_connected;
 
@@ -82,12 +83,27 @@ SQL
 
   $seen_id{$new->artistid}++;
 
-  for (1..6) {
+# check redispatch to storage-specific insert when auto-detected storage
+  if ($storage_type eq 'DBI::Sybase') {
+    DBICTest::Schema->storage_type('::DBI');
+    $schema = get_schema();
+  }
+
+  $new = $schema->resultset('Artist')->create({ name => 'Artist 1' });
+  is ( $seen_id{$new->artistid}, undef, 'id for Artist 1 is unique' );
+  $seen_id{$new->artistid}++;
+
+# inserts happen in a txn, so we make sure it still works inside a txn too
+  $schema->txn_begin;
+
+  for (2..6) {
     $new = $schema->resultset('Artist')->create({ name => 'Artist ' . $_ });
     is ( $seen_id{$new->artistid}, undef, "id for Artist $_ is unique" );
     $seen_id{$new->artistid}++;
   }
 
+  $schema->txn_commit;
+
 # test simple count
   is ($schema->resultset('Artist')->count, 7, 'count(*) of whole table ok');
 
@@ -130,10 +146,39 @@ SQL
 
   is( $it->count, 7, 'COUNT of GROUP_BY ok' );
 
+# do an identity insert (which should happen with no txn when using
+# placeholders.)
+  {
+    no warnings 'redefine';
+    my @debug_out;
+    local *DBIx::Class::Storage::DBI::_query_start = sub {
+      push @debug_out, $_[1];
+    };
+
+    my $txn_used = 0;
+    my $txn_commit = \&DBIx::Class::Storage::DBI::txn_commit;
+    local *DBIx::Class::Storage::DBI::txn_commit = sub {
+      $txn_used = 1;
+      goto &$txn_commit;
+    };
+
+    $schema->resultset('Artist')
+      ->create({ artistid => 999, name => 'mtfnpy' });
+
+    ok((grep /IDENTITY_INSERT/i, @debug_out), 'IDENTITY_INSERT');
+
+    SKIP: {
+      skip 'not testing lack of txn on IDENTITY_INSERT with NoBindVars', 1
+        if $storage_type =~ /NoBindVars/i;
+
+      is $txn_used, 0, 'no txn on insert with IDENTITY_INSERT';
+    }
+  }
+
 # mostly stolen from the blob stuff Nniuq wrote for t/73oracle.t
   SKIP: {
     skip 'TEXT/IMAGE support does not work with FreeTDS', 12
-      if $schema->storage->_using_freetds;
+      if $schema->storage->using_freetds;
 
     my $dbh = $schema->storage->dbh;
     {
@@ -155,9 +200,12 @@ SQL
     $binstr{'large'} = $binstr{'small'} x 1024;
 
     my $maxloblen = length $binstr{'large'};
-    note
-      "Localizing LongReadLen to $maxloblen to avoid truncation of test data";
-    local $dbh->{'LongReadLen'} = $maxloblen * 2;
+    
+    if (not $schema->storage->using_freetds) {
+      $dbh->{'LongReadLen'} = $maxloblen * 2;
+    } else {
+      $dbh->do("set textsize ".($maxloblen * 2));
+    }
 
     my $rs = $schema->resultset('BindType');
     my $last_id;
@@ -208,6 +256,13 @@ SQL
 
     # try a blob update
     my $new_str = $binstr{large} . 'mtfnpy';
+
+    # check redispatch to storage-specific update when auto-detected storage
+    if ($storage_type eq 'DBI::Sybase') {
+      DBICTest::Schema->storage_type('::DBI');
+      $schema = get_schema();
+    }
+
     eval { $rs->search({ id => 1 })->update({ blob => $new_str }) };
     ok !$@, 'updated blob successfully';
     diag $@ if $@;
@@ -217,12 +272,51 @@ SQL
     diag $@ if $@;
     ok($got eq $new_str, "verified updated blob");
   }
+
+# test MONEY column support
+  $schema->storage->dbh_do (sub {
+      my ($storage, $dbh) = @_;
+      eval { $dbh->do("DROP TABLE money_test") };
+      $dbh->do(<<'SQL');
+CREATE TABLE money_test (
+   id INT IDENTITY PRIMARY KEY,
+   amount MONEY NULL
+)
+SQL
+  });
+
+  my $rs = $schema->resultset('Money');
+
+  my $row;
+  lives_ok {
+    $row = $rs->create({ amount => 100 });
+  } 'inserted a money value';
+
+  is eval { $rs->find($row->id)->amount }, 100, 'money value round-trip';
+
+  lives_ok {
+    $row->update({ amount => 200 });
+  } 'updated a money value';
+
+  is eval { $rs->find($row->id)->amount },
+    200, 'updated money value round-trip';
+
+  lives_ok {
+    $row->update({ amount => undef });
+  } 'updated a money value to NULL';
+
+  my $null_amount = eval { $rs->find($row->id)->amount };
+  ok(
+    (($null_amount == undef) && (not $@)),
+    'updated money value to NULL round-trip'
+  );
+  diag $@ if $@;
 }
 
 # clean up our mess
 END {
   if (my $dbh = eval { $schema->storage->_dbh }) {
-    $dbh->do('DROP TABLE artist');
-    eval { $dbh->do('DROP TABLE bindtype_test')    };
+    eval { $dbh->do("DROP TABLE $_") }
+      for qw/artist bindtype_test money_test/;
   }
 }