mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 20:43:02 +01:00
Improvement #7169 - Improve ICU version mismatch diagnostics.
This commit is contained in:
parent
94299500fe
commit
f130e8abd9
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
||||
FB_DLL_EXPORT void LD_version(USHORT* version);
|
||||
FB_DLL_EXPORT ULONG LD_setup_attributes(
|
||||
const ASCII* textTypeName, const ASCII* charSetName, const ASCII* configInfo,
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
else if (module)
|
||||
{
|
||||
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 true;
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
if (tt.texttype_fn_destroy)
|
||||
tt.texttype_fn_destroy(&tt);
|
||||
|
||||
return ret;
|
||||
return true;
|
||||
}
|
||||
catch (const Exception&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1658,7 +1658,9 @@ 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,
|
||||
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)
|
||||
@ -1699,10 +1701,31 @@ INTL_BOOL INTL_builtin_lookup_texttype(texttype* tt, const ASCII* texttype_name,
|
||||
}
|
||||
|
||||
if (func)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -56,7 +56,9 @@ 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,
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user