📄 sqlora.c
字号:
/* $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 + -