/*!
    \brief      This program tests for the problem reported as BUG-4578.
  
    
    \author     Peter Harvey
    \date       July 2004
*/    
#include <stdio.h>
#include <stdlib.h>

#include <windows.h>

#include <sql.h>
#include <sqlext.h>

#define MAX_STR_LEN 1024
#define MAX_DATA_LEN 1024

SQLHENV     hEnv        = SQL_NULL_HENV;
SQLHDBC     hDbc        = SQL_NULL_HDBC;

SQLCHAR *   szConnStrIn = "DRIVER=MySQL ODBC 3.51 Driver;UID=pharvey;PWD=pharvey;Server=192.168.0.16;Port=3306;Database=test;Option=1;";
SQLCHAR *   szDrop      = "DROP TABLE IF EXISTS tb4578";
SQLCHAR *   szCreate    = "CREATE TABLE tb4578 ( a int );";
SQLCHAR *   szInsert    = "INSERT INTO tb4578 VALUES (1089993944),(1089993945),(1089993946),(1089993947);";
SQLCHAR *   szSelect1   = "SELECT FROM_UNIXTIME(a) AS col1 FROM tb4578 UNION SELECT FROM_UNIXTIME(a) FROM tb4578;";
SQLCHAR *   szSelect2   = "SELECT CAST(FROM_UNIXTIME(a) AS CHAR) AS col1 FROM tb4578 UNION SELECT FROM_UNIXTIME(a) FROM tb4578;";

void do_errors( SQLRETURN nReturn, int nLine, SQLSMALLINT nHandleType, SQLHANDLE h )
{
    if ( h )
    {
        SQLSMALLINT nRec = 1;
        SQLCHAR     szSQLState[6];
        SQLINTEGER  nNative;
        SQLCHAR     szMessage[MAX_STR_LEN];
        SQLSMALLINT nMessage;

        *szSQLState = '\0';
        *szMessage  = '\0';

        while ( SQL_SUCCEEDED( SQLGetDiagRec( nHandleType,
                                              h,
                                              nRec,
                                              szSQLState,
                                              &nNative,
                                              szMessage,
                                              MAX_STR_LEN,
                                              &nMessage ) ) )
        {
            szSQLState[5]               = '\0';
            szMessage[MAX_STR_LEN - 1]  = '\0';

            printf( "[%s][%d][%s] %ld %s\n", __FILE__, nLine, szSQLState, nNative, szMessage );
            nRec++;

            *szSQLState = '\0';
            *szMessage  = '\0';
        }
    }

    if ( !SQL_SUCCEEDED( nReturn ) )
    {
        printf( "[%s][%d] test failed\n", __FILE__, nLine );
        exit( 1 );
    }
}

void do_init()
{
    SQLRETURN   nReturn;
    SQLCHAR     szConnStrOut[MAX_STR_LEN];
    SQLSMALLINT nConnStrOut;

    nReturn = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HENV, &hEnv );
    do_errors( nReturn, __LINE__, SQL_HANDLE_ENV, hEnv );

    nReturn = SQLSetEnvAttr( hEnv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, 0 );
    do_errors( nReturn, __LINE__, SQL_HANDLE_ENV, hEnv );

    nReturn = SQLAllocHandle( SQL_HANDLE_DBC, hEnv, &hDbc );
    do_errors( nReturn, __LINE__, SQL_HANDLE_ENV, hEnv );

    nReturn = SQLDriverConnect( hDbc, NULL, szConnStrIn, MAX_STR_LEN, szConnStrOut, MAX_STR_LEN, &nConnStrOut, SQL_DRIVER_NOPROMPT );
    do_errors( nReturn, __LINE__, SQL_HANDLE_DBC, hDbc );

    nReturn = SQLSetConnectAttr( hDbc, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0 );
    do_errors( nReturn, __LINE__, SQL_HANDLE_DBC, hDbc );
}

void do_drop()
{
    SQLHSTMT    hStmt;
    SQLRETURN   nReturn;

    nReturn = SQLAllocHandle( SQL_HANDLE_STMT, hDbc, &hStmt );
    do_errors( nReturn, __LINE__, SQL_HANDLE_DBC, hDbc );

    nReturn = SQLExecDirect( hStmt, szDrop, SQL_NTS );
    do_errors( nReturn, __LINE__, SQL_HANDLE_STMT, hStmt );

    nReturn = SQLFreeHandle( SQL_HANDLE_STMT, hStmt );
}

void do_fini()
{
    SQLRETURN   nReturn;

    if ( hDbc )
    {
        nReturn = SQLFreeHandle( SQL_HANDLE_DBC, hDbc );
        hDbc = SQL_NULL_HDBC;
    }

    if ( hEnv )
    {
        nReturn = SQLFreeHandle( SQL_HANDLE_ENV, hEnv );
        hEnv = SQL_NULL_HENV;
    }
}


void do_create()
{
    SQLHSTMT    hStmt;
    SQLRETURN   nReturn;

    nReturn = SQLAllocHandle( SQL_HANDLE_STMT, hDbc, &hStmt );
    do_errors( nReturn, __LINE__, SQL_HANDLE_DBC, hDbc );

    nReturn = SQLExecDirect( hStmt, szCreate, SQL_NTS );
    do_errors( nReturn, __LINE__, SQL_HANDLE_STMT, hStmt );

    nReturn = SQLFreeHandle( SQL_HANDLE_STMT, hStmt );
}

void do_insert()
{
    SQLHSTMT    hStmt;
    SQLRETURN   nReturn;

    nReturn = SQLAllocHandle( SQL_HANDLE_STMT, hDbc, &hStmt );
    do_errors( nReturn, __LINE__, SQL_HANDLE_DBC, hDbc );

    nReturn = SQLExecDirect( hStmt, szInsert, SQL_NTS );
    do_errors( nReturn, __LINE__, SQL_HANDLE_STMT, hStmt );

    nReturn = SQLFreeHandle( SQL_HANDLE_STMT, hStmt );
}


void do_select( SQLCHAR *szSelect )
{
    SQLHSTMT        hStmt;
    SQLRETURN       nReturn;
    SQLSMALLINT     nCols;
    SQLSMALLINT     nCol;
    SQLCHAR         szName[MAX_DATA_LEN];
    SQLSMALLINT     nName;
    SQLSMALLINT     nType;
    SQLUINTEGER     nLen;
    SQLSMALLINT     nScale;
    SQLSMALLINT     bNullable;
    SQLCHAR         szValue[MAX_DATA_LEN];
    SQLSMALLINT     nValue;

    nReturn = SQLAllocHandle( SQL_HANDLE_STMT, hDbc, &hStmt );
    do_errors( nReturn, __LINE__, SQL_HANDLE_DBC, hDbc );

    nReturn = SQLExecDirect( hStmt, szSelect, SQL_NTS );
    do_errors( nReturn, __LINE__, SQL_HANDLE_STMT, hStmt );

    nReturn = SQLNumResultCols( hStmt, &nCols );
    do_errors( nReturn, __LINE__, SQL_HANDLE_STMT, hStmt );

    printf( "[%s][%d] nCols=%d\n", __FILE__, __LINE__, nCols );

    for ( nCol = 1; nCol <= nCols; nCol++ )
    {
        nReturn = SQLDescribeCol( hStmt, nCol, szName, MAX_DATA_LEN, &nName, &nType, &nLen, &nScale, &bNullable ); 
        do_errors( nReturn, __LINE__, SQL_HANDLE_STMT, hStmt );
        printf( "[%s][%d] nCol=%d nType=%d\n", __FILE__, __LINE__, nCols, nType );
    }
                                     
    while ( 1 )
    {
        nReturn = SQLFetch( hStmt );
        if ( nReturn == SQL_NO_DATA)
            break;
        do_errors( nReturn, __LINE__, SQL_HANDLE_STMT, hStmt );

        for ( nCol = 1; nCol <= nCols; nCol++ )
        {
            nReturn = SQLGetData( hStmt, nCol, SQL_C_CHAR, szValue, MAX_DATA_LEN, &nValue ); 
            do_errors( nReturn, __LINE__, SQL_HANDLE_STMT, hStmt );
            printf( "[%s][%d] szValue=%s\n", __FILE__, __LINE__, szValue );
        }
        printf( "[%s][%d] ---- \n", __FILE__, __LINE__ );
    }

    nReturn = SQLFreeHandle( SQL_HANDLE_STMT, hStmt );
}


int main(int argc, char **argv)
{
    printf( "[%s][%d] Init...\n", __FILE__, __LINE__ );
    do_init();

    printf( "[%s][%d] Drop...\n", __FILE__, __LINE__ );
    do_drop();

    printf( "[%s][%d] Create...\n", __FILE__, __LINE__ );
    do_create();

    printf( "[%s][%d] Insert...\n", __FILE__, __LINE__ );
    do_insert();

    printf( "[%s][%d] Select 1...\n", __FILE__, __LINE__ );
    do_select( szSelect1 );
    
    printf( "[%s][%d] Select 2...\n", __FILE__, __LINE__ );
    do_select( szSelect2 );
    
    printf( "[%s][%d] Fini...\n", __FILE__, __LINE__ );
    do_fini();

    return 0;
}


