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

static SQLHENV env;
static SQLHDBC conn;

#define CHECK_STMT_RESULT(rc, msg, hstmt)	\
    if (!SQL_SUCCEEDED(rc)) \
    { \
      print_diag(msg, SQL_HANDLE_STMT, hstmt); \
      exit(1); \
    }


static void
print_diag(char *msg, SQLSMALLINT htype, SQLHANDLE handle)
{
  char sqlstate[32];
  char message[1000];
  SQLINTEGER nativeerror;
  SQLSMALLINT textlen;
  SQLRETURN ret;

  if (msg)
    printf("%s\n", msg);

  ret = SQLGetDiagRec(htype, handle, 1, 
		      sqlstate, &nativeerror, message, 256, &textlen);
 
  if (ret != SQL_ERROR)
    printf("%s=%s\n", (CHAR *)sqlstate, (CHAR *)message);
}

static void
test_connect(void)
{
  SQLRETURN ret;
  SQLCHAR str[1024];
  SQLSMALLINT strl;

  SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);

  SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);

  SQLAllocHandle(SQL_HANDLE_DBC, env, &conn);
  ret = SQLDriverConnect(conn, NULL, "DSN=psqlodbc_test_dsn;%s", SQL_NTS,
			 str, sizeof(str), &strl,
			 SQL_DRIVER_COMPLETE);
  if (SQL_SUCCEEDED(ret)) {
    printf("connected\n");
  } else {
    print_diag("SQLDriverConnect failed.", SQL_HANDLE_DBC, conn);
    exit(1);
  }
}

int main(int argc, char **argv)
{
  SQLRETURN rc;
  HSTMT hstmt = SQL_NULL_HSTMT;
  char *param1;
  SQLLEN cbParam1;
  long longparam;
  SQL_INTERVAL_STRUCT intervalparam;
  SQLSMALLINT colcount;
  char buf[40];

  test_connect();

  rc = SQLAllocStmt(conn, &hstmt);
  if (!SQL_SUCCEEDED(rc))
  {
    print_diag("failed to allocate stmt handle", SQL_HANDLE_DBC, conn);
    exit(1);
  }

  /****
   * With BoolsAsChar=1, a varchar param with column_size=5 forces a
   * server-side Prepare. So test that.
   */

  /* bind param  */
  param1 = "foo";
  cbParam1 = SQL_NTS;
  rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT,
			SQL_C_CHAR,	/* value type */
			SQL_VARCHAR,	/* param type */
			5,		/* column size. 5 Triggers special
					 * behavior with BoolsAsChar=1 */
			0,		/* dec digits */
			param1,		/* param value ptr */
			0,		/* buffer len */
			&cbParam1	/* StrLen_or_IndPtr */);
  CHECK_STMT_RESULT(rc, "SQLBindParameter failed", hstmt);

  /* Execute a simple query that returns a single value */
  rc = SQLExecDirect(hstmt,
		     (SQLCHAR *) "SELECT 'foobar' WHERE 'foo' = ?", SQL_NTS);
  CHECK_STMT_RESULT(rc, "SQLExecDirect failed", hstmt);

  /* Fetch result */
  rc = SQLFetch(hstmt);
  if (rc == SQL_NO_DATA) 
  {
    printf("SQLFetch returned SQL_NO_DATA\n");
    exit(1);
  }

  /* Should return a single value. Print it. */
  rc = SQLGetData(hstmt,1, SQL_C_CHAR, buf, sizeof(buf), NULL);
  if (!SQL_SUCCEEDED(rc))
  {
    print_diag("SQLGetData failed", SQL_HANDLE_STMT, hstmt);
    exit(1);
  }
  printf("got result: %s\n", buf);

  return 0;
}
