📄 sqlora.c
字号:
dbp->errcode = 0;
*(dbp->errmsg) = '\0';
dbp->status = 0;
EXEC_WHEN_THREADING( _dbv_lock(); ); /* start of critical section */
dbp->attached = FALSE;
dbp->session_created = FALSE;
dbp->used = FALSE;
EXEC_WHEN_THREADING( _dbv_unlock(); ); /* end of critical section */
}
/*---------------------------------------------------------------------------*/
/**
* Returns the thread id of this thread.
* @return The thread id
*/
static inline sqlo_thread_t
DEFUN_VOID(_get_thread_id)
{
#ifdef ENABLE_PTHREADS
return pthread_self();
#elif ENABLE_ORATHREADS
sqlo_thread_t tid = NULL;
OCIThreadIdInit(_oci_envhp, _oci_errhp, &tid);
OCIThreadIdGet(_oci_envhp, _oci_errhp, tid);
return tid;
#endif
return 0;
}
/*-------------------------------------------------------------------------*/
/**
* Resets the number of bindpv entries.
*/
static void
DEFUN(_bindpv_reset, (stp), sqlo_stmt_ptr_t stp)
{
unsigned int bindp_idx;
if (stp) {
for (bindp_idx = 0; bindp_idx < stp->num_bindpv; ++bindp_idx) {
stp->bindpv[ bindp_idx ] = NULL;
}
stp->num_bindpv = 0;
}
}
/*---------------------------------------------------------------------------*/
/**
* Compares two thread ids and returns if they are equal
* @return TRUE if they are equal, FALSE if not.
*/
static inline bool_t
DEFUN(_thread_id_equal, (id1, id2), sqlo_thread_t id1 AND sqlo_thread_t id2)
{
#if ENABLE_ORATHREADS
boolean result;
OCIThreadIdSame(_oci_envhp, _oci_errhp, id1, id2, &result);
return result ? TRUE : FALSE;
#else
return id1 == id2 ? TRUE : FALSE;
#endif
}
/*-------------------------------------------------------------------------*/
/**
* Adds a new stmt to @ref _stmtv[].
* Allocates either a new entry in _stmtv[], or returns an unused.
* @param dbp I - The database ptr.
* @return The new entry, marked as used.
*/
static sqlo_stmt_ptr_t
DEFUN(_get_stmt_ptr, (dbp), const_sqlo_db_ptr_t dbp)
{
register unsigned stmt_idx;
unsigned int first_null_idx; /* first null slot */
unsigned int free_idx;
bool_t found_free;
bool_t first_null_idx_set;
register sqlo_stmt_ptr_t *stpp;
/* check for initialization */
if ((! _sqlo_init) || (_stmtv_size <= 0))
return (NULL) ;
EXEC_WHEN_THREADING( _stmtv_lock(); ); /* start of critical section */
/* we need to check first if there is an unused allocated slot */
first_null_idx_set = FALSE;
found_free = FALSE;
free_idx = 0;
first_null_idx = 0;
for (stmt_idx = 0, stpp = _stmtv; stmt_idx < _stmtv_size; ++stmt_idx, ++stpp) {
if ((*stpp) && (! (*stpp)->used)) { /* free slot found */
free_idx = stmt_idx;
found_free = TRUE;
break ;
} else if ( !first_null_idx_set && !*stpp) {
first_null_idx = stmt_idx; /* save the first null slot */
first_null_idx_set = TRUE;
break;
}
}
/* an unused allocated slot was found */
if (found_free) {
stpp = &_stmtv[ free_idx ];
TRACE(3, fprintf(_get_trace_fp(dbp),
"_get_stmt_ptr: Reusing handle %u\n", free_idx););
(*stpp)->sth = free_idx ;
(*stpp)->used = TRUE ; /* set this flag *before* releasing the mutex */
} else { /* we need to find a NULL slot and allocate it */
if (first_null_idx_set) {
TRACE(3, fprintf(_get_trace_fp(dbp), "_get_stmt_ptr: Added new handle %u\n",
first_null_idx););
stpp = &_stmtv[ first_null_idx ];
*stpp = MALLOC(sizeof(sqlo_stmt_t)) ;
if (*stpp) {
TRACE(4, fprintf(_get_trace_fp(dbp), "_get_stmt_ptr: Allocated %u bytes\n",
(unsigned int)sizeof(sqlo_stmt_t)););
memset( *stpp, 0, sizeof(sqlo_stmt_t)) ;
(*stpp)->sth = first_null_idx ;
(*stpp)->used = TRUE ; /* set the in use flag *before* releasing the mutex */
} else {
EXEC_WHEN_THREADING( _stmtv_unlock(); ); /* end of critical section */
return (NULL) ;
}
} else {
/* no null slot found */
EXEC_WHEN_THREADING( _stmtv_unlock(); ); /* end of critical section */
return (NULL) ;
}
}
EXEC_WHEN_THREADING((*stpp)->thread_id = _get_thread_id(););
EXEC_WHEN_THREADING(_stmtv_unlock();); /* end of critical section */
return (*stpp) ;
}
/*-------------------------------------------------------------------------*/
/**
* Releases a statement.
* Release is done by setting used to 0.
*/
#ifdef CC_PRAGMA_INLINE
#define PRAGMA INLINE _stmt_release
#endif
static inline void
DEFUN(_stmt_release, (stp), sqlo_stmt_ptr_t stp)
{
EXEC_WHEN_THREADING(_stmtv_lock();); /* enter critical section */
stp->thread_id = 0;
stp->used = FALSE;
EXEC_WHEN_THREADING(_stmtv_unlock();); /* leave critical section */
}
/*-------------------------------------------------------------------------*/
/**
* Initializes the stmt structure
* Sets the dbp into stp and copies stmt into the structure.
* @return SQLO_SUCCESS or SQLO_ERRMALLOC
*/
static int
DEFUN(_stmt_init, (stp, dbp, stmt),
sqlo_stmt_ptr_t stp AND
sqlo_db_ptr_t dbp AND
const char *stmt)
{
unsigned int len = (unsigned int)strlen(stmt) + 1;
stp->dbp = dbp;
stp->stmthp = NULL;
stp->stype = 0;
stp->opened = FALSE;
stp->prepared = FALSE;
stp->still_executing = FALSE;
stp->num_executions = 0;
stp->cursor_type = DEFAULT;
if (!stp->stmt) {
if ( MIN_STMT_SIZE > len )
len = MIN_STMT_SIZE;
ERRMALLOC(stp->dbp, stp->stmt, sizeof(char) * len,
"_stmt_init(alloc stmt)", SQLO_ERRMALLOC);
stp->stmt_size = len;
} else if (stp->stmt_size < len ) {
ERREALLOC(stp->dbp, stp->stmt, sizeof(char) * len,
"_stmt_init(realloc stmt))", SQLO_ERRMALLOC);
stp->stmt_size = len;
}
strcpy(stp->stmt, stmt);
return SQLO_SUCCESS;
}
/*-------------------------------------------------------------------------*/
/**
* Creates a new stmt.
* Allocates the stmt entry via @ref _get_stmt_ptr, allocates the statement handle and
* initializes the structure.
* The stmt structure is initialized.
*
* @return SQLO_SUCCESS or < 0 on error.
*/
static int
DEFUN(_stmt_new, (dbp, stmt, stpp),
sqlo_db_ptr_t dbp AND
const char * stmt AND
sqlo_stmt_ptr_t *stpp)
{
register sqlo_stmt_ptr_t stp;
int status;
stp = _get_stmt_ptr(dbp);
if (! stp) {
sprintf(dbp->errmsg, "SLQORALIB *** FATAL *** : allocation of statement failed") ;
return SQLO_ERRMALLOC;
}
/* init the structure */
if (SQLO_SUCCESS != (status = _stmt_init(stp, dbp, stmt))) {
_stmt_release(stp);
return SQLO_ERROR;
}
/*
* Allocate the statement handle
*/
status = OCIHandleAlloc( (dvoid *) dbp->envhp, (dvoid **) &stp->stmthp,
OCI_HTYPE_STMT, (size_t) 0, (dvoid **) 0);
if (status) {
_stmt_release(stp);
return status;
}
*stpp = stp;
return SQLO_SUCCESS;
}
/*-------------------------------------------------------------------------*/
/**
*
* (Re)allocates space for stp->bindpv[] and stp->indpv[] if necessary.
* Sets stp->bindpv_size to the new size.
* Allocates always in steps of MIN_BINDP, to avoid too many reallocations.
*
* @param stp I - The statement pointer.
* @param size I - The requested size.
*
* @return <ul>
* <li>SQLO_SUCCESS on error.
* <li>SQLO_ERRMALLOC on failure.
* </ul>
*/
static int
DEFUN(_alloc_bindp, (stp, size),
sqlo_stmt_ptr_t stp AND
unsigned int size)
{
if (!stp->bindpv_size ) { /* complety empty ? */
/* allocate MIN_BINDP to avoid a lot of reallocations */
if (size < MIN_BINDP)
size = MIN_BINDP;
TRACE(4, fprintf(_get_trace_fp(stp->dbp),
"_alloc_bindp: alloc sth: %u to %u elements\n",
stp->sth, size););
ERRMALLOC(stp->dbp, stp->bindpv, sizeof(OCIBind*) * size,
"_alloc_bindp(bindp)", SQLO_ERRMALLOC);
ERRMALLOC(stp->dbp, stp->indpv, sizeof(short) * size,
"_alloc_bindp(ind)", SQLO_ERRMALLOC);
stp->bindpv_size = size;
_bindpv_reset(stp);
memset(stp->bindpv, 0, size * sizeof(OCIBind*));
memset(stp->indpv, 0, size * sizeof(short));
} else {
/* Still enough space, or realloc necessary? */
if (size > stp->bindpv_size) {
size = 2 * size; /* alloc twice as much, so we don't have to realloc it too often */
TRACE(4, fprintf(_get_trace_fp(stp->dbp),
"_alloc_bindpv: realloc sth: %u to %u elements\n",
stp->sth, size););
ERREALLOC(stp->dbp, stp->bindpv, sizeof(OCIBind*) * size,
"sqlo_realloc_bind(bindpv)", SQLO_ERRMALLOC );
ERREALLOC(stp->dbp, stp->indpv, sizeof(short) * size,
"sqlo_realloc_bind(indp)", SQLO_ERRMALLOC );
stp->bindpv_size = size;
/* init the new elements */
size = size - stp->bindpv_size; /* number of elements to be initialized */
memset(&stp->bindpv[ stp->bindpv_size ], 0, size * sizeof(OCIBind *));
memset(&stp->indpv[ stp->bindpv_size ], 0, size * sizeof(short));
}
}
return(SQLO_SUCCESS);
}
/*-------------------------------------------------------------------------*/
/**
* (Re)allocates more space for output variables.
* (Re)allocates more space for stp->ocolsv[], stp->outv,
* stp->defnpv, stp->ocol_namev_size and stp->ocol_namev.
* Sets stp->defnpv_size is set to the new size.
* Allocates always in steps of MINUM_DEFNPV, to avoid too much memory free/allocs
*
* @param stp I - The statement pointer
* @param size I - The requested size.
*
* @return <ul>
* <li>SQLO_SUCCESS on error.
* <li>SQLO_ERRMALLOC on failure.
* </ul>
*/
static int
DEFUN(_alloc_definep, (stp, size), sqlo_stmt_ptr_t stp AND unsigned int size)
{
register unsigned int i;
if (!stp->defnpv_size ) { /* complety empty ? */
/* allocate MIN_DEFNP to avoid a lot of reallocations */
if (size < MIN_DEFNP)
size = MIN_DEFNP;
TRACE(4, fprintf(_get_trace_fp(stp->dbp),
"_alloc_definep: alloc sth: %u for %u columns\n",
stp->sth, size););
ERRMALLOC(stp->dbp, stp->defnpv, sizeof(OCIDefine *) * size,
"_alloc_definep(alloc defnpv)", SQLO_ERRMALLOC);
ERRMALLOC(stp->dbp, stp->ocolsv, sizeof(sqlo_col_t) * size,
"_alloc_definep(alloc ocols)", SQLO_ERRMALLOC);
ERRMALLOC(stp->dbp, stp->outv, sizeof(char *) * size,
"_alloc_definep(alloc outv)", SQLO_ERRMALLOC);
ERRMALLOC(stp->dbp, stp->outv_size, sizeof(int) * size,
"_alloc_definep(alloc outv_size)", SQLO_ERRMALLOC);
ERRMALLOC(stp->dbp, stp->oindv, sizeof(ub2) * size,
"_alloc_definep(alloc oindv)", SQLO_ERRMALLOC);
ERRMALLOC(stp->dbp, stp->rlenv, sizeof(ub2) * size,
"_alloc_definep(alloc rlenv)", SQLO_ERRMALLOC);
ERRMALLOC(stp->dbp, stp->ocol_namev, sizeof(char *) * size,
"_alloc_definep(alloc ocol_namev)", SQLO_ERRMALLOC);
ERRMALLOC(stp->dbp, stp->ocol_namev_size, sizeof(int) * size,
"_alloc_definep(alloc ocol_namev_size)", SQLO_ERRMALLOC);
memset(stp->defnpv, 0, sizeof(OCIDefine *) * size);
memset(stp->ocolsv, 0, sizeof(sqlo_col_t) * size);
memset(stp->outv, 0, sizeof(char *) * size);
memset(stp->outv_size, 0, sizeof(int) * size);
memset(stp->oindv, 0, sizeof(ub2) * size);
memset(stp->rlenv, 0, sizeof(ub2) * size);
memset(stp->ocol_namev, 0, sizeof(char *) * size);
memset(stp->ocol_namev_size, 0, sizeof(int) * size);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -