Index: driver/results.c =================================================================== --- driver/results.c (revision 1036) +++ driver/results.c (working copy) @@ -43,7 +43,16 @@ stmt->getdata.latest_bytes= stmt->getdata.latest_used= 0; } +void swapBytes(char *dst, char *src, uint srcLen, SQLLEN buffLen ) +{ + memset(dst,0,buffLen); + while (srcLen) + { + *dst++= src[srcLen-1]; + --srcLen; + } +} /** Retrieve the data from a field as a specified ODBC C type. @@ -111,6 +120,28 @@ if (!pcbValue) pcbValue= &tmp; /* Easier code */ + if (field->type == MYSQL_TYPE_BIT) + { + /* 64/8. Is there any constant determining max bit field length? */ + char buff[8]; + + if (fCType != SQL_C_CHAR + && fCType != SQL_C_BINARY + && fCType != SQL_C_WCHAR) + { + swapBytes(buff, value, length, cbValueMax > 8 ? 8 : cbValueMax); + value= buff; + + if (cbValueMax > length) + memset((SQLCHAR *)rgbValue+length,0,cbValueMax-length); + } + else + memset(rgbValue,0, cbValueMax > length ? length + 1 : cbValueMax ); + + return copy_binary_result(stmt, (SQLCHAR *)rgbValue, cbValueMax + , pcbValue, field , value , length); + } + switch (fCType) { case SQL_C_CHAR: /* Handle BLOB -> CHAR conversion */ @@ -193,7 +224,11 @@ case SQL_C_BIT: if (rgbValue) { - if (value[0] == 1 || !atoi(value)) + if (field->type == MYSQL_TYPE_BIT ) + { + *((char *)rgbValue)= value[length-1]; + } + else if (value[0] == 1 || !atoi(value)) *((char *)rgbValue)= 1; else *((char *)rgbValue)= 0; Index: test/my_result.c =================================================================== --- test/my_result.c (revision 1036) +++ test/my_result.c (working copy) @@ -2181,7 +2181,71 @@ return OK; } +/* + Bug#32821(it might be duplicate though): Wrong value if bit field is bound to + other than SQL_C_BIT variable +*/ +DECLARE_TEST(t_bug32821) +{ + SQLRETURN rc; + SQLUINTEGER b; + SQLUSMALLINT c; + SQLINTEGER a_ind, b_ind, c_ind, i; + unsigned char a; + SQLUINTEGER par= sizeof(SQLUSMALLINT)*8+1; + SQLUINTEGER beoyndShortBit= 1<<(par-1); + SQLINTEGER sPar= sizeof(SQLUINTEGER); + + /* 131071 = 0x1ffff - all 1 for field c*/ + const SQLCHAR * insStmt= "insert into t_bug32821 values (0,0,0),(1,1,1)\ + ,(1,255,131071),(1,258,?)"; + const unsigned char expected_a[]= {'\0', '\1', '\1', '\1'}; + const SQLINTEGER expected_b[]= {0L, 1L, 255L, 258L}; + const SQLUSMALLINT expected_c[]= {0, 1, 65535, 0}; + + ok_sql(hstmt, "DROP TABLE IF EXISTS t_bug32821"); + + ok_stmt(hstmt, SQLPrepare(hstmt, "CREATE TABLE t_bug32821 (a BIT(1), b BIT(16)\ + , c BIT(?))", SQL_NTS)); + ok_stmt(hstmt, SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG + , SQL_INTEGER, 0, 0, &par, 0, &sPar )); + ok_stmt(hstmt, SQLExecute(hstmt)); + + ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); + + ok_stmt(hstmt, SQLPrepare(hstmt, insStmt, SQL_NTS)); + ok_stmt(hstmt, SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_ULONG + , SQL_INTEGER, 0, 0, &beoyndShortBit, 0 + , &sPar )); + ok_stmt(hstmt, SQLExecute(hstmt)); + + ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); + + ok_sql(hstmt, "SELECT a,b,c FROM t_bug32821"); + + ok_stmt( hstmt, SQLBindCol( hstmt, 1, SQL_C_BIT, &a, sizeof( a ), &a_ind ) ); + ok_stmt( hstmt, SQLBindCol( hstmt, 2, SQL_C_ULONG, &b, sizeof( b ), &b_ind ) ); + ok_stmt( hstmt, SQLBindCol( hstmt, 3, SQL_C_USHORT, &c, sizeof( c ), &c_ind ) ); + + i= 0; + while( (rc= SQLFetchScroll(hstmt, SQL_FETCH_NEXT, 0)) != SQL_NO_DATA_FOUND) + { + printMessage("testing row #%d", i+1); + is_num(a, expected_a[i]); + is_num(b, expected_b[i]); + is_num(c, expected_c[i]); + ++i; + } + + + ok_stmt(hstmt, SQLFreeStmt(hstmt, SQL_CLOSE)); + + ok_sql(hstmt, "DROP TABLE IF EXISTS t_bug32821"); + return OK; +} + + BEGIN_TESTS ADD_TEST(my_resultset) ADD_TEST(t_convert_type) @@ -2213,6 +2277,7 @@ ADD_TEST(t_bug13776_auto) ADD_TEST(t_bug28617) ADD_TEST(t_bug32684) + ADD_TEST(t_bug32821) END_TESTS