77#include " node.h"
88#include " node_diagnostics_channel.h"
99#include " node_errors.h"
10+ #include " node_external_reference.h"
1011#include " node_mem-inl.h"
1112#include " node_url.h"
1213#include " sqlite3.h"
@@ -64,6 +65,29 @@ using v8::TryCatch;
6465using v8::Uint8Array;
6566using v8::Value;
6667
68+ BindingData::BindingData (Realm* realm, Local<Object> wrap)
69+ : BaseObject(realm, wrap) {
70+ MakeWeak ();
71+ }
72+
73+ void BindingData::MemoryInfo (MemoryTracker* tracker) const {
74+ tracker->TrackFieldWithSize (" open_databases" ,
75+ open_databases.size () * sizeof (DatabaseSync*),
76+ " open_databases" );
77+ }
78+
79+ void BindingData::CreatePerContextProperties (Local<Object> target,
80+ Local<Value> unused,
81+ Local<Context> context,
82+ void * priv) {
83+ Realm* realm = Realm::GetCurrent (context);
84+ realm->AddBindingData <BindingData>(target);
85+ }
86+
87+ void BindingData::RegisterExternalReferences (
88+ ExternalReferenceRegistry* registry) {
89+ }
90+
6791#define CHECK_ERROR_OR_THROW (isolate, db, expr, expected, ret ) \
6892 do { \
6993 int r_ = (expr); \
@@ -868,6 +892,9 @@ DatabaseSync::DatabaseSync(Environment* env,
868892 enable_load_extension_ = allow_load_extension;
869893 ignore_next_sqlite_error_ = false ;
870894
895+ BindingData* binding = env->principal_realm ()->GetBindingData <BindingData>();
896+ if (binding != nullptr ) binding->open_databases .insert (this );
897+
871898 if (open) {
872899 Open ();
873900 }
@@ -891,6 +918,9 @@ void DatabaseSync::DeleteSessions() {
891918}
892919
893920DatabaseSync::~DatabaseSync () {
921+ BindingData* binding = env ()->principal_realm ()->GetBindingData <BindingData>();
922+ if (binding != nullptr ) binding->open_databases .erase (this );
923+
894924 FinalizeBackups ();
895925
896926 if (IsOpen ()) {
@@ -975,11 +1005,25 @@ bool DatabaseSync::Open() {
9751005 env ()->isolate (), this , load_extension_ret, SQLITE_OK, false );
9761006 }
9771007
978- sqlite3_trace_v2 (connection_, SQLITE_TRACE_STMT, TraceCallback, this );
1008+ diagnostics_channel::Channel* ch =
1009+ diagnostics_channel::Channel::Get (env (), " sqlite.db.query" );
1010+ if (ch != nullptr && ch->HasSubscribers ()) {
1011+ sqlite3_trace_v2 (connection_, SQLITE_TRACE_STMT, TraceCallback, this );
1012+ }
9791013
9801014 return true ;
9811015}
9821016
1017+ void DatabaseSync::EnableTracing () {
1018+ if (!IsOpen ()) return ;
1019+ sqlite3_trace_v2 (connection_, SQLITE_TRACE_STMT, TraceCallback, this );
1020+ }
1021+
1022+ void DatabaseSync::DisableTracing () {
1023+ if (!IsOpen ()) return ;
1024+ sqlite3_trace_v2 (connection_, 0 , nullptr , nullptr );
1025+ }
1026+
9831027void DatabaseSync::FinalizeBackups () {
9841028 for (auto backup : backups_) {
9851029 backup->Cleanup ();
@@ -3778,7 +3822,33 @@ static void Initialize(Local<Object> target,
37783822 Local<Context> context,
37793823 void * priv) {
37803824 Environment* env = Environment::GetCurrent (context);
3825+ Realm* realm = env->principal_realm ();
37813826 Isolate* isolate = env->isolate ();
3827+
3828+ // Set up the per-Environment database registry.
3829+ BindingData::CreatePerContextProperties (target, unused, context, priv);
3830+
3831+ // Register a native callback on the sqlite.db.query diagnostic channel so
3832+ // that SQLite tracing is enabled/disabled as subscribers come and go.
3833+ auto * diag_binding =
3834+ realm->GetBindingData <diagnostics_channel::BindingData>();
3835+ auto * sqlite_bd = realm->GetBindingData <BindingData>();
3836+ if (diag_binding != nullptr && sqlite_bd != nullptr ) {
3837+ uint32_t idx =
3838+ diag_binding->GetOrCreateChannelIndex (" sqlite.db.query" );
3839+ BaseObjectPtr<BindingData> bd_ptr (sqlite_bd);
3840+ diag_binding->SetChannelStatusCallback (
3841+ idx, [bd_ptr](bool is_active) {
3842+ BindingData* bd = bd_ptr.get ();
3843+ if (bd == nullptr ) return ;
3844+ for (DatabaseSync* db : bd->open_databases ) {
3845+ if (is_active)
3846+ db->EnableTracing ();
3847+ else
3848+ db->DisableTracing ();
3849+ }
3850+ });
3851+ }
37823852 Local<FunctionTemplate> db_tmpl =
37833853 NewFunctionTemplate (isolate, DatabaseSync::New);
37843854 db_tmpl->InstanceTemplate ()->SetInternalFieldCount (
@@ -3857,3 +3927,5 @@ static void Initialize(Local<Object> target,
38573927} // namespace node
38583928
38593929NODE_BINDING_CONTEXT_AWARE_INTERNAL (sqlite, node::sqlite::Initialize)
3930+ NODE_BINDING_EXTERNAL_REFERENCE(
3931+ sqlite, node::sqlite::BindingData::RegisterExternalReferences)
0 commit comments