/*BINFMTC: -lodbc -lreadline -I/usr/include/readline

Copyright 2006 Junichi Uekawa

Either works:
unixodbc-dev, libmyodbc
libiodbc2-dev

reference:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/odbc/htm/odbcodbc_api_reference.asp

To see list of available drivers use:
$ odbcinst -q -d

$ ./example.c glantank db username password
sqlsh: insert into mytable01 (last_name, first_name) values('Hoge', 'Fuga'); 
sqlsh: select * from mytable01; 
1 Ungo Ungo
2 Hoge Fuga 
2 rows
 */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <readline.h>
#include <history.h>

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

/* determine if return value is OK. */
static int is_ok(SQLRETURN i)
{
  return ((i==SQL_SUCCESS)||(i==SQL_SUCCESS_WITH_INFO));
}      

int main(int argc, char** argv)
{
  const char* server_name=argv[1];
  const char* database=argv[2];
  const char* username=argv[3];
  const char* password=argv[4];
  SQLCHAR out_connstring[1025];
  SQLSMALLINT out_connstring_len;
  char* connstring;
  SQLHANDLE env_handle;
  SQLHANDLE dbc_handle;
  SQLHANDLE stmt_handle;
  char* statement;
  
  SQLSMALLINT numcols;
  SQLLEN numrows;

  asprintf(&connstring, "driver=MySQL;server=%s;database=%s;user=%s;password=%s", 
	   server_name, database, username, password);
  if(!is_ok(SQLAllocHandle(SQL_HANDLE_ENV,
			   SQL_NULL_HANDLE,
			   &env_handle )))
    fprintf(stderr, "error1\n");
  if(!is_ok(SQLSetEnvAttr(env_handle,
			  SQL_ATTR_ODBC_VERSION,
			  (void*)SQL_OV_ODBC3,
			  0 )))
    fprintf(stderr, "error2\n");
  if(!is_ok(SQLAllocHandle(SQL_HANDLE_DBC,
			   env_handle,
			   &dbc_handle )))
    fprintf(stderr, "error3\n");
  if(!is_ok(SQLDriverConnect(dbc_handle, 0, 
			     (SQLCHAR*)connstring, SQL_NTS,
			     out_connstring, sizeof(out_connstring),
			     &out_connstring_len,
			     SQL_DRIVER_COMPLETE
			     )))
    fprintf(stderr, "error4\n");

  while (NULL!=(statement = readline("sqlsh: ")))
    {
      if (*statement=='\0')		/* ignore blanks. */
	{
	  free(statement);
	  continue;
	}
      add_history(statement);
      
      if(!is_ok(SQLAllocHandle(SQL_HANDLE_STMT,
			       dbc_handle,
			       &stmt_handle )))
	fprintf(stderr, "error5\n");
      
      if(!is_ok(SQLPrepare(stmt_handle,
			   (SQLCHAR*)statement,
			   SQL_NTS)))
	fprintf(stderr, "error6\n");
      
      if(!is_ok(SQLExecute(stmt_handle)))
	{
	  SQLCHAR messagetext[1024];
	  SQLSMALLINT len;
	  SQLCHAR sqlstate[6];

	  SQLGetDiagRec(SQL_HANDLE_STMT, stmt_handle, 
			1, sqlstate, NULL, messagetext, sizeof(messagetext), &len);
	  fprintf(stderr, "error7 %s %s\n", sqlstate, messagetext);
	}

      if(!is_ok(SQLNumResultCols(stmt_handle, &numcols)))
	fprintf(stderr, "error8\n");

      if(!is_ok(SQLRowCount(stmt_handle, &numrows)))
	fprintf(stderr, "error9\n");
	
      while(is_ok(SQLFetch(stmt_handle)))
	{
	  SQLUSMALLINT i;
	  SQLLEN indicator;
	  char buffer[1024];

	  for (i=1; i<=numcols; ++i)
	    {
	      if(!is_ok(SQLGetData(stmt_handle, i, SQL_C_CHAR, 
				   buffer, sizeof(buffer), &indicator)))
		fprintf(stderr, "error10\n");
	      printf("%s ", buffer);
	    }
	  printf("\n");
	}
      printf("%i rows\n", (int)numrows);

      free(statement);
      SQLFreeHandle(SQL_HANDLE_STMT, stmt_handle);
    }

  return 0;
}
