Need to open database using immutable parameter.

This requires switching on SQLITE_OPEN_URI because there is no open flag to
make the database immutable. Without immutable, sqlite will still attempt to
create journal and wal files, even when the database is opened read-only.

https://www.sqlite.org/c3ref/open.html

The immutable parameter is a boolean query parameter that indicates that the
database file is stored on read-only media. When immutable is set, SQLite
assumes that the database file cannot be changed, even by a process with higher
privilege, and so the database is opened read-only and all locking and change
detection is disabled.
This commit is contained in:
Ben Radford 2023-05-16 15:29:29 +01:00
parent 78fdd6f24e
commit aa376f4ab1
No known key found for this signature in database
GPG key ID: 9DF5D4640AB888D5

View file

@ -1,6 +1,7 @@
#include "sqlite.hh" #include "sqlite.hh"
#include "globals.hh" #include "globals.hh"
#include "util.hh" #include "util.hh"
#include "url.hh"
#include <sqlite3.h> #include <sqlite3.h>
@ -52,14 +53,16 @@ static void traceSQL(void * x, const char * sql)
SQLite::SQLite(const Path & path, SQLiteOpenMode mode) SQLite::SQLite(const Path & path, SQLiteOpenMode mode)
{ {
bool readOnly = mode == SQLiteOpenMode::ReadOnly;
// useSQLiteWAL also indicates what virtual file system we need. Using // useSQLiteWAL also indicates what virtual file system we need. Using
// `unix-dotfile` is needed on NFS file systems and on Windows' Subsystem // `unix-dotfile` is needed on NFS file systems and on Windows' Subsystem
// for Linux (WSL) where useSQLiteWAL should be false by default. // for Linux (WSL) where useSQLiteWAL should be false by default.
const char *vfs = settings.useSQLiteWAL ? 0 : "unix-dotfile"; const char *vfs = settings.useSQLiteWAL ? 0 : "unix-dotfile";
int flags = mode == SQLiteOpenMode::ReadOnly int flags = readOnly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE;
? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE;
if (mode == SQLiteOpenMode::Normal) flags |= SQLITE_OPEN_CREATE; if (mode == SQLiteOpenMode::Normal) flags |= SQLITE_OPEN_CREATE;
int ret = sqlite3_open_v2(path.c_str(), &db, flags, vfs); auto uri = "file:" + percentEncode(path) + "?immutable=" + (readOnly ? "1" : "0");
int ret = sqlite3_open_v2(uri.c_str(), &db, SQLITE_OPEN_URI | flags, vfs);
if (ret != SQLITE_OK) { if (ret != SQLITE_OK) {
const char * err = sqlite3_errstr(ret); const char * err = sqlite3_errstr(ret);
throw Error("cannot open SQLite database '%s': %s", path, err); throw Error("cannot open SQLite database '%s': %s", path, err);