Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
dcb60f2
Add C++ DetectParamTypes + SQLExecuteFast pipeline
bewithgaurav Apr 29, 2026
14ccf08
Fix DAE handling, MONEY range, and TypeError for unknown types
bewithgaurav Apr 29, 2026
8ab074c
Fix MSVC warnings-as-errors: unused param and catch variable
bewithgaurav Apr 30, 2026
00c85cc
Guard memcpy with null/length check for DevSkim DS121708
bewithgaurav Apr 30, 2026
1c1111e
Merge branch 'main' into bewithgaurav/insertmany-perf-detect-types
jahnvi480 May 6, 2026
bad8acf
STYLE: Fix black formatting in cursor.py
bewithgaurav May 7, 2026
c5a827f
Address PR review: encoding key, subclass support, GIL, exec_rc, curs…
bewithgaurav May 7, 2026
a38ce4e
Address second PR review: refcount leak, geometry+DAE, NaN, parity test
bewithgaurav May 7, 2026
a0e031b
Merge branch 'main' into bewithgaurav/insertmany-perf-detect-types
bewithgaurav Jun 24, 2026
fbd1a07
Merge branch 'main' into bewithgaurav/insertmany-perf-detect-types
bewithgaurav Jul 6, 2026
ba65f46
FIX: Address rubber-duck review findings in fast path
bewithgaurav Jul 1, 2026
bd205cc
Merge remote-tracking branch 'origin/main' into bewithgaurav/insertma…
bewithgaurav Jul 14, 2026
dc1460b
STYLE: Fix black formatting in test_023_fast_path_parity
bewithgaurav Jul 14, 2026
5cf016e
PERF: Convert DetectParamTypes to raw CPython API
bewithgaurav Jul 14, 2026
8e8d622
FIX: Use memcpy_s on MSVC for CodeQL DS121708 compliance
bewithgaurav Jul 14, 2026
cbd2f00
REFACTOR: Rename DDBCSQLExecuteFast → DDBCSQLExecute, old → DDBCSQLEx…
bewithgaurav Jul 14, 2026
fa0e866
REFACTOR: Convert PythonObjectCache + ParamInfo::dataPtr to raw CPython
bewithgaurav Jul 14, 2026
3d73824
FIX: Add ParamInfo copy constructor for pybind11 legacy path compatib…
bewithgaurav Jul 14, 2026
98eb254
FIX: Use explicit byte length for string binding instead of SQL_NTS
bewithgaurav Jul 14, 2026
4ee2db9
TEST: Add edge-case tests and LCOV exclusions for untestable paths
bewithgaurav Jul 14, 2026
8941070
FIX: Address review comments — PyList_SetItem checks and bytearray DA…
bewithgaurav Jul 14, 2026
432b522
FIX: Harden Decimal subclass safety, RAII param cleanup, cache init leak
bewithgaurav Jul 14, 2026
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
80 changes: 47 additions & 33 deletions mssql_python/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1487,11 +1487,6 @@ def execute( # pylint: disable=too-many-locals,too-many-branches,too-many-state
# Getting encoding setting
encoding_settings = self._get_encoding_settings()

# Apply timeout if set (non-zero)
logger.debug("execute: Creating parameter type list")
param_info = ddbc_bindings.ParamInfo
parameters_type = []

# Validate that inputsizes matches parameter count if both are present
if parameters and self._inputsizes:
if len(self._inputsizes) != len(parameters):
Expand All @@ -1503,11 +1498,6 @@ def execute( # pylint: disable=too-many-locals,too-many-branches,too-many-state
Warning,
)

if parameters:
for i, param in enumerate(parameters):
paraminfo = self._create_parameter_types_list(param, param_info, parameters, i)
parameters_type.append(paraminfo)

# Prepare caching: skip SQLPrepare when re-executing the same SQL
# with parameters. The HSTMT is reused via _soft_reset_cursor, so the
# server-side plan from the previous SQLPrepare is still valid.
Expand All @@ -1516,30 +1506,54 @@ def execute( # pylint: disable=too-many-locals,too-many-branches,too-many-state
self.is_stmt_prepared = [False]
effective_use_prepare = use_prepare and not same_sql

if logger.isEnabledFor(logging.DEBUG):
for i, param in enumerate(parameters):
logger.debug(
"""Parameter number: %s, Parameter: %s,
Param Python Type: %s, ParamInfo: %s, %s, %s, %s, %s""",
i + 1,
param,
str(type(param)),
parameters_type[i].paramSQLType,
parameters_type[i].paramCType,
parameters_type[i].columnSize,
parameters_type[i].decimalDigits,
parameters_type[i].inputOutputType,
)

ret = ddbc_bindings.DDBCSQLExecute(
self.hstmt,
operation,
parameters,
parameters_type,
self.is_stmt_prepared,
effective_use_prepare,
encoding_settings,
# Primary path: when no inputsizes override, do type detection + bind + execute
# entirely in C++. ParamInfo never crosses the pybind11 boundary.
use_fast_path = parameters and not (
self._inputsizes and any(s is not None for s in self._inputsizes)
)

if use_fast_path:
ret = ddbc_bindings.DDBCSQLExecute(
self.hstmt,
operation,
parameters,
self.is_stmt_prepared,
effective_use_prepare,
encoding_settings,
)
else:
# Legacy path: Python-side type detection (used when setinputsizes overrides are present)
parameters_type = []
if parameters:
param_info = ddbc_bindings.ParamInfo
for i, param in enumerate(parameters):
paraminfo = self._create_parameter_types_list(param, param_info, parameters, i)
parameters_type.append(paraminfo)

if logger.isEnabledFor(logging.DEBUG):
for i, param in enumerate(parameters):
logger.debug(
"""Parameter number: %s, Parameter: %s,
Param Python Type: %s, ParamInfo: %s, %s, %s, %s, %s""",
i + 1,
param,
str(type(param)),
parameters_type[i].paramSQLType,
parameters_type[i].paramCType,
parameters_type[i].columnSize,
parameters_type[i].decimalDigits,
parameters_type[i].inputOutputType,
)

ret = ddbc_bindings.DDBCSQLExecuteLegacy(
self.hstmt,
operation,
parameters,
parameters_type,
self.is_stmt_prepared,
effective_use_prepare,
encoding_settings,
)
# Check return code
try:

Expand Down
Loading
Loading