packages feed

HDBC-odbc-1.1.3.1: hdbc-odbc-helper.c

#ifdef mingw32_HOST_OS
#include <windows.h>
#endif
#include <sql.h>
#include <sqlext.h>
#include <stdio.h>
#include <stdlib.h>
#include "hdbc-odbc-helper.h"

SQLINTEGER nullData = SQL_NULL_DATA;

int sqlSucceeded(SQLRETURN ret) {
  return SQL_SUCCEEDED(ret);
}

/* Things can't finalize more than once.  
We'd like to let people call them from the app.
Yet we'd also like to be able to have a ForeignPtr finalize them.

So, here's a little wrapper for things. */

void dbc_conditional_finalizer(finalizeonce *conn);

finalizeonce *wrapobjodbc(void *obj, finalizeonce *parentobj) {
  finalizeonce *newobj;
  newobj = malloc(sizeof(finalizeonce));
  if (newobj == NULL) {
    fprintf(stderr, "\nHDBC: could not allocate wrapper!\n");
    return NULL;
  }
  newobj->isfinalized = 0;
  newobj -> refcount = 1;
  newobj->encapobj = obj;
  newobj->extrainfo = NULL;
  newobj->parent = parentobj;
  if (parentobj != NULL)
    (parentobj->refcount)++;
#ifdef HDBC_DEBUG
  fprintf(stderr, "\nWrapped %p at %p\n", obj, newobj);
#endif
  return newobj;
}

finalizeonce *wrapobjodbc_extra(void *obj, void *extra, finalizeonce *parentobj) {
  finalizeonce *newobj = wrapobjodbc(obj, parentobj);
  if (newobj != NULL)
    newobj->extrainfo = extra;
  return newobj;
}
  
void sqlFreeHandleSth_app(finalizeonce *res) {
#ifdef HDBC_DEBUG
  fprintf(stderr, "\nApp cleanup of sth %p requested: %d\n", 
          res->encapobj, res->isfinalized);
#endif
  if (res->isfinalized)
    return;
  SQLCloseCursor((SQLHSTMT) (res->encapobj));
  SQLFreeHandle(SQL_HANDLE_STMT, (SQLHANDLE) (res->encapobj));
  res->isfinalized = 1;
  res->encapobj = NULL;
}

void sqlFreeHandleSth_finalizer(finalizeonce *res) {
#ifdef HDBC_DEBUG
  fprintf(stderr, "\nFinalizer cleanup of sth %p requested: %d\n", 
          res->encapobj, res->isfinalized);
#endif
  sqlFreeHandleSth_app(res);
  (res->refcount)--;            /* Not really important since this is never a 
                                   parent */
  (res->parent->refcount)--;
  dbc_conditional_finalizer(res->parent);
  free(res);
}

SQLRETURN sqlFreeHandleDbc_app(finalizeonce *res) {
  SQLRETURN retval;
#ifdef HDBC_DEBUG
  fprintf(stderr, "\nApp cleanup of dbc %p requested: %d\n", 
          res->encapobj, res->isfinalized);
#endif
  if (res->isfinalized)
    return 0;
  retval = SQLDisconnect((SQLHDBC) (res->encapobj));
  if (SQL_SUCCEEDED(retval)) {
    SQLFreeHandle(SQL_HANDLE_DBC, (SQLHANDLE) (res->encapobj));
    SQLFreeHandle(SQL_HANDLE_ENV, (SQLHANDLE) (res->extrainfo));
    res->isfinalized = 1;
    res->encapobj = NULL;
  }
  return retval;
}

void sqlFreeHandleDbc_finalizer(finalizeonce *res) {
#ifdef HDBC_DEBUG
  fprintf(stderr, "\nFinalizer cleanup of dbc %p requested: %d\n", 
          res->encapobj, res->isfinalized);
#endif
  (res->refcount)--;
  dbc_conditional_finalizer(res);
}

void dbc_conditional_finalizer(finalizeonce *res) {
  if (res->refcount < 1) {
  /* Don't use sqlFreeHandleDbc_app here, because we want to clear it out
     regardless of the success or failues of SQLDisconnect. */
    if (! (res->isfinalized)) {
      SQLDisconnect((SQLHDBC) (res->encapobj));
      SQLFreeHandle(SQL_HANDLE_DBC, (SQLHANDLE) (res->encapobj));
      SQLFreeHandle(SQL_HANDLE_ENV, (SQLHANDLE) (res->extrainfo));
      res->encapobj = NULL;
      res->isfinalized = 1;
    }
    free(res);
  }
}

void *getSqlOvOdbc3(void) {
  return (void *)SQL_OV_ODBC3;
}

SQLRETURN disableAutoCommit(SQLHDBC conn) {
  return SQLSetConnectAttr(conn, SQL_ATTR_AUTOCOMMIT, 
                           (SQLPOINTER) SQL_AUTOCOMMIT_OFF,
                           SQL_IS_UINTEGER);
}

SQLRETURN simpleSqlTables(SQLHSTMT stmt) {
  return SQLTables(stmt, NULL, 0, NULL, 0, "%", 1, "TABLE", 5);
}

SQLRETURN simpleSqlColumns(SQLHSTMT stmt, SQLCHAR *tablename, 
                           SQLSMALLINT tnlen) {
  return SQLColumns(stmt, NULL, 0, NULL, 0, tablename, tnlen, "%", 1);
}