File: svp_live.t

package info (click to toggle)
libdbix-connector-perl 0.60-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 284 kB
  • sloc: perl: 582; makefile: 2
file content (170 lines) | stat: -rw-r--r-- 5,467 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
use strict; use warnings;

use Test::More;
use DBIx::Connector;

my (@table_sql, $dsn, $user, $pass);

if (exists $ENV{DBICTEST_DSN}) {
    ($dsn, $user, $pass) = @ENV{map { "DBICTEST_${_}" } qw/DSN USER PASS/};
    my $driver = (DBI->parse_dsn($dsn))[1];
    if ($driver eq 'Pg') {
        @table_sql = (q{
            SET client_min_messages = warning;
            DROP TABLE IF EXISTS artist;
            CREATE TABLE artist (id serial PRIMARY KEY, name TEXT);
        });
    } elsif ($driver eq 'SQLite') {
        @table_sql = (
            'DROP TABLE IF EXISTS artist',
            q{CREATE TABLE artist (
                 id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name TEXT
             )},
        );
    } elsif ($driver eq 'Firebird') {
        @table_sql = (
            q{RECREATE TABLE artist (id INTEGER, name VARCHAR(100))},
        );
    } elsif ($driver eq 'mysql' or $driver eq 'MariaDB') {
        @table_sql = (
             'DROP TABLE IF EXISTS artist;',
             q{CREATE TABLE artist (
                 id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, name TEXT
             ) ENGINE=InnoDB;
        });
    } else {
        plan skip_all => 'Set DBICTEST_DSN _USER and _PASS to run savepoint tests';
    }
} else {
    plan skip_all => 'Set DBICTEST_DSN _USER and _PASS to run savepoint tests';
}

plan tests => 38;

ok my $conn = DBIx::Connector->new($dsn, $user, $pass, {
    PrintError => 0,
    RaiseError => 1,
}), 'Get a connection';
diag "Connecting to $dsn";
ok my $dbh = $conn->dbh, 'Get the database handle';
isa_ok $dbh, 'DBI::db', 'The handle';

$dbh->do($_) for (
    @table_sql,
    "INSERT INTO artist (id, name) VALUES(1, 'foo')",
);

pass 'Table created';

my $sel = $dbh->prepare('SELECT name FROM artist WHERE id = 1');
my $upd = $dbh->prepare('UPDATE artist SET name = ? WHERE id = 1');

ok $dbh->begin_work, 'Start a transaction';
is $dbh->selectrow_array($sel), 'foo', 'Name should be "foo"';
my $driver = $conn->driver;

# First off, test a generated savepoint name
ok $driver->savepoint($dbh, 'foo'), 'Savepoint "foo"';
ok $upd->execute('Jheephizzy'), 'Update to "Jheephizzy"';
is $dbh->selectrow_array($sel), 'Jheephizzy', 'The name should now be "Jheephizzy"';

# Rollback the generated name
# Active: 0
ok $driver->rollback_to($dbh, 'foo'), 'Rollback the to "foo"';
is $dbh->selectrow_array($sel), 'foo', 'Name should be "foo" again';

ok $upd->execute('Jheephizzy'), 'Update to "Jheephizzy" again';

# Active: 0
ok $driver->savepoint($dbh, 'testing1'), 'Savepoint testing1';
ok $upd->execute('yourmom'), 'Update to "yourmom"';

# Active: 0 1
ok $driver->savepoint($dbh, 'testing2'), 'Savepont testing2';
ok $upd->execute('gphat'), 'Update to "gphat"';
is $dbh->selectrow_array($sel), 'gphat', 'Name should be "gphat"';

# Active: 0 1
# Rollback doesn't DESTROY the savepoint, it just rolls back to the value
# at it's conception
ok $driver->rollback_to($dbh, 'testing2'), 'Rollback testing2';
is $dbh->selectrow_array($sel), 'yourmom', 'Name should be "yourmom"';

# Active: 0 1 2
ok $driver->savepoint($dbh, 'testing3'), 'Savepoint testing3';
ok $upd->execute('coryg'), 'Update to "coryg"';
# Active: 0 1 2 3
ok $driver->savepoint($dbh, 'testing4'), 'Savepoint testing4';
ok $upd->execute('watson'), 'Update to "watson"';

# Release 3, which implicitly releases 4
# Active: 0 1
ok $driver->release($dbh, 'testing3'), 'Release testing3';
is $dbh->selectrow_array($sel), 'watson', 'Name should be "watson"';

# This rolls back savepoint 2
# Active: 0 1
ok $driver->rollback_to($dbh, 'testing2'), 'Rollback to [savepoint2]';
is $dbh->selectrow_array($sel), 'yourmom', 'Name should be "yourmom" again';

# Rollback the original savepoint, taking us back to the beginning, implicitly
# rolling back savepoint 1
ok $driver->rollback_to($dbh, 'foo'), 'Rollback to the beginning';
is $dbh->selectrow_array($sel), 'foo', 'Name should be "foo" once more';

ok $dbh->commit, 'Commit the changes';

# And now to see if svp will behave correctly
$conn->svp (sub {
    $conn->txn( fixup => sub { $upd->execute('Muff') });

    eval {
        $conn->svp(sub {
            $upd->execute('Moff');
            is $dbh->selectrow_array($sel), 'Moff', 'Name should be "Moff" in nested transaction';
            shift->do('SELECT gack from artist');
        });
    };
    ok $@,'Nested transaction failed (good)';
    is $dbh->selectrow_array($sel), 'Muff', 'Rolled back name should be "Muff"';
    $upd->execute('Miff');
});

is $dbh->selectrow_array($sel), 'Miff', 'Savepoint worked: name is "Muff"';

$conn->txn(fixup => sub {
  my ($dbh) = @_;
  $dbh->do("DELETE FROM artist;");
  $dbh->do("INSERT INTO artist (name) VALUES ('All-Time Quarterback');");

  my $token = \do { my $x = "TURN IT OFF" };

  my $ok = eval {
    $conn->svp(sub {
      my ($dbh) = @_;
      $dbh->do("INSERT INTO artist (name) VALUES ('Britney Spears');");
      die $token;
    });
    1;
  };
  my $error = $@;

  ok( ! $ok, "we didn't survive our svp");
  ok(
    (ref $error  && ref $error eq 'SCALAR' && $error == $token),
    "we got the expected error, too"
  ) or diag "got error: $error";

  $dbh->do("INSERT INTO artist (name) VALUES ('Cyndi Lauper');");
});

$conn->txn(sub {
  my ($dbh) = @_;
  my $rows = $dbh->selectcol_arrayref("SELECT name FROM artist ORDER BY name");
  is(@$rows, 2, "we inserted 2 rows");
  is_deeply(
    $rows,
    [ 'All-Time Quarterback', 'Cyndi Lauper' ],
    "...and we omitted the bad one",
  );
});