GeezerVison is showing github.com — sqlite: add readOnly option · nodejs/node@2ec4ae7
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/sqlite.md +2Lines changed: 2 additions & 0 deletions - Display the source diff
- Display the rich diff
| Original file line number | Diff line number | Diff line change |
|---|
@@ -107,6 +107,8 @@ added: v22.5.0 | 107 | 107 | * `open` {boolean} If `true`, the database is opened by the constructor. When | 108 | 108 | this value is `false`, the database must be opened via the `open()` method. | 109 | 109 | **Default:** `true`. | | 110 | + * `readOnly` {boolean} If `true`, the database is opened in read-only mode. | | 111 | + If the database does not exist, opening it will fail. **Default:** `false`. | 110 | 112 | * `enableForeignKeyConstraints` {boolean} If `true`, foreign key constraints | 111 | 113 | are enabled. This is recommended but can be disabled for compatibility with | 112 | 114 | legacy database schemas. The enforcement of foreign key constraints can be | |
Collapse file Copy file name to clipboardExpand all lines: src/node_sqlite.cc +19-1Lines changed: 19 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -126,7 +126,9 @@ bool DatabaseSync::Open() { | 126 | 126 | } | 127 | 127 |
| 128 | 128 | // TODO(cjihrig): Support additional flags. | 129 | | - int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; | | 129 | + int flags = open_config_.get_read_only() | | 130 | + ? SQLITE_OPEN_READONLY | | 131 | + : SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; | 130 | 132 | int r = sqlite3_open_v2( | 131 | 133 | open_config_.location().c_str(), &connection_, flags, nullptr); | 132 | 134 | CHECK_ERROR_OR_THROW(env()->isolate(), connection_, r, SQLITE_OK, false); | @@ -219,6 +221,22 @@ void DatabaseSync::New(const FunctionCallbackInfo<Value>& args) { | 219 | 221 | open = open_v.As<Boolean>()->Value(); | 220 | 222 | } | 221 | 223 |
| | 224 | + Local<String> read_only_string = | | 225 | + FIXED_ONE_BYTE_STRING(env->isolate(), "readOnly"); | | 226 | + Local<Value> read_only_v; | | 227 | + if (!options->Get(env->context(), read_only_string).ToLocal(&read_only_v)) { | | 228 | + return; | | 229 | + } | | 230 | + if (!read_only_v->IsUndefined()) { | | 231 | + if (!read_only_v->IsBoolean()) { | | 232 | + node::THROW_ERR_INVALID_ARG_TYPE( | | 233 | + env->isolate(), | | 234 | + "The \"options.readOnly\" argument must be a boolean."); | | 235 | + return; | | 236 | + } | | 237 | + open_config.set_read_only(read_only_v.As<Boolean>()->Value()); | | 238 | + } | | 239 | + | 222 | 240 | Local<String> enable_foreign_keys_string = | 223 | 241 | FIXED_ONE_BYTE_STRING(env->isolate(), "enableForeignKeyConstraints"); | 224 | 242 | Local<Value> enable_foreign_keys_v; | |
Collapse file Copy file name to clipboardExpand all lines: src/node_sqlite.h +5Lines changed: 5 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -21,6 +21,10 @@ class DatabaseOpenConfiguration { | 21 | 21 |
| 22 | 22 | inline const std::string& location() const { return location_; } | 23 | 23 |
| | 24 | + inline bool get_read_only() const { return read_only_; } | | 25 | + | | 26 | + inline void set_read_only(bool flag) { read_only_ = flag; } | | 27 | + | 24 | 28 | inline bool get_enable_foreign_keys() const { return enable_foreign_keys_; } | 25 | 29 |
| 26 | 30 | inline void set_enable_foreign_keys(bool flag) { | @@ -33,6 +37,7 @@ class DatabaseOpenConfiguration { | 33 | 37 |
| 34 | 38 | private: | 35 | 39 | std::string location_; | | 40 | + bool read_only_ = false; | 36 | 41 | bool enable_foreign_keys_ = true; | 37 | 42 | bool enable_dqs_ = false; | 38 | 43 | }; | |
Collapse file Copy file name to clipboardExpand all lines: test/parallel/test-sqlite-database-sync.js +33Lines changed: 33 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -51,6 +51,39 @@ suite('DatabaseSync() constructor', () => { | 51 | 51 | }); | 52 | 52 | }); | 53 | 53 |
| | 54 | + test('throws if options.readOnly is provided but is not a boolean', (t) => { | | 55 | + t.assert.throws(() => { | | 56 | + new DatabaseSync('foo', { readOnly: 5 }); | | 57 | + }, { | | 58 | + code: 'ERR_INVALID_ARG_TYPE', | | 59 | + message: /The "options\.readOnly" argument must be a boolean/, | | 60 | + }); | | 61 | + }); | | 62 | + | | 63 | + test('is not read-only by default', (t) => { | | 64 | + const dbPath = nextDb(); | | 65 | + const db = new DatabaseSync(dbPath); | | 66 | + db.exec('CREATE TABLE foo (id INTEGER PRIMARY KEY)'); | | 67 | + }); | | 68 | + | | 69 | + test('is read-only if readOnly is set', (t) => { | | 70 | + const dbPath = nextDb(); | | 71 | + { | | 72 | + const db = new DatabaseSync(dbPath); | | 73 | + db.exec('CREATE TABLE foo (id INTEGER PRIMARY KEY)'); | | 74 | + db.close(); | | 75 | + } | | 76 | + { | | 77 | + const db = new DatabaseSync(dbPath, { readOnly: true }); | | 78 | + t.assert.throws(() => { | | 79 | + db.exec('CREATE TABLE bar (id INTEGER PRIMARY KEY)'); | | 80 | + }, { | | 81 | + code: 'ERR_SQLITE_ERROR', | | 82 | + message: /attempt to write a readonly database/, | | 83 | + }); | | 84 | + } | | 85 | + }); | | 86 | + | 54 | 87 | test('throws if options.enableForeignKeyConstraints is provided but is not a boolean', (t) => { | 55 | 88 | t.assert.throws(() => { | 56 | 89 | new DatabaseSync('foo', { enableForeignKeyConstraints: 5 }); | |
|