Skip to content

Commit bcbba72

Browse files
louwersRafaelGSS
authored andcommitted
sqlite: add support for SQLite Session Extension
PR-URL: #54181 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
1 parent 44324aa commit bcbba72

File tree

8 files changed

+842
-46
lines changed

8 files changed

+842
-46
lines changed

deps/sqlite/sqlite.gyp

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
'xcode_settings': {
1313
'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden
1414
},
15+
'defines': [
16+
'SQLITE_ENABLE_SESSION',
17+
'SQLITE_ENABLE_PREUPDATE_HOOK'
18+
],
1519
'include_dirs': ['.'],
1620
'sources': [
1721
'<@(sqlite_sources)',

doc/api/sqlite.md

+101
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,70 @@ added: v22.5.0
155155
Compiles a SQL statement into a [prepared statement][]. This method is a wrapper
156156
around [`sqlite3_prepare_v2()`][].
157157

158+
### `database.createSession([options])`
159+
160+
* `options` {Object} The configuration options for the session.
161+
* `table` {string} A specific table to track changes for. By default, changes to all tables are tracked.
162+
* `db` {string} Name of the database to track. This is useful when multiple databases have been added using [`ATTACH DATABASE`][]. **Default**: `'main'`.
163+
* Returns: {Session} A session handle.
164+
165+
Creates and attaches a session to the database. This method is a wrapper around [`sqlite3session_create()`][] and [`sqlite3session_attach()`][].
166+
167+
### `database.applyChangeset(changeset[, options])`
168+
169+
* `changeset` {Uint8Array} A binary changeset or patchset.
170+
* `options` {Object} The configuration options for how the changes will be applied.
171+
* `filter` {Function} Skip changes that, when targeted table name is supplied to this function, return a truthy value.
172+
By default, all changes are attempted.
173+
* `onConflict` {number} Determines how conflicts are handled. **Default**: `SQLITE_CHANGESET_ABORT`.
174+
* `SQLITE_CHANGESET_OMIT`: conflicting changes are omitted.
175+
* `SQLITE_CHANGESET_REPLACE`: conflicting changes replace existing values.
176+
* `SQLITE_CHANGESET_ABORT`: abort on conflict and roll back databsase.
177+
* Returns: {boolean} Whether the changeset was applied succesfully without being aborted.
178+
179+
An exception is thrown if the database is not
180+
open. This method is a wrapper around [`sqlite3changeset_apply()`][].
181+
182+
```js
183+
const sourceDb = new DatabaseSync(':memory:');
184+
const targetDb = new DatabaseSync(':memory:');
185+
186+
sourceDb.exec('CREATE TABLE data(key INTEGER PRIMARY KEY, value TEXT)');
187+
targetDb.exec('CREATE TABLE data(key INTEGER PRIMARY KEY, value TEXT)');
188+
189+
const session = sourceDb.createSession();
190+
191+
const insert = sourceDb.prepare('INSERT INTO data (key, value) VALUES (?, ?)');
192+
insert.run(1, 'hello');
193+
insert.run(2, 'world');
194+
195+
const changeset = session.changeset();
196+
targetDb.applyChangeset(changeset);
197+
// Now that the changeset has been applied, targetDb contains the same data as sourceDb.
198+
```
199+
200+
## Class: `Session`
201+
202+
### `session.changeset()`
203+
204+
* Returns: {Uint8Array} Binary changeset that can be applied to other databases.
205+
206+
Retrieves a changeset containing all changes since the changeset was created. Can be called multiple times.
207+
An exception is thrown if the database or the session is not open. This method is a wrapper around [`sqlite3session_changeset()`][].
208+
209+
### `session.patchset()`
210+
211+
* Returns: {Uint8Array} Binary patchset that can be applied to other databases.
212+
213+
Similar to the method above, but generates a more compact patchset. See [Changesets and Patchsets][]
214+
in the documentation of SQLite. An exception is thrown if the database or the session is not open. This method is a
215+
wrapper around [`sqlite3session_patchset()`][].
216+
217+
### `session.close()`.
218+
219+
Closes the session. An exception is thrown if the database or the session is not open. This method is a
220+
wrapper around [`sqlite3session_delete()`][].
221+
158222
## Class: `StatementSync`
159223

160224
<!-- YAML
@@ -317,8 +381,39 @@ exception.
317381
| `TEXT` | {string} |
318382
| `BLOB` | {Uint8Array} |
319383

384+
## SQLite constants
385+
386+
The following constants are exported by the `node:sqlite` module.
387+
388+
### SQLite Session constants
389+
390+
#### Conflict-resolution constants
391+
392+
The following constants are meant for use with [`database.applyChangeset()`](#databaseapplychangesetchangeset-options).
393+
394+
<table>
395+
<tr>
396+
<th>Constant</th>
397+
<th>Description</th>
398+
</tr>
399+
<tr>
400+
<td><code>SQLITE_CHANGESET_OMIT</code></td>
401+
<td>Conflicting changes are omitted.</td>
402+
</tr>
403+
<tr>
404+
<td><code>SQLITE_CHANGESET_REPLACE</code></td>
405+
<td>Conflicting changes replace existing values.</td>
406+
</tr>
407+
<tr>
408+
<td><code>SQLITE_CHANGESET_ABORT</code></td>
409+
<td>Abort when a change encounters a conflict and roll back databsase.</td>
410+
</tr>
411+
</table>
412+
413+
[Changesets and Patchsets]: https://www.sqlite.org/sessionintro.html#changesets_and_patchsets
320414
[SQL injection]: https://en.wikipedia.org/wiki/SQL_injection
321415
[`--experimental-sqlite`]: cli.md#--experimental-sqlite
416+
[`ATTACH DATABASE`]: https://www.sqlite.org/lang_attach.html
322417
[`PRAGMA foreign_keys`]: https://www.sqlite.org/pragma.html#pragma_foreign_keys
323418
[`sqlite3_changes64()`]: https://www.sqlite.org/c3ref/changes.html
324419
[`sqlite3_close_v2()`]: https://www.sqlite.org/c3ref/close.html
@@ -327,6 +422,12 @@ exception.
327422
[`sqlite3_last_insert_rowid()`]: https://www.sqlite.org/c3ref/last_insert_rowid.html
328423
[`sqlite3_prepare_v2()`]: https://www.sqlite.org/c3ref/prepare.html
329424
[`sqlite3_sql()`]: https://www.sqlite.org/c3ref/expanded_sql.html
425+
[`sqlite3changeset_apply()`]: https://www.sqlite.org/session/sqlite3changeset_apply.html
426+
[`sqlite3session_attach()`]: https://www.sqlite.org/session/sqlite3session_attach.html
427+
[`sqlite3session_changeset()`]: https://www.sqlite.org/session/sqlite3session_changeset.html
428+
[`sqlite3session_create()`]: https://www.sqlite.org/session/sqlite3session_create.html
429+
[`sqlite3session_delete()`]: https://www.sqlite.org/session/sqlite3session_delete.html
430+
[`sqlite3session_patchset()`]: https://www.sqlite.org/session/sqlite3session_patchset.html
330431
[connection]: https://www.sqlite.org/c3ref/sqlite3.html
331432
[data types]: https://www.sqlite.org/datatype3.html
332433
[double-quoted string literals]: https://www.sqlite.org/quirks.html#dblquote

node.gyp

+1
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,7 @@
882882
# Warn when using deprecated V8 APIs.
883883
'V8_DEPRECATION_WARNINGS=1',
884884
'NODE_OPENSSL_SYSTEM_CERT_PATH="<(openssl_system_ca_path)"',
885+
"SQLITE_ENABLE_SESSION"
885886
],
886887

887888
# - "C4244: conversion from 'type1' to 'type2', possible loss of data"

src/env_properties.h

+3
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@
160160
V(fields_string, "fields") \
161161
V(file_string, "file") \
162162
V(filename_string, "filename") \
163+
V(filter_string, "filter") \
163164
V(fingerprint256_string, "fingerprint256") \
164165
V(fingerprint512_string, "fingerprint512") \
165166
V(fingerprint_string, "fingerprint") \
@@ -246,6 +247,7 @@
246247
V(onchange_string, "onchange") \
247248
V(onclienthello_string, "onclienthello") \
248249
V(oncomplete_string, "oncomplete") \
250+
V(onconflict_string, "onConflict") \
249251
V(onconnection_string, "onconnection") \
250252
V(ondone_string, "ondone") \
251253
V(onerror_string, "onerror") \
@@ -413,6 +415,7 @@
413415
V(shutdown_wrap_template, v8::ObjectTemplate) \
414416
V(socketaddress_constructor_template, v8::FunctionTemplate) \
415417
V(sqlite_statement_sync_constructor_template, v8::FunctionTemplate) \
418+
V(sqlite_session_constructor_template, v8::FunctionTemplate) \
416419
V(streambaseentry_ctor_template, v8::FunctionTemplate) \
417420
V(streambaseoutputstream_constructor_template, v8::ObjectTemplate) \
418421
V(streamentry_ctor_template, v8::FunctionTemplate) \

0 commit comments

Comments
 (0)