/* -*- C -*- */
/* The first example illustrates creating a table, adding some data
 * to it, and selecting the inserted data. The second example shows
 * interactive ad hoc query processing.
 *
 * Actual applications include more complete error checking following
 * calls to SQL/CLI routines. That material is omitted from this
 * Appendix for the sake of clarity.
 *
 * This file is adapted for PostgreSQL
 * from the CLI Annex in the SQL98 August 1994 draft standard.
 * Thomas G. Lockhart 1999-06-16
 */

/*
 * B.1  Create table, insert, select
 *
 * This example function creates a table, inserts data into the table,
 * and selects the inserted data.
 *
 * This example illustrates the execution of SQL statement text
 * both using the Prepare() and Execute()  method and using the
 * ExecDirect() method. The example also illustrates both the case
 * where the application uses the automatically-generated descriptors
 * and the case where the application allocates a descriptor of its
 * own and associates this descriptor with the SQL statement.
 *
 * Code comments include the equivalent statements in embedded SQL
 * to show how embedded SQL operations correspond to SQL/CLI function
 * calls.
 */

#include <sqlcli.h>
#include <string.h>

#ifndef NULL
#define NULL   0
#endif

int print_err(SQLSMALLINT handletype, SQLINTEGER handle);

int example1(SQLCHAR *server, SQLCHAR *uid, SQLCHAR *authen)
{
  SQLHENV     henv;
  SQLHDBC     hdbc;
  SQLHDESC    hdesc;
  SQLHDESC    hdesc1;
  SQLHDESC    hdesc2;
  SQLHSTMT    hstmt;
  SQLINTEGER  id;
  SQLSMALLINT idind;
  SQLCHAR     name[51];
  SQLINTEGER  namelen;
  SQLSMALLINT nameind;

  /* EXEC SQL CONNECT TO :server USER :uid; */

  /* allocate an environment handle */
  SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
  /* allocate a connection handle */
  SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);

  /* connect to database */
  if (SQLConnect(hdbc, server, SQL_NTS, uid, SQL_NTS,
		 authen, SQL_NTS)
      != SQL_SUCCESS)
    return(print_err(SQL_HANDLE_DBC, hdbc));

  /* allocate a statement handle */
  SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);

  /* EXEC SQL CREATE TABLE NAMEID (ID integer, NAME varchar(50));  */
  {
    SQLCHAR create[]  ="CREATE TABLE NAMEID (ID integer,"
      " NAME varchar(50))";

    /* execute the CREATE TABLE statement */
    if (SQLExecDirect(hstmt, create, SQL_NTS) != SQL_SUCCESS)
      return(print_err(SQL_HANDLE_STMT, hstmt));
  }

  /* EXEC SQL COMMIT WORK; */
  /* commit CREATE TABLE */
  SQLEndTran(SQL_HANDLE_ENV, henv, SQL_COMMIT);
  /* EXEC SQL INSERT INTO NAMEID VALUES ( :id, :name ); */
  {
    SQLCHAR insert[]=  "INSERT INTO NAMEID VALUES (?, ?)";

    /* show the use of SQLPrepare/SQLExecute method */
    /* prepare the INSERT */
    if (SQLPrepare(hstmt, insert, SQL_NTS) != SQL_SUCCESS)
      return(print_err(SQL_HANDLE_STMT, hstmt));
    /* application parameter descriptor */
    SQLGetStmtAttr(hstmt, SQL_ATTR_APP_PARAM_
		   DESC, &hdesc1, 0L,
		   (SQLINTEGER *)NULL);
    SQLSetDescRec(hdesc1, 1, SQL_INTEGER, 0, 0L, 0, 0,
		  (SQLPOINTER)&id, (SQLINTEGER *)NULL, (SQLSMALLINT *)NULL);
    SQLSetDescRec(hdesc1, 2, SQL_CHAR, 0, 0L, 0, 0,
		  (SQLPOINTER)name, (SQLINTEGER *)NULL,
		  (SQLSMALLINT *)NULL);
    /* implementation parameter descriptor */
    SQLGetStmtAttr(hstmt, SQL_ATTR_IMP_PARAM_
		   DESC, &hdesc2, 0L,
		   (SQLINTEGER *)NULL);
    SQLSetDescRec(hdesc2, 1, SQL_INTEGER, 0, 0L, 0, 0,
		  (SQLPOINTER)NULL, (SQLINTEGER *)NULL,
		  (SQLSMALLINT *)NULL);
    SQLSetDescRec(hdesc2, 2, SQL_VARCHAR, 0, 50L, 0, 0,
		  (SQLPOINTER)NULL, (SQLINTEGER *)NULL,
		  (SQLSMALLINT *)NULL);

    /* assign parameter values and execute the INSERT */
    id=500;
    (void)strcpy(name, "Babbage");
    if (SQLExecute(hstmt) != SQL_SUCCESS)
      return(print_err(SQL_HANDLE_STMT, hstmt));
  }
  /* EXEC SQL COMMIT WORK; */
  SQLEndTran(SQL_HANDLE_ENV, henv, SQL_COMMIT);
  /* commit inserts */

  /* EXEC SQL DECLARE c1 CURSOR FOR SELECT ID, NAME FROM NAMEID; */
  /* EXEC SQL OPEN c1; */
  /* The application doesn't specify "declare c1 cursor for" */
  {
    SQLCHAR select[]=  "select ID, NAME from NAMEID";
    if (SQLExecDirect(hstmt, select, SQL_NTS) != SQL_SUCCESS)
      return(print_err(SQL_HANDLE_STMT, hstmt));
  }

  /* EXEC SQL FETCH c1 INTO :id, :name; */
  /* this time, explicitly allocate an application row descriptor */
  SQLAllocHandle(SQL_HANDLE_DESC, hdbc, &hdesc);
  SQLSetDescRec(hdesc, 1, SQL_INTEGER, 0, 0L, 0, 0,
		(SQLPOINTER)&id, (SQLINTEGER *)NULL, (SQLSMALLINT *)&idind);

  SQLSetDescRec(hdesc, 2, SQL_
		CHAR, 0, (SQLINTEGER)sizeof(name),
		0, 0, (SQLPOINTER)&name, (SQLINTEGER *)&namelen,
		(SQLSMALLINT *)&nameind);
  /* associate descriptor with statement handle */
  SQLSetStmtAttr(hstmt, SQL_ATTR_APP_ROW_DESC, &hdesc, 0);
  /* execute the fetch */
  SQLFetch(hstmt);

  /* EXEC SQL COMMIT WORK; */
  /* commit the transaction  */
  SQLEndTran(SQL_HANDLE_ENV, henv, SQL_COMMIT);

  /* EXEC SQL CLOSE c1; */
  SQLClose(hstmt);
  /* free the statement handle */
  SQLFreeHandle(SQL_HANDLE_STMT, hstmt);

  /* EXEC SQL DISCONNECT; */
  /* disconnect from the database */
  SQLDisconnect(hdbc);
  /* free descriptor handle */
  SQLFreeHandle(SQL_HANDLE_DESC, hdesc);
  /* free descriptor handle */
  SQLFreeHandle(SQL_HANDLE_DESC, hdesc1);
  /* free descriptor handle */
  SQLFreeHandle(SQL_HANDLE_DESC, hdesc2);
  /* free connection handle */
  SQLFreeHandle(SQL_HANDLE_DBC,  hdbc);
  /* free environment handle */
  SQLFreeHandle(SQL_HANDLE_ENV,  henv);

  return(0);
}
