Skip to content

Commit 432f0c4

Browse files
committed
src, doc, test: allow generating patchset
1 parent 9e63561 commit 432f0c4

File tree

4 files changed

+39
-5
lines changed

4 files changed

+39
-5
lines changed

doc/api/sqlite.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,13 @@ database2.applyChangeset(changeset); // Will now contain the same data as datab
207207
Retrieves a changeset containing all changes since the changeset was created. Can be called multiple times.
208208
An exception is thrown if the database is not open. This method is a wrapper around [`sqlite3session_changeset()`][].
209209

210+
### `session.patchset()`
211+
212+
* Returns: {Uint8Array} Binary patchset that can be applied to other databases.
213+
214+
Similar to the method above, but generates a more compact patchset. See [Changesets and Patchsets][] in the documentation of SQLite.
215+
An exception is thrown if the database is not open. This method is a wrapper around [`sqlite3session_patchset()`][].
216+
210217
## Class: `StatementSync`
211218

212219
<!-- YAML
@@ -380,7 +387,9 @@ exception.
380387
[`sqlite3session_attach()`]: https://www.sqlite.org/session/sqlite3session_attach.html
381388
[`sqlite3session_create()`]: https://www.sqlite.org/session/sqlite3session_create.html
382389
[`sqlite3session_changeset()`]: https://www.sqlite.org/session/sqlite3session_changeset.html
390+
[`sqlite3session_patchset()`]: https://www.sqlite.org/session/sqlite3session_patchset.html
383391
[`sqlite3changeset_apply()`]: https://www.sqlite.org/session/sqlite3changeset_apply.html
392+
[Changesets and Patchsets]: https://www.sqlite.org/sessionintro.html#changesets_and_patchsets
384393
[connection]: https://www.sqlite.org/c3ref/sqlite3.html
385394
[data types]: https://www.sqlite.org/datatype3.html
386395
[in memory]: https://www.sqlite.org/inmemorydb.html

src/node_sqlite.cc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -886,14 +886,22 @@ Local<FunctionTemplate> Session::GetConstructorTemplate(
886886
tmpl->SetClassName(FIXED_ONE_BYTE_STRING(env->isolate(), "Session"));
887887
tmpl->InstanceTemplate()->SetInternalFieldCount(
888888
Session::kInternalFieldCount);
889-
SetProtoMethod(isolate, tmpl, "changeset", Session::Changeset);
889+
SetProtoMethod(isolate,
890+
tmpl,
891+
"changeset",
892+
Session::Changeset<sqlite3session_changeset>);
893+
SetProtoMethod(isolate,
894+
tmpl,
895+
"patchset",
896+
Session::Changeset<sqlite3session_patchset>);
890897
env->set_sqlite_session_constructor_template(tmpl);
891898
}
892899
return tmpl;
893900
}
894901

895902
void Session::MemoryInfo(MemoryTracker* tracker) const {}
896903

904+
template<Sqlite3ChangesetGenFunc sqliteChangesetFunc>
897905
void Session::Changeset(const v8::FunctionCallbackInfo<v8::Value>& args) {
898906
Session* session;
899907
ASSIGN_OR_RETURN_UNWRAP(&session, args.This());
@@ -903,7 +911,7 @@ void Session::Changeset(const v8::FunctionCallbackInfo<v8::Value>& args) {
903911

904912
int nChangeset;
905913
void* pChangeset;
906-
int r = sqlite3session_changeset(session->session_, &nChangeset, &pChangeset);
914+
int r = sqliteChangesetFunc(session->session_, &nChangeset, &pChangeset);
907915
CHECK_ERROR_OR_THROW(env->isolate(), db, r, SQLITE_OK, void());
908916

909917
auto freeChangeset = OnScopeLeave([&] {

src/node_sqlite.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,13 +84,16 @@ class StatementSync : public BaseObject {
8484
v8::Local<v8::Value> ColumnNameToValue(const int column);
8585
};
8686

87+
using Sqlite3ChangesetGenFunc = int (*)(sqlite3_session*, int*, void**);
88+
8789
class Session : public BaseObject {
8890
public:
8991
Session(Environment* env,
9092
v8::Local<v8::Object> object,
9193
BaseObjectWeakPtr<DatabaseSync> database,
9294
sqlite3_session* session);
9395
~Session() override;
96+
template<Sqlite3ChangesetGenFunc sqliteChangesetFunc>
9497
static void Changeset(const v8::FunctionCallbackInfo<v8::Value>& args);
9598
void MemoryInfo(MemoryTracker* tracker) const override;
9699
static v8::Local<v8::FunctionTemplate> GetConstructorTemplate(

test/parallel/test-sqlite.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -997,15 +997,29 @@ suite('session extension', () => {
997997
t.assert.strictEqual(sessionTest.changeset().length, 0);
998998
});
999999

1000-
test("wrong argument name of other database", (t) => {
1000+
test('wrong argument name of other database', (t) => {
10011001
const database = new DatabaseSync(':memory:');
10021002
t.assert.throws(() => {
1003-
const session = database.createSession({
1003+
database.createSession({
10041004
db: 123
10051005
});
10061006
}, {
10071007
name: 'TypeError',
10081008
message: 'The "options.db" argument must be a string.'
10091009
});
1010-
})
1010+
});
1011+
1012+
test('generate patchset', (t) => {
1013+
const database = new DatabaseSync(':memory:');
1014+
database.exec('CREATE TABLE data(key INTEGER PRIMARY KEY, value TEXT)');
1015+
1016+
database.exec("INSERT INTO data VALUES ('1', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.')");
1017+
1018+
const session = database.createSession();
1019+
database.exec("UPDATE data SET value = 'hi' WHERE key = 1");
1020+
1021+
t.assert.ok(
1022+
session.patchset().length < session.changeset().length,
1023+
'expected patchset to be smaller than changeset');
1024+
});
10111025
});

0 commit comments

Comments
 (0)