From 2c5bebc4e4077f88f7f1b54474c781eddd4f5e33 Mon Sep 17 00:00:00 2001 From: Bart Louwers Date: Mon, 18 Nov 2024 01:57:04 +0100 Subject: [PATCH] sqlite: add support for SQLite Session Extension PR-URL: https://github.com/nodejs/node/pull/54181 Reviewed-By: Yagiz Nizipli Reviewed-By: James M Snell Reviewed-By: Colin Ihrig --- deps/sqlite/sqlite.gyp | 4 + doc/api/sqlite.md | 101 +++++++ node.gyp | 1 + src/env_properties.h | 3 + src/node_sqlite.cc | 359 +++++++++++++++++++++---- src/node_sqlite.h | 35 +++ test/parallel/test-sqlite-session.js | 384 +++++++++++++++++++++++++++ tools/doc/type-parser.mjs | 1 + 8 files changed, 842 insertions(+), 46 deletions(-) create mode 100644 test/parallel/test-sqlite-session.js diff --git a/deps/sqlite/sqlite.gyp b/deps/sqlite/sqlite.gyp index c37ae18d78bc37..c3ecef214ad004 100644 --- a/deps/sqlite/sqlite.gyp +++ b/deps/sqlite/sqlite.gyp @@ -12,6 +12,10 @@ 'xcode_settings': { 'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden }, + 'defines': [ + 'SQLITE_ENABLE_SESSION', + 'SQLITE_ENABLE_PREUPDATE_HOOK' + ], 'include_dirs': ['.'], 'sources': [ '<@(sqlite_sources)', diff --git a/doc/api/sqlite.md b/doc/api/sqlite.md index 42cfbd45a35761..ac12a5b2582ed7 100644 --- a/doc/api/sqlite.md +++ b/doc/api/sqlite.md @@ -155,6 +155,70 @@ added: v22.5.0 Compiles a SQL statement into a [prepared statement][]. This method is a wrapper around [`sqlite3_prepare_v2()`][]. +### `database.createSession([options])` + +* `options` {Object} The configuration options for the session. + * `table` {string} A specific table to track changes for. By default, changes to all tables are tracked. + * `db` {string} Name of the database to track. This is useful when multiple databases have been added using [`ATTACH DATABASE`][]. **Default**: `'main'`. +* Returns: {Session} A session handle. + +Creates and attaches a session to the database. This method is a wrapper around [`sqlite3session_create()`][] and [`sqlite3session_attach()`][]. + +### `database.applyChangeset(changeset[, options])` + +* `changeset` {Uint8Array} A binary changeset or patchset. +* `options` {Object} The configuration options for how the changes will be applied. + * `filter` {Function} Skip changes that, when targeted table name is supplied to this function, return a truthy value. + By default, all changes are attempted. + * `onConflict` {number} Determines how conflicts are handled. **Default**: `SQLITE_CHANGESET_ABORT`. + * `SQLITE_CHANGESET_OMIT`: conflicting changes are omitted. + * `SQLITE_CHANGESET_REPLACE`: conflicting changes replace existing values. + * `SQLITE_CHANGESET_ABORT`: abort on conflict and roll back databsase. +* Returns: {boolean} Whether the changeset was applied succesfully without being aborted. + +An exception is thrown if the database is not +open. This method is a wrapper around [`sqlite3changeset_apply()`][]. + +```js +const sourceDb = new DatabaseSync(':memory:'); +const targetDb = new DatabaseSync(':memory:'); + +sourceDb.exec('CREATE TABLE data(key INTEGER PRIMARY KEY, value TEXT)'); +targetDb.exec('CREATE TABLE data(key INTEGER PRIMARY KEY, value TEXT)'); + +const session = sourceDb.createSession(); + +const insert = sourceDb.prepare('INSERT INTO data (key, value) VALUES (?, ?)'); +insert.run(1, 'hello'); +insert.run(2, 'world'); + +const changeset = session.changeset(); +targetDb.applyChangeset(changeset); +// Now that the changeset has been applied, targetDb contains the same data as sourceDb. +``` + +## Class: `Session` + +### `session.changeset()` + +* Returns: {Uint8Array} Binary changeset that can be applied to other databases. + +Retrieves a changeset containing all changes since the changeset was created. Can be called multiple times. +An exception is thrown if the database or the session is not open. This method is a wrapper around [`sqlite3session_changeset()`][]. + +### `session.patchset()` + +* Returns: {Uint8Array} Binary patchset that can be applied to other databases. + +Similar to the method above, but generates a more compact patchset. See [Changesets and Patchsets][] +in the documentation of SQLite. An exception is thrown if the database or the session is not open. This method is a +wrapper around [`sqlite3session_patchset()`][]. + +### `session.close()`. + +Closes the session. An exception is thrown if the database or the session is not open. This method is a +wrapper around [`sqlite3session_delete()`][]. + ## Class: `StatementSync`