Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
878c7bb
mssql_python/cursor.py
subrata-ms Nov 17, 2025
87fd98c
test case addition
subrata-ms Nov 17, 2025
ce3a27d
reverting python changes and fixing it in ddbc
subrata-ms Nov 17, 2025
7c5a0dd
mix data set with NONE
subrata-ms Nov 17, 2025
be42d81
Merge branch 'main' into InsertNoneDataType
subrata-ms Nov 25, 2025
ee21ccf
linting fix
subrata-ms Nov 25, 2025
13a2a19
Merge branch 'main' into InsertNoneDataType
subrata-ms Dec 11, 2025
daf1e96
Merge branch 'main' into InsertNoneDataType
subrata-ms Dec 15, 2025
93721b1
code review comment
subrata-ms Dec 15, 2025
c2acddc
Merge branch 'main' into InsertNoneDataType
subrata-ms Dec 15, 2025
44049cb
added comprehensive test cases for this change
subrata-ms Dec 15, 2025
02de6f6
Merge remote changes: Added atexit cleanup, fixed DBC handle leak, se…
subrata-ms Dec 15, 2025
051be7f
fixing linting issues
subrata-ms Dec 15, 2025
3900973
Merge branch 'main' into InsertNoneDataType
subrata-ms Dec 16, 2025
56cb334
Fixing the test failure in PR test pipeline
subrata-ms Dec 16, 2025
5805f83
Merge branch 'main' into InsertNoneDataType
subrata-ms Dec 16, 2025
bc55fd1
reducing the number of thread count to provide stability on the test
subrata-ms Dec 16, 2025
1c37a67
Merge remote changes
subrata-ms Dec 16, 2025
0533463
linting issue fix
subrata-ms Dec 16, 2025
c2c6be0
fixing unstable test
subrata-ms Dec 16, 2025
db7e90a
skipping the test for intermitent issues
subrata-ms Dec 17, 2025
09f23b1
Merge branch 'main' into InsertNoneDataType
subrata-ms Dec 17, 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
27 changes: 27 additions & 0 deletions mssql_python/pybind/ddbc_bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2335,6 +2335,33 @@ SQLRETURN BindParameterArray(SQLHANDLE hStmt, const py::list& columnwise_params,
bufferLength = sizeof(SQLGUID);
break;
}
case SQL_C_DEFAULT: {
// Handle NULL parameters - all values in this column should be NULL
LOG("BindParameterArray: Binding SQL_C_DEFAULT (NULL) array - param_index=%d, count=%zu", paramIndex, paramSetSize);

// Verify all values are indeed NULL
for (size_t i = 0; i < paramSetSize; ++i) {
if (!columnValues[i].is_none()) {
LOG("BindParameterArray: SQL_C_DEFAULT non-NULL value detected - param_index=%d, row=%zu", paramIndex, i);
ThrowStdException("SQL_C_DEFAULT (99) should only be used for NULL parameters at index " + std::to_string(paramIndex));
}
}

// For NULL parameters, we need to allocate a minimal buffer and set all indicators to SQL_NULL_DATA
// Use SQL_C_CHAR as a safe default C type for NULL values
char* nullBuffer = AllocateParamBufferArray<char>(tempBuffers, paramSetSize);
strLenOrIndArray = AllocateParamBufferArray<SQLLEN>(tempBuffers, paramSetSize);

for (size_t i = 0; i < paramSetSize; ++i) {
nullBuffer[i] = 0;
strLenOrIndArray[i] = SQL_NULL_DATA;
}

dataPtr = nullBuffer;
bufferLength = 1;
LOG("BindParameterArray: SQL_C_DEFAULT bound - param_index=%d, all_null=true", paramIndex);
break;
}
default: {
LOG("BindParameterArray: Unsupported C type - "
"param_index=%d, C_type=%d",
Expand Down
32 changes: 32 additions & 0 deletions tests/test_004_cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -1598,6 +1598,38 @@ def test_executemany_empty_parameter_list(cursor, db_connection):
db_connection.commit()


def test_executemany_NONE_parameter_list(cursor, db_connection):
"""Test executemany with an NONE parameter list."""
try:
cursor.execute("CREATE TABLE #pytest_empty_params (val VARCHAR(50))")
data = [(None,), (None,)]
cursor.executemany("INSERT INTO #pytest_empty_params VALUES (?)", data)
db_connection.commit()

cursor.execute("SELECT COUNT(*) FROM #pytest_empty_params")
count = cursor.fetchone()[0]
assert count == 2
finally:
cursor.execute("DROP TABLE IF EXISTS #pytest_empty_params")
db_connection.commit()


def test_executemany_MIX_NONE_parameter_list(cursor, db_connection):
"""Test executemany with an NONE parameter list."""
try:
cursor.execute("CREATE TABLE #pytest_empty_params (val VARCHAR(50))")
data = [(None,), ("Test",), (None,)]
cursor.executemany("INSERT INTO #pytest_empty_params VALUES (?)", data)
db_connection.commit()

cursor.execute("SELECT COUNT(*) FROM #pytest_empty_params")
count = cursor.fetchone()[0]
assert count == 3
finally:
cursor.execute("DROP TABLE IF EXISTS #pytest_empty_params")
db_connection.commit()


def test_executemany_Decimal_list(cursor, db_connection):
"""Test executemany with an decimal parameter list."""
try:
Expand Down
Loading