use strict; use warnings; use Test::More; use DBI; use DBD::SQLite; my $dbfile = 'abc.sqlite'; # we are opening the same database and at some point # we have the same DB opened with 2 different handles # First time here to lock it my $dbh_locked = DBI->connect( "dbi:SQLite:dbname=$dbfile", '', '', { RaiseError => 0, # don't die on error sqlite_open_flags => DBD::SQLite::OPEN_READWRITE | DBD::SQLite::OPEN_CREATE } ); ok(defined $dbh_locked, "connect()"); # this causes the driver to timeout and not to wait # for the lock forever $dbh_locked->sqlite_busy_timeout(1000); # milliseconds my $SQL = 'PRAGMA locking_mode = EXCLUSIVE'; my $ret = eval { $dbh_locked->do($SQL) }; ok(defined $ret, "do SQL: $SQL"); $SQL = 'BEGIN EXCLUSIVE'; $ret = eval { $dbh_locked->do($SQL) }; ok(defined $ret, "do SQL: $SQL"); # now db is locked, we have 15 seconds # to test the locked db before unlock diag("DB is now locked."); # Second time, we open the DB here to check if it's locked # check that the db is locked my $dbh = DBI->connect( "dbi:SQLite:dbname=$dbfile", '', '', { RaiseError => 0, # don't die sqlite_open_flags => DBD::SQLite::OPEN_READONLY, TraceLevel => 1, } ); ok(defined $dbh, "connected to db '$dbfile'."); # set this to a short timeout (millis) because it can wait forever # and our child will be dead soon! $dbh->sqlite_busy_timeout(1000); $SQL = 'BEGIN IMMEDIATE'; $ret = eval { $dbh->do($SQL) }; ok(!defined $ret, "database is locked and SQL must fail: '$SQL'."); $dbh->disconnect; $dbh_locked->disconnect; done_testing();