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 " simdutf.h"
@@ -80,6 +81,28 @@ inline MaybeLocal<String> Utf8StringMaybeOneByte(Isolate* isolate,
8081 isolate, input.data (), NewStringType::kNormal , len);
8182}
8283
84+ BindingData::BindingData (Realm* realm, Local<Object> wrap)
85+ : BaseObject(realm, wrap) {
86+ MakeWeak ();
87+ }
88+
89+ void BindingData::MemoryInfo (MemoryTracker* tracker) const {
90+ tracker->TrackFieldWithSize (" open_databases" ,
91+ open_databases.size () * sizeof (DatabaseSync*),
92+ " open_databases" );
93+ }
94+
95+ void BindingData::CreatePerContextProperties (Local<Object> target,
96+ Local<Value> unused,
97+ Local<Context> context,
98+ void * priv) {
99+ Realm* realm = Realm::GetCurrent (context);
100+ realm->AddBindingData <BindingData>(target);
101+ }
102+
103+ void BindingData::RegisterExternalReferences (
104+ ExternalReferenceRegistry* registry) {}
105+
83106#define CHECK_ERROR_OR_THROW (isolate, db, expr, expected, ret ) \
84107 do { \
85108 int r_ = (expr); \
@@ -887,6 +910,9 @@ DatabaseSync::DatabaseSync(Environment* env,
887910 enable_load_extension_ = allow_load_extension;
888911 ignore_next_sqlite_error_ = false ;
889912
913+ BindingData* binding = env->principal_realm ()->GetBindingData <BindingData>();
914+ if (binding != nullptr ) binding->open_databases .insert (this );
915+
890916 if (open) {
891917 Open ();
892918 }
@@ -910,6 +936,10 @@ void DatabaseSync::DeleteSessions() {
910936}
911937
912938DatabaseSync::~DatabaseSync () {
939+ BindingData* binding =
940+ env ()->principal_realm ()->GetBindingData <BindingData>();
941+ if (binding != nullptr ) binding->open_databases .erase (this );
942+
913943 FinalizeBackups ();
914944
915945 if (IsOpen ()) {
@@ -994,11 +1024,25 @@ bool DatabaseSync::Open() {
9941024 env ()->isolate (), this , load_extension_ret, SQLITE_OK, false );
9951025 }
9961026
997- sqlite3_trace_v2 (connection_, SQLITE_TRACE_STMT, TraceCallback, this );
1027+ diagnostics_channel::Channel* ch =
1028+ diagnostics_channel::Channel::Get (env (), " sqlite.db.query" );
1029+ if (ch != nullptr && ch->HasSubscribers ()) {
1030+ sqlite3_trace_v2 (connection_, SQLITE_TRACE_STMT, TraceCallback, this );
1031+ }
9981032
9991033 return true ;
10001034}
10011035
1036+ void DatabaseSync::EnableTracing () {
1037+ if (!IsOpen ()) return ;
1038+ sqlite3_trace_v2 (connection_, SQLITE_TRACE_STMT, TraceCallback, this );
1039+ }
1040+
1041+ void DatabaseSync::DisableTracing () {
1042+ if (!IsOpen ()) return ;
1043+ sqlite3_trace_v2 (connection_, 0 , nullptr , nullptr );
1044+ }
1045+
10021046void DatabaseSync::FinalizeBackups () {
10031047 for (auto backup : backups_) {
10041048 backup->Cleanup ();
@@ -3966,7 +4010,31 @@ static void Initialize(Local<Object> target,
39664010 Local<Context> context,
39674011 void * priv) {
39684012 Environment* env = Environment::GetCurrent (context);
4013+ Realm* realm = env->principal_realm ();
39694014 Isolate* isolate = env->isolate ();
4015+
4016+ // Set up the per-Environment database registry.
4017+ BindingData::CreatePerContextProperties (target, unused, context, priv);
4018+
4019+ // Register a native callback on the sqlite.db.query diagnostic channel so
4020+ // that SQLite tracing is enabled/disabled as subscribers come and go.
4021+ auto * diag_binding =
4022+ realm->GetBindingData <diagnostics_channel::BindingData>();
4023+ auto * sqlite_bd = realm->GetBindingData <BindingData>();
4024+ if (diag_binding != nullptr && sqlite_bd != nullptr ) {
4025+ uint32_t idx = diag_binding->GetOrCreateChannelIndex (" sqlite.db.query" );
4026+ BaseObjectPtr<BindingData> bd_ptr (sqlite_bd);
4027+ diag_binding->SetChannelStatusCallback (idx, [bd_ptr](bool is_active) {
4028+ BindingData* bd = bd_ptr.get ();
4029+ if (bd == nullptr ) return ;
4030+ for (DatabaseSync* db : bd->open_databases ) {
4031+ if (is_active)
4032+ db->EnableTracing ();
4033+ else
4034+ db->DisableTracing ();
4035+ }
4036+ });
4037+ }
39704038 Local<FunctionTemplate> db_tmpl =
39714039 NewFunctionTemplate (isolate, DatabaseSync::New);
39724040 db_tmpl->InstanceTemplate ()->SetInternalFieldCount (
@@ -4047,3 +4115,5 @@ static void Initialize(Local<Object> target,
40474115} // namespace node
40484116
40494117NODE_BINDING_CONTEXT_AWARE_INTERNAL (sqlite, node::sqlite::Initialize)
4118+ NODE_BINDING_EXTERNAL_REFERENCE(
4119+ sqlite, node::sqlite::BindingData::RegisterExternalReferences)
0 commit comments