diff --git a/dbdimp.c b/dbdimp.c index 8fdb7b8..b825beb 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -570,6 +570,26 @@ sqlite_st_execute(SV *sth, imp_sth_t *imp_sth) } } } + else if (DBIc_is(imp_dbh, DBIcf_BegunWork)) { + char *sql = sqlite3_sql(imp_sth->stmt); + if (((sql[0] == 'C' || sql[0] == 'c') && + (sql[1] == 'O' || sql[1] == 'o') && + (sql[2] == 'M' || sql[2] == 'm') && + (sql[3] == 'M' || sql[3] == 'm') && + (sql[4] == 'I' || sql[4] == 'i') && + (sql[5] == 'T' || sql[5] == 't')) || + ((sql[0] == 'R' || sql[0] == 'r') && + (sql[1] == 'O' || sql[1] == 'o') && + (sql[2] == 'L' || sql[2] == 'l') && + (sql[3] == 'L' || sql[3] == 'l') && + (sql[4] == 'B' || sql[4] == 'b') && + (sql[5] == 'A' || sql[5] == 'a') && + (sql[6] == 'C' || sql[6] == 'c') && + (sql[7] == 'K' || sql[7] == 'k'))) { + DBIc_off(imp_dbh, DBIcf_BegunWork); + DBIc_on(imp_dbh, DBIcf_AutoCommit); + } + } imp_sth->nrow = 0; diff --git a/t/rt_52573_manual_exclusive_lock.t b/t/rt_52573_manual_exclusive_lock.t index 2505ae5..db0f3e9 100644 --- a/t/rt_52573_manual_exclusive_lock.t +++ b/t/rt_52573_manual_exclusive_lock.t @@ -7,7 +7,7 @@ BEGIN { } use t::lib::Test; -use Test::More tests => 94; +use Test::More tests => 92 * 4 + 2; use Test::NoWarnings; my $dbh = connect_ok( @@ -18,185 +18,197 @@ my $dbh = connect_ok( $dbh->do('create table foo (id)'); -# scenario 1: AutoCommit => 1 and no begin_work +my @funcs = ( + sub { shift->rollback }, + sub { shift->commit }, + sub { shift->do('rollback') }, + sub { shift->do('commit') }, +); -ok $dbh->{AutoCommit}, "AutoCommit is on"; -ok !$dbh->{BegunWork}, "BegunWork is off"; -eval { $dbh->do('insert into foo (id) values (1)'); }; -ok !$@, 'a statement works'; -diag $@ if $@; -# eval { $dbh->rollback }; -# ok !$@, "rollback ignored: nothing to be rolled back"; -# diag $@ if $@; -ok $dbh->{AutoCommit}, "AutoCommit is still on"; -ok !$dbh->{BegunWork}, "BegunWork is still off"; +foreach my $func (@funcs) { + # scenario 1: AutoCommit => 1 and no begin_work -# scenario 2: AutoCommit => 1 and begin_work and implicit BEGIN + eval { $dbh->{AutoCommit} = 1 }; # initialize + ok $dbh->{AutoCommit}, "AutoCommit is on"; + ok !$dbh->{BegunWork}, "BegunWork is off"; + eval { $dbh->do('insert into foo (id) values (1)'); }; + ok !$@, 'a statement works'; + diag $@ if $@; + # eval { $func->($dbh) }; + # ok !$@, "commit/rollback ignored"; + # diag $@ if $@; + ok $dbh->{AutoCommit}, "AutoCommit is still on"; + ok !$dbh->{BegunWork}, "BegunWork is still off"; -eval { $dbh->begin_work }; -ok !$@, "begin_work works"; -ok !$dbh->{AutoCommit}, "AutoCommit is turned off"; -ok $dbh->{BegunWork}, "BegunWork is turned on"; -eval { $dbh->begin_work }; -like $@ => qr/Already in a transaction/, "but second begin_work should fail"; -eval { $dbh->do('insert into foo (id) values (1)'); }; -ok !$@, "other statement should work"; -diag $@ if $@; -eval { $dbh->rollback }; -ok !$@, 'rolled back'; -diag $@ if $@; -ok $dbh->{AutoCommit}, "AutoCommit is turned on"; -ok !$dbh->{BegunWork}, "BegunWork is turned off"; + # scenario 2: AutoCommit => 1 and begin_work and implicit BEGIN -# scenario 3: AutoCommit => 1 and begin_work and explicit and immediate BEGIN + eval { $dbh->begin_work }; + ok !$@, "begin_work works"; + ok !$dbh->{AutoCommit}, "AutoCommit is turned off"; + ok $dbh->{BegunWork}, "BegunWork is turned on"; + eval { $dbh->begin_work }; + like $@ => qr/Already in a transaction/, "but second begin_work should fail"; + eval { $dbh->do('insert into foo (id) values (1)'); }; + ok !$@, "other statement should work"; + diag $@ if $@; + eval { $func->($dbh) }; + ok !$@, 'rolled back/committed'; + diag $@ if $@; + ok $dbh->{AutoCommit}, "AutoCommit is turned on"; + ok !$dbh->{BegunWork}, "BegunWork is turned off"; -eval { $dbh->begin_work }; -ok !$@, "begin_work works"; -ok !$dbh->{AutoCommit}, "AutoCommit is turned off"; -ok $dbh->{BegunWork}, "BegunWork is turned on"; -eval { $dbh->do('BEGIN EXCLUSIVE TRANSACTION') }; -ok !$@, "first BEGIN should be passed through"; -diag $@ if $@; -eval { $dbh->do('BEGIN TRANSACTION') }; -like $@ => qr/cannot start a transaction/, "second BEGIN should fail"; -eval { $dbh->begin_work }; -like $@ => qr/Already in a transaction/, "and second begin_work also should fail"; -eval { $dbh->do('insert into foo (id) values (1)'); }; -ok !$@, 'other statement should work'; -diag $@ if $@; -eval { $dbh->rollback }; -ok !$@, 'rolled back'; -diag $@ if $@; -ok $dbh->{AutoCommit}, "AutoCommit is turned on now"; -ok !$dbh->{BegunWork}, "BegunWork is turned off"; + # scenario 3: AutoCommit => 1 and begin_work and explicit and immediate BEGIN -# scenario 4: AutoCommit => 1 and begin_work and explicit but not immediate BEGIN -eval { $dbh->begin_work }; -ok !$@, "begin_work works"; -ok !$dbh->{AutoCommit}, "AutoCommit is turned off"; -ok $dbh->{BegunWork}, "BegunWork is turned on"; -eval { $dbh->do('insert into foo (id) values (1)'); }; -ok !$@, 'statement should work'; -diag $@ if $@; -eval { $dbh->do('BEGIN TRANSACTION') }; -like $@ => qr/cannot start a transaction/, "BEGIN after other statements should fail"; -eval { $dbh->begin_work }; -like $@ => qr/Already in a transaction/, "and second begin_work also should fail"; -eval { $dbh->do('insert into foo (id) values (1)'); }; -ok !$@, 'other statement should work'; -diag $@ if $@; -eval { $dbh->rollback }; -ok !$@, 'rolled back'; -diag $@ if $@; -ok $dbh->{AutoCommit}, "AutoCommit is turned on now"; -ok !$dbh->{BegunWork}, "BegunWork is turned off"; + eval { $dbh->begin_work }; + ok !$@, "begin_work works"; + ok !$dbh->{AutoCommit}, "AutoCommit is turned off"; + ok $dbh->{BegunWork}, "BegunWork is turned on"; + eval { $dbh->do('BEGIN EXCLUSIVE TRANSACTION') }; + ok !$@, "first BEGIN should be passed through"; + diag $@ if $@; + eval { $dbh->do('BEGIN TRANSACTION') }; + like $@ => qr/cannot start a transaction/, "second BEGIN should fail"; + eval { $dbh->begin_work }; + like $@ => qr/Already in a transaction/, "and second begin_work also should fail"; + eval { $dbh->do('insert into foo (id) values (1)'); }; + ok !$@, 'other statement should work'; + diag $@ if $@; + eval { $func->($dbh) }; + ok !$@, 'rolled back/committed'; + diag $@ if $@; + ok $dbh->{AutoCommit}, "AutoCommit is turned on now"; + ok !$dbh->{BegunWork}, "BegunWork is turned off"; -# scenario 5: AutoCommit => 1 and explicit BEGIN and no begin_work -ok $dbh->{AutoCommit}, "AutoCommit is on"; -ok !$dbh->{BegunWork}, "BegunWork is off"; -eval { $dbh->do('BEGIN TRANSACTION'); }; -ok !$@, 'BEGIN should work'; -diag $@ if $@; -ok !$dbh->{AutoCommit}, "AutoCommit is turned off"; -ok $dbh->{BegunWork}, "BegunWork is turned on"; -eval { $dbh->do('BEGIN TRANSACTION') }; -like $@ => qr/cannot start a transaction/, "second BEGIN should fail"; -eval { $dbh->do('insert into foo (id) values (1)'); }; -ok !$@, 'other statement should work'; -diag $@ if $@; -eval { $dbh->rollback }; -ok !$@, 'rolled back'; -diag $@ if $@; -ok $dbh->{AutoCommit}, "AutoCommit is turned on now"; -ok !$dbh->{BegunWork}, "BegunWork is turned off"; + # scenario 4: AutoCommit => 1 and begin_work and explicit but not immediate BEGIN + eval { $dbh->begin_work }; + ok !$@, "begin_work works"; + ok !$dbh->{AutoCommit}, "AutoCommit is turned off"; + ok $dbh->{BegunWork}, "BegunWork is turned on"; + eval { $dbh->do('insert into foo (id) values (1)'); }; + ok !$@, 'statement should work'; + diag $@ if $@; + eval { $dbh->do('BEGIN TRANSACTION') }; + like $@ => qr/cannot start a transaction/, "BEGIN after other statements should fail"; + eval { $dbh->begin_work }; + like $@ => qr/Already in a transaction/, "and second begin_work also should fail"; + eval { $dbh->do('insert into foo (id) values (1)'); }; + ok !$@, 'other statement should work'; + diag $@ if $@; + eval { $func->($dbh) }; + ok !$@, 'rolled back/committed'; + diag $@ if $@; + ok $dbh->{AutoCommit}, "AutoCommit is turned on now"; + ok !$dbh->{BegunWork}, "BegunWork is turned off"; -# scenario 6: AutoCommit => 1 and explicit BEGIN and begin_work -ok $dbh->{AutoCommit}, "AutoCommit is on"; -ok !$dbh->{BegunWork}, "BegunWork is off"; -eval { $dbh->do('BEGIN TRANSACTION'); }; -ok !$@, 'BEGIN should work'; -diag $@ if $@; -ok !$dbh->{AutoCommit}, "AutoCommit is turned off"; -ok $dbh->{BegunWork}, "BegunWork is turned on"; -eval { $dbh->do('BEGIN TRANSACTION') }; -like $@ => qr/cannot start a transaction/, "second BEGIN should fail"; -eval { $dbh->begin_work }; -like $@ => qr/Already in a transaction/, "and second begin_work also should fail"; -eval { $dbh->do('insert into foo (id) values (1)'); }; -ok !$@, 'other statement should work'; -diag $@ if $@; -eval { $dbh->rollback }; -ok !$@, 'rolled back'; -diag $@ if $@; -ok $dbh->{AutoCommit}, "AutoCommit is turned on now"; -ok !$dbh->{BegunWork}, "BegunWork is turned off"; + # scenario 5: AutoCommit => 1 and explicit BEGIN and no begin_work + ok $dbh->{AutoCommit}, "AutoCommit is on"; + ok !$dbh->{BegunWork}, "BegunWork is off"; + eval { $dbh->do('BEGIN TRANSACTION'); }; + ok !$@, 'BEGIN should work'; + diag $@ if $@; + ok !$dbh->{AutoCommit}, "AutoCommit is turned off"; + ok $dbh->{BegunWork}, "BegunWork is turned on"; + eval { $dbh->do('BEGIN TRANSACTION') }; + like $@ => qr/cannot start a transaction/, "second BEGIN should fail"; + eval { $dbh->do('insert into foo (id) values (1)'); }; + ok !$@, 'other statement should work'; + diag $@ if $@; + eval { $func->($dbh) }; + ok !$@, 'rolled back/committed'; + diag $@ if $@; + ok $dbh->{AutoCommit}, "AutoCommit is turned on now"; + ok !$dbh->{BegunWork}, "BegunWork is turned off"; -# scenario 7: AutoCommit => 0 and explicit BEGIN -eval { $dbh->{AutoCommit} = 1 }; # to initialize -ok $dbh->{AutoCommit}, "AutoCommit is on"; -ok !$dbh->{BegunWork}, "BegunWork is off"; -eval { $dbh->{AutoCommit} = 0 }; -ok !$@, "AutoCommit is turned off"; -ok !$dbh->{BegunWork}, "BegunWork is still off"; -eval { $dbh->do('BEGIN TRANSACTION'); }; -ok !$@, 'BEGIN should work'; -diag $@ if $@; -ok !$dbh->{AutoCommit}, "AutoCommit is turned off"; -ok !$dbh->{BegunWork}, "BegunWork is still off"; -eval { $dbh->do('BEGIN TRANSACTION') }; -like $@ => qr/cannot start a transaction/, "second BEGIN should fail"; -eval { $dbh->begin_work }; -like $@ => qr/Already in a transaction/, "and begin_work also should fail"; -eval { $dbh->do('insert into foo (id) values (1)'); }; -ok !$@, 'other statement should work'; -diag $@ if $@; -eval { $dbh->rollback }; -ok !$@, 'rolled back'; -diag $@ if $@; -ok !$dbh->{AutoCommit}, "AutoCommit is still off"; -ok !$dbh->{BegunWork}, "BegunWork is still off"; + # scenario 6: AutoCommit => 1 and explicit BEGIN and begin_work + ok $dbh->{AutoCommit}, "AutoCommit is on"; + ok !$dbh->{BegunWork}, "BegunWork is off"; + eval { $dbh->do('BEGIN TRANSACTION'); }; + ok !$@, 'BEGIN should work'; + diag $@ if $@; + ok !$dbh->{AutoCommit}, "AutoCommit is turned off"; + ok $dbh->{BegunWork}, "BegunWork is turned on"; + eval { $dbh->do('BEGIN TRANSACTION') }; + like $@ => qr/cannot start a transaction/, "second BEGIN should fail"; + eval { $dbh->begin_work }; + like $@ => qr/Already in a transaction/, "and second begin_work also should fail"; + eval { $dbh->do('insert into foo (id) values (1)'); }; + ok !$@, 'other statement should work'; + diag $@ if $@; + eval { $func->($dbh) }; + ok !$@, 'rolled back/committed'; + diag $@ if $@; + ok $dbh->{AutoCommit}, "AutoCommit is turned on now"; + ok !$dbh->{BegunWork}, "BegunWork is turned off"; -# scenario 8: AutoCommit => 0 and begin_work -eval { $dbh->{AutoCommit} = 1 }; # to initialize -ok $dbh->{AutoCommit}, "AutoCommit is on"; -ok !$dbh->{BegunWork}, "BegunWork is off"; -eval { $dbh->{AutoCommit} = 0 }; -ok !$@, "AutoCommit is turned off"; -ok !$dbh->{BegunWork}, "BegunWork is still off"; -eval { $dbh->begin_work; }; -like $@ => qr/Already in a transaction/, "begin_work should fail"; -ok !$dbh->{AutoCommit}, "AutoCommit is still off"; -ok !$dbh->{BegunWork}, "BegunWork is still off"; -eval { $dbh->do('BEGIN TRANSACTION') }; -ok !$@, "BEGIN should work"; -diag $@ if $@; -ok !$dbh->{AutoCommit}, "AutoCommit is still off"; -ok !$dbh->{BegunWork}, "BegunWork is still off"; -eval { $dbh->begin_work }; -like $@ => qr/Already in a transaction/, "and second begin_work also should fail"; -eval { $dbh->do('insert into foo (id) values (1)'); }; -ok !$@, 'other statement should work'; -diag $@ if $@; -eval { $dbh->rollback }; -ok !$@, 'rolled back'; -diag $@ if $@; -ok !$dbh->{AutoCommit}, "AutoCommit is still off"; -ok !$dbh->{BegunWork}, "BegunWork is still off"; + # scenario 7: AutoCommit => 0 and explicit BEGIN + eval { $dbh->{AutoCommit} = 1 }; # to initialize + ok $dbh->{AutoCommit}, "AutoCommit is on"; + ok !$dbh->{BegunWork}, "BegunWork is off"; + eval { $dbh->{AutoCommit} = 0 }; + ok !$@, "AutoCommit is turned off"; + ok !$dbh->{BegunWork}, "BegunWork is still off"; + eval { $dbh->do('BEGIN TRANSACTION'); }; + ok !$@, 'BEGIN should work'; + diag $@ if $@; + ok !$dbh->{AutoCommit}, "AutoCommit is turned off"; + ok !$dbh->{BegunWork}, "BegunWork is still off"; + eval { $dbh->do('BEGIN TRANSACTION') }; + like $@ => qr/cannot start a transaction/, "second BEGIN should fail"; + eval { $dbh->begin_work }; + like $@ => qr/Already in a transaction/, "and begin_work also should fail"; + eval { $dbh->do('insert into foo (id) values (1)'); }; + ok !$@, 'other statement should work'; + diag $@ if $@; + eval { $func->($dbh) }; + ok !$@, 'rolled back/committed'; + diag $@ if $@; + ok !$dbh->{AutoCommit}, "AutoCommit is still off"; + ok !$dbh->{BegunWork}, "BegunWork is still off"; -# scenario 9: AutoCommit => 0 and implicit BEGIN -eval { $dbh->{AutoCommit} = 1 }; # to initialize -ok $dbh->{AutoCommit}, "AutoCommit is on"; -ok !$dbh->{BegunWork}, "BegunWork is off"; -eval { $dbh->{AutoCommit} = 0 }; -ok !$@, "AutoCommit is turned off"; -ok !$dbh->{BegunWork}, "BegunWork is still off"; -eval { $dbh->do('insert into foo (id) values (1)'); }; -ok !$@, 'other statement should work'; -diag $@ if $@; -ok !$dbh->{AutoCommit}, "AutoCommit is still off"; -ok !$dbh->{BegunWork}, "BegunWork is still off"; -eval { $dbh->rollback }; -ok !$@, 'rolled back'; -diag $@ if $@; -ok !$dbh->{AutoCommit}, "AutoCommit is still off"; -ok !$dbh->{BegunWork}, "BegunWork is still off"; + # scenario 8: AutoCommit => 0 and begin_work + eval { $dbh->{AutoCommit} = 1 }; # to initialize + ok $dbh->{AutoCommit}, "AutoCommit is on"; + ok !$dbh->{BegunWork}, "BegunWork is off"; + eval { $dbh->{AutoCommit} = 0 }; + ok !$@, "AutoCommit is turned off"; + ok !$dbh->{BegunWork}, "BegunWork is still off"; + eval { $dbh->begin_work; }; + like $@ => qr/Already in a transaction/, "begin_work should fail"; + ok !$dbh->{AutoCommit}, "AutoCommit is still off"; + ok !$dbh->{BegunWork}, "BegunWork is still off"; + eval { $dbh->do('BEGIN TRANSACTION') }; + ok !$@, "BEGIN should work"; + diag $@ if $@; + ok !$dbh->{AutoCommit}, "AutoCommit is still off"; + ok !$dbh->{BegunWork}, "BegunWork is still off"; + eval { $dbh->begin_work }; + like $@ => qr/Already in a transaction/, "and second begin_work also should fail"; + eval { $dbh->do('insert into foo (id) values (1)'); }; + ok !$@, 'other statement should work'; + diag $@ if $@; + eval { $func->($dbh) }; + ok !$@, 'rolled back/committed'; + diag $@ if $@; + ok !$dbh->{AutoCommit}, "AutoCommit is still off"; + ok !$dbh->{BegunWork}, "BegunWork is still off"; + + # scenario 9: AutoCommit => 0 and implicit BEGIN + eval { $dbh->{AutoCommit} = 1 }; # to initialize + ok $dbh->{AutoCommit}, "AutoCommit is on"; + ok !$dbh->{BegunWork}, "BegunWork is off"; + eval { $dbh->{AutoCommit} = 0 }; + ok !$@, "AutoCommit is turned off"; + ok !$dbh->{BegunWork}, "BegunWork is still off"; + eval { $dbh->do('insert into foo (id) values (1)'); }; + ok !$@, 'other statement should work'; + diag $@ if $@; + ok !$dbh->{AutoCommit}, "AutoCommit is still off"; + ok !$dbh->{BegunWork}, "BegunWork is still off"; + eval { $func->($dbh) }; + ok !$@, 'rolled back/committed'; + diag $@ if $@; + ok !$dbh->{AutoCommit}, "AutoCommit is still off"; + ok !$dbh->{BegunWork}, "BegunWork is still off"; +} +eval { $dbh->{AutoCommit} = 1 }; # to end transaction +$dbh->disconnect;