From 5d8ee699b4b762eb9ce3c6eb3b17f4c10d6d4ad1 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sun, 3 Apr 2016 14:25:56 +0100 Subject: [PATCH] CommodsDatabase: Work around problems with readonly db --- yarrg/CommodsDatabase.pm | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/yarrg/CommodsDatabase.pm b/yarrg/CommodsDatabase.pm index 0d491c4..1f977d4 100644 --- a/yarrg/CommodsDatabase.pm +++ b/yarrg/CommodsDatabase.pm @@ -35,6 +35,7 @@ use warnings; use DBI; use POSIX; +use DBD::SQLite; use Commods; @@ -67,6 +68,31 @@ sub db_connect_core ($) { my $opts = { AutoCommit=>0, RaiseError=>1, ShowErrorStatement=>1, sqlite_unicode=>1 }; + + # DBI now wants to start a transaction whenever we even say + # SELECT. But this doesn't work if the DB is readonly. We can + # work around this by setting autocommit, in which case there is + # no need for a transaction for read-only db commands. Autocommit + # is (obviously) safe with readonly operations. But callers in + # yarrg do not specify to us whether they intend to write. So we + # decide, by looking at the file mode. And as belt-and-braces we + # set sqlite's own readonly flag as well. + # http://stackoverflow.com/questions/30082008/attempt-to-write-a-readonly-database-but-im-not + # http://stackoverflow.com/questions/35208727/can-sqlite-db-files-be-made-read-only + # http://cpansearch.perl.org/src/ISHIGAKI/DBD-SQLite-1.39/Changes + # (see entry for 1.38_01) + # http://stackoverflow.com/questions/17793672/perl-dbi-treats-setting-sqlite-db-cache-size-as-a-write-operation-when-subclassi + # https://rt.cpan.org/Public/Bug/Display.html?id=56444# + my $readonly = + (access $fn, POSIX::W_OK) ? 0 : + ($! == EACCES) ? 1 : + ($! == ENOENT) ? 0 : + die "$fn access(,W_OK) $!"; + if ($readonly) { + $opts->{sqlite_open_flags} = DBD::SQLite::OPEN_READONLY; + $opts->{AutoCommit}=1; + } + my $h= DBI->connect("dbi:SQLite:$fn",'','',$opts) or die "$fn $DBI::errstr ?"; return $h; -- 2.30.2