mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
sqlite: add readOnly option
Allow opening existing SQLite databases with SQLITE_OPEN_READONLY set. PR-URL: https://github.com/nodejs/node/pull/55567 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
This commit is contained in:
parent
996708042b
commit
a465b206d7
@ -107,6 +107,8 @@ added: v22.5.0
|
||||
* `open` {boolean} If `true`, the database is opened by the constructor. When
|
||||
this value is `false`, the database must be opened via the `open()` method.
|
||||
**Default:** `true`.
|
||||
* `readOnly` {boolean} If `true`, the database is opened in read-only mode.
|
||||
If the database does not exist, opening it will fail. **Default:** `false`.
|
||||
* `enableForeignKeyConstraints` {boolean} If `true`, foreign key constraints
|
||||
are enabled. This is recommended but can be disabled for compatibility with
|
||||
legacy database schemas. The enforcement of foreign key constraints can be
|
||||
|
@ -126,7 +126,9 @@ bool DatabaseSync::Open() {
|
||||
}
|
||||
|
||||
// TODO(cjihrig): Support additional flags.
|
||||
int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||
int flags = open_config_.get_read_only()
|
||||
? SQLITE_OPEN_READONLY
|
||||
: SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
||||
int r = sqlite3_open_v2(
|
||||
open_config_.location().c_str(), &connection_, flags, nullptr);
|
||||
CHECK_ERROR_OR_THROW(env()->isolate(), connection_, r, SQLITE_OK, false);
|
||||
@ -219,6 +221,22 @@ void DatabaseSync::New(const FunctionCallbackInfo<Value>& args) {
|
||||
open = open_v.As<Boolean>()->Value();
|
||||
}
|
||||
|
||||
Local<String> read_only_string =
|
||||
FIXED_ONE_BYTE_STRING(env->isolate(), "readOnly");
|
||||
Local<Value> read_only_v;
|
||||
if (!options->Get(env->context(), read_only_string).ToLocal(&read_only_v)) {
|
||||
return;
|
||||
}
|
||||
if (!read_only_v->IsUndefined()) {
|
||||
if (!read_only_v->IsBoolean()) {
|
||||
node::THROW_ERR_INVALID_ARG_TYPE(
|
||||
env->isolate(),
|
||||
"The \"options.readOnly\" argument must be a boolean.");
|
||||
return;
|
||||
}
|
||||
open_config.set_read_only(read_only_v.As<Boolean>()->Value());
|
||||
}
|
||||
|
||||
Local<String> enable_foreign_keys_string =
|
||||
FIXED_ONE_BYTE_STRING(env->isolate(), "enableForeignKeyConstraints");
|
||||
Local<Value> enable_foreign_keys_v;
|
||||
|
@ -21,6 +21,10 @@ class DatabaseOpenConfiguration {
|
||||
|
||||
inline const std::string& location() const { return location_; }
|
||||
|
||||
inline bool get_read_only() const { return read_only_; }
|
||||
|
||||
inline void set_read_only(bool flag) { read_only_ = flag; }
|
||||
|
||||
inline bool get_enable_foreign_keys() const { return enable_foreign_keys_; }
|
||||
|
||||
inline void set_enable_foreign_keys(bool flag) {
|
||||
@ -33,6 +37,7 @@ class DatabaseOpenConfiguration {
|
||||
|
||||
private:
|
||||
std::string location_;
|
||||
bool read_only_ = false;
|
||||
bool enable_foreign_keys_ = true;
|
||||
bool enable_dqs_ = false;
|
||||
};
|
||||
|
@ -51,6 +51,39 @@ suite('DatabaseSync() constructor', () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('throws if options.readOnly is provided but is not a boolean', (t) => {
|
||||
t.assert.throws(() => {
|
||||
new DatabaseSync('foo', { readOnly: 5 });
|
||||
}, {
|
||||
code: 'ERR_INVALID_ARG_TYPE',
|
||||
message: /The "options\.readOnly" argument must be a boolean/,
|
||||
});
|
||||
});
|
||||
|
||||
test('is not read-only by default', (t) => {
|
||||
const dbPath = nextDb();
|
||||
const db = new DatabaseSync(dbPath);
|
||||
db.exec('CREATE TABLE foo (id INTEGER PRIMARY KEY)');
|
||||
});
|
||||
|
||||
test('is read-only if readOnly is set', (t) => {
|
||||
const dbPath = nextDb();
|
||||
{
|
||||
const db = new DatabaseSync(dbPath);
|
||||
db.exec('CREATE TABLE foo (id INTEGER PRIMARY KEY)');
|
||||
db.close();
|
||||
}
|
||||
{
|
||||
const db = new DatabaseSync(dbPath, { readOnly: true });
|
||||
t.assert.throws(() => {
|
||||
db.exec('CREATE TABLE bar (id INTEGER PRIMARY KEY)');
|
||||
}, {
|
||||
code: 'ERR_SQLITE_ERROR',
|
||||
message: /attempt to write a readonly database/,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
test('throws if options.enableForeignKeyConstraints is provided but is not a boolean', (t) => {
|
||||
t.assert.throws(() => {
|
||||
new DatabaseSync('foo', { enableForeignKeyConstraints: 5 });
|
||||
|
Loading…
Reference in New Issue
Block a user