@@ -55,6 +55,9 @@ static const char * const begin_statements[] = {
55
55
56
56
static int pysqlite_connection_set_isolation_level (pysqlite_Connection * self , PyObject * isolation_level , void * Py_UNUSED (ignored ));
57
57
static 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 );
58
61
59
62
static PyObject *
60
63
new_statement_cache (pysqlite_Connection * self , int maxsize )
@@ -170,9 +173,9 @@ pysqlite_connection_init_impl(pysqlite_Connection *self,
170
173
self -> thread_ident = PyThread_get_thread_ident ();
171
174
self -> check_same_thread = check_same_thread ;
172
175
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 ) ;
176
179
177
180
self -> Warning = state -> Warning ;
178
181
self -> Error = state -> Error ;
@@ -216,6 +219,13 @@ pysqlite_do_all_statements(pysqlite_Connection *self)
216
219
}
217
220
}
218
221
222
+ #define VISIT_CALLBACK_CONTEXT (ctx ) \
223
+ do { \
224
+ if (ctx) { \
225
+ Py_VISIT(ctx->callable); \
226
+ } \
227
+ } while (0)
228
+
219
229
static int
220
230
connection_traverse (pysqlite_Connection * self , visitproc visit , void * arg )
221
231
{
@@ -225,12 +235,21 @@ connection_traverse(pysqlite_Connection *self, visitproc visit, void *arg)
225
235
Py_VISIT (self -> cursors );
226
236
Py_VISIT (self -> row_factory );
227
237
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
231
242
return 0 ;
232
243
}
233
244
245
+ static inline void
246
+ clear_callback_context (callback_context * ctx )
247
+ {
248
+ if (ctx != NULL ) {
249
+ Py_CLEAR (ctx -> callable );
250
+ }
251
+ }
252
+
234
253
static int
235
254
connection_clear (pysqlite_Connection * self )
236
255
{
@@ -239,9 +258,9 @@ connection_clear(pysqlite_Connection *self)
239
258
Py_CLEAR (self -> cursors );
240
259
Py_CLEAR (self -> row_factory );
241
260
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 );
245
264
return 0 ;
246
265
}
247
266
@@ -255,6 +274,14 @@ connection_close(pysqlite_Connection *self)
255
274
}
256
275
}
257
276
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
+
258
285
static void
259
286
connection_dealloc (pysqlite_Connection * self )
260
287
{
@@ -264,6 +291,7 @@ connection_dealloc(pysqlite_Connection *self)
264
291
265
292
/* Clean up if user has not called .close() explicitly. */
266
293
connection_close (self );
294
+ free_callback_contexts (self );
267
295
268
296
tp -> tp_free (self );
269
297
Py_DECREF (tp );
@@ -600,6 +628,19 @@ _pysqlite_build_py_params(sqlite3_context *context, int argc,
600
628
return NULL ;
601
629
}
602
630
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
+
603
644
// Checks the Python exception and sets the appropriate SQLite error code.
604
645
static void
605
646
set_sqlite_error (sqlite3_context * context , const char * msg )
@@ -615,14 +656,7 @@ set_sqlite_error(sqlite3_context *context, const char *msg)
615
656
sqlite3_result_error (context , msg , -1 );
616
657
}
617
658
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 );
626
660
}
627
661
628
662
static void
@@ -796,10 +830,21 @@ static void
796
830
free_callback_context (callback_context * ctx )
797
831
{
798
832
assert (ctx != NULL );
799
- Py_DECREF (ctx -> callable );
833
+ Py_XDECREF (ctx -> callable );
800
834
PyMem_Free (ctx );
801
835
}
802
836
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
+
803
848
static void
804
849
destructor_callback (void * ctx )
805
850
{
@@ -917,33 +962,22 @@ authorizer_callback(void *ctx, int action, const char *arg1,
917
962
PyGILState_STATE gilstate = PyGILState_Ensure ();
918
963
919
964
PyObject * ret ;
920
- int rc ;
965
+ int rc = SQLITE_DENY ;
921
966
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 );
924
971
925
972
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 );
934
974
rc = SQLITE_DENY ;
935
975
}
936
976
else {
937
977
if (PyLong_Check (ret )) {
938
978
rc = _PyLong_AsInt (ret );
939
979
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 );
947
981
rc = SQLITE_DENY ;
948
982
}
949
983
}
@@ -964,8 +998,10 @@ progress_callback(void *ctx)
964
998
965
999
int rc ;
966
1000
PyObject * ret ;
967
- ret = _PyObject_CallNoArg ((PyObject * )ctx );
968
1001
1002
+ assert (ctx != NULL );
1003
+ PyObject * callable = ((callback_context * )ctx )-> callable ;
1004
+ ret = _PyObject_CallNoArg (callable );
969
1005
if (!ret ) {
970
1006
/* abort query if error occurred */
971
1007
rc = -1 ;
@@ -975,13 +1011,7 @@ progress_callback(void *ctx)
975
1011
Py_DECREF (ret );
976
1012
}
977
1013
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 );
985
1015
}
986
1016
987
1017
PyGILState_Release (gilstate );
@@ -1015,21 +1045,18 @@ trace_callback(void *ctx, const char *statement_string)
1015
1045
PyObject * ret = NULL ;
1016
1046
py_statement = PyUnicode_DecodeUTF8 (statement_string ,
1017
1047
strlen (statement_string ), "replace" );
1048
+ assert (ctx != NULL );
1018
1049
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 );
1020
1052
Py_DECREF (py_statement );
1021
1053
}
1022
1054
1023
1055
if (ret ) {
1024
1056
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 );
1033
1060
}
1034
1061
1035
1062
PyGILState_Release (gilstate );
@@ -1058,17 +1085,20 @@ pysqlite_connection_set_authorizer_impl(pysqlite_Connection *self,
1058
1085
int rc ;
1059
1086
if (callable == Py_None ) {
1060
1087
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 );
1062
1089
}
1063
1090
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 );
1067
1097
}
1068
1098
if (rc != SQLITE_OK ) {
1069
1099
PyErr_SetString (self -> OperationalError ,
1070
1100
"Error setting authorizer callback" );
1071
- Py_XSETREF ( self -> function_pinboard_authorizer_cb , NULL );
1101
+ set_callback_context ( & self -> authorizer_ctx , NULL );
1072
1102
return NULL ;
1073
1103
}
1074
1104
Py_RETURN_NONE ;
@@ -1095,11 +1125,15 @@ pysqlite_connection_set_progress_handler_impl(pysqlite_Connection *self,
1095
1125
if (callable == Py_None ) {
1096
1126
/* None clears the progress handler previously set */
1097
1127
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 );
1103
1137
}
1104
1138
Py_RETURN_NONE ;
1105
1139
}
@@ -1136,15 +1170,19 @@ pysqlite_connection_set_trace_callback_impl(pysqlite_Connection *self,
1136
1170
#else
1137
1171
sqlite3_trace (self -> db , 0 , (void * )0 );
1138
1172
#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
+ }
1141
1180
#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 );
1143
1182
#else
1144
- sqlite3_trace (self -> db , trace_callback , callable );
1183
+ sqlite3_trace (self -> db , trace_callback , ctx );
1145
1184
#endif
1146
- Py_INCREF (callable );
1147
- Py_XSETREF (self -> function_pinboard_trace_callback , callable );
1185
+ set_callback_context (& self -> trace_ctx , ctx );
1148
1186
}
1149
1187
1150
1188
Py_RETURN_NONE ;
0 commit comments