From b1ec6be604d4af9de043416ebb809a0a254f6a00 Mon Sep 17 00:00:00 2001 From: Michael Bianco Date: Wed, 10 Jan 2024 11:10:08 -0700 Subject: [PATCH] docs: add more TRACE calls for easier debugging --- src/connection.cpp | 6 +++++- src/cursor.cpp | 20 +++++++++++++++++--- src/params.cpp | 4 ++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/connection.cpp b/src/connection.cpp index d459bf4d..074f7438 100644 --- a/src/connection.cpp +++ b/src/connection.cpp @@ -154,6 +154,8 @@ static bool ApplyPreconnAttrs(HDBC hdbc, SQLINTEGER ikey, PyObject *value, char return false; } + TRACE("ApplyPreconnAttrs.SQLSetConnectAttrW key=%d value=%p vallen=%d\n", ikey, ivalue); + Py_BEGIN_ALLOW_THREADS ret = SQLSetConnectAttrW(hdbc, ikey, ivalue, vallen); Py_END_ALLOW_THREADS @@ -186,7 +188,7 @@ PyObject* Connection_New(PyObject* pConnectString, bool fAutoCommit, long timeou return RaiseErrorFromHandle(0, "SQLAllocHandle", SQL_NULL_HANDLE, SQL_NULL_HANDLE); // - // Attributes that must be set before connecting. + // Attributes that must be set before connecting. These are passed via `attr_before` in python. // if (attrs_before) @@ -363,6 +365,8 @@ static PyObject* Connection_set_attr(PyObject* self, PyObject* args) Connection* cnxn = (Connection*)self; + TRACE("SQLSetConnectAttr id=%d value=%d\n", id, value); + SQLRETURN ret; Py_BEGIN_ALLOW_THREADS ret = SQLSetConnectAttr(cnxn->hdbc, id, (SQLPOINTER)(intptr_t)value, SQL_IS_INTEGER); diff --git a/src/cursor.cpp b/src/cursor.cpp index f0520f6c..0a55c425 100644 --- a/src/cursor.cpp +++ b/src/cursor.cpp @@ -325,7 +325,7 @@ static bool free_results(Cursor* self, int flags) // this even when a query has not been executed. // If we ran out of memory, it is possible that we have a cursor but colinfos is zero. However, we should be - // deleting this object, so the cursor will be freed when the HSTMT is destroyed. */ + // deleting this object, so the cursor will be freed when the HSTMT is destroyed. assert((flags & STATEMENT_MASK) != 0); assert((flags & PREPARED_MASK) != 0); @@ -344,6 +344,8 @@ static bool free_results(Cursor* self, int flags) if (StatementIsValid(self)) { + TRACE("free_results: %p\n", self); + if ((flags & STATEMENT_MASK) == FREE_STATEMENT) { Py_BEGIN_ALLOW_THREADS @@ -387,6 +389,8 @@ static bool free_results(Cursor* self, int flags) self->rowcount = -1; + TRACE("free_results: done\n"); + return true; } @@ -407,6 +411,8 @@ static void closeimpl(Cursor* cur) HSTMT hstmt = cur->hstmt; cur->hstmt = SQL_NULL_HANDLE; + TRACE("SQLFreeHandle\n"); + SQLRETURN ret; Py_BEGIN_ALLOW_THREADS ret = SQLFreeHandle(SQL_HANDLE_STMT, hstmt); @@ -415,6 +421,8 @@ static void closeimpl(Cursor* cur) // If there is already an exception, don't overwrite it. if (!SQL_SUCCEEDED(ret) && !PyErr_Occurred()) RaiseErrorFromHandle(cur->cnxn, "SQLFreeHandle", cur->cnxn->hdbc, SQL_NULL_HANDLE); + } else { + TRACE("Invalid statement handle, skipping SQLFreeHandle\n"); } Py_XDECREF(cur->pPreparedSQL); @@ -750,12 +758,16 @@ static PyObject* execute(Cursor* cur, PyObject* pSql, PyObject* params, bool ski const char* pch = PyBytes_AS_STRING(query.Get()); SQLINTEGER cch = (SQLINTEGER)(PyBytes_GET_SIZE(query.Get()) / (isWide ? sizeof(uint16_t) : 1)); + TRACE("cursor.execute: isWide=%d query_len=%d\n", isWide, cch); + Py_BEGIN_ALLOW_THREADS if (isWide) ret = SQLExecDirectW(cur->hstmt, (SQLWCHAR*)pch, cch); else ret = SQLExecDirect(cur->hstmt, (SQLCHAR*)pch, cch); Py_END_ALLOW_THREADS + + TRACE("cursor.execute, finished\n"); } if (cur->cnxn->hdbc == SQL_NULL_HANDLE) @@ -1136,7 +1148,7 @@ static PyObject* Cursor_setinputsizes(PyObject* self, PyObject* sizes) PyErr_SetString(ProgrammingError, "Invalid cursor object."); return 0; } - + Cursor *cur = (Cursor*)self; if (Py_None == sizes) { @@ -2526,6 +2538,8 @@ Cursor_New(Connection* cnxn) if (cnxn->timeout) { + TRACE("cursor.new: setting timeout to %d\n", cnxn->timeout); + Py_BEGIN_ALLOW_THREADS ret = SQLSetStmtAttr(cur->hstmt, SQL_ATTR_QUERY_TIMEOUT, (SQLPOINTER)(uintptr_t)cnxn->timeout, 0); Py_END_ALLOW_THREADS @@ -2538,7 +2552,7 @@ Cursor_New(Connection* cnxn) } } - TRACE("cursor.new cnxn=%p hdbc=%d cursor=%p hstmt=%d\n", (Connection*)cur->cnxn, ((Connection*)cur->cnxn)->hdbc, cur, cur->hstmt); + TRACE("cursor.new: cnxn=%p hdbc=%d cursor=%p hstmt=%d\n", (Connection*)cur->cnxn, ((Connection*)cur->cnxn)->hdbc, cur, cur->hstmt); } return cur; diff --git a/src/params.cpp b/src/params.cpp index 1a0547ea..3894428c 100644 --- a/src/params.cpp +++ b/src/params.cpp @@ -1310,6 +1310,8 @@ void FreeParameterData(Cursor* cur) { // Unbinds the parameters and frees the parameter buffer. + TRACE("FreeParameterData"); + if (cur->paramInfos) { // MS ODBC will crash if we use an HSTMT after the HDBC has been freed. @@ -1330,6 +1332,8 @@ void FreeParameterInfo(Cursor* cur) // Internal function to free just the cached parameter information. This is not used by the general cursor code // since this information is also freed in the less granular free_results function that clears everything. + TRACE("FreeParameterInfo"); + Py_XDECREF(cur->pPreparedSQL); PyMem_Free(cur->paramtypes); cur->pPreparedSQL = 0;