Add trace_v2 support.

This commit is contained in:
Charles Leifer 2023-09-15 07:59:45 -05:00
parent d2b5458d95
commit e5f01bddd8
2 changed files with 63 additions and 6 deletions

View file

@ -474,7 +474,7 @@ static PyObject * pysqlite_blob_subscript(pysqlite_Blob *self, PyObject *item)
static int pysqlite_blob_ass_subscript(pysqlite_Blob *self, PyObject *item, PyObject *value) static int pysqlite_blob_ass_subscript(pysqlite_Blob *self, PyObject *item, PyObject *value)
{ {
int rc; int rc = 0;
if (!pysqlite_check_blob(self)) { if (!pysqlite_check_blob(self)) {
return -1; return -1;

View file

@ -44,6 +44,10 @@
#define HAVE_BACKUP_API #define HAVE_BACKUP_API
#endif #endif
#if SQLITE_VERSION_NUMBER >= 3014002
#define HAVE_TRACE_V2
#endif
#if SQLITE_VERSION_NUMBER >= 3025000 #if SQLITE_VERSION_NUMBER >= 3025000
#define HAVE_WINDOW_FUNCTION #define HAVE_WINDOW_FUNCTION
#endif #endif
@ -1192,16 +1196,60 @@ static int _progress_handler(void* user_arg)
return rc; return rc;
} }
#ifdef HAVE_TRACE_V2
static int _trace_callback(unsigned int type, void *ctx, void *stmt, void *sql)
{
if (type != SQLITE_TRACE_STMT) {
return 0;
}
PyGILState_STATE gilstate = PyGILState_Ensure();
PyObject *py_statement = NULL;
const char *expanded_sql = sqlite3_expanded_sql((sqlite3_stmt *)stmt);
if (expanded_sql == NULL) {
sqlite3 *db = sqlite3_db_handle((sqlite3_stmt *)stmt);
if (sqlite3_errcode(db) == SQLITE_NOMEM) {
(void)PyErr_NoMemory();
goto exit;
}
PyErr_SetString(pysqlite_DataError, "Expanded SQL string exceeds the maximum string length");
if (_pysqlite_enable_callback_tracebacks) {
PyErr_Print();
} else {
PyErr_Clear();
}
py_statement = PyUnicode_FromString((const char *)sql);
} else {
py_statement = PyUnicode_FromString(expanded_sql);
sqlite3_free((void *)expanded_sql);
}
if (py_statement) {
PyObject *ret = PyObject_CallFunctionObjArgs((PyObject*)ctx, py_statement, NULL);
Py_DECREF(py_statement);
Py_XDECREF(ret);
}
if (PyErr_Occurred()) {
if (_pysqlite_enable_callback_tracebacks) {
PyErr_Print();
} else {
PyErr_Clear();
}
}
exit:
PyGILState_Release(gilstate);
return 0;
}
#else
static void _trace_callback(void* user_arg, const char* statement_string) static void _trace_callback(void* user_arg, const char* statement_string)
{ {
PyObject *py_statement = NULL; PyObject *py_statement = NULL;
PyObject *ret = NULL; PyObject *ret = NULL;
PyGILState_STATE gilstate; PyGILState_STATE gilstate = PyGILState_Ensure();
py_statement = PyUnicode_FromString(statement_string);
gilstate = PyGILState_Ensure();
py_statement = PyUnicode_DecodeUTF8(statement_string,
strlen(statement_string), "replace");
if (py_statement) { if (py_statement) {
ret = PyObject_CallFunctionObjArgs((PyObject*)user_arg, py_statement, NULL); ret = PyObject_CallFunctionObjArgs((PyObject*)user_arg, py_statement, NULL);
Py_DECREF(py_statement); Py_DECREF(py_statement);
@ -1219,6 +1267,7 @@ static void _trace_callback(void* user_arg, const char* statement_string)
PyGILState_Release(gilstate); PyGILState_Release(gilstate);
} }
#endif
static PyObject* pysqlite_connection_set_authorizer(pysqlite_Connection* self, PyObject* args, PyObject* kwargs) static PyObject* pysqlite_connection_set_authorizer(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)
{ {
@ -1300,10 +1349,18 @@ static PyObject* pysqlite_connection_set_trace_callback(pysqlite_Connection* sel
if (trace_callback == Py_None) { if (trace_callback == Py_None) {
/* None clears the trace callback previously set */ /* None clears the trace callback previously set */
#ifdef HAVE_TRACE_V2
sqlite3_trace_v2(self->db, SQLITE_TRACE_STMT, NULL, (void*)0);
#else
sqlite3_trace(self->db, 0, (void*)0); sqlite3_trace(self->db, 0, (void*)0);
#endif
Py_XSETREF(self->function_pinboard_trace_callback, NULL); Py_XSETREF(self->function_pinboard_trace_callback, NULL);
} else { } else {
#ifdef HAVE_TRACE_V2
sqlite3_trace_v2(self->db, SQLITE_TRACE_STMT, _trace_callback, trace_callback);
#else
sqlite3_trace(self->db, _trace_callback, trace_callback); sqlite3_trace(self->db, _trace_callback, trace_callback);
#endif
Py_INCREF(trace_callback); Py_INCREF(trace_callback);
Py_XSETREF(self->function_pinboard_trace_callback, trace_callback); Py_XSETREF(self->function_pinboard_trace_callback, trace_callback);
} }