mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-02-02 10:00:38 +01:00
Update way to deliver parameterized exceptions so the client doesn't need special handling
This commit is contained in:
parent
67cd8f6035
commit
72fab0e317
@ -103,13 +103,11 @@ Parameterized exceptions (FB 3.0)
|
||||
Notes:
|
||||
The status vector is generated using that codes combination:
|
||||
isc_except, <exception number>,
|
||||
isc_formatted_exception, <exception message>, <exception parameters>
|
||||
isc_formatted_exception, <formatted exception message>,
|
||||
<defined exception message>, <exception parameters>
|
||||
|
||||
The client library formats isc_formatted_exception in an special way, using the exception
|
||||
parameters as argument to the exception message, instead of formatting all arguments of
|
||||
isc_formatted_exception for a predefined internal text. That's important for any code that
|
||||
formats status vectors without the help of the client library. Also, the client library older
|
||||
than 3.0 will not be able to correctly format exceptions raised in this new way.
|
||||
Since new error code (isc_formatted_exception) is used, it's necessary that the client is v3.0
|
||||
or at least uses firebird.msg from v3.0 so that it can translate the status vector to string.
|
||||
|
||||
@N means the N parameter (where N starts at 1) passed in the exception raise command. If a N
|
||||
parameter is not passed, the text is not substituted. If NULL is passed, it's replaced by string
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#include "../common/classes/fb_string.h"
|
||||
#include <stdio.h>
|
||||
|
||||
namespace MsgFormat
|
||||
@ -110,6 +111,26 @@ private:
|
||||
char* m_current_pos;
|
||||
};
|
||||
|
||||
|
||||
// Wraps a reference to a Firebird::string.
|
||||
class StringRefStream : public BaseStream
|
||||
{
|
||||
public:
|
||||
StringRefStream(Firebird::string& aRef)
|
||||
: ref(aRef)
|
||||
{
|
||||
}
|
||||
|
||||
virtual int write(const void* str, unsigned int n)
|
||||
{
|
||||
ref.append((const char*) str, n);
|
||||
return n;
|
||||
}
|
||||
|
||||
private:
|
||||
Firebird::string& ref;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // FB_BASESTREAM_H
|
||||
|
@ -259,9 +259,8 @@ int MsgPrint(BaseStream& out_stream, const char* format, const SafeArg& arg, boo
|
||||
break;
|
||||
default:
|
||||
{
|
||||
const int start = userFormatting ? 1 : 0;
|
||||
const int pos = start + iter[1] - '0';
|
||||
if (pos > start && static_cast<size_t>(pos) <= arg.m_count)
|
||||
const int pos = iter[1] - '0';
|
||||
if (pos > 0 && static_cast<size_t>(pos) <= arg.m_count)
|
||||
out_bytes += MsgPrintHelper(out_stream, arg.m_arguments[pos - 1]);
|
||||
else
|
||||
{
|
||||
@ -378,18 +377,7 @@ int fb_msg_format(void* handle, USHORT facility, USHORT number, unsigned int bsi
|
||||
total_msg = fb_utils::snprintf(buffer, bsize, msg, rep[0], rep[1], rep[2], rep[3], rep[4]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ENCODE_ISC_MSG(number, facility) == isc_formatted_exception && arg.getCount() > 0)
|
||||
{
|
||||
Firebird::HalfStaticArray<char, BUFFER_SMALL> msgBuffer(bsize);
|
||||
MsgFormat::StringStream msgStream(msgBuffer.begin(), bsize);
|
||||
MsgPrintHelper(msgStream, arg.getCell(0));
|
||||
|
||||
total_msg = MsgPrint(buffer, bsize, msgBuffer.begin(), arg, 1);
|
||||
}
|
||||
else
|
||||
total_msg = MsgPrint(buffer, bsize, msg, arg);
|
||||
}
|
||||
total_msg = MsgPrint(buffer, bsize, msg, arg);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -95,6 +95,7 @@ int MsgPrint(char* plainstring, unsigned int s_size, const char* format, const S
|
||||
|
||||
// E. Prints a formatted string into stderr and flushed the buffer.
|
||||
int MsgPrintErr(const char* format, const SafeArg& arg, bool userFormatting = false);
|
||||
|
||||
} // namespace
|
||||
|
||||
// Type safe replacement of the old gds__msg_format.
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#include "firebird.h"
|
||||
#include "../jrd/common.h"
|
||||
#include "../common/classes/BaseStream.h"
|
||||
#include "../common/classes/MsgPrint.h"
|
||||
#include "../dsql/StmtNodes.h"
|
||||
#include "../dsql/node.h"
|
||||
#include "../jrd/jrd.h"
|
||||
@ -934,13 +936,11 @@ void ExceptionNode::setError(thread_db* tdbb) const
|
||||
{
|
||||
status << Arg::Gds(isc_except) << Arg::Num(xcpCode) <<
|
||||
Arg::Gds(isc_random) << Arg::Str(exName) <<
|
||||
Arg::Gds(msgCode) << Arg::Str(s);
|
||||
Arg::Gds(msgCode);
|
||||
}
|
||||
else if (s)
|
||||
{
|
||||
status << Arg::Gds(isc_except) << Arg::Num(xcpCode) <<
|
||||
Arg::Gds(msgCode) << Arg::Str(s);
|
||||
}
|
||||
Arg::Gds(msgCode);
|
||||
else if (exName.hasData())
|
||||
{
|
||||
ERR_post(Arg::Gds(isc_except) << Arg::Num(xcpCode) <<
|
||||
@ -949,7 +949,8 @@ void ExceptionNode::setError(thread_db* tdbb) const
|
||||
else
|
||||
ERR_post(Arg::Gds(isc_except) << Arg::Num(xcpCode));
|
||||
|
||||
// Preallocate the strings, because Arg::StatusVector store the pointers.
|
||||
// Preallocate objects, because Arg::StatusVector store pointers.
|
||||
string formattedMsg;
|
||||
ObjectsArray<string> paramsStr;
|
||||
|
||||
if (parameters)
|
||||
@ -964,11 +965,24 @@ void ExceptionNode::setError(thread_db* tdbb) const
|
||||
paramsStr.push(MOV_make_string2(tdbb, value, ttype_metadata));
|
||||
}
|
||||
|
||||
// And add the values to the status vector only when they are all created and will
|
||||
// not move in paramsStr.
|
||||
// And add the values to the args and status vector only after they are all created
|
||||
// and will not move in paramsStr.
|
||||
|
||||
MsgFormat::SafeArg arg;
|
||||
for (unsigned i = 0; i < parameters->nod_count; ++i)
|
||||
arg << paramsStr[i].c_str();
|
||||
|
||||
MsgFormat::StringRefStream stream(formattedMsg);
|
||||
MsgFormat::MsgPrint(stream, s, arg, true);
|
||||
|
||||
status << formattedMsg;
|
||||
status << s; // add the exception text
|
||||
|
||||
for (unsigned i = 0; i < parameters->nod_count; ++i)
|
||||
status << paramsStr[i];
|
||||
}
|
||||
else
|
||||
status << s; // add the exception text
|
||||
|
||||
ERR_post(status);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user