1998-07-18 00:57:32 +00:00
|
|
|
/** Error stack management functions
|
|
|
|
|
|
|
|
Copyright (C) 1995 by Ke Jin <kejin@empress.com>
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
**/
|
|
|
|
|
|
|
|
#include <../iodbc/iodbc.h>
|
|
|
|
|
|
|
|
#include <../iodbc/isql.h>
|
|
|
|
#include <../iodbc/isqlext.h>
|
|
|
|
|
|
|
|
#include <../iodbc/dlproc.h>
|
|
|
|
|
|
|
|
#include <../iodbc/herr.h>
|
|
|
|
#include <../iodbc/henv.h>
|
|
|
|
#include <../iodbc/hdbc.h>
|
|
|
|
#include <../iodbc/hstmt.h>
|
|
|
|
|
|
|
|
#include <../iodbc/itrace.h>
|
|
|
|
|
|
|
|
#include "../iodbc/herr.ci"
|
1998-07-25 08:31:39 +00:00
|
|
|
#include <strings.h>
|
|
|
|
#include <stdio.h>
|
1998-07-18 00:57:32 +00:00
|
|
|
|
|
|
|
static HERR _iodbcdm_popsqlerr( HERR herr )
|
|
|
|
{
|
|
|
|
sqlerr_t* list = (sqlerr_t*)herr;
|
|
|
|
sqlerr_t* next;
|
|
|
|
|
|
|
|
if( herr == SQL_NULL_HERR )
|
|
|
|
{
|
|
|
|
return herr;
|
|
|
|
}
|
|
|
|
|
|
|
|
next = list->next;
|
|
|
|
|
|
|
|
MEM_FREE (list);
|
|
|
|
|
|
|
|
return next;
|
|
|
|
}
|
|
|
|
|
|
|
|
void _iodbcdm_freesqlerrlist( HERR herrlist )
|
|
|
|
{
|
|
|
|
HERR list;
|
|
|
|
|
|
|
|
for(list = herrlist; list!= 0; )
|
|
|
|
{
|
|
|
|
list = _iodbcdm_popsqlerr(list);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
HERR _iodbcdm_pushsqlerr (
|
|
|
|
HERR herr,
|
|
|
|
sqlstcode_t code,
|
|
|
|
char* msg )
|
|
|
|
{
|
|
|
|
sqlerr_t* ebuf;
|
|
|
|
sqlerr_t* perr = (sqlerr_t*)herr;
|
|
|
|
int idx = 0;
|
|
|
|
|
|
|
|
if(herr != SQL_NULL_HERR )
|
|
|
|
{
|
|
|
|
idx = perr->idx + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( idx == 64 )
|
|
|
|
/* over wirte the top entry to prevent error stack blow out */
|
|
|
|
{
|
|
|
|
perr->code = code;
|
|
|
|
perr->msg = msg;
|
|
|
|
|
|
|
|
return herr;
|
|
|
|
}
|
|
|
|
|
|
|
|
ebuf = (sqlerr_t*)MEM_ALLOC (sizeof(sqlerr_t));
|
|
|
|
|
|
|
|
if( ebuf == NULL )
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
ebuf->msg = msg;
|
|
|
|
ebuf->code = code;
|
|
|
|
ebuf->idx = idx;
|
|
|
|
ebuf->next = (sqlerr_t*)herr;
|
|
|
|
|
|
|
|
return (HERR)ebuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char FAR* _iodbcdm_getsqlstate (
|
|
|
|
HERR herr,
|
|
|
|
void FAR* tab )
|
|
|
|
{
|
|
|
|
sqlerr_t* perr = (sqlerr_t*)herr;
|
|
|
|
sqlerrmsg_t* ptr;
|
|
|
|
|
|
|
|
if( herr == SQL_NULL_HERR || tab == NULL )
|
|
|
|
{
|
|
|
|
return (char FAR*)NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
for( ptr = tab;
|
|
|
|
ptr->code != en_sqlstat_total;
|
|
|
|
ptr++ )
|
|
|
|
{
|
|
|
|
if(ptr->code == perr->code)
|
|
|
|
{
|
|
|
|
return (char FAR*)(ptr->stat);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (char FAR*)NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char FAR* _iodbcdm_getsqlerrmsg(
|
|
|
|
HERR herr,
|
|
|
|
void FAR* errtab )
|
|
|
|
{
|
|
|
|
sqlerr_t* perr = (sqlerr_t*)herr;
|
|
|
|
sqlerrmsg_t* ptr;
|
|
|
|
|
|
|
|
if( herr == SQL_NULL_HERR )
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( perr->msg == NULL && errtab == NULL )
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( perr->msg != NULL )
|
|
|
|
{
|
|
|
|
return perr->msg;
|
|
|
|
}
|
|
|
|
|
|
|
|
for( ptr = (sqlerrmsg_t*)errtab;
|
|
|
|
ptr->code != en_sqlstat_total;
|
|
|
|
ptr++ )
|
|
|
|
{
|
|
|
|
if( ptr->code == perr->code )
|
|
|
|
{
|
|
|
|
return (char FAR*)ptr->msg;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return (char FAR*)NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
RETCODE SQL_API SQLError (
|
|
|
|
HENV henv,
|
|
|
|
HDBC hdbc,
|
|
|
|
HSTMT hstmt,
|
|
|
|
UCHAR FAR* szSqlstate,
|
|
|
|
SDWORD FAR* pfNativeError,
|
|
|
|
UCHAR FAR* szErrorMsg,
|
|
|
|
SWORD cbErrorMsgMax,
|
|
|
|
SWORD FAR* pcbErrorMsg )
|
|
|
|
{
|
|
|
|
GENV_t FAR* genv = (GENV_t FAR*) henv;
|
|
|
|
DBC_t FAR* pdbc = (DBC_t FAR*) hdbc;
|
|
|
|
STMT_t FAR* pstmt = (STMT_t FAR*)hstmt;
|
|
|
|
HDBC thdbc;
|
|
|
|
|
|
|
|
HENV dhenv = SQL_NULL_HENV;
|
|
|
|
HDBC dhdbc = SQL_NULL_HDBC;
|
|
|
|
HSTMT dhstmt = SQL_NULL_HSTMT;
|
|
|
|
|
|
|
|
HERR herr = SQL_NULL_HERR;
|
|
|
|
HPROC hproc = SQL_NULL_HPROC;
|
|
|
|
|
|
|
|
char FAR* errmsg = NULL;
|
|
|
|
char FAR* ststr = NULL;
|
|
|
|
|
|
|
|
int handle = 0;
|
|
|
|
RETCODE retcode = SQL_SUCCESS;
|
|
|
|
|
|
|
|
if( hstmt != SQL_NULL_HSTMT ) /* retrive stmt err */
|
|
|
|
{
|
|
|
|
herr = pstmt->herr;
|
|
|
|
thdbc = pstmt->hdbc;
|
|
|
|
|
|
|
|
if( thdbc == SQL_NULL_HDBC )
|
|
|
|
{
|
|
|
|
return SQL_INVALID_HANDLE;
|
|
|
|
}
|
|
|
|
hproc = _iodbcdm_getproc( thdbc, en_Error );
|
|
|
|
dhstmt = pstmt->dhstmt;
|
|
|
|
handle = 3;
|
|
|
|
}
|
|
|
|
else if( hdbc != SQL_NULL_HDBC ) /* retrive dbc err */
|
|
|
|
{
|
|
|
|
herr = pdbc->herr;
|
|
|
|
thdbc = hdbc;
|
|
|
|
if( thdbc == SQL_NULL_HDBC )
|
|
|
|
{
|
|
|
|
return SQL_INVALID_HANDLE;
|
|
|
|
}
|
|
|
|
hproc = _iodbcdm_getproc( thdbc, en_Error );
|
|
|
|
dhdbc = pdbc->dhdbc;
|
|
|
|
handle = 2;
|
|
|
|
|
|
|
|
if( herr == SQL_NULL_HERR
|
|
|
|
&& pdbc->henv == SQL_NULL_HENV )
|
|
|
|
{
|
|
|
|
return SQL_NO_DATA_FOUND;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if( henv != SQL_NULL_HENV ) /* retrive env err */
|
|
|
|
{
|
|
|
|
herr = genv->herr;
|
|
|
|
|
|
|
|
/* Drivers shouldn't push error message
|
|
|
|
* on envoriment handle */
|
|
|
|
|
|
|
|
if( herr == SQL_NULL_HERR )
|
|
|
|
{
|
|
|
|
return SQL_NO_DATA_FOUND;
|
|
|
|
}
|
|
|
|
|
|
|
|
handle = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return SQL_INVALID_HANDLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( szErrorMsg != NULL )
|
|
|
|
{
|
|
|
|
if( cbErrorMsgMax < 0
|
|
|
|
|| cbErrorMsgMax > SQL_MAX_MESSAGE_LENGTH - 1 )
|
|
|
|
{
|
|
|
|
return SQL_ERROR;
|
|
|
|
/* SQLError() doesn't post error for itself */
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( herr == SQL_NULL_HERR ) /* no err on drv mng */
|
|
|
|
{
|
|
|
|
/* call driver */
|
|
|
|
if( hproc == SQL_NULL_HPROC )
|
|
|
|
{
|
|
|
|
PUSHSQLERR ( herr, en_IM001 );
|
|
|
|
|
|
|
|
return SQL_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
CALL_DRIVER ( thdbc, retcode, hproc, en_Error, (
|
|
|
|
dhenv, dhdbc, dhstmt,
|
|
|
|
szSqlstate, pfNativeError,
|
|
|
|
szErrorMsg, cbErrorMsgMax, pcbErrorMsg) )
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
retcode = hproc(dhenv, dhdbc, dhstmt,
|
|
|
|
szSqlstate, pfNativeError,
|
|
|
|
szErrorMsg, cbErrorMsgMax, pcbErrorMsg);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return retcode;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( szSqlstate != NULL )
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
|
|
|
|
/* get sql state string */
|
|
|
|
ststr = (char FAR*)_iodbcdm_getsqlstate( herr,
|
|
|
|
(void FAR*)sqlerrmsg_tab );
|
|
|
|
|
|
|
|
if( ststr == NULL)
|
|
|
|
{
|
|
|
|
len = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
len = (int)STRLEN(ststr);
|
|
|
|
}
|
|
|
|
|
|
|
|
STRNCPY ( szSqlstate, ststr, len );
|
|
|
|
szSqlstate[len] = 0;
|
|
|
|
/* buffer size of szSqlstate is not checked. Applications
|
|
|
|
* suppose provide enough ( not less than 6 bytes ) buffer
|
|
|
|
* or NULL for it.
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
if( pfNativeError != NULL )
|
|
|
|
{
|
|
|
|
/* native error code is specific to data source */
|
|
|
|
*pfNativeError = (SDWORD)0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( szErrorMsg == NULL || cbErrorMsgMax == 0 )
|
|
|
|
{
|
|
|
|
if( pcbErrorMsg != NULL )
|
|
|
|
{
|
|
|
|
*pcbErrorMsg = (SWORD)0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
char msgbuf[256] = { '\0' };
|
|
|
|
|
|
|
|
/* get sql state message */
|
|
|
|
errmsg = _iodbcdm_getsqlerrmsg(herr,
|
|
|
|
(void FAR*)sqlerrmsg_tab);
|
|
|
|
|
|
|
|
if(errmsg == NULL)
|
|
|
|
{
|
|
|
|
errmsg = (char FAR*)"";
|
|
|
|
}
|
|
|
|
|
|
|
|
sprintf(msgbuf, "%s%s", sqlerrhd, errmsg);
|
|
|
|
|
|
|
|
len = STRLEN( msgbuf );
|
|
|
|
|
|
|
|
if( len < cbErrorMsgMax - 1 )
|
|
|
|
{
|
|
|
|
retcode = SQL_SUCCESS;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
len = cbErrorMsgMax - 1;
|
|
|
|
retcode = SQL_SUCCESS_WITH_INFO;
|
|
|
|
/* and not posts error for itself */
|
|
|
|
}
|
|
|
|
|
|
|
|
STRNCPY((char*)szErrorMsg, msgbuf, len);
|
|
|
|
szErrorMsg[len] = 0;
|
|
|
|
|
|
|
|
if( pcbErrorMsg != NULL)
|
|
|
|
{
|
|
|
|
*pcbErrorMsg = (SWORD)len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(handle) /* free this err */
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
genv->herr = _iodbcdm_popsqlerr(genv->herr);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
pdbc->herr = _iodbcdm_popsqlerr(pdbc->herr);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
pstmt->herr= _iodbcdm_popsqlerr(pstmt->herr);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retcode;
|
|
|
|
}
|