Description
Issue Summary
Using on
/ addListener
multiple times with the same event name does not fire any of the attached listeners. This seems to be true for all events that use the Register*Callback
function from database.cc
. I will use on('change')
as an example.
This is due to the way the Database::Register*Callback
functions are implemented:
void Database::RegisterUpdateCallback(Baton* b) {
std::unique_ptr<Baton> baton(b);
assert(baton->db->open);
assert(baton->db->_handle);
Database* db = baton->db;
if (db->update_event == NULL) {
// Add it.
db->update_event = new AsyncUpdate(db, UpdateCallback);
sqlite3_update_hook(db->_handle, UpdateCallback, db);
}
else {
// Remove it.
sqlite3_update_hook(db->_handle, NULL, NULL);
db->update_event->finish();
db->update_event = NULL;
}
}
Calling on('change', ...)
will invoke this function which will eventually call Database::RegisterUpdateCallback
.
The first call to on('change', ...)
will register the Database::UpdateCallback
. The seconds call will remove it. The third call will register the callback again.
Fix:
db.configure
/Database::Configure
is called with a second argument that states whether the callback should be registered or removed. This argument is not passed toDatabase::Register*Callback
.
Note: Calling on('change', ...)
an odd number of times will lead to the correct behavior.
Steps to Reproduce
You can use this example code to reproduce the error.
const db = new Database(':memory:');
db.on('change', () => { console.log ('listener 1')});
db.on('change', () => { console.log ('listener 2')});
//Uncomment next to see all listeners
//db.on('change', () => { console.log ('listener 3')});
db.exec(`
CREATE TABLE "test" (
name TEXT
)
`, () => {
db.exec(`
INSERT INTO "test" (
name
) VALUES (
'test'
)
`)
});
Version
^5.1.2
Node.js Version
v18.2.0
How did you install the library?
Does not apply
Activity
little-brother commentedon Apr 6, 2023
Also there is no doc about it :(