Bug #22446 MyODBC inserts wrong parameter values for prepared statements (64-bit Linux)

Submitted: 18 Sep 2006 16:00 Modified: 6 Dec 2006 9:40
Reporter: Bogdan Degtyariov Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / ODBC Severity:S1 (Critical)
Version:3.51.13 OS:
Assigned to: Bogdan Degtyariov CPU Architecture:Any
Tags: SQLPrepare

[18 Sep 2006 16:00] Bogdan Degtyariov
Description:
When running MyODBC 3.51.13 on RHEL4 64-bit prepared statements work incorrectly whereas 32-bit Linux doesn't have such problems:
Fragment from MySQL Qurey Log:
--------------------------------------------------------------------
1 Query       DROP TABLE TESTPREPARED
1 Query       CREATE TABLE TESTPREPARED ( COL1 INTEGER )
1 Query       INSERT INTO TESTPREPARED VALUES (22)
1 Query       SELECT COL1 FROM TESTPREPARED WHERE COL1 = 8589934614
--------------------------------------------------------------------
COL1 = 8589934614 should be 22 instead of 8589934614

How to repeat:
#include <iostream>

#include <sql.h>
#include <sqlext.h>
#include <stdio.h>

#ifndef TRUE
#define TRUE 1
#endif

#define MAXCOLS 100
#define MAX_DATA_LEN 255

SQLHENV  henv;
SQLHDBC  hdbc;
SQLHSTMT hstmt;

SQLINTEGER PrintError(SQLSMALLINT handleType, SQLHANDLE handle, SQLRETURN rcode)
{

    SQLRETURN rc = SQL_ERROR;
    SQLCHAR sqlState[6];
    SQLCHAR eMsg[SQL_MAX_MESSAGE_LENGTH];
    SQLINTEGER nError;
    SQLSMALLINT msgLen;
    
    if (rcode == SQL_NO_DATA)
    {
        std::cout << "NO DATA .. .. .." << std::endl;
        return(SQL_NO_DATA);
    }
    else
    {
        rc = SQLGetDiagRec(handleType, handle, 1, sqlState, &nError, eMsg, sizeof(eMsg), &msgLen);
        if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO)
        {
            std::cout << " Error: " << eMsg << std::endl;
        }
        return (SQL_ERROR);
    }
}

int main(int argc, char * argv[])
{

    SQLRETURN rc;

    if (argc != 4) 
    {
        std::cout << "USAGE: DBClassTet <DSN name> <username> <password>" << std::endl;
        return -1;
    }

    rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_ENV, henv, rc));

    rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_NTS);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_ENV, henv, rc));

#ifdef UNIXODBC_USE
    char version[100];
    rc = SQLGetEnvAttr(henv, SQL_ATTR_UNIXODBC_VERSION, (SQLPOINTER)version, sizeof(version), 0);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_ENV, henv, rc));
        
    std::cout << "Version of unixODBC " << version << std::endl;
#endif
    rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_ENV, henv, rc));
        
    std::cout << "Connecting to " << argv[1] << std::endl;

    rc = SQLConnect(hdbc, (SQLCHAR *)argv[1], SQL_NTS, 
                  (SQLCHAR *)argv[2], SQL_NTS, 
                  (SQLCHAR *)argv[3], SQL_NTS);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_DBC, hdbc, rc));
        
    rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_DBC, hdbc, rc));
        
    /*************************************************************************************/
    
    rc = SQLExecDirect(hstmt, (SQLCHAR *)"DROP TABLE TESTPREPARED", SQL_NTS);

    rc = SQLExecDirect(hstmt, (SQLCHAR *)"CREATE TABLE TESTPREPARED ( COL1 INTEGER )", SQL_NTS);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_STMT, hstmt, rc));

    rc = SQLExecDirect(hstmt, (SQLCHAR *)"INSERT INTO TESTPREPARED VALUES (22)", SQL_NTS);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_STMT, hstmt, rc));

    rc = SQLPrepare(hstmt, (SQLCHAR *)"SELECT COL1 FROM TESTPREPARED WHERE COL1 = ?", SQL_NTS);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_STMT, hstmt, rc));

    SQLSMALLINT type;
    SQLUINTEGER precision;
    SQLSMALLINT scale;
    SQLSMALLINT nullable;

    rc = SQLDescribeParam(hstmt, 1, &type, &precision, &scale, &nullable);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_STMT, hstmt, rc));

    if (type != SQL_INTEGER)
    {
        std::cout << "Unexpected type -> " << type << std::endl;
    }

    SQLINTEGER paramValue = 22;

    rc = SQLBindParameter(hstmt,1,SQL_PARAM_INPUT, SQL_C_ULONG,SQL_INTEGER,0,0, (SQLPOINTER)&paramValue, sizeof(SQLINTEGER), 0);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_STMT, hstmt, rc));

    rc = SQLFreeStmt(hstmt,SQL_UNBIND) ;
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_STMT, hstmt, rc));
        
    rc = SQLFreeStmt(hstmt,SQL_CLOSE) ;
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_STMT, hstmt, rc));

    rc = SQLExecute(hstmt);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_STMT, hstmt, rc));

    SQLINTEGER data;
    SQLINTEGER status;

    rc = SQLBindCol(hstmt, 1, SQL_C_ULONG, &data, sizeof(data), &status);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_STMT, hstmt, rc));

    rc = SQLFetch(hstmt);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        PrintError(SQL_HANDLE_STMT, hstmt, rc);
    
    std::cout << "rc=" << rc << " data=" << data << std::endl;

    /*************************************************************************************/
    
    rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
            return(PrintError(SQL_HANDLE_STMT, hstmt, rc));
    
    rc = SQLDisconnect(hdbc);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
            return(PrintError(SQL_HANDLE_DBC, hdbc, rc));
    
    rc = SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
            return(PrintError(SQL_HANDLE_DBC, hdbc, rc));
                    
    rc = SQLFreeHandle(SQL_HANDLE_ENV, henv);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
            return(PrintError(SQL_HANDLE_ENV, henv, rc));
    
    return(0);
}   

Suggested fix:
It worth rechecking platform-dependent types
[5 Dec 2006 20:05] Bogdan Degtyariov
posted doc info
[6 Dec 2006 9:40] MC Brown
A note has been added to the 3.5.13 changelog.

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.041 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.