#include <windows.h>
#include <sqlext.h>

/* Program shall demonstrate failure on insert of long unicode string
   via ODBC "sqlod32w.dll", version 7.5.00.18, into "long unicode"
   column.

   PREREQUISITES:
   -------------
   - Unicode-enabled MaxDB of version 7.5.00.18 (i.e., _UNICODE = YES)
   - Default code set to unicode (i.e., DEFAULT_CODE = UNICODE)
   - Table with "long unicode" column (i.e.,
     "CREATE TABLE test (val long unicode)"
   - ODBC-datasource with sqlod32w.dll "MaxDB (Unicode)" ODBC-driver
   - _PACKAGE_SIZE has default value of MaxDB small database template
     (i.e., 36864)
*/


// CONNECT PARAMETERS...
const char dbname[]   = "dbname";
const char username[] = "dba";
const char password[] = "dba";


int main(int argc, char* argv[])
{
  SQLRETURN rc = SQL_SUCCESS;

  SQLHENV henv = 0;
  rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);

  rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);

  SQLHDBC hdbc = 0;
  rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);

  rc = SQLSetConnectAttr(hdbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, 0);

  rc = SQLConnect(hdbc, (SQLCHAR*)dbname, SQL_NTS,
                        (SQLCHAR*)username, SQL_NTS,
                        (SQLCHAR*)password, SQL_NTS);

  SQLHSTMT hstmt;
  rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);

  /*   Write two unicode values (UCS-2 format) into "long unicode"
       column of unicode enabled MaxDB database (vers. 7.5.00.18),
       using the "MaxDB (Unicode)" ODBC-driver (sqlod32w.dll,
       version 7.5.00.18).
       First value has working length, second value has
       failing length (when param _PACKET_SIZE of DB has
       default value of small database template, i.e. '36864')
   */
  const SQLLEN MAX_LONG_STR = 25000;
  SQLLEN MAX_LONG_STR_BUF = (MAX_LONG_STR+1)*sizeof(SQLWCHAR);

  // working length
  unsigned int nWorkingStrLen = 5000;

  // failing length
  unsigned int nFailingStrLen = MAX_LONG_STR;

  SQLWCHAR *sValue = new SQLWCHAR[MAX_LONG_STR+1];

  rc = SQLPrepare (hstmt, (SQLCHAR*)"INSERT INTO ADONIS.test (val)  VALUES (?)", SQL_NTS);

  SQLLEN nIndIn = SQL_NTS;
  rc = SQLBindParameter (hstmt,
                         1,
                         SQL_PARAM_INPUT,
                         SQL_C_WCHAR,
                         SQL_WLONGVARCHAR,
                         MAX_LONG_STR_BUF,
                         0,
                         sValue,
                         MAX_LONG_STR_BUF,
                         &nIndIn);

  for (unsigned int i = 0; i < nWorkingStrLen; ++i)
  {
    sValue[i] = 'a';
  }
  sValue[nWorkingStrLen] = L'\0'; // terminate string

  // execute works fine with unicode-string of this length
  rc = SQLExecute( hstmt) ;


  for (i = 0; i < nFailingStrLen; ++i)
  {
    sValue[i] = 'a';
  }
  sValue[nFailingStrLen] = L'\0'; // terminate string

  /* program hangs when executing next line with unicode-string
     of "nFailingStrLen". Function does not return, data volume
     of database is written until it is full...
   */
  rc = SQLExecute( hstmt) ;


  rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt);

  rc = SQLDisconnect(hdbc);

  rc = SQLFreeHandle(SQL_HANDLE_DBC, hdbc);

  rc = SQLFreeHandle(SQL_HANDLE_ENV, henv);

  delete [] sValue;

  return rc;
}
