8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-22 17:23:03 +01:00

Improvement #7169 - Improve ICU version mismatch diagnostics.

This commit is contained in:
Adriano dos Santos Fernandes 2022-04-21 15:24:53 -03:00
parent 94299500fe
commit f130e8abd9
13 changed files with 238 additions and 114 deletions

View File

@ -664,7 +664,7 @@ bool IntlUtil::readOneChar(Jrd::CharSet* cs, const UCHAR** s, const UCHAR* end,
}
// Transform ICU-VERSION attribute (given by the user) in COLL-VERSION (to be stored).
// Add COLL-VERSION attribute.
bool IntlUtil::setupIcuAttributes(charset* cs, const string& specificAttributes,
const string& configInfo, string& newSpecificAttributes)
{
@ -681,10 +681,19 @@ bool IntlUtil::setupIcuAttributes(charset* cs, const string& specificAttributes,
map.get("ICU-VERSION", icuVersion);
string collVersion;
if (!UnicodeUtil::getCollVersion(icuVersion, configInfo, collVersion))
auto icu = UnicodeUtil::getCollVersion(icuVersion, configInfo, collVersion);
if (!icu)
return false;
map.remove("ICU-VERSION");
if (icuVersion.isEmpty())
{
int majorVersion, minorVersion;
UnicodeUtil::getICUVersion(icu, majorVersion, minorVersion);
icuVersion.printf("%d.%d", majorVersion, minorVersion);
map.put("ICU-VERSION", icuVersion);
}
map.remove("COLL-VERSION");
if (collVersion.hasData())
@ -781,16 +790,6 @@ bool IntlUtil::readAttributeChar(Jrd::CharSet* cs, const UCHAR** s, const UCHAR*
}
void IntlUtil::getDefaultCollationAttributes(UCharBuffer& collAttributes, charset& cs)
{
string attributes("ICU-VERSION=");
attributes += Jrd::UnicodeUtil::getDefaultIcuVersion();
setupIcuAttributes(&cs, attributes, "", attributes);
collAttributes.push(reinterpret_cast<const UCHAR*>(attributes.c_str()), attributes.length());
}
static void unicodeDestroy(texttype* tt)
{
delete[] const_cast<ASCII*>(tt->texttype_name);

View File

@ -94,7 +94,6 @@ public:
static bool setupIcuAttributes(charset* cs, const string& specificAttributes,
const string& configInfo, string& newSpecificAttributes);
static void getDefaultCollationAttributes(UCharBuffer& collAttributes, charset& cs);
private:
static string escapeAttribute(Jrd::CharSet* cs, const string& s);

View File

@ -354,6 +354,20 @@ typedef INTL_BOOL (*pfn_INTL_lookup_texttype) (
const ASCII* config_info
);
/* typedef for texttype lookup entry-point - with status buffer */
typedef INTL_BOOL (*pfn_INTL_lookup_texttype_with_status) (
char* status_buffer,
ULONG status_buffer_length,
texttype* tt,
const ASCII* texttype_name,
const ASCII* charset_name,
USHORT attributes,
const UCHAR* specific_attributes,
ULONG specific_attributes_length,
INTL_BOOL ignore_attributes,
const ASCII* config_info
);
/* typedef for charset lookup entry-point */
typedef INTL_BOOL (*pfn_INTL_lookup_charset) (
charset* cs,
@ -379,6 +393,7 @@ typedef ULONG (*pfn_INTL_setup_attributes) (
#define TEXTTYPE_ENTRYPOINT LD_lookup_texttype
#define TEXTTYPE_WITH_STATUS_ENTRYPOINT LD_lookup_texttype_with_status
#define CHARSET_ENTRYPOINT LD_lookup_charset
#define INTL_VERSION_ENTRYPOINT LD_version
#define INTL_SETUP_ATTRIBUTES_ENTRYPOINT LD_setup_attributes

View File

@ -92,22 +92,24 @@ public:
// System-wide ICU have no version number at entries names
if (!majorVersion)
{
fb_assert(false); // ASF: I don't think this code path is correct.
if (module->findSymbol(NULL, name, ptr))
return;
}
else
{
// ICU has several schemas for entries names
const char* patterns[] =
const char* const patterns[] =
{
"%s_%d", "%s_%d_%d", "%s_%d%d", "%s", NULL
"%s_%d", "%s_%d_%d", "%s_%d%d", "%s"
};
string symbol;
for (const char** p = patterns; *p; ++p)
for (auto pattern : patterns)
{
symbol.printf(*p, name, majorVersion, minorVersion);
symbol.printf(pattern, name, majorVersion, minorVersion);
if (module->findSymbol(NULL, symbol, ptr))
return;
}
@ -323,6 +325,7 @@ private:
getEntryPoint("ucnv_open", module, ucnv_open);
getEntryPoint("ucnv_close", module, ucnv_close);
getEntryPoint("ucnv_fromUChars", module, ucnv_fromUChars);
getEntryPoint("u_getVersion", module, u_getVersion);
getEntryPoint("u_tolower", module, u_tolower);
getEntryPoint("u_toupper", module, u_toupper);
getEntryPoint("u_strCompare", module, u_strCompare);
@ -381,8 +384,11 @@ public:
if (o)
{
o->vMajor = majorVersion;
o->vMinor = minorVersion;
UVersionInfo versionInfo;
o->u_getVersion(versionInfo);
o->vMajor = versionInfo[0];
o->vMinor = versionInfo[1];
}
return o;
@ -509,15 +515,15 @@ static ModuleLoader::Module* formatAndLoad(const char* templateName,
else
{
// ICU has several schemas for placing version into file name
const char* patterns[] =
const char* const patterns[] =
{
"%d_%d", "%d%d", NULL
"%d_%d", "%d.%d", "%d%d"
};
PathName s, filename;
for (const char** p = patterns; *p; ++p)
for (auto pattern : patterns)
{
s.printf(*p, majorVersion, minorVersion);
s.printf(pattern, majorVersion, minorVersion);
filename.printf(templateName, s.c_str());
module = ModuleLoader::fixAndLoadModule(NULL, filename);
@ -1171,7 +1177,7 @@ UnicodeUtil::ICU* UnicodeUtil::loadICU(const string& icuVersion, const string& c
getVersions(configInfo, versions);
if (versions.isEmpty())
gds__log("No versions");
gds__log("No ICU versions specified");
string version = icuVersion.isEmpty() ? versions[0] : icuVersion;
if (version == "default")
@ -1298,6 +1304,13 @@ UnicodeUtil::ICU* UnicodeUtil::loadICU(const string& icuVersion, const string& c
}
void UnicodeUtil::getICUVersion(ICU* icu, int& majorVersion, int& minorVersion)
{
majorVersion = icu->majorVersion;
minorVersion = icu->minorVersion;
}
UnicodeUtil::ConversionICU& UnicodeUtil::getConversionICU()
{
if (convIcu)
@ -1411,13 +1424,13 @@ string UnicodeUtil::getDefaultIcuVersion()
}
bool UnicodeUtil::getCollVersion(const Firebird::string& icuVersion,
UnicodeUtil::ICU* UnicodeUtil::getCollVersion(const Firebird::string& icuVersion,
const Firebird::string& configInfo, Firebird::string& collVersion)
{
ICU* icu = loadICU(icuVersion, configInfo);
if (!icu)
return false;
return nullptr;
char version[U_MAX_VERSION_STRING_LENGTH];
icu->uVersionToString(icu->collVersion, version);
@ -1427,7 +1440,7 @@ bool UnicodeUtil::getCollVersion(const Firebird::string& icuVersion,
else
collVersion = version;
return true;
return icu;
}
UnicodeUtil::Utf16Collation* UnicodeUtil::Utf16Collation::create(
@ -1502,12 +1515,11 @@ UnicodeUtil::Utf16Collation* UnicodeUtil::Utf16Collation::create(
tt->texttype_pad_option = (attributes & TEXTTYPE_ATTR_PAD_SPACE) ? true : false;
ICU* icu = loadICU(collVersion, locale, configInfo);
if (!icu)
{
gds__log("loadICU failed");
return NULL;
}
string icuVersion;
if (specificAttributes.get(IntlUtil::convertAsciiToUtf16("ICU-VERSION"), icuVersion))
icuVersion = IntlUtil::convertUtf16ToAscii(icuVersion, &error);
const auto icu = loadICU(icuVersion, collVersion, locale, configInfo);
UErrorCode status = U_ZERO_ERROR;
HalfStaticArray<UChar, BUFFER_TINY> rulesBuffer;
@ -2000,8 +2012,8 @@ ULONG UnicodeUtil::Utf16Collation::canonical(ULONG srcLen, const USHORT* src, UL
UnicodeUtil::ICU* UnicodeUtil::Utf16Collation::loadICU(
const Firebird::string& collVersion, const Firebird::string& locale,
const Firebird::string& configInfo)
const string& icuVersion, const string& collVersion,
const string& locale, const string& configInfo)
{
ObjectsArray<string> versions;
getVersions(configInfo, versions);
@ -2044,7 +2056,13 @@ UnicodeUtil::ICU* UnicodeUtil::Utf16Collation::loadICU(
return icu;
}
return NULL;
string errorMsg;
errorMsg.printf(
"An ICU library with collation version %s is required but was not found. "
"You may try to install ICU version %s, used to register the collation in this database "
"or look for 'gfix -icu' in Firebird documentation.",
collVersion.c_str(), icuVersion.c_str());
(Arg::Gds(isc_random) << errorMsg).raise();
}

View File

@ -58,6 +58,7 @@ public:
const UChar *src, int32_t srcLength,
UErrorCode *pErrorCode);
void (U_EXPORT2* u_getVersion) (UVersionInfo versionArray);
UChar32 (U_EXPORT2* u_tolower) (UChar32 c);
UChar32 (U_EXPORT2* u_toupper) (UChar32 c);
int32_t (U_EXPORT2* u_strCompare) (const UChar* s1, int32_t length1,
@ -177,7 +178,8 @@ public:
static ConversionICU& getConversionICU();
static ICU* loadICU(const Firebird::string& icuVersion, const Firebird::string& configInfo);
static bool getCollVersion(const Firebird::string& icuVersion,
static void getICUVersion(ICU* icu, int& majorVersion, int& minorVersion);
static ICU* getCollVersion(const Firebird::string& icuVersion,
const Firebird::string& configInfo, Firebird::string& collVersion);
class Utf16Collation
@ -241,8 +243,8 @@ public:
ArrayComparator<USHORT>
> ContractionsPrefixMap;
static ICU* loadICU(const Firebird::string& collVersion, const Firebird::string& locale,
const Firebird::string& configInfo);
static ICU* loadICU(const Firebird::string& icuVersion, const Firebird::string& collVersion,
const Firebird::string& locale, const Firebird::string& configInfo);
void normalize(ULONG* strLen, const USHORT** str, bool forNumericSort,
Firebird::HalfStaticArray<USHORT, BUFFER_SMALL / 2>& buffer) const;

View File

@ -51,15 +51,11 @@ static bool texttype_default_init(texttype* tt,
ULONG specificAttributesLength)
//const ASCII* configInfo)
{
charset cs;
AutoPtr<charset> cs(FB_NEW charset);
memset(&cs, 0, sizeof(cs));
// test if that ICU charset exist
if (CSICU_charset_init(&cs, charSetName))
{
IntlUtil::finiCharset(&cs);
}
else
if (!CSICU_charset_init(cs, charSetName))
return false;
if ((attributes & ~TEXTTYPE_ATTR_PAD_SPACE) ||
@ -72,7 +68,7 @@ static bool texttype_default_init(texttype* tt,
}
// name comes from stack. Copy it.
ASCII* p = FB_NEW_POOL(*getDefaultMemoryPool()) ASCII[strlen(name) + 1];
ASCII* p = FB_NEW ASCII[strlen(name) + 1];
strcpy(p, name);
tt->texttype_name = p;
@ -93,23 +89,24 @@ static bool texttype_unicode_init(texttype* tt,
ULONG specificAttributesLength,
const ASCII* configInfo)
{
charset* cs = FB_NEW_POOL(*getDefaultMemoryPool()) charset;
AutoPtr<charset> cs(FB_NEW charset);
memset(cs, 0, sizeof(*cs));
// test if that charset exist
if (!LD_lookup_charset(cs, charSetName, configInfo))
{
Firebird::SimpleDelete<charset>::clear(cs);
return false;
}
Firebird::UCharBuffer specificAttributesBuffer;
memcpy(specificAttributesBuffer.getBuffer(specificAttributesLength),
specificAttributes, specificAttributesLength);
// ASF: Don't free "cs". It'will be used in the collation.
return Firebird::IntlUtil::initUnicodeCollation(tt, cs, name,
auto ret = Firebird::IntlUtil::initUnicodeCollation(tt, cs, name,
attributes, specificAttributesBuffer, configInfo);
cs.release();
return ret;
}
@ -120,7 +117,7 @@ bool LCICU_setup_attributes(const ASCII* name, const ASCII* charSetName, const A
if (len > 8 && strcmp(name + len - 8, "_UNICODE") == 0)
{
AutoPtr<charset> cs(FB_NEW_POOL(*getDefaultMemoryPool()) charset);
AutoPtr<charset> cs(FB_NEW charset);
memset(cs, 0, sizeof(*cs));
// test if that charset exist

View File

@ -28,6 +28,7 @@
#include "../intl/ld_proto.h"
#include "../intl/cs_icu.h"
#include "../intl/lc_icu.h"
#include "../common/utils_proto.h"
#include "fb_exception.h"
#ifdef HAVE_SYS_PARAM_H
@ -491,20 +492,12 @@ FB_DLL_EXPORT INTL_BOOL LD_lookup_charset(charset* cs, const ASCII* name, const
}
FB_DLL_EXPORT INTL_BOOL LD_lookup_texttype(texttype* tt, const ASCII* texttype_name, const ASCII* charset_name,
USHORT attributes, const UCHAR* specific_attributes,
ULONG specific_attributes_length, INTL_BOOL ignore_attributes,
const ASCII* config_info)
FB_DLL_EXPORT INTL_BOOL LD_lookup_texttype_with_status(char* status_buffer, ULONG status_buffer_length,
texttype* tt, const ASCII* texttype_name, const ASCII* charset_name,
USHORT attributes, const UCHAR* specific_attributes,
ULONG specific_attributes_length, INTL_BOOL ignore_attributes,
const ASCII* config_info)
{
const ASCII* configInfo;
// ASF: We can't read config_info if version < INTL_VERSION_2,
// since it wasn't pushed in the stack by the engine.
if (version >= INTL_VERSION_2)
configInfo = config_info;
else
configInfo = "";
if (ignore_attributes)
{
attributes = TEXTTYPE_ATTR_PAD_SPACE;
@ -512,6 +505,8 @@ FB_DLL_EXPORT INTL_BOOL LD_lookup_texttype(texttype* tt, const ASCII* texttype_n
specific_attributes_length = 0;
}
string errorMsg;
try
{
for (int i = 0; collations[i].collationName; ++i)
@ -527,7 +522,7 @@ FB_DLL_EXPORT INTL_BOOL LD_lookup_texttype(texttype* tt, const ASCII* texttype_n
{
if (strcmp(charSets[j].charSetName, charset_name) == 0)
{
if (LD_lookup_charset(&cs, charset_name, configInfo))
if (LD_lookup_charset(&cs, charset_name, config_info))
break;
return false;
@ -547,13 +542,50 @@ FB_DLL_EXPORT INTL_BOOL LD_lookup_texttype(texttype* tt, const ASCII* texttype_n
return LCICU_texttype_init(
tt, texttype_name, charset_name, attributes, specific_attributes,
specific_attributes_length, configInfo);
specific_attributes_length, config_info);
}
catch (const Firebird::BadAlloc&)
catch (const Firebird::status_exception& ex)
{
auto status = ex.value();
TEXT temp[BUFFER_LARGE];
while (fb_interpret(temp, sizeof(temp), &status))
{
if (errorMsg.hasData())
errorMsg += "\n-";
errorMsg += temp;
}
}
catch (...)
{
fb_assert(false);
return false;
errorMsg = "Uncaught exception";
}
if (status_buffer_length)
fb_utils::copy_terminate(status_buffer, errorMsg.c_str(), status_buffer_length);
return false;
}
FB_DLL_EXPORT INTL_BOOL LD_lookup_texttype(texttype* tt, const ASCII* texttype_name, const ASCII* charset_name,
USHORT attributes, const UCHAR* specific_attributes,
ULONG specific_attributes_length, INTL_BOOL ignore_attributes,
const ASCII* config_info)
{
const ASCII* configInfo;
// ASF: We can't read config_info if version < INTL_VERSION_2,
// since it wasn't pushed in the stack by the engine.
if (version >= INTL_VERSION_2)
configInfo = config_info;
else
configInfo = "";
return LD_lookup_texttype_with_status(nullptr, 0, tt, texttype_name, charset_name, attributes, specific_attributes,
specific_attributes_length, ignore_attributes, configInfo);
}

View File

@ -39,10 +39,18 @@ struct CsConvertImpl
extern USHORT version;
FB_DLL_EXPORT INTL_BOOL LD_lookup_charset(charset* cs, const ASCII* name, const ASCII* config_info);
FB_DLL_EXPORT INTL_BOOL LD_lookup_texttype_with_status(char* status_buffer, ULONG status_buffer_length,
texttype* tt, const ASCII* texttype_name, const ASCII* charset_name,
USHORT attributes, const UCHAR* specific_attributes,
ULONG specific_attributes_length, INTL_BOOL ignore_attributes,
const ASCII* config_info);
FB_DLL_EXPORT INTL_BOOL LD_lookup_texttype(texttype* tt, const ASCII* texttype_name, const ASCII* charset_name,
USHORT attributes, const UCHAR* specific_attributes,
ULONG specific_attributes_length, INTL_BOOL ignore_attributes,
const ASCII* config_info);
USHORT attributes, const UCHAR* specific_attributes,
ULONG specific_attributes_length, INTL_BOOL ignore_attributes,
const ASCII* config_info);
FB_DLL_EXPORT void LD_version(USHORT* version);
FB_DLL_EXPORT ULONG LD_setup_attributes(
const ASCII* textTypeName, const ASCII* charSetName, const ASCII* configInfo,

View File

@ -625,7 +625,7 @@ bool IntlManager::lookupCharSet(const string& charSetName, charset* cs)
}
bool IntlManager::lookupCollation(const string& collationName,
void IntlManager::lookupCollation(const string& collationName,
const string& charSetName,
USHORT attributes, const UCHAR* specificAttributes,
ULONG specificAttributesLen, bool ignoreAttributes,
@ -633,32 +633,56 @@ bool IntlManager::lookupCollation(const string& collationName,
{
ExternalInfo charSetExternalInfo;
ExternalInfo collationExternalInfo;
char statusBuffer[BUFFER_LARGE] = "";
if (charSetCollations->get(charSetName + ":" + charSetName, charSetExternalInfo) &&
charSetCollations->get(charSetName + ":" + collationName, collationExternalInfo))
{
pfn_INTL_lookup_texttype lookupFunction = NULL;
ModuleLoader::Module* module = nullptr;
if (collationExternalInfo.moduleName.hasData())
modules->get(collationExternalInfo.moduleName, module);
pfn_INTL_lookup_texttype_with_status lookupStatusFunction = nullptr;
if (collationExternalInfo.moduleName.isEmpty())
lookupFunction = INTL_builtin_lookup_texttype;
else
{
ModuleLoader::Module* module;
lookupStatusFunction = INTL_builtin_lookup_texttype_status;
else if (module)
module->findSymbol(nullptr, STRINGIZE(TEXTTYPE_WITH_STATUS_ENTRYPOINT), lookupStatusFunction);
if (modules->get(collationExternalInfo.moduleName, module) && module)
module->findSymbol(NULL, STRINGIZE(TEXTTYPE_ENTRYPOINT), lookupFunction);
if (lookupStatusFunction)
{
if ((*lookupStatusFunction)(statusBuffer, sizeof(statusBuffer),
tt, collationExternalInfo.name.c_str(), charSetExternalInfo.name.c_str(),
attributes, specificAttributes, specificAttributesLen, ignoreAttributes,
collationExternalInfo.configInfo.c_str()))
{
return;
}
}
if (lookupFunction &&
(*lookupFunction)(tt, collationExternalInfo.name.c_str(), charSetExternalInfo.name.c_str(),
attributes, specificAttributes, specificAttributesLen, ignoreAttributes,
collationExternalInfo.configInfo.c_str()))
else if (module)
{
return true;
pfn_INTL_lookup_texttype lookupFunction = nullptr;
module->findSymbol(nullptr, STRINGIZE(TEXTTYPE_ENTRYPOINT), lookupFunction);
if (lookupFunction &&
(*lookupFunction)(tt, collationExternalInfo.name.c_str(), charSetExternalInfo.name.c_str(),
attributes, specificAttributes, specificAttributesLen, ignoreAttributes,
collationExternalInfo.configInfo.c_str()))
{
return;
}
}
}
return false;
if (statusBuffer[0])
{
(Arg::Gds(isc_collation_not_installed) << collationName << charSetName <<
Arg::Gds(isc_random) << statusBuffer
).raise();
}
else
(Arg::Gds(isc_collation_not_installed) << collationName << charSetName).raise();
}

View File

@ -47,7 +47,7 @@ public:
static bool lookupCharSet(const Firebird::string& charSetName, charset* cs);
static bool lookupCollation(const Firebird::string& collationName,
static void lookupCollation(const Firebird::string& collationName,
const Firebird::string& charSetName,
USHORT attributes, const UCHAR* specificAttributes,
ULONG specificAttributesLen, bool ignoreAttributes,

View File

@ -133,7 +133,7 @@ using namespace Firebird;
static bool allSpaces(CharSet*, const BYTE*, ULONG, ULONG);
static int blocking_ast_collation(void* ast_object);
static void pad_spaces(thread_db*, CHARSET_ID, BYTE *, ULONG);
static INTL_BOOL lookup_texttype(texttype* tt, const SubtypeInfo* info);
static void lookup_texttype(texttype* tt, const SubtypeInfo* info);
static GlobalPtr<Mutex> createCollationMtx;
@ -387,15 +387,10 @@ Collation* CharSetContainer::lookupCollation(thread_db* tdbb, USHORT tt_id)
}
Attachment* const att = tdbb->getAttachment();
texttype* tt = FB_NEW_POOL(*att->att_pool) texttype;
AutoPtr<texttype> tt(FB_NEW_POOL(*att->att_pool) texttype);
memset(tt, 0, sizeof(texttype));
if (!lookup_texttype(tt, &info))
{
delete tt;
ERR_post(Arg::Gds(isc_collation_not_installed) << Arg::Str(info.collationName) <<
Arg::Str(info.charsetName));
}
lookup_texttype(tt, &info);
if (charset_collations.getCount() <= id)
charset_collations.grow(id + 1);
@ -415,9 +410,12 @@ Collation* CharSetContainer::lookupCollation(thread_db* tdbb, USHORT tt_id)
}
}
charset_collations[id] = Collation::createInstance(*att->att_pool, tt_id, tt, info.attributes, charset);
charset_collations[id] = Collation::createInstance(*att->att_pool, tt_id,
tt, info.attributes, charset);
charset_collations[id]->name = info.collationName;
tt.release();
// we don't need a lock in the charset
if (id != 0)
{
@ -489,9 +487,9 @@ void CharSetContainer::unloadCollation(thread_db* tdbb, USHORT tt_id)
}
static INTL_BOOL lookup_texttype(texttype* tt, const SubtypeInfo* info)
static void lookup_texttype(texttype* tt, const SubtypeInfo* info)
{
return IntlManager::lookupCollation(info->baseCollationName.c_str(), info->charsetName.c_str(),
IntlManager::lookupCollation(info->baseCollationName.c_str(), info->charsetName.c_str(),
info->attributes, info->specificAttributes.begin(),
info->specificAttributes.getCount(), info->ignoreAttributes, tt);
}
@ -1170,12 +1168,19 @@ bool INTL_texttype_validate(Jrd::thread_db* tdbb, const SubtypeInfo* info)
texttype tt;
memset(&tt, 0, sizeof(tt));
bool ret = lookup_texttype(&tt, info);
try
{
lookup_texttype(&tt, info);
if (ret && tt.texttype_fn_destroy)
tt.texttype_fn_destroy(&tt);
if (tt.texttype_fn_destroy)
tt.texttype_fn_destroy(&tt);
return ret;
return true;
}
catch (const Exception&)
{
return false;
}
}

View File

@ -1658,10 +1658,12 @@ INTL_BOOL INTL_builtin_lookup_charset(charset* cs, const ASCII* charset_name, co
}
INTL_BOOL INTL_builtin_lookup_texttype(texttype* tt, const ASCII* texttype_name, const ASCII* charset_name,
USHORT attributes, const UCHAR* specific_attributes,
ULONG specific_attributes_length, INTL_BOOL ignore_attributes,
const ASCII* config_info)
INTL_BOOL INTL_builtin_lookup_texttype_status(
char* status_buffer, ULONG status_buffer_length,
texttype* tt, const ASCII* texttype_name, const ASCII* charset_name,
USHORT attributes, const UCHAR* specific_attributes,
ULONG specific_attributes_length, INTL_BOOL ignore_attributes,
const ASCII* config_info)
{
if (ignore_attributes)
{
@ -1700,8 +1702,29 @@ INTL_BOOL INTL_builtin_lookup_texttype(texttype* tt, const ASCII* texttype_name,
if (func)
{
return func(tt, texttype_name, charset_name, attributes,
specific_attributes, specific_attributes_length, ignore_attributes, config_info);
Firebird::string errorMsg;
try
{
return func(tt, texttype_name, charset_name, attributes,
specific_attributes, specific_attributes_length, ignore_attributes, config_info);
}
catch (const Firebird::status_exception& ex)
{
auto status = ex.value();
TEXT temp[BUFFER_LARGE];
while (fb_interpret(temp, sizeof(temp), &status))
{
if (errorMsg.hasData())
errorMsg += "\n-";
errorMsg += temp;
}
if (status_buffer_length)
fb_utils::copy_terminate(status_buffer, errorMsg.c_str(), status_buffer_length);
}
}
return false;

View File

@ -56,10 +56,12 @@ USHORT INTL_string_to_key(Jrd::thread_db*, USHORT, const dsc*, dsc*, USHORT);
// Built-in charsets/texttypes interface
INTL_BOOL INTL_builtin_lookup_charset(charset* cs, const ASCII* charset_name, const ASCII* config_info);
INTL_BOOL INTL_builtin_lookup_texttype(texttype* tt, const ASCII* texttype_name, const ASCII* charset_name,
USHORT attributes, const UCHAR* specific_attributes,
ULONG specific_attributes_length, INTL_BOOL ignore_attributes,
const ASCII* config_info);
INTL_BOOL INTL_builtin_lookup_texttype_status(
char* status_buffer, ULONG status_buffer_length,
texttype* tt, const ASCII* texttype_name, const ASCII* charset_name,
USHORT attributes, const UCHAR* specific_attributes,
ULONG specific_attributes_length, INTL_BOOL ignore_attributes,
const ASCII* config_info);
ULONG INTL_builtin_setup_attributes(const ASCII* textTypeName, const ASCII* charSetName,
const ASCII* configInfo, ULONG srcLen, const UCHAR* src, ULONG dstLen, UCHAR* dst);