/* ----------------------------------------------------------------------------
 * Raima Database Manager
 *
 * Copyright (c) 2012 Raima Inc.,  All rights reserved.
 *
 * Use of this software, whether in source code format, or in executable,
 * binary object code form, is governed by the Raima LICENSE which
 * is fully described in the LICENSE.TXT file, included within this
 * distribution of files.
 * ----------------------------------------------------------------------------
 */

#include <stdio.h>

/* sqlext.h is required in all files using ODBC */
#include "sqlext.h"

#define SQL_EMPSTR      ((SQLCHAR *) "")
#define DBEXISTS_ERROR  "[Raima Inc.][rdmrdbc-12.dll][Raima Database Manager]" \
                        "database already exists: HelloWorld_db"

/* EXAMPLE - Hello World for ODBC */
/* Each time you run this example, a new record is created in the
 * database, then all existing records are read from the database
 * and printed.
 *
 * The following ODBC Functions are illustrated:
 *      SQLAllocHandle/SQLFreeHandle
 *      SQLConnect/SQLDisconnect
 *      SQLExecDirect
 *      SQLFetch
 *      SQLGetData
 *
 * They are fully documented in http://docs.raima.com/rdm/.
 *
 * Each of these functions returns an ODBC diagnostic code, where the
 * value SQL_SUCCESS indicates a successful call.
 *
 * For simplicity, this example does not check all return codes, but good
 * programming practices would dictate that they are checked after each
 * ODBC call.
 *
 */
static SQLINTEGER get_error(
    SQLSMALLINT  handleType,
    SQLHANDLE    handle,
    SQLCHAR     *errmsg,
    SQLSMALLINT  msgSize)
{
    SQLCHAR    state[SQL_SQLSTATE_SIZE + 1];
    SQLINTEGER error;

    (void) SQLGetDiagRec(handleType, handle, 1, state, &error,
            errmsg, msgSize, NULL);

    return error;
}

/* =======================================================================
*/
static SQLRETURN create_database(
    void)
{
    SQLRETURN odbcCode;
    SQLHENV   hEnv;
    SQLHDBC   hDbc;
    SQLHSTMT  hStmt;

    /* Allocate handles */
    odbcCode = SQLAllocHandle(SQL_HANDLE_ENV, NULL, &hEnv);
    odbcCode = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc);
    odbcCode = SQLConnect(hDbc, SQL_EMPSTR, SQL_NTS, SQL_EMPSTR, SQL_NTS,
            SQL_EMPSTR, SQL_NTS);
    odbcCode = SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt);

    /* Attempt to create the database.  If the database already exists
     * this will fail and we simply open the existing database. */
    odbcCode = SQLExecDirect(hStmt, (SQLCHAR *) "CREATE DATABASE HelloWorld_db",
            SQL_NTS);
    if (SQL_SUCCEEDED(odbcCode))
    {
        (void) SQLExecDirect(hStmt,
                (SQLCHAR *) "CREATE TABLE hw_table (message char(30))",
                SQL_NTS);
        (void) SQLEndTran(SQL_HANDLE_DBC, hDbc, SQL_COMMIT);
        (void) SQLExecDirect(hStmt, (SQLCHAR *) "CLOSE HellowWorld_db", SQL_NTS);
    }
    else
    {
        SQLCHAR errmsg[256];

        (void) get_error(SQL_HANDLE_STMT, hStmt, errmsg, sizeof(errmsg));
        if (strcmp((char *) errmsg, DBEXISTS_ERROR) == 0)
            odbcCode = SQL_SUCCESS;
        else
            fprintf(stderr, "Error creating the HelloWorld database\n");
    }

    /* Free the handles */
    (void) SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
    (void) SQLDisconnect(hDbc);
    (void) SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
    (void) SQLFreeHandle(SQL_HANDLE_ENV, hEnv);

    return odbcCode;
}

/* =======================================================================
*/
int32_t main(void)
{
    SQLHENV   hEnv;
    SQLHDBC   hDbc;
    SQLHSTMT  hStmt;
    SQLRETURN odbcCode;

    create_database();

    /* Allocate handles */
    odbcCode = SQLAllocHandle(SQL_HANDLE_ENV, NULL, &hEnv);
    odbcCode = SQLAllocHandle(SQL_HANDLE_DBC, hEnv, &hDbc);
    odbcCode = SQLConnect(hDbc, SQL_EMPSTR, SQL_NTS, SQL_EMPSTR, SQL_NTS,
            SQL_EMPSTR, SQL_NTS);
    odbcCode = SQLAllocHandle(SQL_HANDLE_STMT, hDbc, &hStmt);

    /* Open the database */
    odbcCode = SQLExecDirect(hStmt, (SQLCHAR *) "OPEN HelloWorld_db", SQL_NTS);
    if (SQL_SUCCEEDED(odbcCode))
    {
        /* Add a new row to hw_table */
        odbcCode = SQLExecDirect(hStmt,
                        (SQLCHAR *) "INSERT INTO hw_table VALUES 'Hello World'",
                        SQL_NTS);
        (void) SQLEndTran(SQL_HANDLE_DBC, hDbc, SQL_COMMIT);

        if (SQL_SUCCEEDED(odbcCode))
        {
            char colValue[31];

            /* Retrieve and display all rows from hw_table */
            odbcCode = SQLExecDirect(hStmt,
                    (SQLCHAR *) "SELECT message FROM hw_table", SQL_NTS);

            while ((odbcCode = SQLFetch(hStmt)) == SQL_SUCCESS)
            {
                odbcCode = SQLGetData(hStmt, 1, SQL_C_CHAR, colValue,
                        sizeof(colValue), NULL);
                if (SQL_SUCCEEDED(odbcCode))
                    printf("%s\n", colValue);
            }
        }
    }

    /* Free the handles */
    (void) SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
    (void) SQLDisconnect(hDbc);
    (void) SQLFreeHandle(SQL_HANDLE_DBC, hDbc);
    (void) SQLFreeHandle(SQL_HANDLE_ENV, hEnv);

    printf("\nPress <Enter> to continue . . .\n");
    getchar();

    return EXIT_SUCCESS;
}
