@@ -209,11 +209,7 @@ void Database::EIO_BeginClose(Baton* baton) {
209209 assert (baton->db ->handle );
210210 assert (baton->db ->pending == 0 );
211211
212- if (baton->db ->debug_trace ) {
213- delete baton->db ->debug_trace ;
214- baton->db ->debug_trace = NULL ;
215- }
216-
212+ baton->db ->RemoveCallbacks ();
217213 eio_custom (EIO_Close, EIO_PRI_DEFAULT, EIO_AfterClose, baton);
218214}
219215
@@ -315,6 +311,11 @@ Handle<Value> Database::Configure(const Arguments& args) {
315311 Baton* baton = new Baton (db, handle);
316312 db->Schedule (RegisterTraceCallback, baton);
317313 }
314+ else if (args[0 ]->Equals (String::NewSymbol (" profile" ))) {
315+ Local<Function> handle;
316+ Baton* baton = new Baton (db, handle);
317+ db->Schedule (RegisterProfileCallback, baton);
318+ }
318319 else {
319320 return ThrowException (Exception::Error (String::Concat (
320321 args[0 ]->ToString (),
@@ -369,6 +370,49 @@ void Database::TraceCallback(EV_P_ ev_async *w, int revents) {
369370 queries.clear ();
370371}
371372
373+ void Database::RegisterProfileCallback (Baton* baton) {
374+ assert (baton->db ->open );
375+ assert (baton->db ->handle );
376+ Database* db = baton->db ;
377+
378+ if (db->debug_profile == NULL ) {
379+ // Add it.
380+ db->debug_profile = new AsyncProfile (db, ProfileCallback);
381+ sqlite3_profile (db->handle , ProfileCallback, db);
382+ }
383+ else {
384+ // Remove it.
385+ sqlite3_profile (db->handle , NULL , NULL );
386+ delete db->debug_profile ;
387+ db->debug_profile = NULL ;
388+ }
389+
390+ delete baton;
391+ }
392+
393+ void Database::ProfileCallback (void * db, const char * sql, sqlite3_uint64 nsecs) {
394+ // Note: This function is called in the thread pool.
395+ // Note: Some queries, such as "EXPLAIN" queries, are not sent through this.
396+ static_cast <Database*>(db)->debug_profile ->send (ProfileInfo (sql, nsecs));
397+ }
398+
399+ void Database::ProfileCallback (EV_P_ ev_async *w, int revents) {
400+ // Note: This function is called in the main V8 thread.
401+ HandleScope scope;
402+ AsyncProfile* async = static_cast <AsyncProfile*>(w->data );
403+
404+ std::vector<ProfileInfo> queries = async->get ();
405+ for (unsigned int i = 0 ; i < queries.size (); i++) {
406+ Local<Value> argv[] = {
407+ String::NewSymbol (" profile" ),
408+ String::New (queries[i].first .c_str ()),
409+ Integer::New ((double )queries[i].second / 1000000.0 )
410+ };
411+ EMIT_EVENT (async->parent ->handle_ , 3 , argv);
412+ }
413+ queries.clear ();
414+ }
415+
372416Handle<Value> Database::Exec (const Arguments& args) {
373417 HandleScope scope;
374418 Database* db = ObjectWrap::Unwrap<Database>(args.This ());
@@ -511,6 +555,17 @@ int Database::EIO_AfterLoadExtension(eio_req *req) {
511555 return 0 ;
512556}
513557
558+ void Database::RemoveCallbacks () {
559+ if (debug_trace) {
560+ delete debug_trace;
561+ debug_trace = NULL ;
562+ }
563+ if (debug_profile) {
564+ delete debug_profile;
565+ debug_profile = NULL ;
566+ }
567+ }
568+
514569/* *
515570 * Override this so that we can properly close the database when this object
516571 * gets garbage collected.
@@ -537,10 +592,7 @@ void Database::Unref() {
537592void Database::Destruct (Persistent<Value> value, void *data) {
538593 Database* db = static_cast <Database*>(data);
539594
540- if (db->debug_trace ) {
541- delete db->debug_trace ;
542- db->debug_trace = NULL ;
543- }
595+ db->RemoveCallbacks ();
544596
545597 if (db->handle ) {
546598 eio_custom (EIO_Destruct, EIO_PRI_DEFAULT, EIO_AfterDestruct, db);
0 commit comments