2001-05-23 15:26:42 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: Dynamic SQL runtime support
|
2003-10-05 08:27:16 +02:00
|
|
|
* MODULE: err.cpp
|
2001-05-23 15:26:42 +02:00
|
|
|
* DESCRIPTION: Error handlers
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Interbase Public
|
|
|
|
* License Version 1.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy
|
|
|
|
* of the License at http://www.Inprise.com/IPL.html
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an
|
|
|
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
|
|
|
* or implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
|
|
|
*
|
|
|
|
* The Original Code was created by Inprise Corporation
|
|
|
|
* and its predecessors. Portions created by Inprise Corporation are
|
|
|
|
* Copyright (C) Inprise Corporation.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
2002-06-29 08:56:51 +02:00
|
|
|
*
|
|
|
|
* 27 Nov 2001 Ann W. Harrison - preserve string arguments in
|
|
|
|
* ERRD_post_warning
|
2002-10-29 03:59:57 +01:00
|
|
|
*
|
|
|
|
* 2002.10.28 Sean Leyne - Code cleanup, removed obsolete "MPEXL" port
|
|
|
|
*
|
2002-10-30 07:40:58 +01:00
|
|
|
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
|
|
|
|
*
|
2001-05-23 15:26:42 +02:00
|
|
|
*/
|
|
|
|
|
2001-07-30 01:43:24 +02:00
|
|
|
#include "firebird.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/ib_stdio.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "../jrd/common.h"
|
2001-07-12 07:46:06 +02:00
|
|
|
#ifdef HAVE_STDARG_H
|
2001-05-23 15:26:42 +02:00
|
|
|
#include <stdarg.h>
|
2001-07-12 07:46:06 +02:00
|
|
|
#endif
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
#include "../dsql/dsql.h"
|
|
|
|
#include "../dsql/sqlda.h"
|
2003-11-11 13:19:20 +01:00
|
|
|
#include "gen/iberror.h"
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/iberr.h"
|
|
|
|
#include "../dsql/errd_proto.h"
|
|
|
|
#include "../dsql/utld_proto.h"
|
2003-03-01 16:59:08 +01:00
|
|
|
|
|
|
|
// This is the only one place in dsql code, where we need both
|
|
|
|
// dsql.h and err_proto.h.
|
|
|
|
// To avoid warnings, undefine some macro's here
|
2003-10-03 04:00:40 +02:00
|
|
|
//#undef BUGCHECK
|
|
|
|
//#undef IBERROR
|
2003-03-01 16:59:08 +01:00
|
|
|
|
2002-07-02 14:20:50 +02:00
|
|
|
#include "../jrd/err_proto.h"
|
2003-03-01 16:59:08 +01:00
|
|
|
|
|
|
|
// To ensure that suspicious macro's not used in this file,
|
|
|
|
// undefine them once more.
|
2003-10-03 04:00:40 +02:00
|
|
|
//#undef BUGCHECK
|
|
|
|
//#undef IBERROR
|
2003-03-01 16:59:08 +01:00
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
#include "../jrd/gds_proto.h"
|
|
|
|
#include "../jrd/thd_proto.h"
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef DEV_BUILD
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
ERRD_assert_msg
|
|
|
|
|
|
|
|
@brief Generate an assertion failure with a message
|
|
|
|
|
|
|
|
|
|
|
|
@param msg
|
|
|
|
@param file
|
|
|
|
@param lineno
|
|
|
|
|
|
|
|
**/
|
2001-12-24 03:51:06 +01:00
|
|
|
void ERRD_assert_msg(const char* msg, const char* file, ULONG lineno)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
char buffer[100];
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
sprintf(buffer, "Assertion failure: %s File: %s Line: %ld\n", // NTX: dev build
|
2001-12-24 03:51:06 +01:00
|
|
|
(msg ? msg : ""), (file ? file : ""), lineno);
|
2001-05-23 15:26:42 +02:00
|
|
|
ERRD_bugcheck(buffer);
|
|
|
|
}
|
2003-11-28 07:48:34 +01:00
|
|
|
#endif // DEV_BUILD
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
ERRD_bugcheck
|
|
|
|
|
|
|
|
@brief Somebody has screwed up. Bugcheck.
|
|
|
|
|
|
|
|
|
|
|
|
@param text
|
|
|
|
|
|
|
|
**/
|
2001-12-24 03:51:06 +01:00
|
|
|
void ERRD_bugcheck(const char* text)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
TEXT s[128];
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
sprintf(s, "INTERNAL: %s", text); // TXNN
|
2001-05-23 15:26:42 +02:00
|
|
|
ERRD_error(-1, s);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
ERRD_error
|
|
|
|
|
|
|
|
@brief This routine should only be used by fatal
|
|
|
|
error messages, those that cannot use the
|
|
|
|
normal error routines because something
|
|
|
|
is very badly wrong. ERRD_post() should
|
|
|
|
be used by most error messages, especially
|
|
|
|
so that strings will be handled.
|
|
|
|
|
|
|
|
|
|
|
|
@param code
|
|
|
|
@param text
|
|
|
|
|
|
|
|
**/
|
2001-12-24 03:51:06 +01:00
|
|
|
void ERRD_error( int code, const char* text)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2002-12-10 12:53:53 +01:00
|
|
|
TEXT s[256];
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-02-02 12:02:12 +01:00
|
|
|
tsql* tdsql = GET_THREAD_DATA;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
sprintf(s, "** DSQL error: %s **\n", text);
|
|
|
|
TRACE(s);
|
|
|
|
|
2003-10-05 08:27:16 +02:00
|
|
|
ISC_STATUS* status_vector = tdsql->tsql_status;
|
|
|
|
if (status_vector) {
|
2003-11-11 13:19:20 +01:00
|
|
|
*status_vector++ = isc_arg_gds;
|
|
|
|
*status_vector++ = isc_random;
|
|
|
|
*status_vector++ = isc_arg_cstring;
|
2002-07-02 14:20:50 +02:00
|
|
|
*status_vector++ = strlen(s);
|
|
|
|
*status_vector++ = reinterpret_cast<long>(s);
|
2003-11-11 13:19:20 +01:00
|
|
|
*status_vector++ = isc_arg_end;
|
2002-06-29 08:56:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ERRD_punt();
|
|
|
|
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
ERRD_post_warning
|
|
|
|
|
|
|
|
@brief Post a warning to the current status vector.
|
|
|
|
|
|
|
|
|
|
|
|
@param status
|
|
|
|
@param
|
|
|
|
|
|
|
|
**/
|
2003-09-12 03:41:03 +02:00
|
|
|
bool ERRD_post_warning(ISC_STATUS status, ...)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
#pragma FB_COMPILER_MESSAGE("Warning, using STATUS array to hold pointers to STATUSes!")
|
2003-02-12 20:28:13 +01:00
|
|
|
// meaning; if sizeof(long) != sizeof(void*), this code WILL crash something.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
|
|
|
|
VA_START(args, status);
|
2003-02-12 20:28:13 +01:00
|
|
|
|
2004-02-02 12:02:12 +01:00
|
|
|
ISC_STATUS* status_vector = ((tsql*) GET_THREAD_DATA)->tsql_status;
|
2003-02-12 20:28:13 +01:00
|
|
|
int indx = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-11 13:19:20 +01:00
|
|
|
if (status_vector[0] != isc_arg_gds ||
|
|
|
|
(status_vector[0] == isc_arg_gds && status_vector[1] == 0 &&
|
|
|
|
status_vector[2] != isc_arg_warning))
|
2003-02-12 20:28:13 +01:00
|
|
|
{
|
2003-11-28 07:48:34 +01:00
|
|
|
// this is a blank status vector
|
2003-11-11 13:19:20 +01:00
|
|
|
status_vector[0] = isc_arg_gds;
|
2001-05-23 15:26:42 +02:00
|
|
|
status_vector[1] = 0;
|
2003-11-11 13:19:20 +01:00
|
|
|
status_vector[2] = isc_arg_end;
|
2001-05-23 15:26:42 +02:00
|
|
|
indx = 2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-11-28 07:48:34 +01:00
|
|
|
// find end of a status vector
|
2003-02-12 20:28:13 +01:00
|
|
|
int warning_indx = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_STATUS(status_vector, indx, warning_indx);
|
2003-02-12 20:28:13 +01:00
|
|
|
if (indx) {
|
2001-05-23 15:26:42 +02:00
|
|
|
--indx;
|
2003-02-12 20:28:13 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
// stuff the warning
|
2003-02-12 20:28:13 +01:00
|
|
|
if (indx + 3 >= ISC_STATUS_LENGTH)
|
|
|
|
{
|
2003-11-28 07:48:34 +01:00
|
|
|
// not enough free space
|
2003-09-12 03:41:03 +02:00
|
|
|
return false;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
2003-02-12 20:28:13 +01:00
|
|
|
|
2003-11-11 13:19:20 +01:00
|
|
|
status_vector[indx++] = isc_arg_warning;
|
2003-02-12 20:28:13 +01:00
|
|
|
status_vector[indx++] = status;
|
|
|
|
int type, len;
|
|
|
|
while ((type = va_arg(args, int)) && (indx + 3 < ISC_STATUS_LENGTH))
|
|
|
|
{
|
|
|
|
|
|
|
|
char* pszTmp = NULL;
|
|
|
|
switch (status_vector[indx++] = type)
|
|
|
|
{
|
2003-11-11 13:19:20 +01:00
|
|
|
case isc_arg_warning:
|
2003-04-10 08:32:58 +02:00
|
|
|
status_vector[indx++] = (ISC_STATUS) va_arg(args, ISC_STATUS);
|
2003-02-12 20:28:13 +01:00
|
|
|
break;
|
|
|
|
|
2003-11-11 13:19:20 +01:00
|
|
|
case isc_arg_string:
|
2003-02-12 20:28:13 +01:00
|
|
|
pszTmp = va_arg(args, char*);
|
|
|
|
if (strlen(pszTmp) >= MAX_ERRSTR_LEN) {
|
2003-11-11 13:19:20 +01:00
|
|
|
status_vector[(indx - 1)] = isc_arg_cstring;
|
2003-02-12 20:28:13 +01:00
|
|
|
status_vector[indx++] = MAX_ERRSTR_LEN;
|
|
|
|
}
|
|
|
|
status_vector[indx++] = reinterpret_cast<long>(ERR_cstring(pszTmp));
|
|
|
|
break;
|
|
|
|
|
2003-11-11 13:19:20 +01:00
|
|
|
case isc_arg_interpreted:
|
2003-02-12 20:28:13 +01:00
|
|
|
pszTmp = va_arg(args, char*);
|
|
|
|
status_vector[indx++] = reinterpret_cast<long>(ERR_cstring(pszTmp));
|
|
|
|
break;
|
|
|
|
|
2003-11-11 13:19:20 +01:00
|
|
|
case isc_arg_cstring:
|
2003-02-12 20:28:13 +01:00
|
|
|
len = va_arg(args, int);
|
|
|
|
status_vector[indx++] =
|
2003-04-10 08:32:58 +02:00
|
|
|
(ISC_STATUS) (len >= MAX_ERRSTR_LEN) ? MAX_ERRSTR_LEN : len;
|
2003-02-12 20:28:13 +01:00
|
|
|
pszTmp = va_arg(args, char*);
|
|
|
|
status_vector[indx++] = reinterpret_cast<long>(ERR_cstring(pszTmp));
|
|
|
|
break;
|
|
|
|
|
2003-11-11 13:19:20 +01:00
|
|
|
case isc_arg_number:
|
2003-04-10 08:32:58 +02:00
|
|
|
status_vector[indx++] = (ISC_STATUS) va_arg(args, SLONG);
|
2003-02-12 20:28:13 +01:00
|
|
|
break;
|
|
|
|
|
2003-11-11 13:19:20 +01:00
|
|
|
case isc_arg_vms:
|
|
|
|
case isc_arg_unix:
|
|
|
|
case isc_arg_win32:
|
2003-02-12 20:28:13 +01:00
|
|
|
default:
|
2003-04-10 08:32:58 +02:00
|
|
|
status_vector[indx++] = (ISC_STATUS) va_arg(args, int);
|
2003-02-12 20:28:13 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2003-11-11 13:19:20 +01:00
|
|
|
status_vector[indx] = isc_arg_end;
|
2003-09-12 03:41:03 +02:00
|
|
|
return true;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
ERRD_post
|
|
|
|
|
|
|
|
@brief Post an error, copying any potentially
|
|
|
|
transient data before we punt.
|
|
|
|
|
|
|
|
|
|
|
|
@param status
|
|
|
|
@param
|
|
|
|
|
|
|
|
**/
|
2003-04-10 08:32:58 +02:00
|
|
|
void ERRD_post(ISC_STATUS status, ...)
|
2001-05-23 15:26:42 +02:00
|
|
|
{
|
2001-12-29 12:41:29 +01:00
|
|
|
int warning_indx = 0;
|
|
|
|
|
2004-02-02 12:02:12 +01:00
|
|
|
ISC_STATUS* status_vector = ((tsql*) GET_THREAD_DATA)->tsql_status;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
// stuff the status into temp buffer
|
2003-11-18 08:58:35 +01:00
|
|
|
ISC_STATUS_ARRAY tmp_status;
|
2001-05-23 15:26:42 +02:00
|
|
|
MOVE_CLEAR(tmp_status, sizeof(tmp_status));
|
|
|
|
STUFF_STATUS(tmp_status, status);
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
// calculate length of the status
|
2003-11-18 08:58:35 +01:00
|
|
|
int tmp_status_len = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_STATUS(tmp_status, tmp_status_len, warning_indx);
|
2003-11-04 00:59:24 +01:00
|
|
|
fb_assert(warning_indx == 0);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-11 13:19:20 +01:00
|
|
|
if (status_vector[0] != isc_arg_gds ||
|
|
|
|
(status_vector[0] == isc_arg_gds && status_vector[1] == 0 &&
|
|
|
|
status_vector[2] != isc_arg_warning))
|
2001-12-29 12:41:29 +01:00
|
|
|
{
|
2003-11-28 07:48:34 +01:00
|
|
|
// this is a blank status vector
|
2003-11-11 13:19:20 +01:00
|
|
|
status_vector[0] = isc_arg_gds;
|
|
|
|
status_vector[1] = isc_dsql_error;
|
|
|
|
status_vector[2] = isc_arg_end;
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|
2003-11-18 08:58:35 +01:00
|
|
|
int status_len = 0;
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_STATUS(status_vector, status_len, warning_indx);
|
|
|
|
if (status_len)
|
|
|
|
--status_len;
|
|
|
|
|
2001-12-29 12:41:29 +01:00
|
|
|
// check for duplicated error code
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < ISC_STATUS_LENGTH; i++)
|
|
|
|
{
|
2003-11-11 13:19:20 +01:00
|
|
|
if (status_vector[i] == isc_arg_end && i == status_len) {
|
2003-11-28 07:48:34 +01:00
|
|
|
break; // end of argument list
|
2001-12-29 12:41:29 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-29 12:41:29 +01:00
|
|
|
if (i && i == warning_indx) {
|
2003-11-28 07:48:34 +01:00
|
|
|
break; // vector has no more errors
|
2001-12-29 12:41:29 +01:00
|
|
|
}
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (status_vector[i] == tmp_status[1] && i &&
|
2003-11-11 13:19:20 +01:00
|
|
|
status_vector[i - 1] != isc_arg_warning &&
|
2001-05-23 15:26:42 +02:00
|
|
|
i + tmp_status_len - 2 < ISC_STATUS_LENGTH &&
|
|
|
|
(memcmp(&status_vector[i], &tmp_status[1],
|
2003-04-10 08:32:58 +02:00
|
|
|
sizeof(ISC_STATUS) * (tmp_status_len - 2)) == 0))
|
2001-12-29 12:41:29 +01:00
|
|
|
{
|
2003-11-28 07:48:34 +01:00
|
|
|
// duplicate found
|
2001-05-23 15:26:42 +02:00
|
|
|
ERRD_punt();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-12-29 12:41:29 +01:00
|
|
|
// if the status_vector has only warnings then adjust err_status_len
|
|
|
|
int err_status_len = i;
|
|
|
|
if (err_status_len == 2 && warning_indx) {
|
2001-05-23 15:26:42 +02:00
|
|
|
err_status_len = 0;
|
2001-12-29 12:41:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int warning_count = 0;
|
2003-11-18 08:58:35 +01:00
|
|
|
ISC_STATUS_ARRAY warning_status;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
if (warning_indx) {
|
|
|
|
/* copy current warning(s) to a temp buffer */
|
|
|
|
MOVE_CLEAR(warning_status, sizeof(warning_status));
|
|
|
|
MOVE_FASTER(&status_vector[warning_indx], warning_status,
|
2003-04-10 08:32:58 +02:00
|
|
|
sizeof(ISC_STATUS) * (ISC_STATUS_LENGTH - warning_indx));
|
2001-05-23 15:26:42 +02:00
|
|
|
PARSE_STATUS(warning_status, warning_count, warning_indx);
|
|
|
|
}
|
|
|
|
|
2001-12-29 12:41:29 +01:00
|
|
|
// add the status into a real buffer right in between last
|
|
|
|
// error and first warning
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2001-12-29 12:41:29 +01:00
|
|
|
i = err_status_len + tmp_status_len;
|
|
|
|
if (i < ISC_STATUS_LENGTH)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
MOVE_FASTER(tmp_status, &status_vector[err_status_len],
|
2003-04-10 08:32:58 +02:00
|
|
|
sizeof(ISC_STATUS) * tmp_status_len);
|
2001-05-23 15:26:42 +02:00
|
|
|
/* copy current warning(s) to the status_vector */
|
2001-12-29 12:41:29 +01:00
|
|
|
if (warning_count && i + warning_count - 1 < ISC_STATUS_LENGTH)
|
|
|
|
{
|
2001-05-23 15:26:42 +02:00
|
|
|
MOVE_FASTER(warning_status, &status_vector[i - 1],
|
2003-04-10 08:32:58 +02:00
|
|
|
sizeof(ISC_STATUS) * warning_count);
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ERRD_punt();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-15 04:01:51 +01:00
|
|
|
/**
|
|
|
|
|
|
|
|
ERRD_punt
|
|
|
|
|
|
|
|
@brief Error stuff has been copied to
|
|
|
|
status vector. Now punt.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**/
|
2001-05-23 15:26:42 +02:00
|
|
|
void ERRD_punt(void)
|
|
|
|
{
|
2004-02-02 12:02:12 +01:00
|
|
|
tsql* tdsql = GET_THREAD_DATA;
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
// Save any strings in a permanent location
|
2001-05-23 15:26:42 +02:00
|
|
|
|
|
|
|
UTLD_save_status_strings(tdsql->tsql_status);
|
|
|
|
|
2003-11-28 07:48:34 +01:00
|
|
|
// Give up whatever we were doing and return to the user.
|
2001-05-23 15:26:42 +02:00
|
|
|
|
2004-03-01 04:35:23 +01:00
|
|
|
Firebird::status_exception::raise(tdsql->tsql_status);
|
2001-05-23 15:26:42 +02:00
|
|
|
}
|
|
|
|
|