Skip to content

Commit

Permalink
Added ability to receive updates from sqlite3_update_hook
Browse files Browse the repository at this point in the history
closes #419

- this adds support for a `change` event which forwards events arising
  from `sqlite3_update_hook`
  • Loading branch information
soukand authored and daniellockyer committed Sep 13, 2022
1 parent 97cc584 commit 946a3f6
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 2 deletions.
2 changes: 1 addition & 1 deletion lib/sqlite3.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ Statement.prototype.map = function() {

let isVerbose = false;

const supportedEvents = [ 'trace', 'profile', 'insert', 'update', 'delete' ];
const supportedEvents = [ 'trace', 'profile', 'change' ];

Database.prototype.addListener = Database.prototype.on = function(type) {
const val = EventEmitter.prototype.addListener.apply(this, arguments);
Expand Down
12 changes: 11 additions & 1 deletion src/database.cc
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,11 @@ Napi::Value Database::Configure(const Napi::CallbackInfo& info) {
Baton* baton = new LimitBaton(db, handle, id, value);
db->Schedule(SetLimit, baton);
}
else if (info[0].StrictEquals(Napi::String::New(env, "change"))) {
Napi::Function handle;
Baton* baton = new Baton(db, handle);
db->Schedule(RegisterUpdateCallback, baton);
}
else {
Napi::TypeError::New(env, (StringConcat(
#if V8_MAJOR_VERSION > 6
Expand Down Expand Up @@ -556,12 +561,13 @@ void Database::UpdateCallback(Database *db, UpdateInfo* i) {
Napi::HandleScope scope(env);

Napi::Value argv[] = {
Napi::String::New(env, "change"),
Napi::String::New(env, sqlite_authorizer_string(info->type)),
Napi::String::New(env, info->database.c_str()),
Napi::String::New(env, info->table.c_str()),
Napi::Number::New(env, info->rowid),
};
EMIT_EVENT(db->Value(), 4, argv);
EMIT_EVENT(db->Value(), 5, argv);
}

Napi::Value Database::Exec(const Napi::CallbackInfo& info) {
Expand Down Expand Up @@ -762,4 +768,8 @@ void Database::RemoveCallbacks() {
debug_profile->finish();
debug_profile = NULL;
}
if (update_event) {
update_event->finish();
update_event = NULL;
}
}
75 changes: 75 additions & 0 deletions test/update_hook.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
var sqlite3 = require('..');
var assert = require('assert');

describe('update_hook', function() {
var db;

beforeEach(function(done) {
db = new sqlite3.Database(':memory:', function(err) {
if (err) return done(err);

db.run("CREATE TABLE update_hooks_test (id int PRIMARY KEY, value text)", done);
});
});

it('emits insert event on inserting data to table', function(done) {
db.addListener('change', function(eventType, database, table, rowId) {
assert.equal(eventType, 'insert');
assert.equal(database, 'main');
assert.equal(table, 'update_hooks_test');
assert.equal(rowId, 1);

return done();
});

db.run("INSERT INTO update_hooks_test VALUES (1, 'value')", function(err) {
if (err) return done(err);
});
});

it('emits update event on row modification in table', function(done) {
db.run("INSERT INTO update_hooks_test VALUES (2, 'value'), (3, 'value4')", function(err) {
if (err) return done(err);

db.addListener('change', function(eventType, database, table, rowId) {
assert.equal(eventType, 'update');
assert.equal(database, 'main');
assert.equal(table, 'update_hooks_test');
assert.equal(rowId, 1);

db.all("SELECT * FROM update_hooks_test WHERE rowid = ?", rowId, function(err, rows) {
assert.deepEqual(rows, [{ id: 2, value: 'new_val' }]);

return done(err);
});
});

db.run("UPDATE update_hooks_test SET value = 'new_val' WHERE id = 2", function(err) {
if (err) return done(err);
});
});
});

it('emits delete event on row was deleted from table', function(done) {
db.run("INSERT INTO update_hooks_test VALUES (2, 'value')", function(err) {
if (err) return done(err);

db.addListener('change', function(eventType, database, table, rowId) {
assert.equal(eventType, 'delete');
assert.equal(database, 'main');
assert.equal(table, 'update_hooks_test');
assert.equal(rowId, 1);

return done();
});

db.run("DELETE FROM update_hooks_test WHERE id = 2", function(err) {
if (err) return done(err);
});
});
});

afterEach(function(done) {
db.close(done);
});
});

0 comments on commit 946a3f6

Please sign in to comment.