-
Notifications
You must be signed in to change notification settings - Fork 27
FEAT: datetimeoffset support in executemany() #260
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds comprehensive support for the SQL Server DATETIMEOFFSET type in both Python and C++ layers, enabling timezone-aware datetime handling in executemany() operations and regular queries. It introduces new SQL constants, enhances datetime parsing logic to handle timezone information, and implements proper parameter binding and data fetching for DATETIMEOFFSET values.
- Adds
SQL_DATETIMEOFFSETandSQL_C_SS_TIMESTAMPOFFSETconstants to support the new SQL type - Implements timezone-aware datetime parsing and type mapping logic
- Removes unused helper method and refactors
executemanytype inference logic
Reviewed Changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| mssql_python/constants.py | Adds SQL constants for DATETIMEOFFSET support |
| mssql_python/cursor.py | Enhances datetime parsing and type mapping, removes unused method |
| mssql_python/pybind/ddbc_bindings.cpp | Implements C++ DateTimeOffset struct, parameter binding, and data fetching |
| tests/test_004_cursor.py | Adds comprehensive tests for DATETIMEOFFSET functionality |
| tests/test_003_connection.py | Removes unused import statements |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
sumitmsft
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few comments
e1253f2 to
5f45001
Compare
978fe43 to
41c1592
Compare
41c1592 to
93df1a2
Compare
📊 Code Coverage Report
Diff CoverageDiff: main...HEAD, staged and unstaged changes
Summary
mssql_python/pybind/ddbc_bindings.cppLines 1946-1965 1946 for (size_t i = 0; i < paramSetSize; ++i) {
1947 const py::handle& param = columnValues[i];
1948
1949 if (param.is_none()) {
! 1950 std::memset(&dtoArray[i], 0, sizeof(DateTimeOffset));
! 1951 strLenOrIndArray[i] = SQL_NULL_DATA;
1952 } else {
1953 if (!py::isinstance(param, datetimeType)) {
! 1954 ThrowStdException(MakeParamMismatchErrorStr(info.paramCType, paramIndex));
! 1955 }
1956
1957 py::object tzinfo = param.attr("tzinfo");
1958 if (tzinfo.is_none()) {
! 1959 ThrowStdException("Datetime object must have tzinfo for SQL_C_SS_TIMESTAMPOFFSET at paramIndex " +
! 1960 std::to_string(paramIndex));
! 1961 }
1962
1963 // Populate the C++ struct directly from the Python datetime object.
1964 dtoArray[i].year = static_cast<SQLSMALLINT>(param.attr("year").cast<int>());
1965 dtoArray[i].month = static_cast<SQLUSMALLINT>(param.attr("month").cast<int>());Lines 1982-1990 1982 }
1983 dataPtr = dtoArray;
1984 bufferLength = sizeof(DateTimeOffset);
1985 break;
! 1986 }
1987 case SQL_C_NUMERIC: {
1988 SQL_NUMERIC_STRUCT* numericArray = AllocateParamBufferArray<SQL_NUMERIC_STRUCT>(tempBuffers, paramSetSize);
1989 strLenOrIndArray = AllocateParamBufferArray<SQLLEN>(tempBuffers, paramSetSize);
1990 for (size_t i = 0; i < paramSetSize; ++i) {Lines 3223-3234 3223 );
3224 py_dt = py_dt.attr("astimezone")(datetime.attr("timezone").attr("utc"));
3225 row.append(py_dt);
3226 } else {
! 3227 row.append(py::none());
! 3228 }
3229 break;
! 3230 }
3231 case SQL_GUID: {
3232 SQLGUID* guidValue = &buffers.guidBuffers[col - 1][i];
3233 uint8_t reordered[16];
3234 reordered[0] = ((char*)&guidValue->Data1)[3];📋 Files Needing Attention📉 Files with overall lowest coverage (click to expand)mssql_python.pybind.ddbc_bindings.cpp: 67.4%
mssql_python.pybind.connection.connection.cpp: 68.3%
mssql_python.ddbc_bindings.py: 68.5%
mssql_python.pybind.connection.connection_pool.cpp: 78.9%
mssql_python.cursor.py: 79.1%
mssql_python.connection.py: 81.7%
mssql_python.helpers.py: 84.7%
mssql_python.auth.py: 85.3%
mssql_python.type.py: 86.8%
mssql_python.pooling.py: 88.8%🔗 Quick Links
|
Work Item / Issue Reference
Summary
This pull request adds comprehensive support for the SQL Server
DATETIMEOFFSETtype in both the Python and C++ layers of the codebase. It introduces new constants, enhances the datetime parsing logic to handle timezone-aware datetimes, and updates the parameter binding and data fetching logic to correctly handleDATETIMEOFFSETvalues. The changes ensure accurate round-trip of timezone-aware datetime values between Python and SQL Server.Support for DATETIMEOFFSET type:
SQL_DATETIMEOFFSETandSQL_C_SS_TIMESTAMPOFFSETconstants to bothmssql_python/constants.pyand the C++ bindings (ddbc_bindings.cpp). [1] [2]DateTimeOffsetC++ struct and integrated it into buffer management for column data. [1] [2] [3]datetimeobjects asDATETIMEOFFSET, including array binding forexecutemany. [1] [2] [3]DATETIMEOFFSETcolumns, ensuring Python receives timezone-awaredatetimeobjects in UTC. [1] [2] [3]Datetime parsing and mapping improvements:
_parse_datetimeinmssql_python/cursor.pyto support parsing timezone-aware datetime strings, improving compatibility withDATETIMEOFFSET.datetimeobjects, mapping the latter toDATETIMEOFFSET.Refactoring and cleanup:
_select_best_sample_valuestatic method frommssql_python/cursor.pyas type inference is now handled differently.executemanyto use the new_compute_column_typemethod, aligning with the improved datetime handling.