From d3c9c6ed3f50fcd81faac886bf05a7237e904d13 Mon Sep 17 00:00:00 2001 From: Bart Louwers Date: Sat, 2 Nov 2024 19:17:33 +0100 Subject: [PATCH 01/31] sqlite: add support for SQLite Session Extension --- deps/sqlite/sqlite.gyp | 4 + doc/api/sqlite.md | 75 ++++++++ src/env_properties.h | 1 + src/node_sqlite.cc | 309 ++++++++++++++++++++++++++++-- src/node_sqlite.h | 37 ++++ test/parallel/test-sqlite.js | 357 ++++++++++++++++++++++++++++++++++- tools/doc/type-parser.mjs | 1 + 7 files changed, 766 insertions(+), 18 deletions(-) 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 34dfdaf1b11365..5d1235927d110a 100644 --- a/doc/api/sqlite.md +++ b/doc/api/sqlite.md @@ -164,6 +164,74 @@ 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} An optional object used to configure the session. + * `table` {string} When provided, only changes to this table are tracked by the created session. + By default, changes to all tables are tracked. + * `db` {string} Name of the database to track. 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} An optional object to configure how changes are applied. + * `filter` {Function} Optional function. Skips changes when a truthy value is returned from it. + Takes the name of the table that a change targets as first argument. When this option is not + provided all changes are attempted. + * `onConflict` {number} Determines how conflicts are handled. When provided, must be one of the values below: + * `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 (default). +* 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()`][]. + +Example usage is demonstrated below. + +```js +const database1 = new DatabaseSync(':memory:'); +const database2 = new DatabaseSync(':memory:'); + +database1.exec('CREATE TABLE data(key INTEGER PRIMARY KEY, value TEXT)'); +database2.exec('CREATE TABLE data(key INTEGER PRIMARY KEY, value TEXT)'); + +const session = database1.createSession(); + +const insert = database1.prepare('INSERT INTO data (key, value) VALUES (?, ?)'); +insert.run(1, 'hello'); +insert.run(2, 'world'); + +const changeset = session.changeset(); +database2.applyChangeset(changeset); +// Now database2 contains the same data as database1 +``` + +## 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`