【问题标题】:Force readonly when connecting to sqlite file连接到 sqlite 文件时强制只读
【发布时间】:2016-03-25 06:05:19
【问题描述】:

在许多前端, 我希望使用从主服务器镜像的 sqlite3 文件的只读连接来强制执行我的脚本。

有没有办法说 DBI 做到这一点?

目前,我正在这样做:

       $dbHand = DBI->connect("dbi:SQLite:dbname=$dbName", $dbUser, $dbPass, {
            PrintError => 0,
            RaiseError => 1,
            AutoCommit => 1,
    }) or die $DBI::errstr;

并获得完全访问权限。

  • 我的 perl 不流利,我必须维护/改进现有的
  • (我不想处理文件权限)

【问题讨论】:

标签: perl sqlite dbi


【解决方案1】:

使用sqlite_open_flags 属性,如DBD::SQLite documentation 中所述:

use DBD::SQLite;
my $dbh = DBI->connect("dbi:SQLite:$dbfile", undef, undef, {
  sqlite_open_flags => DBD::SQLite::OPEN_READONLY,
});

如果您尝试打开一个不存在的数据库(通常会创建一个新数据库)或尝试写入现有数据库,这将导致错误。

请注意,您必须明确 use DBD::SQLite; 才能使用常量 DBD::SQLite::OPEN_READONLY


请注意,DBI 提供了ReadOnly 句柄属性,但 DBD::SQLite 在 v1.49_05 之前不支持它:

use strict;
use warnings;

use Data::Dump;
use DBI;

my $db = 'foo.db';
unlink $db if -f $db;

my $dbh = DBI->connect("dbi:SQLite:dbname=$db",'','', {
    RaiseError => 1,
    ReadOnly   => 1
});

$dbh->do( q{CREATE TABLE foo(id INTEGER, name TEXT)} );
$dbh->do( q{INSERT INTO foo VALUES(1, 'foo')} );
my $values = $dbh->selectall_arrayref( q{SELECT * FROM foo} );

dd $values;

输出:

[[1, "foo"]]

切换到sqlite_open_flags => DBD::SQLite::OPEN_READONLY 会导致错误。

如果数据库不存在:

DBI connect('dbname=foo.db','',...) failed: unable to open database file

如果数据库存在:

DBD::SQLite::db do failed: attempt to write a readonly database

从 DBD::SQLite v1.49_05 开始,您还可以使用ReadOnly 属性,但只能作为connect 的一个选项。连接后设置属性不起作用并抛出警告:

my $dbh = DBI->connect("dbi:SQLite:dbname=$db",'','', {
    RaiseError => 1
});
$dbh->{ReadOnly} = 1;

输出:

DBD::SQLite::db STORE 警告:ReadOnly 已设置,但它只是建议性的

【讨论】:

  • 我注意到 DBD::SQLite 文档没有提到 ReadOnly 选项,而是展示了一种完全不同的方法;这让我很好奇。我打开a ticket 是因为 DBD::SQLite 没有在这里保持讨价还价……它甚至没有警告ReadOnly 被忽略!
【解决方案2】:

刚刚设置

$dbHand ->{ReadOnly} = 1

here所述

【讨论】:

  • 不幸的是,DBD::SQLite 似乎不尊重这一点。看我的回答。
  • @Overnuts:请注意 ThisSuitIsBlackNot 中的 commentsolution。看起来这个标准解决方案对于 SQLite 是错误的
  • 这是fixed in DBD::SQLite 1.49_05(开发者版本)。不幸的是,您必须将属性设置为connect 的选项;连接后将其设置在手柄上不起作用并引发警告。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-28
  • 2018-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-11
  • 1970-01-01
相关资源
最近更新 更多