/*!
    \brief      This program tests for the problem reported as BUG-3727.
  
    
    \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=;PWD=;Server=localhost;Port=3306;Database=test;Stmt=SET NAMES cp1256";
SQLCHAR *   szShowVariables = "SHOW VARIABLES LIKE 'char%';";

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;

    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 );
}

void do_driverconnect()
{
    SQLRETURN   nReturn;
    SQLCHAR     szConnStrOut[MAX_STR_LEN];
    SQLSMALLINT nConnStrOut;

    nReturn = SQLDriverConnect( hDbc, NULL, szConnStrIn, MAX_STR_LEN, szConnStrOut, MAX_STR_LEN, &nConnStrOut, SQL_DRIVER_NOPROMPT );
    do_errors( nReturn, __LINE__, SQL_HANDLE_DBC, hDbc );
}

void do_connect()
{
    SQLRETURN   nReturn;

    nReturn = SQLConnect( hDbc, "test", SQL_NTS, "", SQL_NTS, "", SQL_NTS );
    do_errors( nReturn, __LINE__, SQL_HANDLE_DBC, hDbc );
}

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_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 );

    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  ", szName );
    }
    printf( "\n-----------------------------\n" );

    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  ", szValue );
        }
        printf( "\n" );
    }

    nReturn = SQLFreeHandle( SQL_HANDLE_STMT, hStmt );
}


int main(int argc, char **argv)
{
    /* test 1 */
    printf( "[%s][%d] Init...\n", __FILE__, __LINE__ );
    do_init();

    printf( "[%s][%d] Driver Connect...\n", __FILE__, __LINE__ );
    do_driverconnect();

    printf( "[%s][%d] Select...\n", __FILE__, __LINE__ );
    do_select( szShowVariables );
    
    printf( "[%s][%d] Fini...\n", __FILE__, __LINE__ );
    do_fini();

    /* test 2 */
    printf( "[%s][%d] Init...\n", __FILE__, __LINE__ );
    do_init();

    printf( "[%s][%d] Connect...\n", __FILE__, __LINE__ );
    do_connect();

    printf( "[%s][%d] Select...\n", __FILE__, __LINE__ );
    do_select( szShowVariables );
    
    printf( "[%s][%d] Fini...\n", __FILE__, __LINE__ );
    do_fini();

    return 0;
}


