@@ -55,6 +55,9 @@ static const char * const begin_statements[] = {
5555
5656static int pysqlite_connection_set_isolation_level (pysqlite_Connection * self , PyObject * isolation_level , void * Py_UNUSED (ignored ));
5757static void _pysqlite_drop_unused_cursor_references (pysqlite_Connection * self );
58+ static void free_callback_context (callback_context * ctx );
59+ static void set_callback_context (callback_context * * ctx_pp ,
60+ callback_context * ctx );
5861
5962static PyObject *
6063new_statement_cache (pysqlite_Connection * self , int maxsize )
@@ -170,9 +173,9 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
170173 self -> thread_ident = PyThread_get_thread_ident ();
171174 self -> check_same_thread = check_same_thread ;
172175
173- self -> function_pinboard_trace_callback = NULL ;
174- self -> function_pinboard_progress_handler = NULL ;
175- self -> function_pinboard_authorizer_cb = NULL ;
176+ set_callback_context ( & self -> trace_ctx , NULL ) ;
177+ set_callback_context ( & self -> progress_ctx , NULL ) ;
178+ set_callback_context ( & self -> authorizer_ctx , NULL ) ;
176179
177180 self -> Warning = state -> Warning ;
178181 self -> Error = state -> Error ;
@@ -216,6 +219,13 @@ pysqlite_do_all_statements(pysqlite_Connection *self)
216219 }
217220}
218221
222+ #define VISIT_CALLBACK_CONTEXT (ctx ) \
223+ do { \
224+ if (ctx) { \
225+ Py_VISIT(ctx->callable); \
226+ } \
227+ } while (0)
228+
219229static int
220230connection_traverse (pysqlite_Connection * self , visitproc visit , void * arg )
221231{
@@ -225,12 +235,21 @@ connection_traverse(pysqlite_Connection *self, visitproc visit, void *arg)
225235 Py_VISIT (self -> cursors );
226236 Py_VISIT (self -> row_factory );
227237 Py_VISIT (self -> text_factory );
228- Py_VISIT (self -> function_pinboard_trace_callback );
229- Py_VISIT (self -> function_pinboard_progress_handler );
230- Py_VISIT (self -> function_pinboard_authorizer_cb );
238+ VISIT_CALLBACK_CONTEXT (self -> trace_ctx );
239+ VISIT_CALLBACK_CONTEXT (self -> progress_ctx );
240+ VISIT_CALLBACK_CONTEXT (self -> authorizer_ctx );
241+ #undef VISIT_CALLBACK_CONTEXT
231242 return 0 ;
232243}
233244
245+ static inline void
246+ clear_callback_context (callback_context * ctx )
247+ {
248+ if (ctx != NULL ) {
249+ Py_CLEAR (ctx -> callable );
250+ }
251+ }
252+
234253static int
235254connection_clear (pysqlite_Connection * self )
236255{
@@ -239,9 +258,9 @@ connection_clear(pysqlite_Connection *self)
239258 Py_CLEAR (self -> cursors );
240259 Py_CLEAR (self -> row_factory );
241260 Py_CLEAR (self -> text_factory );
242- Py_CLEAR (self -> function_pinboard_trace_callback );
243- Py_CLEAR (self -> function_pinboard_progress_handler );
244- Py_CLEAR (self -> function_pinboard_authorizer_cb );
261+ clear_callback_context (self -> trace_ctx );
262+ clear_callback_context (self -> progress_ctx );
263+ clear_callback_context (self -> authorizer_ctx );
245264 return 0 ;
246265}
247266
@@ -255,6 +274,14 @@ connection_close(pysqlite_Connection *self)
255274 }
256275}
257276
277+ static void
278+ free_callback_contexts (pysqlite_Connection * self )
279+ {
280+ set_callback_context (& self -> trace_ctx , NULL );
281+ set_callback_context (& self -> progress_ctx , NULL );
282+ set_callback_context (& self -> authorizer_ctx , NULL );
283+ }
284+
258285static void
259286connection_dealloc (pysqlite_Connection * self )
260287{
@@ -264,6 +291,7 @@ connection_dealloc(pysqlite_Connection *self)
264291
265292 /* Clean up if user has not called .close() explicitly. */
266293 connection_close (self );
294+ free_callback_contexts (self );
267295
268296 tp -> tp_free (self );
269297 Py_DECREF (tp );
@@ -600,6 +628,19 @@ _pysqlite_build_py_params(sqlite3_context *context, int argc,
600628 return NULL ;
601629}
602630
631+ static void
632+ print_or_clear_traceback (callback_context * ctx )
633+ {
634+ assert (ctx != NULL );
635+ assert (ctx -> state != NULL );
636+ if (ctx -> state -> enable_callback_tracebacks ) {
637+ PyErr_Print ();
638+ }
639+ else {
640+ PyErr_Clear ();
641+ }
642+ }
643+
603644// Checks the Python exception and sets the appropriate SQLite error code.
604645static void
605646set_sqlite_error (sqlite3_context * context , const char * msg )
@@ -615,14 +656,7 @@ set_sqlite_error(sqlite3_context *context, const char *msg)
615656 sqlite3_result_error (context , msg , -1 );
616657 }
617658 callback_context * ctx = (callback_context * )sqlite3_user_data (context );
618- assert (ctx != NULL );
619- assert (ctx -> state != NULL );
620- if (ctx -> state -> enable_callback_tracebacks ) {
621- PyErr_Print ();
622- }
623- else {
624- PyErr_Clear ();
625- }
659+ print_or_clear_traceback (ctx );
626660}
627661
628662static void
@@ -796,10 +830,21 @@ static void
796830free_callback_context (callback_context * ctx )
797831{
798832 assert (ctx != NULL );
799- Py_DECREF (ctx -> callable );
833+ Py_XDECREF (ctx -> callable );
800834 PyMem_Free (ctx );
801835}
802836
837+ static void
838+ set_callback_context (callback_context * * ctx_pp , callback_context * ctx )
839+ {
840+ assert (ctx_pp != NULL );
841+ callback_context * tmp = * ctx_pp ;
842+ * ctx_pp = ctx ;
843+ if (tmp != NULL ) {
844+ free_callback_context (tmp );
845+ }
846+ }
847+
803848static void
804849destructor_callback (void * ctx )
805850{
@@ -917,33 +962,22 @@ authorizer_callback(void *ctx, int action, const char *arg1,
917962 PyGILState_STATE gilstate = PyGILState_Ensure ();
918963
919964 PyObject * ret ;
920- int rc ;
965+ int rc = SQLITE_DENY ;
921966
922- ret = PyObject_CallFunction ((PyObject * )ctx , "issss" , action , arg1 , arg2 ,
923- dbname , access_attempt_source );
967+ assert (ctx != NULL );
968+ PyObject * callable = ((callback_context * )ctx )-> callable ;
969+ ret = PyObject_CallFunction (callable , "issss" , action , arg1 , arg2 , dbname ,
970+ access_attempt_source );
924971
925972 if (ret == NULL ) {
926- pysqlite_state * state = pysqlite_get_state (NULL );
927- if (state -> enable_callback_tracebacks ) {
928- PyErr_Print ();
929- }
930- else {
931- PyErr_Clear ();
932- }
933-
973+ print_or_clear_traceback (ctx );
934974 rc = SQLITE_DENY ;
935975 }
936976 else {
937977 if (PyLong_Check (ret )) {
938978 rc = _PyLong_AsInt (ret );
939979 if (rc == -1 && PyErr_Occurred ()) {
940- pysqlite_state * state = pysqlite_get_state (NULL );
941- if (state -> enable_callback_tracebacks ) {
942- PyErr_Print ();
943- }
944- else {
945- PyErr_Clear ();
946- }
980+ print_or_clear_traceback (ctx );
947981 rc = SQLITE_DENY ;
948982 }
949983 }
@@ -964,8 +998,10 @@ progress_callback(void *ctx)
964998
965999 int rc ;
9661000 PyObject * ret ;
967- ret = _PyObject_CallNoArg ((PyObject * )ctx );
9681001
1002+ assert (ctx != NULL );
1003+ PyObject * callable = ((callback_context * )ctx )-> callable ;
1004+ ret = _PyObject_CallNoArg (callable );
9691005 if (!ret ) {
9701006 /* abort query if error occurred */
9711007 rc = -1 ;
@@ -975,13 +1011,7 @@ progress_callback(void *ctx)
9751011 Py_DECREF (ret );
9761012 }
9771013 if (rc < 0 ) {
978- pysqlite_state * state = pysqlite_get_state (NULL );
979- if (state -> enable_callback_tracebacks ) {
980- PyErr_Print ();
981- }
982- else {
983- PyErr_Clear ();
984- }
1014+ print_or_clear_traceback (ctx );
9851015 }
9861016
9871017 PyGILState_Release (gilstate );
@@ -1015,21 +1045,18 @@ trace_callback(void *ctx, const char *statement_string)
10151045 PyObject * ret = NULL ;
10161046 py_statement = PyUnicode_DecodeUTF8 (statement_string ,
10171047 strlen (statement_string ), "replace" );
1048+ assert (ctx != NULL );
10181049 if (py_statement ) {
1019- ret = PyObject_CallOneArg ((PyObject * )ctx , py_statement );
1050+ PyObject * callable = ((callback_context * )ctx )-> callable ;
1051+ ret = PyObject_CallOneArg (callable , py_statement );
10201052 Py_DECREF (py_statement );
10211053 }
10221054
10231055 if (ret ) {
10241056 Py_DECREF (ret );
1025- } else {
1026- pysqlite_state * state = pysqlite_get_state (NULL );
1027- if (state -> enable_callback_tracebacks ) {
1028- PyErr_Print ();
1029- }
1030- else {
1031- PyErr_Clear ();
1032- }
1057+ }
1058+ else {
1059+ print_or_clear_traceback (ctx );
10331060 }
10341061
10351062 PyGILState_Release (gilstate );
@@ -1058,17 +1085,20 @@ pysqlite_connection_set_authorizer_impl(pysqlite_Connection *self,
10581085 int rc ;
10591086 if (callable == Py_None ) {
10601087 rc = sqlite3_set_authorizer (self -> db , NULL , NULL );
1061- Py_XSETREF ( self -> function_pinboard_authorizer_cb , NULL );
1088+ set_callback_context ( & self -> authorizer_ctx , NULL );
10621089 }
10631090 else {
1064- Py_INCREF (callable );
1065- Py_XSETREF (self -> function_pinboard_authorizer_cb , callable );
1066- rc = sqlite3_set_authorizer (self -> db , authorizer_callback , callable );
1091+ callback_context * ctx = create_callback_context (self -> state , callable );
1092+ if (ctx == NULL ) {
1093+ return NULL ;
1094+ }
1095+ rc = sqlite3_set_authorizer (self -> db , authorizer_callback , ctx );
1096+ set_callback_context (& self -> authorizer_ctx , ctx );
10671097 }
10681098 if (rc != SQLITE_OK ) {
10691099 PyErr_SetString (self -> OperationalError ,
10701100 "Error setting authorizer callback" );
1071- Py_XSETREF ( self -> function_pinboard_authorizer_cb , NULL );
1101+ set_callback_context ( & self -> authorizer_ctx , NULL );
10721102 return NULL ;
10731103 }
10741104 Py_RETURN_NONE ;
@@ -1095,11 +1125,15 @@ pysqlite_connection_set_progress_handler_impl(pysqlite_Connection *self,
10951125 if (callable == Py_None ) {
10961126 /* None clears the progress handler previously set */
10971127 sqlite3_progress_handler (self -> db , 0 , 0 , (void * )0 );
1098- Py_XSETREF (self -> function_pinboard_progress_handler , NULL );
1099- } else {
1100- sqlite3_progress_handler (self -> db , n , progress_callback , callable );
1101- Py_INCREF (callable );
1102- Py_XSETREF (self -> function_pinboard_progress_handler , callable );
1128+ set_callback_context (& self -> progress_ctx , NULL );
1129+ }
1130+ else {
1131+ callback_context * ctx = create_callback_context (self -> state , callable );
1132+ if (ctx == NULL ) {
1133+ return NULL ;
1134+ }
1135+ sqlite3_progress_handler (self -> db , n , progress_callback , ctx );
1136+ set_callback_context (& self -> progress_ctx , ctx );
11031137 }
11041138 Py_RETURN_NONE ;
11051139}
@@ -1136,15 +1170,19 @@ pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self,
11361170#else
11371171 sqlite3_trace (self -> db , 0 , (void * )0 );
11381172#endif
1139- Py_XSETREF (self -> function_pinboard_trace_callback , NULL );
1140- } else {
1173+ set_callback_context (& self -> trace_ctx , NULL );
1174+ }
1175+ else {
1176+ callback_context * ctx = create_callback_context (self -> state , callable );
1177+ if (ctx == NULL ) {
1178+ return NULL ;
1179+ }
11411180#ifdef HAVE_TRACE_V2
1142- sqlite3_trace_v2 (self -> db , SQLITE_TRACE_STMT , trace_callback , callable );
1181+ sqlite3_trace_v2 (self -> db , SQLITE_TRACE_STMT , trace_callback , ctx );
11431182#else
1144- sqlite3_trace (self -> db , trace_callback , callable );
1183+ sqlite3_trace (self -> db , trace_callback , ctx );
11451184#endif
1146- Py_INCREF (callable );
1147- Py_XSETREF (self -> function_pinboard_trace_callback , callable );
1185+ set_callback_context (& self -> trace_ctx , ctx );
11481186 }
11491187
11501188 Py_RETURN_NONE ;
0 commit comments