8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-27 06:43:04 +01:00
firebird-mirror/src/dsql/errd.cpp

325 lines
7.2 KiB
C++
Raw Normal View History

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.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
*/
#include "firebird.h"
2004-04-29 00:00:03 +02:00
#include <stdio.h>
2001-05-23 15:26:42 +02:00
#include <string.h>
#include "../jrd/common.h"
#include "../dsql/dsql.h"
#include "../dsql/sqlda.h"
#include "gen/iberror.h"
2008-02-28 14:48:16 +01:00
#include "../jrd/jrd.h"
2001-05-23 15:26:42 +02:00
#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
//#undef BUGCHECK
//#undef IBERROR
2003-03-01 16:59:08 +01: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.
//#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 "../common/utils_proto.h"
2001-05-23 15:26:42 +02:00
2008-02-28 14:48:16 +01:00
using namespace Jrd;
using namespace Firebird;
2008-02-28 14:48:16 +01:00
2001-05-23 15:26:42 +02:00
static void internal_post(const ISC_STATUS* status_vector);
2001-05-23 15:26:42 +02:00
#ifdef DEV_BUILD
/**
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[MAXPATHLEN + 100];
2001-05-23 15:26:42 +02:00
fb_utils::snprintf(buffer, sizeof(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);
}
#endif // DEV_BUILD
2001-05-23 15:26:42 +02: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[MAXPATHLEN + 120];
fb_utils::snprintf(s, sizeof(s), "INTERNAL: %s", text); // TXNN
2008-04-12 18:07:45 +02:00
ERRD_error(s);
2001-05-23 15:26:42 +02: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
**/
2008-04-12 18:07:45 +02:00
void ERRD_error(const char* text)
2001-05-23 15:26:42 +02:00
{
TEXT s[MAXPATHLEN + 140];
fb_utils::snprintf(s, sizeof(s), "** DSQL error: %s **\n", text);
2001-05-23 15:26:42 +02:00
TRACE(s);
status_exception::raise(Arg::Gds(isc_random) << Arg::Str(s));
2001-05-23 15:26:42 +02:00
}
/**
ERRD_post_warning
@brief Post a warning to the current status vector.
@param status
@param
**/
bool ERRD_post_warning(const Firebird::Arg::StatusVector& v)
2001-05-23 15:26:42 +02:00
{
2008-02-28 14:48:16 +01:00
ISC_STATUS* status_vector = JRD_get_thread_data()->tdbb_status_vector;
int indx = 0;
2001-05-23 15:26:42 +02:00
if (status_vector[0] != isc_arg_gds ||
(status_vector[0] == isc_arg_gds && status_vector[1] == 0 &&
status_vector[2] != isc_arg_warning))
{
// this is a blank status vector
status_vector[0] = isc_arg_gds;
2001-05-23 15:26:42 +02:00
status_vector[1] = 0;
status_vector[2] = isc_arg_end;
2001-05-23 15:26:42 +02:00
indx = 2;
}
else
{
// find end of a status vector
int warning_indx = 0;
2001-05-23 15:26:42 +02:00
PARSE_STATUS(status_vector, indx, warning_indx);
if (indx) {
2001-05-23 15:26:42 +02:00
--indx;
}
2001-05-23 15:26:42 +02:00
}
if (indx + v.length() + 1 < ISC_STATUS_LENGTH)
{
memcpy(&status_vector[indx], v.value(), sizeof(ISC_STATUS) * (v.length() + 1));
ERR_make_permanent(&status_vector[indx]);
return true;
2001-05-23 15:26:42 +02:00
}
// not enough free space
return false;
}
/**
ERRD_post
@brief Post an error, copying any potentially
transient data before we punt.
@param statusVector
@param
**/
void ERRD_post(const Firebird::Arg::StatusVector& statusVector)
{
internal_post(statusVector.value());
}
/**
internal_post
@brief Post an error, copying any potentially
transient data before we punt.
@param tmp_status
@param
**/
static void internal_post(const ISC_STATUS* tmp_status)
{
ISC_STATUS* status_vector = JRD_get_thread_data()->tdbb_status_vector;
2001-05-23 15:26:42 +02:00
// calculate length of the status
2006-05-04 04:57:26 +02:00
int tmp_status_len = 0, warning_indx = 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
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
{
// this is a blank status vector
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
}
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++)
{
if (status_vector[i] == isc_arg_end && i == status_len) {
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) {
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 &&
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
{
// 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;
ISC_STATUS_ARRAY warning_status;
2001-05-23 15:26:42 +02:00
if (warning_indx) {
2004-03-07 08:58:55 +01:00
// copy current warning(s) to a temp buffer
2001-05-23 15:26:42 +02:00
MOVE_CLEAR(warning_status, sizeof(warning_status));
2008-02-03 12:20:48 +01:00
memcpy(warning_status, &status_vector[warning_indx],
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)
{
2008-08-29 04:18:50 +02:00
memcpy(&status_vector[err_status_len], tmp_status, sizeof(ISC_STATUS) * tmp_status_len);
ERR_make_permanent(&status_vector[err_status_len]);
2004-03-07 08:58:55 +01: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)
{
2008-02-03 12:20:48 +01:00
memcpy(&status_vector[i - 1], warning_status,
2003-04-10 08:32:58 +02:00
sizeof(ISC_STATUS) * warning_count);
2001-05-23 15:26:42 +02:00
}
}
ERRD_punt();
}
/**
ERRD_punt
@brief Error stuff has been copied to
status vector. Now punt.
**/
void ERRD_punt(const ISC_STATUS* local)
2001-05-23 15:26:42 +02:00
{
2008-02-28 14:48:16 +01:00
thread_db* tdbb = JRD_get_thread_data();
2001-05-23 15:26:42 +02:00
// copy local status into user status
if (local) {
2008-02-28 14:48:16 +01:00
UTLD_copy_status(local, tdbb->tdbb_status_vector);
}
// Save any strings in a permanent location
2001-05-23 15:26:42 +02:00
2008-02-28 14:48:16 +01:00
UTLD_save_status_strings(tdbb->tdbb_status_vector);
2001-05-23 15:26:42 +02:00
// Give up whatever we were doing and return to the user.
2001-05-23 15:26:42 +02:00
status_exception::raise(tdbb->tdbb_status_vector);
2001-05-23 15:26:42 +02:00
}