diff --git a/dbdimp.c b/dbdimp.c index fbeaff8..dc7443c 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -414,9 +414,18 @@ sqlite_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pa val = hv_fetch(hv, "sqlite_extended_result_codes", 28, 0); extended = (val && SvOK(*val)) ? !(!SvTRUE(*val)) : 0; } + if (hv_exists(hv, "ReadOnly", 8)) { + val = hv_fetch(hv, "ReadOnly", 8, 0); + if ((val && SvOK(*val)) ? SvIV(*val) : 0) { + flag |= SQLITE_OPEN_READONLY; + } + } if (hv_exists(hv, "sqlite_open_flags", 17)) { val = hv_fetch(hv, "sqlite_open_flags", 17, 0); - flag = (val && SvOK(*val)) ? SvIV(*val) : 0; + flag |= (val && SvOK(*val)) ? SvIV(*val) : 0; + if (flag & SQLITE_OPEN_READONLY) { + hv_stores(hv, "ReadOnly", newSViv(1)); + } } } rc = sqlite_open2(dbname, &(imp_dbh->db), flag, extended); @@ -694,6 +703,12 @@ sqlite_db_STORE_attrib(SV *dbh, imp_dbh_t *imp_dbh, SV *keysv, SV *valuesv) DBIc_set(imp_dbh, DBIcf_AutoCommit, SvTRUE(valuesv)); return TRUE; } + if (strEQ(key, "ReadOnly")) { + if (SvTRUE(valuesv) && !sqlite3_db_readonly(imp_dbh->db, "main")) { + sqlite_error(dbh, 0, "ReadOnly is set but it's only advisory"); + } + return FALSE; + } if (strEQ(key, "sqlite_allow_multiple_statements")) { imp_dbh->allow_multiple_statements = !(! SvTRUE(valuesv)); return TRUE; diff --git a/t/60_readonly.t b/t/60_readonly.t new file mode 100644 index 0000000..896de1a --- /dev/null +++ b/t/60_readonly.t @@ -0,0 +1,44 @@ +#!/usr/bin/perl + +use strict; +BEGIN { + $| = 1; + $^W = 1; +} + +use t::lib::Test qw/connect_ok/; +use Test::More; +use DBD::SQLite::Constants qw/SQLITE_OPEN_READONLY/; +use Test::NoWarnings; + +plan tests => 14; + +{ + my $dbh = connect_ok( + sqlite_open_flags => SQLITE_OPEN_READONLY, + RaiseError => 0, + PrintError => 0, + ); + ok $dbh->{ReadOnly}; + ok !$dbh->do('CREATE TABLE foo (id)'); + like $dbh->errstr => qr/attempt to write a readonly database/; +} + +{ + my $dbh = connect_ok(ReadOnly => 1, PrintError => 0, RaiseError => 0); + ok $dbh->{ReadOnly}; + ok !$dbh->do('CREATE TABLE foo (id)'); + like $dbh->errstr => qr/attempt to write a readonly database/; +} + +{ + my $dbh = connect_ok(PrintWarn => 0, PrintError => 0, RaiseError => 0); + $dbh->{ReadOnly} = 1; + ok !$dbh->err; + like $dbh->errstr => qr/ReadOnly is set but/; + ok $dbh->{ReadOnly}; + + # this is ok because $dbh is not actually readonly (though we + # told so) + ok $dbh->do('CREATE TABLE foo (id)'); +}