diff --git a/dbdimp.c b/dbdimp.c index 4d5ec6a..e420a3b 100644 --- a/dbdimp.c +++ b/dbdimp.c @@ -459,6 +459,15 @@ sqlite_db_login6(SV *dbh, imp_dbh_t *imp_dbh, char *dbname, char *user, char *pa sqlite3_busy_timeout(imp_dbh->db, SQL_TIMEOUT); + if (hv) { + if (hv_exists(hv, "sqlite_defensive", 16)) { + val = hv_fetch(hv, "sqlite_defensive", 16, 0); + if (val && SvIOK(*val)) { + sqlite3_db_config(imp_dbh->db, SQLITE_DBCONFIG_DEFENSIVE, SvIV(*val), 0); + } + } + } + #if 0 /* ** As of 1.26_06 foreign keys support was enabled by default, diff --git a/lib/DBD/SQLite.pm b/lib/DBD/SQLite.pm index 8e79e43..aae801a 100644 --- a/lib/DBD/SQLite.pm +++ b/lib/DBD/SQLite.pm @@ -1660,6 +1660,11 @@ for details. If set to true, DBD::SQLite uses extended result codes where appropriate (see L). +=item sqlite_defensive + +If set to true, language features that allow ordinary SQL to deliberately +corrupt the database file are prohibited. + =back =head2 Statement Handle Attributes diff --git a/t/65_db_config.t b/t/65_db_config.t index 4bdf123..c4c9b5d 100644 --- a/t/65_db_config.t +++ b/t/65_db_config.t @@ -11,7 +11,7 @@ use SQLiteTest qw/connect_ok @CALL_FUNCS/; use Test::More; use DBD::SQLite::Constants qw/:database_connection_configuration_options/; -#plan tests => 7 * @CALL_FUNCS; +plan tests => 38 * @CALL_FUNCS + 3; # LOOKASIDE for my $func (@CALL_FUNCS) { @@ -182,4 +182,15 @@ for my $func (@CALL_FUNCS) { } } -done_testing; \ No newline at end of file +# DEFENSIVE at connection +SKIP: { + skip 'DEFENSIVE is not supported', 8 if !SQLITE_DBCONFIG_DEFENSIVE; + my $dbh = connect_ok(RaiseError => 1, PrintError => 0, sqlite_defensive => 1); + + my $sql = 'CREATE TABLE foo (id, text)'; + $dbh->do($sql); + $dbh->do('PRAGMA writable_schema=ON'); + eval { $dbh->do('UPDATE sqlite_master SET name = ? WHERE name = ?', undef, 'bar', 'foo'); }; + ok $@, "updating sqlite_master is prohibited"; + like $@ => qr/table sqlite_master may not be modified/; +}