8
0
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:
asfernandes 2010-01-08 14:13:12 +00:00
parent 67cd8f6035
commit 72fab0e317
5 changed files with 50 additions and 28 deletions

View File

@ -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

View File

@ -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

View File

@ -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
{

View File

@ -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.

View File

@ -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);
}