@@ -1967,36 +1967,41 @@ SQLRETURN BindParameterArray(SQLHANDLE hStmt,
19671967 SQLGUID* guidArray = AllocateParamBufferArray<SQLGUID>(tempBuffers, paramSetSize);
19681968 strLenOrIndArray = AllocateParamBufferArray<SQLLEN>(tempBuffers, paramSetSize);
19691969
1970- py::object uuid_type = py::module_::import (" uuid" ). attr ( " UUID " );
1971-
1970+ py::module_ uuid_mod = py::module_::import (" uuid" );
1971+ py::object uuid_class = uuid_mod. attr ( " UUID " );
19721972 for (size_t i = 0 ; i < paramSetSize; ++i) {
1973- if (columnValues[i].is_none ()) {
1973+ const py::handle& element = columnValues[i];
1974+ std::array<unsigned char , 16 > uuid_bytes;
1975+ if (element.is_none ()) {
19741976 std::memset (&guidArray[i], 0 , sizeof (SQLGUID));
19751977 strLenOrIndArray[i] = SQL_NULL_DATA;
1976- } else if ( py::isinstance (columnValues[i], uuid_type)) {
1977- py::bytes uuid_bytes = columnValues[i]. attr ( " bytes " );
1978- const unsigned char * uuid_data = reinterpret_cast < const unsigned char *>( PyBytes_AS_STRING (uuid_bytes. ptr ()));
1979-
1980- if (PyBytes_GET_SIZE (uuid_bytes .ptr ()) != 16 ) {
1978+ continue ;
1979+ }
1980+ else if (py::isinstance<py::bytes>(element)) {
1981+ py::bytes b = element. cast <py::bytes>();
1982+ if (PyBytes_GET_SIZE (b .ptr ()) != 16 ) {
19811983 ThrowStdException (" UUID binary data must be exactly 16 bytes long." );
19821984 }
1983-
1984- guidArray[i].Data1 = (static_cast <uint32_t >(uuid_data[3 ]) << 24 ) |
1985- (static_cast <uint32_t >(uuid_data[2 ]) << 16 ) |
1986- (static_cast <uint32_t >(uuid_data[1 ]) << 8 ) |
1987- (static_cast <uint32_t >(uuid_data[0 ]));
1988- guidArray[i].Data2 = (static_cast <uint16_t >(uuid_data[5 ]) << 8 ) |
1989- (static_cast <uint16_t >(uuid_data[4 ]));
1990- guidArray[i].Data3 = (static_cast <uint16_t >(uuid_data[7 ]) << 8 ) |
1991- (static_cast <uint16_t >(uuid_data[6 ]));
1992- std::memcpy (guidArray[i].Data4 , &uuid_data[8 ], 8 );
1993-
1994- strLenOrIndArray[i] = sizeof (SQLGUID);
1995- } else {
1985+ std::memcpy (uuid_bytes.data (), PyBytes_AS_STRING (b.ptr ()), 16 );
1986+ }
1987+ else if (py::isinstance (element, uuid_class)) {
1988+ py::bytes b = element.attr (" bytes_le" ).cast <py::bytes>();
1989+ std::memcpy (uuid_bytes.data (), PyBytes_AS_STRING (b.ptr ()), 16 );
1990+ }
1991+ else {
19961992 ThrowStdException (MakeParamMismatchErrorStr (info.paramCType , paramIndex));
19971993 }
1994+ guidArray[i].Data1 = (static_cast <uint32_t >(uuid_bytes[3 ]) << 24 ) |
1995+ (static_cast <uint32_t >(uuid_bytes[2 ]) << 16 ) |
1996+ (static_cast <uint32_t >(uuid_bytes[1 ]) << 8 ) |
1997+ (static_cast <uint32_t >(uuid_bytes[0 ]));
1998+ guidArray[i].Data2 = (static_cast <uint16_t >(uuid_bytes[5 ]) << 8 ) |
1999+ (static_cast <uint16_t >(uuid_bytes[4 ]));
2000+ guidArray[i].Data3 = (static_cast <uint16_t >(uuid_bytes[7 ]) << 8 ) |
2001+ (static_cast <uint16_t >(uuid_bytes[6 ]));
2002+ std::memcpy (guidArray[i].Data4 , uuid_bytes.data () + 8 , 8 );
2003+ strLenOrIndArray[i] = sizeof (SQLGUID);
19982004 }
1999-
20002005 dataPtr = guidArray;
20012006 bufferLength = sizeof (SQLGUID);
20022007 break ;
@@ -3133,15 +3138,24 @@ SQLRETURN FetchBatchData(SQLHSTMT hStmt, ColumnBuffers& buffers, py::list& colum
31333138 break ;
31343139 }
31353140 case SQL_GUID: {
3141+ SQLLEN indicator = buffers.indicators [col - 1 ][i];
3142+ if (indicator == SQL_NULL_DATA) {
3143+ row.append (py::none ());
3144+ break ;
3145+ }
31363146 SQLGUID* guidValue = &buffers.guidBuffers [col - 1 ][i];
3137- // We already have the raw bytes from SQL Server in the SQLGUID struct.
3138- // We do not need to perform any additional reordering here, as the C++
3139- // SQLGUID struct is already laid out in the non-standard SQL Server byte order.
3140- std::vector<char > guid_bytes (16 );
3141- std::memcpy (guid_bytes.data (), guidValue, sizeof (SQLGUID));
3142-
3143- // Convert the raw C++ byte vector to a Python bytes object
3144- py::bytes py_guid_bytes (guid_bytes.data (), guid_bytes.size ());
3147+ uint8_t reordered[16 ];
3148+ reordered[0 ] = ((char *)&guidValue->Data1 )[3 ];
3149+ reordered[1 ] = ((char *)&guidValue->Data1 )[2 ];
3150+ reordered[2 ] = ((char *)&guidValue->Data1 )[1 ];
3151+ reordered[3 ] = ((char *)&guidValue->Data1 )[0 ];
3152+ reordered[4 ] = ((char *)&guidValue->Data2 )[1 ];
3153+ reordered[5 ] = ((char *)&guidValue->Data2 )[0 ];
3154+ reordered[6 ] = ((char *)&guidValue->Data3 )[1 ];
3155+ reordered[7 ] = ((char *)&guidValue->Data3 )[0 ];
3156+ std::memcpy (reordered + 8 , guidValue->Data4 , 8 );
3157+
3158+ py::bytes py_guid_bytes (reinterpret_cast <char *>(reordered), 16 );
31453159 py::dict kwargs;
31463160 kwargs[" bytes" ] = py_guid_bytes;
31473161 py::object uuid_obj = py::module_::import (" uuid" ).attr (" UUID" )(**kwargs);
0 commit comments