diff --git a/examples/simple-chaining.js b/examples/simple-chaining.js index 17a78785b..a14832206 100644 --- a/examples/simple-chaining.js +++ b/examples/simple-chaining.js @@ -9,8 +9,15 @@ var db; function createDb() { console.log("createDb chain"); db = new sqlite3.Database('chain.sqlite3', createTable); + + listenDatabaseUpdates(); } +function listenDatabaseUpdates() { + db.addListener('change', function(eventType, database, table, rowId) { + console.log("database was changed", eventType, database, table, rowId); + }); +} function createTable() { console.log("createTable lorem"); diff --git a/lib/sqlite3.js b/lib/sqlite3.js index c8e3e8c6c..cea21cb3e 100644 --- a/lib/sqlite3.js +++ b/lib/sqlite3.js @@ -146,7 +146,7 @@ Statement.prototype.map = function() { var isVerbose = false; -var supportedEvents = [ 'trace', 'profile', 'insert', 'update', 'delete' ]; +var supportedEvents = [ 'trace', 'profile', 'change' ]; Database.prototype.addListener = Database.prototype.on = function(type) { var val = EventEmitter.prototype.addListener.apply(this, arguments); diff --git a/src/database.cc b/src/database.cc index ace5fa0b0..36b5d0911 100644 --- a/src/database.cc +++ b/src/database.cc @@ -344,6 +344,11 @@ NAN_METHOD(Database::Configure) { baton->status = Nan::To(info[1]).FromJust(); db->Schedule(SetBusyTimeout, baton); } + else if (Nan::Equals(info[0], Nan::New("change").ToLocalChecked()).FromJust()) { + Local handle; + Baton* baton = new Baton(db, handle); + db->Schedule(RegisterUpdateCallback, baton); + } else { return Nan::ThrowError(Exception::Error(String::Concat( #if V8_MAJOR_VERSION > 6 @@ -499,12 +504,13 @@ void Database::UpdateCallback(Database *db, UpdateInfo* info) { Nan::HandleScope scope; Local argv[] = { + Nan::New("change").ToLocalChecked(), Nan::New(sqlite_authorizer_string(info->type)).ToLocalChecked(), Nan::New(info->database.c_str()).ToLocalChecked(), Nan::New(info->table.c_str()).ToLocalChecked(), Nan::New(info->rowid), }; - EMIT_EVENT(db->handle(), 4, argv); + EMIT_EVENT(db->handle(), 5, argv); delete info; } diff --git a/test/update_hook.test.js b/test/update_hook.test.js new file mode 100644 index 000000000..ab70ebc81 --- /dev/null +++ b/test/update_hook.test.js @@ -0,0 +1,76 @@ +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); + }); +});