1use strict;
2use warnings;
3
4use DBI;
5use Test::More;
6use lib 't', '.';
7require 'lib.pl';
8
9use vars qw($have_transactions $got_warning $test_dsn $test_user $test_password);
10
11my $dbh;
12eval {$dbh= DBI->connect($test_dsn, $test_user, $test_password,
13                      { RaiseError => 1, PrintError => 1, AutoCommit => 0 });};
14if ($@) {
15    plan skip_all => "no database connection";
16}
17
18sub catch_warning ($) {
19    $got_warning = 1;
20}
21
22sub num_rows($$$) {
23    my($dbh, $table, $num) = @_;
24    my($sth, $got);
25
26    if (!($sth = $dbh->prepare("SELECT * FROM dbd_mysql_t50commit"))) {
27      return "Failed to prepare: err " . $dbh->err . ", errstr "
28        . $dbh->errstr;
29    }
30    if (!$sth->execute) {
31      return "Failed to execute: err " . $dbh->err . ", errstr "
32        . $dbh->errstr;
33    }
34    $got = 0;
35    while ($sth->fetchrow_arrayref) {
36      ++$got;
37    }
38    if ($got ne $num) {
39      return "Wrong result: Expected $num rows, got $got.\n";
40    }
41    return '';
42}
43
44$have_transactions = have_transactions($dbh);
45my $engine= $have_transactions ? 'InnoDB' : 'MyISAM';
46
47if ($have_transactions) {
48  plan tests => 22;
49
50  ok $dbh->do("DROP TABLE IF EXISTS dbd_mysql_t50commit"), "drop table if exists dbd_mysql_t50commit";
51  my $create =<<EOT;
52CREATE TABLE dbd_mysql_t50commit (
53    id INT(4) NOT NULL default 0,
54    name VARCHAR(64) NOT NULL default ''
55) ENGINE=$engine
56EOT
57
58  ok $dbh->do($create), 'create dbd_mysql_t50commit';
59
60  ok !$dbh->{AutoCommit}, "\$dbh->{AutoCommit} not defined |$dbh->{AutoCommit}|";
61
62  $dbh->{AutoCommit} = 0;
63  ok !$dbh->err;
64  ok !$dbh->errstr;
65  ok !$dbh->{AutoCommit};
66
67  ok $dbh->do("INSERT INTO dbd_mysql_t50commit VALUES (1, 'Jochen')"),
68  "insert into dbd_mysql_t50commit (1, 'Jochen')";
69
70  my $msg;
71  $msg = num_rows($dbh, 'dbd_mysql_t50commit', 1);
72  ok !$msg;
73
74  ok $dbh->rollback, 'rollback';
75
76  $msg = num_rows($dbh, 'dbd_mysql_t50commit', 0);
77  ok !$msg;
78
79  ok $dbh->do("DELETE FROM dbd_mysql_t50commit WHERE id = 1"), "delete from dbd_mysql_t50commit where id = 1";
80
81  $msg = num_rows($dbh, 'dbd_mysql_t50commit', 0);
82  ok !$msg;
83  ok $dbh->commit, 'commit';
84
85  $msg = num_rows($dbh, 'dbd_mysql_t50commit', 0);
86  ok !$msg;
87
88  # Check auto rollback after disconnect
89  ok $dbh->do("INSERT INTO dbd_mysql_t50commit VALUES (1, 'Jochen')");
90
91  $msg = num_rows($dbh, 'dbd_mysql_t50commit', 1);
92  ok !$msg;
93
94  ok $dbh->disconnect;
95
96  ok ($dbh = DBI->connect($test_dsn, $test_user, $test_password));
97
98  ok $dbh, "connected";
99
100  $msg = num_rows($dbh, 'dbd_mysql_t50commit', 0);
101  ok !$msg;
102
103  ok $dbh->{AutoCommit}, "\$dbh->{AutoCommit} $dbh->{AutoCommit}";
104  ok $dbh->do("DROP TABLE dbd_mysql_t50commit");
105
106}
107else {
108  plan tests => 13;
109
110  ok $dbh->do("DROP TABLE IF EXISTS dbd_mysql_t50commit"), "drop table if exists dbd_mysql_t50commit";
111  my $create =<<EOT;
112  CREATE TABLE dbd_mysql_t50commit (
113      id INT(4) NOT NULL default 0,
114      name VARCHAR(64) NOT NULL default ''
115      ) ENGINE=$engine
116EOT
117
118  ok $dbh->do($create), 'create dbd_mysql_t50commit';
119
120  # Tests for databases that don't support transactions
121  # Check whether AutoCommit mode works.
122
123  ok $dbh->do("INSERT INTO dbd_mysql_t50commit VALUES (1, 'Jochen')");
124  my $msg = num_rows($dbh, 'dbd_mysql_t50commit', 1);
125  ok !$msg;
126
127  ok $dbh->disconnect;
128
129  ok ($dbh = DBI->connect($test_dsn, $test_user, $test_password));
130
131  $msg = num_rows($dbh, 'dbd_mysql_t50commit', 1);
132  ok !$msg;
133
134  ok $dbh->do("INSERT INTO dbd_mysql_t50commit VALUES (2, 'Tim')");
135
136  my $result;
137  $@ = '';
138
139  $SIG{__WARN__} = \&catch_warning;
140
141  $got_warning = 0;
142
143  eval { $result = $dbh->commit; };
144
145  $SIG{__WARN__} = 'DEFAULT';
146
147  ok $got_warning;
148
149#   Check whether rollback issues a warning in AutoCommit mode
150#   We accept error messages as being legal, because the DBI
151#   requirement of just issuing a warning seems scary.
152  ok $dbh->do("INSERT INTO dbd_mysql_t50commit VALUES (3, 'Alligator')");
153
154  $@ = '';
155  $SIG{__WARN__} = \&catch_warning;
156  $got_warning = 0;
157  eval { $result = $dbh->rollback; };
158  $SIG{__WARN__} = 'DEFAULT';
159
160  ok $got_warning, "Should be warning defined upon rollback of non-trx table";
161
162  ok $dbh->do("DROP TABLE dbd_mysql_t50commit");
163  ok $dbh->disconnect();
164}
165