@@ -17,6 +17,9 @@ static ErlNifResourceType* connection_type = NULL;
1717static ErlNifResourceType * statement_type = NULL ;
1818static sqlite3_mem_methods default_alloc_methods = {0 };
1919
20+ ErlNifPid * log_hook_pid = NULL ;
21+ ErlNifMutex * log_hook_mutex = NULL ;
22+
2023typedef struct connection
2124{
2225 sqlite3 * db ;
@@ -956,6 +959,11 @@ on_load(ErlNifEnv* env, void** priv, ERL_NIF_TERM info)
956959 return -1 ;
957960 }
958961
962+ log_hook_mutex = enif_mutex_create ("exqlite:log_hook" );
963+ if (!log_hook_mutex ) {
964+ return -1 ;
965+ }
966+
959967 return 0 ;
960968}
961969
@@ -965,6 +973,7 @@ on_unload(ErlNifEnv* caller_env, void* priv_data)
965973 assert (caller_env );
966974
967975 sqlite3_config (SQLITE_CONFIG_MALLOC , & default_alloc_methods );
976+ enif_mutex_destroy (log_hook_mutex );
968977}
969978
970979//
@@ -1065,6 +1074,61 @@ exqlite_set_update_hook(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
10651074 return make_atom (env , "ok" );
10661075}
10671076
1077+ //
1078+ // Log Notifications
1079+ //
1080+
1081+ void
1082+ log_callback (void * arg , int iErrCode , const char * zMsg )
1083+ {
1084+ if (log_hook_pid == NULL ) {
1085+ return ;
1086+ }
1087+
1088+ ErlNifEnv * msg_env = enif_alloc_env ();
1089+ ERL_NIF_TERM error = make_binary (msg_env , zMsg , strlen (zMsg ));
1090+ ERL_NIF_TERM msg = enif_make_tuple3 (msg_env , make_atom (msg_env , "log" ), enif_make_int (msg_env , iErrCode ), error );
1091+
1092+ if (!enif_send (NULL , log_hook_pid , msg_env , msg )) {
1093+ enif_mutex_lock (log_hook_mutex );
1094+ sqlite3_config (SQLITE_CONFIG_LOG , NULL , NULL );
1095+ enif_free (log_hook_pid );
1096+ log_hook_pid = NULL ;
1097+ enif_mutex_unlock (log_hook_mutex );
1098+ }
1099+
1100+ enif_free_env (msg_env );
1101+ }
1102+
1103+ static ERL_NIF_TERM
1104+ exqlite_set_log_hook (ErlNifEnv * env , int argc , const ERL_NIF_TERM argv [])
1105+ {
1106+ assert (env );
1107+
1108+ if (argc != 1 ) {
1109+ return enif_make_badarg (env );
1110+ }
1111+
1112+ ErlNifPid * pid = (ErlNifPid * )enif_alloc (sizeof (ErlNifPid ));
1113+ if (!enif_get_local_pid (env , argv [0 ], pid )) {
1114+ enif_free (pid );
1115+ return make_error_tuple (env , "invalid_pid" );
1116+ }
1117+
1118+ enif_mutex_lock (log_hook_mutex );
1119+
1120+ if (log_hook_pid ) {
1121+ enif_free (log_hook_pid );
1122+ }
1123+
1124+ log_hook_pid = pid ;
1125+ sqlite3_config (SQLITE_CONFIG_LOG , log_callback , NULL );
1126+
1127+ enif_mutex_unlock (log_hook_mutex );
1128+
1129+ return make_atom (env , "ok" );
1130+ }
1131+
10681132//
10691133// Most of our nif functions are going to be IO bounded
10701134//
@@ -1086,6 +1150,7 @@ static ErlNifFunc nif_funcs[] = {
10861150 {"release" , 2 , exqlite_release , ERL_NIF_DIRTY_JOB_IO_BOUND },
10871151 {"enable_load_extension" , 2 , exqlite_enable_load_extension , ERL_NIF_DIRTY_JOB_IO_BOUND },
10881152 {"set_update_hook" , 2 , exqlite_set_update_hook , ERL_NIF_DIRTY_JOB_IO_BOUND },
1153+ {"set_log_hook" , 1 , exqlite_set_log_hook , ERL_NIF_DIRTY_JOB_IO_BOUND },
10891154};
10901155
10911156ERL_NIF_INIT (Elixir .Exqlite .Sqlite3NIF , nif_funcs , on_load , NULL , NULL , on_unload )
0 commit comments