
#include <iostream>
#include <windows.h>
#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 if (rcode == SQL_NEED_DATA)
    {
        std::cout << "NEED DATA .. .. .." << std::endl;
        return (SQL_NEED_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;
	argv[1] = "myodbc1";
	argv[2] = "root";
	argv[3] = "";

    //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));
        
    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));
    
        
    /*************************************************************************************/
    
    SQLINTEGER status;

	rc = SQLExecDirect(hstmt, (SQLCHAR *)"USE test", SQL_NTS);

    rc = SQLExecDirect(hstmt, (SQLCHAR *)"DROP TABLE IF EXISTS TESTSTREAM", SQL_NTS);

    rc = SQLExecDirect(hstmt, (SQLCHAR *)"CREATE TABLE TESTSTREAM ( COL1 LONG VARCHAR ) ENGINE=InnoDB DEFAULT CHARSET=latin1", SQL_NTS);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_STMT, hstmt, rc));

    rc = SQLExecDirect(hstmt, (SQLCHAR *)"INSERT INTO TESTSTREAM VALUES ('ABCDEF')", SQL_NTS);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_STMT, hstmt, rc));
        
    rc = SQLExecDirect(hstmt, (SQLCHAR *)"SELECT COL1 FROM TESTSTREAM", SQL_NTS);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_STMT, hstmt, rc));

    rc = SQLFetchScroll(hstmt,SQL_FETCH_NEXT,0);
        if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        PrintError(SQL_HANDLE_STMT, hstmt, rc);

    SQLINTEGER size = 10;

    char* buf = new char[size];

    rc = SQLGetData(hstmt, 1, SQL_C_CHAR, (SQLCHAR*)buf, 10, &size);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_STMT, hstmt, rc));

    for (int i=0; i < size ; i++)
    {   
        std::cout << buf[i];
    }
    std::cout << std::endl;


    status = SQL_LEN_DATA_AT_EXEC(0);
    rc = SQLBindCol(hstmt, 1, SQL_C_CHAR, (SQLPOINTER)0, 0, &status);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        return(PrintError(SQL_HANDLE_STMT, hstmt, rc));


    std::cout << "SQLSetPos" << std::endl;
    rc = SQLSetPos(hstmt,1, SQL_UPDATE, SQL_LOCK_NO_CHANGE);
    if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
        PrintError(SQL_HANDLE_STMT, hstmt, rc);

    if ( rc != SQL_NEED_DATA )
        return(rc);


    SQLINTEGER param;
    SQLRETURN rc2;

    do
    {
        std::cout << "SQLParamData" << std::endl;
        rc2 = SQLParamData(hstmt, (SQLPOINTER*)&param);
        if (rc2 != SQL_SUCCESS && rc2 != SQL_SUCCESS_WITH_INFO)
            PrintError(SQL_HANDLE_STMT, hstmt, rc2);
    
        if ( rc == SQL_NEED_DATA )
        {
            std::cout << "SQLPutData" << std::endl;
            rc = SQLPutData(hstmt, (SQLCHAR*)buf, size);
            if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO)
                return(PrintError(SQL_HANDLE_STMT, hstmt, rc));
        }
    }
    while ( rc2 == SQL_NEED_DATA);

    std::cout << "DONE " << 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);
}   
