📄 sqlora.c
字号:
/* $Id: sqlora.c,v 1.71 2004/05/28 03:04:15 kpoitschke Exp $ *//** * @file sqlora.c * libsqlora8 Implementation * * @author Kai Poitschke * * Copyright (c) 1991-2004 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.71 2004/05/28 03:04:15 kpoitschke 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(ENABLE_WINTHREADS)#include <windows.h>#else# if defined(HAVE_PTHREAD_H)#include <pthread.h># endif#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(_p) {void ** l_p= (void **)&(_p); if ( *l_p != NULL ) {g_free( *l_p); *l_p = NULL; } }#else# define MALLOC malloc# define REALLOC realloc# define FREE(_p) {void ** l_p= (void**)&(_p); if ( *l_p != NULL ) {free( *l_p); *l_p = NULL; } }#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/*#define TEST_WITH_SIZEOF_RETURNING_ULONG*/#ifdef TEST_WITH_SIZEOF_RETURNING_ULONG#define sizeof(_a) (unsigned long)sizeof(_a)#endif#if defined(ENABLE_PTHREADS) || defined(ENABLE_ORATHREADS) || defined(ENABLE_WINTHREADS)/** * Defines if the library was compiled with --enable-pthreads */enum {THREADS_ENABLED = 1};#elseenum {THREADS_ENABLED = 0};#endif#ifdef ENABLE_PTHREADStypedef pthread_t sqlo_thread_t;typedef pthread_mutex_t sqlo_mutex_t;#else# ifdef ENABLE_ORATHREADStypedef OCIThreadMutex * sqlo_mutex_t;typedef OCIThreadId * sqlo_thread_t;# else# ifdef ENABLE_WINTHREADStypedef HANDLE sqlo_mutex_t;typedef unsigned long sqlo_thread_t;# elsetypedef unsigned long sqlo_mutex_t; /* dummy */typedef unsigned long sqlo_thread_t; /* dummy */# endif# endif#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(); _env_unlock(); _init_unlock(); )#define ENCODE_STH(_sth, _dbh) ((int)(_dbh << (sizeof(sqlo_stmt_handle_t)/2 * 8) | _sth))#define DECODE_STH(_sth) ((ub4) _sth & 0x0000ffff)#define DECODE_DBH(_sth) ((ub4) (_sth >> (sizeof(sqlo_stmt_handle_t)/2 * 8)) & 0x007fff)/*------------------------------------------------------------------------- * CONSTANTS *-----------------------------------------------------------------------*//** * @enum _sqlora_constants */enum _sqlora_constants { SQLO_MAX_DB = 0x00007fff, /**< max. number of allowed db connections */ SQLO_MAX_CURSORS = 0x0000ffff, /**< max. number of allowed cursors per db connection */ /* changed the MIN_ sizes for better testing (to make sure we do some reallocations) */ MIN_BINDP = 1 /*64*/, /**< Initial number of bind pointers * that were allocated */ MIN_DEFNP = 1 /*32*/, /**< Initial number of define pointers * that were allocated */ MIN_OBUF_SIZE = 1 /*32*/, /**< Minimum size of the output buffer for columns * in the select list */ MIN_COL_NAME_LEN = 1 /*31*/, /**< Minimum size for a name or a column */ MIN_STMT_SIZE = 10 /* 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 p_trace_level I - The min trace level where cmd should be executed * @param p_cmd I - The commands to be executed in case of * _trace_level >= p_trace_level. * * @par Example: * TRACE(3, fprintf(g_ftp, "Calling foo()\n");); */#define TRACE(p_trace_level, p_cmd) \ if ( TRACE_ENABLED && \ (NULL != _trace_fp) && \ (_trace_level >= p_trace_level) ) { \ { p_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 p_dbp->errmsg, p_dbp->status is set to p_retcode and * the macro returns p_retcode * p_func should be a string identifying the * location (function name) where the ERRMALLOC was called * @param p_dbp I - The pointer to the database strucuture * @param p_ptr O - The allocated memory * @param p_len I - The number of bytes to allocate * @param p_func I - The function name where this macro was called * @param p_retcode I - The return code, the caller wants to return if the malloc fails. */#define ERRMALLOC(p_dbp, p_ptr, p_len, p_func, p_retcode) \{ \ sqlo_db_struct_ptr_t l_dbp = p_dbp; \ int l_len = p_len; \ CONST char * l_func = p_func; \ int l_retcode = p_retcode; \ (p_ptr) = MALLOC((l_len)); \ if ( !(p_ptr) ) { \ if ( l_dbp ) { \ sprintf( (l_dbp)->errmsg, \ "Cannot malloc %u bytes in %s\n", \ (unsigned int)(l_len), l_func); \ TRACE(1, (void) fputs((l_dbp)->errmsg, \ _get_trace_fp(l_dbp));); \ } \ l_dbp->status = l_retcode; \ /* make sure we release all locks */ \ UNLOCK_ALL; \ return l_retcode; \ } \ TRACE(4, fprintf( _get_trace_fp(l_dbp), \ "Allocated %u bytes in %s\n", \ (unsigned int) (l_len), l_func);); \}/** * @def ERREALLOC * Rellocates _len bytes memory at _ptr. * If no memory could be allocated, an error message is * put in p_dbp->errmsg, p_dbp->status is set to p_retcode * and the macro returns p_retcode * _func should be a string identifying the * location (function name) where the ERRMALLOC was called * @param p_dbp I - The pointer to the database strucuture * @param p_ptr O - The allocated memory * @param p_len I - The number of bytes to allocate * @param p_func I - The function name where this macro was called * @param p_retcode I - The return code, the caller wants to return if the malloc fails. */#define ERREALLOC(p_dbp, p_ptr, p_len, p_func, p_retcode) \{ \ sqlo_db_struct_ptr_t l_dbp = p_dbp; \ int l_len = p_len; \ CONST char * l_func = p_func; \ int l_retcode = p_retcode; \ (p_ptr) = REALLOC((p_ptr), (l_len)); \ if ( !(p_ptr) ) { \ if ( l_dbp ) { \ sprintf( (l_dbp)->errmsg, \ "Cannot realloc %u bytes in %s\n", \ (unsigned int)(l_len), l_func); \ TRACE( 1, (void) fputs((l_dbp)->errmsg, \ _get_trace_fp(l_dbp));); \ } \ /* make sure we release all locks */ \ l_dbp->status = p_retcode; \ UNLOCK_ALL; \ return l_retcode; \ } \ TRACE(4, fprintf(_get_trace_fp(l_dbp), \ "Reallocated %u bytes in %s\n", \ (unsigned int)(l_len), l_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 p_dbp O - The pointer to the _sqlo_db_t structure for the _dbh. * @param p_dbh I - The database handle to check. * @param p_func I - The callers function name. Used for error message. * @param p_errval I - The value to return in case of an error. */#define CHECK_DBHANDLE(p_dbp, p_dbh, p_func, p_errval) \{ \ int l_dbh = p_dbh; \ CONST char * l_func = p_func; \ if ( !VALID_DBH_RANGE(l_dbh) || \ !_dbv[ l_dbh ] || \ !_dbv[ l_dbh ]->used) { \ TRACE(1, fprintf(_trace_fp, \ "Invalid Database handle %d in %s\n", \ l_dbh, l_func);); \ /* make sure we release all locks */ \ UNLOCK_ALL; \ return (p_errval); \ } \ p_dbp = _dbv[ l_dbh ]; \}/** * @def CHECK_STHANDLE * Checks for a valid sth and sets the stp or returns with error * If the st handle is invalid, the macro calls return _errval. * @param p_stp O - The pointer to the _sqlo_stmt_t structure for the _sth. * @param p_sth I - The statement handle to check. * @param p_func I - The callers function name. Used for error message. * @param p_errval I - The value to return in case of an error. */#define CHECK_STHANDLE(p_stp, p_sth, p_func, p_errval) \{ \ if ( NULL == (p_stp = _sth2stp( p_sth, p_func ) ) || \ !p_stp->used ) { \ return p_errval; \ } \}/** * @def CHECK_OCI_STATUS * Checks and saves the OCI return status. * If the status is != OCI_SUCCESS, the function _save_oci_status is called to * save the error message in the database structure. * * @param p_dbp I - The pointer to the database structure. * @param p_stat I - The status to check. * @param p_action I - The action you executed causing this status * @param p_object I - The object on which you did _action. */#define CHECK_OCI_STATUS(p_dbp, p_stat, p_action, p_object) \{ \ sqlo_db_struct_ptr_t l_dbp = p_dbp; \ int l_stat = p_stat; \ (l_dbp)->status = p_stat; \ TRACE(4, fprintf(_get_trace_fp(l_dbp), \ "CHECK_OCI_STATUS[%u]: %d at %d\n", \ l_dbp->dbh, l_stat, __LINE__);); \ if (OCI_SUCCESS != l_stat && \ OCI_STILL_EXECUTING != l_stat) { \ _save_oci_status(l_dbp, p_action, p_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 p_dbp I - The pointer to the database structure. * @param p_stat I - The status to check. * @param p_action I - The action you executed causing this status * @param p_object I - The object on which you did _action. */#define CHECK_OCI_STATUS_RETURN(p_dbp, p_stat, p_action, p_object) \{ \ sqlo_db_struct_ptr_t l_dbp2 = p_dbp; \ int l_stat2 = p_stat; \ CHECK_OCI_STATUS(l_dbp2, l_stat2, p_action, p_object); \ if (OCI_SUCCESS != l_stat2) { \ UNLOCK_ALL; \ return (l_stat2); \ } \}/** * @def VALID_DBH_RANGE * Expression resolves to true, if the passed dbh is in a valid range. * * @param _dbh I - The dbh to be checked. */#define VALID_DBH_RANGE(_dbh) ( _dbh >= 0 && _dbh < (int)_dbv_size )/* 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;/**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -