From b4220250ce8a3d3b94f1e1d53ee4b180118158f7 Mon Sep 17 00:00:00 2001 From: Kenichi Ishigaki Date: Thu, 20 Oct 2011 16:14:56 +0000 Subject: [PATCH] applied another patch by Yuriy Kaminskiy to fix finalize issues --- dbdimp.c | 3 +- t/47_execute.t | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 t/47_execute.t diff --git a/dbdimp.c b/dbdimp.c index 9668d71..c61ee46 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -581,6 +581,7 @@ sqlite_st_prepare(SV *sth, imp_sth_t *imp_sth, char *statement, SV *attribs) sqlite_error(sth, rc, sqlite3_errmsg(imp_dbh->db)); if (imp_sth->stmt) { rc = sqlite3_finalize(imp_sth->stmt); + imp_sth->stmt = NULL; if (rc != SQLITE_OK) { sqlite_error(sth, rc, sqlite3_errmsg(imp_dbh->db)); } @@ -827,7 +828,6 @@ sqlite_st_execute(SV *sth, imp_sth_t *imp_sth) if (sqlite3_reset(imp_sth->stmt) != SQLITE_OK) { sqlite_error(sth, imp_sth->retval, sqlite3_errmsg(imp_dbh->db)); } - imp_sth->stmt = NULL; return -6; /* -> undef in SQLite.xsi */ } } @@ -991,6 +991,7 @@ sqlite_st_destroy(SV *sth, imp_sth_t *imp_sth) /* finalize sth when active connection */ rc = sqlite3_finalize(imp_sth->stmt); + imp_sth->stmt = NULL; if (rc != SQLITE_OK) { sqlite_error(sth, rc, sqlite3_errmsg(imp_dbh->db)); } diff --git a/t/47_execute.t b/t/47_execute.t new file mode 100644 index 0000000..8751c47 --- /dev/null +++ b/t/47_execute.t @@ -0,0 +1,84 @@ +#!/usr/bin/perl + +# Trigger locking error and test prepared statement is still valid afterwards + +use strict; +BEGIN { + $| = 1; + $^W = 1; +} + +use t::lib::Test qw/connect_ok dbfile @CALL_FUNCS/; +use Test::More; +use Test::NoWarnings; + +plan tests => 10 * @CALL_FUNCS + 1; + +foreach my $call_func (@CALL_FUNCS) { + + my $dbh = connect_ok( + dbfile => 'foo', + RaiseError => 1, + PrintError => 0, + AutoCommit => 0, + ); + + my $dbh2 = connect_ok( + dbfile => 'foo', + RaiseError => 1, + PrintError => 0, + AutoCommit => 0, + ); + + my $dbfile = dbfile('foo'); + + # NOTE: Let's make it clear what we're doing here. + # $dbh starts locking with the first INSERT statement. + # $dbh2 tries to INSERT, but as the database is locked, + # it starts waiting. However, $dbh won't release the lock. + # Eventually $dbh2 gets timed out, and spits an error, saying + # the database is locked. So, we don't need to let $dbh2 wait + # too much here. It should be timed out anyway. + ok($dbh->$call_func(300, 'busy_timeout')); + ok($dbh2->$call_func(300, 'busy_timeout')); + + $dbh->do("CREATE TABLE Blah ( id INTEGER )"); + $dbh->do("INSERT INTO Blah VALUES ( 1 )"); + $dbh->commit; + my $sth; + ok($sth = $dbh->prepare("SELECT id FROM Blah")); + $sth->execute; + { + my $row; + ok($row = $sth->fetch); + ok($row && $row->[0] == 1); + } + $sth->finish; + $dbh->commit; + $dbh2->do("BEGIN EXCLUSIVE"); + eval { + $sth->execute; + }; + ok($@); + if ($@) { + print "# expected execute failure : $@"; + $sth->finish; + $dbh->rollback; + } + $dbh2->commit; + $sth->execute; + { + my $row; + ok($row = $sth->fetch); + ok($row && $row->[0] == 1); + } + $sth->finish; + $dbh->commit; + + $dbh2->disconnect; + undef($dbh2); + $dbh->disconnect; + undef($dbh); + + unlink $dbfile; +}