Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e3c9c4f
Final Linting for all cpp and python files with Workflow
jahnvi480 Nov 17, 2025
c2e32cb
Pushing changes in confest
jahnvi480 Nov 17, 2025
9847708
Final
jahnvi480 Nov 17, 2025
83b011e
Add VS Code extension recommendations for development setup
jahnvi480 Nov 18, 2025
ade9a05
Merge branch 'main' of https://github.com/microsoft/mssql-python into…
jahnvi480 Nov 19, 2025
10744c8
FIX: Encoding Decoding
jahnvi480 Nov 24, 2025
27310da
Python linting issue
jahnvi480 Nov 24, 2025
b1bbd7d
Resolving conflicts
jahnvi480 Nov 25, 2025
353f9a9
FIX: Timeout during cursor creation and not execute
jahnvi480 Nov 25, 2025
8dfc892
setting integer values
jahnvi480 Nov 25, 2025
b8c1dc3
Resolving confusion
jahnvi480 Nov 28, 2025
6583708
Resolving comments
jahnvi480 Nov 28, 2025
4ad47ca
Resolving comments
jahnvi480 Nov 28, 2025
79706c7
Merge branch 'main' into jahnvi/250_encoding_decoding
jahnvi480 Nov 28, 2025
f5079bb
Merge branch 'main' of https://github.com/microsoft/mssql-python into…
jahnvi480 Nov 28, 2025
c2ea17e
Merge branch 'jahnvi/250_encoding_decoding' of https://github.com/mic…
jahnvi480 Nov 28, 2025
b85445d
Adding more test cases
jahnvi480 Nov 28, 2025
d2104d1
Resolving conflicts'
jahnvi480 Dec 10, 2025
c907b03
Removing conflicts
jahnvi480 Dec 10, 2025
a70bf38
Removing conflicts
jahnvi480 Dec 10, 2025
3818ede
Removing conflicts
jahnvi480 Dec 10, 2025
8981b01
Resolving issue
jahnvi480 Dec 10, 2025
9c1c5ef
Merge branch 'main' into jahnvi/timeout_291
jahnvi480 Dec 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions mssql_python/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ class ConstantsDDBC(Enum):
# Reset Connection Constants
SQL_RESET_CONNECTION_YES = 1

# Query Timeout Constants
SQL_ATTR_QUERY_TIMEOUT = 0


class GetInfoConstants(Enum):
"""
Expand Down
35 changes: 21 additions & 14 deletions mssql_python/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -681,13 +681,34 @@ def _initialize_cursor(self) -> None:
Initialize the DDBC statement handle.
"""
self._allocate_statement_handle()
self._set_timeout()

def _allocate_statement_handle(self) -> None:
"""
Allocate the DDBC statement handle.
"""
self.hstmt = self._connection._conn.alloc_statement_handle()

def _set_timeout(self) -> None:
"""
Set the query timeout attribute on the statement handle.
This is called once when the cursor is created and after any handle reallocation.
Following pyodbc's approach for better performance.
"""
if self._timeout > 0:
logger.debug("_set_timeout: Setting query timeout=%d seconds", self._timeout)
try:
timeout_value = int(self._timeout)
ret = ddbc_bindings.DDBCSQLSetStmtAttr(
self.hstmt,
ddbc_sql_const.SQL_ATTR_QUERY_TIMEOUT.value,
timeout_value,
)
check_error(ddbc_sql_const.SQL_HANDLE_STMT.value, self.hstmt, ret)
logger.debug("Query timeout set to %d seconds", timeout_value)
except Exception as e: # pylint: disable=broad-exception-caught
logger.warning("Failed to set query timeout: %s", str(e))

def _reset_cursor(self) -> None:
"""
Reset the DDBC statement handle.
Expand Down Expand Up @@ -1216,20 +1237,6 @@ def execute( # pylint: disable=too-many-locals,too-many-branches,too-many-state
encoding_settings = self._get_encoding_settings()

# Apply timeout if set (non-zero)
if self._timeout > 0:
logger.debug("execute: Setting query timeout=%d seconds", self._timeout)
try:
timeout_value = int(self._timeout)
ret = ddbc_bindings.DDBCSQLSetStmtAttr(
self.hstmt,
ddbc_sql_const.SQL_ATTR_QUERY_TIMEOUT.value,
timeout_value,
)
check_error(ddbc_sql_const.SQL_HANDLE_STMT.value, self.hstmt, ret)
logger.debug("Set query timeout to %d seconds", timeout_value)
except Exception as e: # pylint: disable=broad-exception-caught
logger.warning("Failed to set query timeout: %s", str(e))

logger.debug("execute: Creating parameter type list")
param_info = ddbc_bindings.ParamInfo
parameters_type = []
Expand Down
15 changes: 11 additions & 4 deletions mssql_python/pybind/ddbc_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2837,7 +2837,6 @@ py::object FetchLobColumnData(SQLHSTMT hStmt, SQLUSMALLINT colIndex, SQLSMALLINT
}

// For SQL_C_CHAR data, decode using the specified encoding
// Create py::bytes once to avoid double allocation
py::bytes raw_bytes(buffer.data(), buffer.size());
try {
py::object decoded = raw_bytes.attr("decode")(charEncoding, "strict");
Expand Down Expand Up @@ -2916,7 +2915,6 @@ SQLRETURN SQLGetData_wrap(SqlHandlePtr StatementHandle, SQLUSMALLINT colCount, p
if (numCharsInData < dataBuffer.size()) {
// SQLGetData will null-terminate the data
// Use Python's codec system to decode bytes with specified encoding
// Create py::bytes once to avoid double allocation
py::bytes raw_bytes(reinterpret_cast<char*>(dataBuffer.data()),
static_cast<size_t>(dataLen));
try {
Expand Down Expand Up @@ -4395,8 +4393,17 @@ PYBIND11_MODULE(ddbc_bindings, m) {
"Set the decimal separator character");
m.def(
"DDBCSQLSetStmtAttr",
[](SqlHandlePtr stmt, SQLINTEGER attr, SQLPOINTER value) {
return SQLSetStmtAttr_ptr(stmt->get(), attr, value, 0);
[](SqlHandlePtr stmt, SQLINTEGER attr, py::object value) {
SQLPOINTER ptr_value;
if (py::isinstance<py::int_>(value)) {
// For integer attributes like SQL_ATTR_QUERY_TIMEOUT
ptr_value =
reinterpret_cast<SQLPOINTER>(static_cast<SQLULEN>(value.cast<int64_t>()));
} else {
// For pointer attributes
ptr_value = value.cast<SQLPOINTER>();
}
return SQLSetStmtAttr_ptr(stmt->get(), attr, ptr_value, 0);
},
"Set statement attributes");
m.def("DDBCSQLGetTypeInfo", &SQLGetTypeInfo_Wrapper,
Expand Down
Loading
Loading