use strict; use warnings; use DBI; use Test::More; use lib 't', '.'; require 'lib.pl'; use vars qw($got_warning $test_dsn $test_user $test_password); my $dbh = DbiTestConnect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0, AutoCommit => 0 }); sub catch_warning ($) { $got_warning = 1; } sub num_rows($$$) { my($dbh, $table, $num) = @_; my($sth, $got); if (!($sth = $dbh->prepare("SELECT * FROM dbd_mysql_t50commit"))) { return "Failed to prepare: err " . $dbh->err . ", errstr " . $dbh->errstr; } if (!$sth->execute) { return "Failed to execute: err " . $dbh->err . ", errstr " . $dbh->errstr; } $got = 0; while ($sth->fetchrow_arrayref) { ++$got; } if ($got ne $num) { return "Wrong result: Expected $num rows, got $got.\n"; } return ''; } my $engines = $dbh->selectall_hashref('SHOW ENGINES', 'Engine'); my $have_innodb = exists $engines->{InnoDB} && $engines->{InnoDB}->{Support} ne 'NO'; my $have_myisam = exists $engines->{MyISAM} && $engines->{MyISAM}->{Support} ne 'NO'; plan tests => 1 + ($have_myisam ? 12 : 0) + ($have_innodb ? 22 : 0); if ($have_innodb) { ok $dbh->do("DROP TABLE IF EXISTS dbd_mysql_t50commit"), "drop table if exists dbd_mysql_t50commit"; my $create =<do($create), 'create dbd_mysql_t50commit'; ok !$dbh->{AutoCommit}, "\$dbh->{AutoCommit} not defined |$dbh->{AutoCommit}|"; $dbh->{AutoCommit} = 0; ok !$dbh->err; ok !$dbh->errstr; ok !$dbh->{AutoCommit}; ok $dbh->do("INSERT INTO dbd_mysql_t50commit VALUES (1, 'Jochen')"), "insert into dbd_mysql_t50commit (1, 'Jochen')"; my $msg; $msg = num_rows($dbh, 'dbd_mysql_t50commit', 1); ok !$msg; ok $dbh->rollback, 'rollback'; $msg = num_rows($dbh, 'dbd_mysql_t50commit', 0); ok !$msg; ok $dbh->do("DELETE FROM dbd_mysql_t50commit WHERE id = 1"), "delete from dbd_mysql_t50commit where id = 1"; $msg = num_rows($dbh, 'dbd_mysql_t50commit', 0); ok !$msg; ok $dbh->commit, 'commit'; $msg = num_rows($dbh, 'dbd_mysql_t50commit', 0); ok !$msg; # Check auto rollback after disconnect ok $dbh->do("INSERT INTO dbd_mysql_t50commit VALUES (1, 'Jochen')"); $msg = num_rows($dbh, 'dbd_mysql_t50commit', 1); ok !$msg; ok $dbh->disconnect; ok ($dbh = DBI->connect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0 })); ok $dbh, "connected" or die; $msg = num_rows($dbh, 'dbd_mysql_t50commit', 0); ok !$msg; ok $dbh->{AutoCommit}, "\$dbh->{AutoCommit} $dbh->{AutoCommit}"; ok $dbh->do("DROP TABLE dbd_mysql_t50commit"); } if ($have_myisam) { ok $dbh->do("DROP TABLE IF EXISTS dbd_mysql_t50commit"), "drop table if exists dbd_mysql_t50commit"; my $create =<do($create), 'create dbd_mysql_t50commit'; # Tests for databases that don't support transactions # Check whether AutoCommit mode works. ok $dbh->do("INSERT INTO dbd_mysql_t50commit VALUES (1, 'Jochen')"); my $msg = num_rows($dbh, 'dbd_mysql_t50commit', 1); ok !$msg; ok $dbh->disconnect; ok ($dbh = DBI->connect($test_dsn, $test_user, $test_password, { RaiseError => 1, PrintError => 0 })); $msg = num_rows($dbh, 'dbd_mysql_t50commit', 1); ok !$msg; ok $dbh->do("INSERT INTO dbd_mysql_t50commit VALUES (2, 'Tim')"); my $result; $SIG{__WARN__} = \&catch_warning; $got_warning = 0; eval { $result = $dbh->commit; }; $SIG{__WARN__} = 'DEFAULT'; ok $got_warning; # Check whether rollback issues a warning in AutoCommit mode # We accept error messages as being legal, because the DBI # requirement of just issuing a warning seems scary. ok $dbh->do("INSERT INTO dbd_mysql_t50commit VALUES (3, 'Alligator')"); $SIG{__WARN__} = \&catch_warning; $got_warning = 0; eval { $result = $dbh->rollback; }; $SIG{__WARN__} = 'DEFAULT'; ok $got_warning, "Should be warning defined upon rollback of non-trx table"; ok $dbh->do("DROP TABLE dbd_mysql_t50commit"); } ok $dbh->disconnect();