2929#define SQL_SS_XML (-152 )
3030#define SQL_SS_UDT (-151 )
3131#define SQL_SS_VARIANT (-150 )
32- #define SQL_CA_SS_BASE 1200
33- #define SQL_CA_SS_VARIANT_TYPE (SQL_CA_SS_BASE + 15 )
34- #define SQL_CA_SS_VARIANT_SQL_TYPE (SQL_CA_SS_BASE + 16 )
35- #define SQL_CA_SS_VARIANT_SERVER_TYPE (SQL_CA_SS_BASE + 17 )
32+ #define SQL_CA_SS_VARIANT_TYPE (1215 )
3633
3734#define STRINGIFY_FOR_CASE (x ) \
3835 case x: \
@@ -2934,16 +2931,15 @@ SQLSMALLINT MapVariantCTypeToSQLType(SQLLEN variantCType) {
29342931 return SQL_VARCHAR;
29352932 case SQL_C_WCHAR:
29362933 return SQL_WVARCHAR;
2937- // Date/time types - handle both old-style (9, 10, 11) and new-style (91, 92, 93) codes
2938- case 9 : // SQL_C_DATE (old style)
2939- case SQL_C_TYPE_DATE: // 91 (new style)
2934+ case 9 :
2935+ case SQL_C_TYPE_DATE:
29402936 return SQL_TYPE_DATE;
2941- case 10 : // SQL_C_TIME (old style)
2942- case SQL_C_TYPE_TIME: // 92 (new style)
2943- case 16384 : // SQL Server variant TIME type (observed value)
2937+ case 10 :
2938+ case SQL_C_TYPE_TIME:
2939+ case 16384 :
29442940 return SQL_TYPE_TIME;
2945- case 11 : // SQL_C_TIMESTAMP (old style)
2946- case SQL_C_TYPE_TIMESTAMP: // 93 (new style)
2941+ case 11 :
2942+ case SQL_C_TYPE_TIMESTAMP:
29472943 return SQL_TYPE_TIMESTAMP;
29482944 case SQL_C_BINARY:
29492945 return SQL_VARBINARY;
@@ -2956,7 +2952,6 @@ SQLSMALLINT MapVariantCTypeToSQLType(SQLLEN variantCType) {
29562952 case SQL_C_STINYINT:
29572953 return SQL_TINYINT;
29582954 default :
2959- // Unknown type, fallback to WVARCHAR for string conversion
29602955 return SQL_WVARCHAR;
29612956 }
29622957}
@@ -2999,37 +2994,24 @@ SQLRETURN SQLGetData_wrap(SqlHandlePtr StatementHandle, SQLUSMALLINT colCount, p
29992994 continue ;
30002995 }
30012996
3002- printf (" [DEBUG] SQLGetData_wrap: Column %d - dataType=%d, columnSize=%lu\n " , i, dataType,
3003- (unsigned long )columnSize);
3004-
30052997 // Preprocess sql_variant: detect underlying type and handle NULL
3006- // This allows reuse of existing fetch logic instead of duplicating code
30072998 SQLSMALLINT effectiveDataType = dataType;
30082999 if (dataType == SQL_SS_VARIANT) {
3009- // Step 1: Check for NULL using header read
30103000 SQLLEN indicator;
30113001 ret = SQLGetData_ptr (hStmt, i, SQL_C_BINARY, NULL , 0 , &indicator);
30123002 if (indicator == SQL_NULL_DATA) {
30133003 row.append (py::none ());
3014- continue ; // Skip to next column
3004+ continue ;
30153005 }
3016-
3017- // Step 2: Get the variant's underlying C data type
30183006 SQLLEN variantCType = 0 ;
30193007 ret =
30203008 SQLColAttribute_ptr (hStmt, i, SQL_CA_SS_VARIANT_TYPE, NULL , 0 , NULL , &variantCType);
30213009 if (!SQL_SUCCEEDED (ret)) {
30223010 LOG (" SQLGetData: Failed to get sql_variant underlying type for column %d" , i);
30233011 row.append (py::none ());
3024- continue ; // Skip to next column
3012+ continue ;
30253013 }
3026-
3027- printf (" [DEBUG] SQLGetData_wrap: sql_variant column %d has variantCType=%ld\n " , i,
3028- (long )variantCType);
3029-
3030- // Step 3: Map C type to SQL type so existing code can handle it
30313014 effectiveDataType = MapVariantCTypeToSQLType (variantCType);
3032- printf (" [DEBUG] SQLGetData_wrap: Mapped to effectiveDataType=%d\n " , effectiveDataType);
30333015 }
30343016
30353017 switch (effectiveDataType) {
@@ -4198,19 +4180,11 @@ SQLRETURN FetchMany_wrap(SqlHandlePtr StatementHandle, py::list& rows, int fetch
41984180 SQLSMALLINT dataType = colMeta[" DataType" ].cast <SQLSMALLINT>();
41994181 SQLULEN columnSize = colMeta[" ColumnSize" ].cast <SQLULEN>();
42004182
4201- printf (" [DEBUG] FetchMany_wrap: Column %d - dataType=%d, columnSize=%lu\n " , i + 1 , dataType,
4202- (unsigned long )columnSize);
4203-
4204- // Detect LOB columns that need SQLGetData streaming
4205- // sql_variant always uses SQLGetData for native type preservation
4206- if (dataType == SQL_SS_VARIANT) {
4207- lobColumns.push_back (i + 1 ); // 1-based
4208- } else if ((dataType == SQL_WVARCHAR || dataType == SQL_WLONGVARCHAR ||
4209- dataType == SQL_VARCHAR || dataType == SQL_LONGVARCHAR ||
4210- dataType == SQL_VARBINARY || dataType == SQL_LONGVARBINARY ||
4211- dataType == SQL_SS_XML || dataType == SQL_SS_UDT) &&
4212- (columnSize == 0 || columnSize == SQL_NO_TOTAL ||
4213- columnSize > SQL_MAX_LOB_SIZE)) {
4183+ if (dataType == SQL_SS_VARIANT ||
4184+ ((dataType == SQL_WVARCHAR || dataType == SQL_WLONGVARCHAR || dataType == SQL_VARCHAR ||
4185+ dataType == SQL_LONGVARCHAR || dataType == SQL_VARBINARY ||
4186+ dataType == SQL_LONGVARBINARY || dataType == SQL_SS_XML || dataType == SQL_SS_UDT) &&
4187+ (columnSize == 0 || columnSize == SQL_NO_TOTAL || columnSize > SQL_MAX_LOB_SIZE))) {
42144188 lobColumns.push_back (i + 1 ); // 1-based
42154189 }
42164190 }
@@ -4300,8 +4274,6 @@ SQLRETURN FetchAll_wrap(SqlHandlePtr StatementHandle, py::list& rows,
43004274 return ret;
43014275 }
43024276
4303- // Detect LOB columns FIRST (before calculateRowSize)
4304- // This allows sql_variant to skip the binding path entirely
43054277 std::vector<SQLUSMALLINT> lobColumns;
43064278 for (SQLSMALLINT i = 0 ; i < numCols; i++) {
43074279 auto colMeta = columnNames[i].cast <py::dict>();
@@ -4313,14 +4285,11 @@ SQLRETURN FetchAll_wrap(SqlHandlePtr StatementHandle, py::list& rows,
43134285
43144286 // Detect LOB columns that need SQLGetData streaming
43154287 // sql_variant always uses SQLGetData for native type preservation
4316- if (dataType == SQL_SS_VARIANT) {
4317- lobColumns.push_back (i + 1 ); // 1-based
4318- } else if ((dataType == SQL_WVARCHAR || dataType == SQL_WLONGVARCHAR ||
4319- dataType == SQL_VARCHAR || dataType == SQL_LONGVARCHAR ||
4320- dataType == SQL_VARBINARY || dataType == SQL_LONGVARBINARY ||
4321- dataType == SQL_SS_XML) &&
4322- (columnSize == 0 || columnSize == SQL_NO_TOTAL ||
4323- columnSize > SQL_MAX_LOB_SIZE)) {
4288+ if (dataType == SQL_SS_VARIANT ||
4289+ ((dataType == SQL_WVARCHAR || dataType == SQL_WLONGVARCHAR || dataType == SQL_VARCHAR ||
4290+ dataType == SQL_LONGVARCHAR || dataType == SQL_VARBINARY ||
4291+ dataType == SQL_LONGVARBINARY || dataType == SQL_SS_XML) &&
4292+ (columnSize == 0 || columnSize == SQL_NO_TOTAL || columnSize > SQL_MAX_LOB_SIZE))) {
43244293 lobColumns.push_back (i + 1 ); // 1-based
43254294 }
43264295 }
0 commit comments