⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sqlora.c

📁 一个很好用的Linux/Unix下Oracle OCI开发接口封装库
💻 C
📖 第 1 页 / 共 5 页
字号:
/* $id: sqlora.c,v 1.48 2002/07/19 12:37:24 kpoitschke Exp $ */
/**
 * @file sqlora.c
 * libsqlora8 Implementation
 *
 * @author Kai Poitschke
 *
 * Copyright (c) 1991-2002 Kai Poitschke (kai[_at]poitschke.de)
 *
 *   This file is part of the libsqlora8 package which can be found
 *   at http://www.poitschke.de/libsqlora8/
 */

/*
 *     Permission to use, copy, modify, and distribute this software for
 *     any purpose with or without fee is hereby granted, provided that
 *     the above copyright notice and this permission notice appear in all
 *     copies.
 *
 *     THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 *     WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 *     MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 *     IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
 *     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 *     USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *     ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 *     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 *     OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 *     SUCH DAMAGE.
 */

const char * _sqlo_sqloraID="$Id: sqlora.c,v 1.1 2005/01/13 02:56:43 cvsroot Exp $";

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
#include <errno.h>

#ifdef HAVE_UNISTD_H            /* for my windows friends  */
#    include <unistd.h>
#endif
#include <ctype.h>
#include <assert.h>

#if defined(HAVE_PTHREAD_H)
#include <pthread.h>
#endif

#include "oci.h"
#include "sqlora.h"

/* If glib is enabled, we use the glib allocators */
#ifdef USE_GLIB_ALLOC
#  include "glib.h"
#  define MALLOC g_malloc
#  define REALLOC g_realloc
#  define FREE g_free
#else
#  define MALLOC malloc
#  define REALLOC realloc
#  define FREE free 
#endif

#if defined(WIN32)
#define inline __inline
#endif

#if defined (__STDC__) || defined (_AIX) || defined(PROTOTYPES) ||\
            (defined (__mips) && defined (_SYSTYPE_SVR4)) ||\
             defined(WIN32) || defined(__cplusplus)\
            
#  define AND ,
#  define DEFUN(name, arglist, args)      name(args)
#  define DEFUN_VOID(name)                name(void) 
/*
 * Macro to use instead of "void" for arguments that must have
 * type "void *" in ANSI C;  maps them to type "char *" in
 * non-ANSI systems.
 */
#  define VOID void
#else
#  define AND ;
#  define DEFUN(name, arglist, args)      name arglist args;
#  define DEFUN_VOID(name)                name()
#  define VOID char
#endif

#ifndef NULL
#   define NULL 0
#endif

#ifdef TEST_WITH_SIZEOF_RETURNING_ULONG
#define sizeof(_a) (unsigned long)sizeof(_a)
#endif

#if defined(ENABLE_PTHREADS) || defined(ENABLE_ORATHREADS)
/**
 * @enum
 * Defines if the library was compiled with --enable-pthreads
 */
enum {THREADS_ENABLED = 1};
#else
enum {THREADS_ENABLED = 0};
#endif

#ifdef ENABLE_PTHREADS
typedef pthread_t sqlo_thread_t;
typedef pthread_mutex_t sqlo_mutex_t;
#elif ENABLE_ORATHREADS
typedef OCIThreadMutex * sqlo_mutex_t;
typedef OCIThreadId * sqlo_thread_t;
#else
typedef unsigned long sqlo_mutex_t; /* dummy */
typedef unsigned long sqlo_thread_t; /* dummy */
#endif

/**
 * @def EXEC_WHEN_THREADING
 * Executes _cmd if library was compiled with threading and initialized in threaded mode
 * @param _cmd I - The code to execute
 */
#define EXEC_WHEN_THREADING(_cmd) \
     if (THREADS_ENABLED && OCI_THREADED == _oci_init_mode) { _cmd }

/**
 * @def UNLOCK_ALL
 * Release all mutex locks
 */
#define UNLOCK_ALL EXEC_WHEN_THREADING(_dbv_unlock(); _stmtv_unlock(); _env_unlock(); )


/*-------------------------------------------------------------------------
 * CONSTANTS
 *-----------------------------------------------------------------------*/
/**
 * @enum _sqlora_constants
 */
enum _sqlora_constants {                       

  MIN_BINDP = 64,               /**< Initial number of bind pointers
                                 * that were allocated 
                                 */

  MIN_DEFNP = 32,               /**< Initial number of define pointers
                                 * that were allocated 
                                 */

  MIN_OBUF_SIZE = 32,           /**< Minimum size of the output buffer for columns 
                                 * in the select list 
                                 */

  MIN_COL_NAME_LEN = 31,        /**< Minimum size for a name or a column */

  MIN_STMT_SIZE =  1024,        /**< Mininum allocation for sqlo_stmt_t.stmt */

  DEF_PREFETCH_ROWS = 100,      /**< The default number of prefetched rows */

  SQLO_MAX_ERRMSG_LEN = 2047,   /**< The maximum length of the error message buffer */

  MAX_PATH_LEN = 512,           /**< for the trace file */
  
  MAX_VNAME_LEN = 255,          /**< Max variable name len read from the environment */
  
  MAX_LONG_SIZE = (1024*64),     /**< Max size for LONG output variables */

#ifdef LIBSQLORA8_TRACE_ENABLED
  TRACE_ENABLED = 1      /**< configured with enabled trace */
#else
  TRACE_ENABLED = 0      /**< configured with disabled trace */
#endif

};


/*-------------------------------------------------------------------------
 * MACROS
 *-----------------------------------------------------------------------*/
#undef TRUE
#undef FALSE

/**
 * Boolean TRUE
 */
#define TRUE ((1 == 1))

/**
 * Boolean FALSE
 */
#define FALSE (!TRUE)

/**
 * @def TRACE
 * Execute cmd when the trace level of the library is >= the trace level
 * passed to the macro.
 * @param _trc_level   I - The min trace level where cmd should be executed
 * @param _cmd         I - The commands to be executed in case of 
 *                         _trace_level >= trc_level.
 *
 * @par Example:
 * TRACE(3, fprintf(g_ftp, "Calling foo()\n"););
 */
#define TRACE(_trc_level, _cmd) if (TRACE_ENABLED) \
{\
   if ( (NULL != _trace_fp) && _trace_level >= _trc_level) {\
      { _cmd } \
      (void) fflush(_trace_fp); \
   }\
}

/**
 * @def ERRMALLOC
 * Allocates _len bytes memory for _ptr
 *
 * If no memory could be allocated, an error message is
 * put in _dbp->errmsg and the macro returns _retcode
 * _func should be a string identifying the
 * location (function name) where the ERRMALLOC was called
 * @param _dbp     I - The pointer to the database strucuture
 * @param _ptr     O - The allocated memory
 * @param _len     I - The number of bytes to allocate
 * @param _func    I - The function name where this macro was called
 * @param _retcode I - The return code, the caller wants to return if the malloc fails.
 */
#define ERRMALLOC(_dbp, _ptr, _len, _func, _retcode)   \
{\
   (_ptr) = MALLOC((_len));\
   if (!(_ptr) && (_dbp)) {\
	sprintf((_dbp)->errmsg,\
            "Cannot malloc %u bytes in %s\n", (unsigned int)(_len), _func);\
	TRACE(1, (void) fputs((_dbp)->errmsg, _get_trace_fp(_dbp)););\
    /* make sure we release all locks */ \
    UNLOCK_ALL \
	return _retcode;\
   }\
   TRACE(4, fprintf(_get_trace_fp(_dbp), "Allocated %u bytes in %s\n", \
                    (unsigned int)(_len), _func););\
}

/**
 * @def ERREALLOC
 * Rellocates _len bytes memory at _ptr.
 * If no memory could be allocated, an error message is
 * put in _dbp->errmsg and the macro returns _retcode
 * _func should be a string identifying the
 * location (function name) where the ERRMALLOC was called
 * @param _dbp      I - The pointer to the database strucuture
 * @param _ptr      O - The allocated memory
 * @param _len      I - The number of bytes to allocate
 * @param _func     I - The function name where this macro was called
 * @param _retcode  I - The return code, the caller wants to return if the malloc fails.
 */
#define ERREALLOC(_dbp, _ptr, _len, _func, _retcode)   \
{\
   (_ptr) = REALLOC((_ptr), (_len));\
   if (!(_ptr) && (_dbp)) {\
	sprintf((_dbp)->errmsg,\
            "Cannot realloc %u bytes in %s\n", (unsigned int)(_len), _func);\
	TRACE(1, (void) fputs((_dbp)->errmsg, _get_trace_fp(_dbp)););\
    /* make sure we release all locks */ \
    UNLOCK_ALL \
	return _retcode;\
   }\
   TRACE(4, fprintf(_get_trace_fp(_dbp), "Reallocated %u bytes in %s\n", \
                                 (unsigned int)(_len), _func););\
}

/**
 * @def CHECK_DBHANDLE
 * Checks for a valid dbh and sets the dbp or returns with error.
 * If the db handle is invalid, the macro calls return _errval.
 * @param _dbp    O - The pointer to the _sqlo_db_t structure for the _dbh.
 * @param _dbh    I - The database handle to check.
 * @param _func   I - The callers function name. Used for error message.
 * @param _errval I - The value to return in case of an error.
 */
#define CHECK_DBHANDLE(_dbp, _dbh, _func, _errval)\
{\
  if (_dbh >= (int) _dbv_size || _dbh < 0 || !_dbv[ _dbh ] || !_dbv[ _dbh ]->used) {\
    TRACE(1, fprintf(_trace_fp, "Invalid Database handle %d in %s\n",\
                      _dbh, _func);); \
    /* make sure we release all locks */ \
    UNLOCK_ALL; \
    return (_errval); \
  }\
  _dbp = _dbv[_dbh];\
}

/**
 * @def CHECK_STHANDLE
 * Checks for a valid sth and sets the stp or returns with error
 * If the db handle is invalid, the macro calls return _errval.
 * @param _stp    O - The pointer to the _sqlo_stmt_t structure for the _sth.
 * @param _sth    I - The statement handle to check.
 * @param _func   I - The callers function name. Used for error message.
 * @param _errval I - The value to return in case of an error.
 */
#define CHECK_STHANDLE(_stp, _sth, _func, _errval) \
{\
  if (_sth >= (int) _stmtv_size || _sth < 0 || !_stmtv[ _sth ] || !_stmtv[ _sth ]->used) {\
      sqlo_db_ptr_t  xdbp; \
      if ((xdbp = (_dbv[0]))) { \
          sprintf (xdbp->errmsg, "Invalid sth %d passed to %s (line: %d)\n",\
                                 _sth, _func,__LINE__); \
      }\
      TRACE(1, fprintf(_trace_fp, "Invalid sth %d passed to %s (line: %d)\n",\
                              _sth, _func, __LINE__););\
      /* make sure we release all locks */ \
      UNLOCK_ALL; \
      return (_errval);\
    }\
  _stp = _stmtv[_sth];\
}

/**
 * @def CHECK_OCI_STATUS
 * Checks and saves the OCI return status.
 * If the status is != OCI_SUCCESS, the function save_status is called to
 * save the status in the database structure.
 *
 * @param _dbp    I - The pointer to the database structure.
 * @param _stat   I - The status to check.
 * @param _action I - The action you executed causing this status
 * @param _object I - The object on which you did _action.
 */
#define CHECK_OCI_STATUS(_dbp, _stat, _action, _object) { \
        (_dbp)->status = _stat;\
        TRACE(4, fprintf(_get_trace_fp(_dbp), "CHECK_OCI_STATUS[%u]: %d at %d\n", \
                         _dbp->dbh, _stat, __LINE__););\
        if (OCI_SUCCESS != _stat) {\
          _save_oci_status(_dbp, _action, _object, __LINE__);\
        }\
}

/**
 * @def CHECK_OCI_STATUS_RETURN
 * Checks and saves the OCI status and returns the status on failure.
 *
 * Calls CHECK_OCI_STATUS and returns the status if it is != OCI_SUCCESS.
 *
 * @param _dbp  I - The pointer to the database structure.
 * @param _stat I - The status to check.
 * @param _action I - The action you executed causing this status
 * @param _object I - The object on which you did _action.
 */
#define CHECK_OCI_STATUS_RETURN(_dbp, _stat, _action, _object) { \
        CHECK_OCI_STATUS(_dbp, _stat, _action, _object);\
        if (OCI_SUCCESS != _stat) { \
          UNLOCK_ALL; \
          return (_stat); \
        }\
}


/* If we have usleep we wait this amount of microseconds in a 
 * OCI_STILL_EXECUTING loop
 */
#ifdef HAVE_USLEEP
#  define SQLO_USLEEP usleep(1000)
#else
#  define SQLO_USLEEP
#endif


/*-------------------------------------------------------------------------
 * TYPES
 *-----------------------------------------------------------------------*/

/**
 * Boolean type
 */
typedef unsigned char bool_t;


/**
 * Cursor types
 */
typedef enum {
  DEFAULT   = 0,                /**< standard cursor */
  REFCURSOR = 1,                /**< ref cursor type */
  NTABLE    = 2                 /**< nested table cursor */
} sqlo_cursor_type_e;

/**
 * Stores information about the database connection.
 */
typedef struct {

  unsigned int dbh;              /**< The db handle used to address this entry */


  OCIServer * srvhp;                                     /**< OCI server handle */

  OCIError * errhp;                                       /**< OCI error handle */

  OCISvcCtx * svchp;                            /**< OCI service context handle */

  OCISession * authp;                     /**< OCI authorization session handle */

  char * tnsname;                             /**< The TNS name of the database */

  int status;                                        /**< The last status code */

  char errmsg[2*SQLO_MAX_ERRMSG_LEN+1];              /**< The last error message */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -