| Bug #32821 | Gives wrong value fetching from a bit column | ||
|---|---|---|---|
| Submitted: | 28 Nov 2007 17:32 | Modified: | 16 Jan 21:24 |
| Reporter: | John Water | ||
| Status: | In progress | ||
| Category: | Connector/ODBC | Severity: | S2 (Serious) |
| Version: | 3.51.21.00 and 5.01.00.00 | OS: | Microsoft Windows (XP) |
| Assigned to: | Lawrin Novitsky | Target Version: | |
| Tags: | ODBC driver, bit column | ||
| Triage: | D3 (Medium) | ||
[19 Feb 2008 21:56]
Lawrin Novitsky
Patch v.1.0
Attachment: bug32821.patch (application/octet-stream, text), 4.27 KiB.
[20 Feb 2008 16:28]
Lawrin Novitsky
Forgot to remove couple of lines in previous variant of the patch
Attachment: bug32821_2.patch (application/octet-stream, text), 3.92 KiB.
[30 Mar 2008 23:00]
Lawrin Novitsky
reworked patch. now i like it better. thought would post it along w/ 30349, but it takes longer.
Attachment: bug32821v2.patch (application/octet-stream, text), 9.21 KiB.
[20 Oct 2008 19:54]
Jess Balint
What is the purpose of using binary2numeric() and then (numericValue & (SQLSCHAR)(-1))? We shouldn't have SQL_C_BIT in isNumericCType(). Also, we can remove this: if (value[0] == 1 || anyNonZeroByte(value, length)) It will be fixed in Bug#39644 (however we decide to do it).
[21 Oct 2008 23:05]
Lawrin Novitsky
> What is the purpose of using binary2numeric() and then (numericValue & > (SQLSCHAR)(-1))? hmm, it's been so long time ago :) I think it's to avoid casting warnings, zero-ing all bits what we don't need for every particular c-type. > We shouldn't have SQL_C_BIT in isNumericCType(). well, i've just checked - in my local version it's alredy been commented out > Also, we can remove this: if (value[0] == 1 || anyNonZeroByte(value, length)) doesn't it fix that bug you refer to? because doing this I was aware of it too.

Description: The MyODBC driver, v3.51.21.00 and v5.01.00.00 will give a value of zero for non-zero values in a column with a datatype of bit, if SQL_C_USHORT is used in SQLBindCol. Here is the sample source code (the full source code, executable for Windows, and an ODBC tracing file will be attached in a zip file: ------------------------------------------------------------------------ .... char * create_table = "create table test (pk int primary key, c1 bit)"; char * insert_stmt1 = "insert into test values( 1, 0 )"; char * insert_stmt2 = "insert into test values( 2, 1 )"; char * select_table = "select pk, c1 from test"; .... ret = SQLPrepare( stmt, (SQLCHAR *)select_table, SQL_NTS ); ret = SQLExecute( stmt ); ret = SQLBindCol( stmt, 1, SQL_C_SLONG, &pk, sizeof( pk ), &pk_ind ); ret = SQLBindCol( stmt, 2, SQL_C_USHORT, &c1, sizeof( c1 ), &c1_ind ); while( TRUE ) { ret = SQLFetchScroll( stmt, SQL_FETCH_NEXT, 0 ); if( SQL_SUCCEEDED( ret ) ) { printf( "SQLFetch: ret = %d: pk = %d, c1 = %d, pk_ind %ld, c1_ind = %ld\n", ret, pk, c1, pk_ind, c1_ind ); .... ---------------------------------------------------------------------------- The results will be SQLFetch: ret = 0: pk = 1, c1 = 0, pk_ind 4, c1_ind = 2 SQLFetch: ret = 0: pk = 2, c1 = 0, pk_ind 4, c1_ind = 2 This is wrong: c1 should be 1 in the second row. By the way, it works well if you run the repro against Microsoft SQL Server and Sybase ASE. How to repeat: The steps to repro: 1) unzip the attached file; 2) run odbcbug "dsn=your_dsn;uid=your_uid;pwd=your_pwd" then you'll see something like SQLFetch: ret = 0: pk = 1, c1 = 0, pk_ind 4, c1_ind = 2 SQLFetch: ret = 0: pk = 2, c1 = 0, pk_ind 4, c1_ind = 2 Fetch completed! on your command window.