Commit b8f718c7 by Konstantin Käfer

implement insert/update/delete hook

parent 7fa46343
...@@ -122,9 +122,11 @@ Statement.prototype.map = function() { ...@@ -122,9 +122,11 @@ Statement.prototype.map = function() {
var isVerbose = false; var isVerbose = false;
var supportedEvents = [ 'trace', 'profile', 'insert', 'update', 'delete' ];
Database.prototype.addListener = Database.prototype.on = function(type) { Database.prototype.addListener = Database.prototype.on = function(type) {
var val = EventEmitter.prototype.addListener.apply(this, arguments); var val = EventEmitter.prototype.addListener.apply(this, arguments);
if (type === 'trace' || type === 'profile') { if (supportedEvents.indexOf(type) >= 0) {
this.configure(type, true); this.configure(type, true);
} }
return val; return val;
...@@ -132,7 +134,7 @@ Database.prototype.addListener = Database.prototype.on = function(type) { ...@@ -132,7 +134,7 @@ Database.prototype.addListener = Database.prototype.on = function(type) {
Database.prototype.removeListener = function(type) { Database.prototype.removeListener = function(type) {
var val = EventEmitter.prototype.removeListener.apply(this, arguments); var val = EventEmitter.prototype.removeListener.apply(this, arguments);
if ((type === 'trace' || type === 'profile') && !this._events[type]) { if (supportedEvents.indexOf(type) >= 0 && !this._events[type]) {
this.configure(type, false); this.configure(type, false);
} }
return val; return val;
...@@ -140,7 +142,7 @@ Database.prototype.removeListener = function(type) { ...@@ -140,7 +142,7 @@ Database.prototype.removeListener = function(type) {
Database.prototype.removeAllListeners = function(type) { Database.prototype.removeAllListeners = function(type) {
var val = EventEmitter.prototype.removeAllListeners.apply(this, arguments); var val = EventEmitter.prototype.removeAllListeners.apply(this, arguments);
if (type === 'trace' || type === 'profile') { if (supportedEvents.indexOf(type) >= 0) {
this.configure(type, false); this.configure(type, false);
} }
return val; return val;
......
...@@ -413,6 +413,51 @@ void Database::ProfileCallback(Database *db, ProfileInfo* info) { ...@@ -413,6 +413,51 @@ void Database::ProfileCallback(Database *db, ProfileInfo* info) {
delete info; delete info;
} }
void Database::RegisterUpdateCallback(Baton* baton) {
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);
delete db->update_event;
db->update_event = NULL;
}
delete baton;
}
void Database::UpdateCallback(void* db, int type, const char* database,
const char* table, sqlite3_int64 rowid) {
// Note: This function is called in the thread pool.
// Note: Some queries, such as "EXPLAIN" queries, are not sent through this.
UpdateInfo* info = new UpdateInfo();
info->type = type;
info->database = std::string(database);
info->table = std::string(table);
info->rowid = rowid;
static_cast<Database*>(db)->update_event->send(info);
}
void Database::UpdateCallback(Database *db, UpdateInfo* info) {
HandleScope scope;
Local<Value> argv[] = {
String::NewSymbol(sqlite_authorizer_string(info->type)),
String::New(info->database.c_str()),
String::New(info->table.c_str()),
Integer::New(info->rowid),
};
EMIT_EVENT(db->handle_, 4, argv);
delete info;
}
Handle<Value> Database::Exec(const Arguments& args) { Handle<Value> Database::Exec(const Arguments& args) {
HandleScope scope; HandleScope scope;
Database* db = ObjectWrap::Unwrap<Database>(args.This()); Database* db = ObjectWrap::Unwrap<Database>(args.This());
......
...@@ -86,7 +86,7 @@ public: ...@@ -86,7 +86,7 @@ public:
struct UpdateInfo { struct UpdateInfo {
int type; int type;
std::string database; std::string database;
std::string tablename; std::string table;
sqlite3_int64 rowid; sqlite3_int64 rowid;
}; };
...@@ -155,7 +155,7 @@ protected: ...@@ -155,7 +155,7 @@ protected:
static void ProfileCallback(Database* db, ProfileInfo* info); static void ProfileCallback(Database* db, ProfileInfo* info);
static void RegisterUpdateCallback(Baton* baton); static void RegisterUpdateCallback(Baton* baton);
static void UpdateCallback(void* db, int type, const char* database, const char* table, sqlite3_uint64 rowid); static void UpdateCallback(void* db, int type, const char* database, const char* table, sqlite3_int64 rowid);
static void UpdateCallback(Database* db, UpdateInfo* info); static void UpdateCallback(Database* db, UpdateInfo* info);
void RemoveCallbacks(); void RemoveCallbacks();
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define NODE_SQLITE3_SRC_MACROS_H #define NODE_SQLITE3_SRC_MACROS_H
const char* sqlite_code_string(int code); const char* sqlite_code_string(int code);
const char* sqlite_authorizer_string(int type);
#define REQUIRE_ARGUMENTS(n) \ #define REQUIRE_ARGUMENTS(n) \
......
...@@ -86,3 +86,12 @@ const char* sqlite_code_string(int code) { ...@@ -86,3 +86,12 @@ const char* sqlite_code_string(int code) {
default: return "UNKNOWN"; default: return "UNKNOWN";
} }
} }
const char* sqlite_authorizer_string(int type) {
switch (type) {
case SQLITE_INSERT: return "insert";
case SQLITE_UPDATE: return "update";
case SQLITE_DELETE: return "delete";
default: return "";
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment