From 51b0d1aca4a060826695dd5d92eef5df109b3e6d Mon Sep 17 00:00:00 2001 From: asfernandes Date: Tue, 15 Oct 2013 15:26:34 +0000 Subject: [PATCH] Frontport fix for CORE-4244 - Problem with creation procedure which contain adding text in DOS864 charset. --- src/common/CharSet.h | 25 +++++++++++++++++++++---- src/common/TextType.cpp | 36 +++++++++++++++++++++++++++--------- src/jrd/evl_string.h | 8 +++++--- src/jrd/opt.cpp | 16 ++++++++++------ 4 files changed, 63 insertions(+), 22 deletions(-) diff --git a/src/common/CharSet.h b/src/common/CharSet.h index 054f10dfa4..dd6aad6e65 100644 --- a/src/common/CharSet.h +++ b/src/common/CharSet.h @@ -55,10 +55,27 @@ protected: : id(_id), cs(_cs) { - sqlMatchAnyLength = getConvFromUnicode().convert( - sizeof(SQL_MATCH_ANY_CHARS), &SQL_MATCH_ANY_CHARS, sizeof(sqlMatchAny), sqlMatchAny); - sqlMatchOneLength = getConvFromUnicode().convert( - sizeof(SQL_MATCH_1_CHAR), &SQL_MATCH_1_CHAR, sizeof(sqlMatchOne), sqlMatchOne); + try + { + sqlMatchAnyLength = getConvFromUnicode().convert(sizeof(SQL_MATCH_ANY_CHARS), + &SQL_MATCH_ANY_CHARS, sizeof(sqlMatchAny), sqlMatchAny); + } + catch (const Firebird::Exception&) + { + memset(sqlMatchAny, 0, sizeof(sqlMatchAny)); + sqlMatchAnyLength = 0; + } + + try + { + sqlMatchOneLength = getConvFromUnicode().convert( + sizeof(SQL_MATCH_1_CHAR), &SQL_MATCH_1_CHAR, sizeof(sqlMatchOne), sqlMatchOne); + } + catch (const Firebird::Exception&) + { + memset(sqlMatchOne, 0, sizeof(sqlMatchOne)); + sqlMatchOneLength = 0; + } } private: diff --git a/src/common/TextType.cpp b/src/common/TextType.cpp index e8b4e0b405..6bec7dc8d5 100644 --- a/src/common/TextType.cpp +++ b/src/common/TextType.cpp @@ -104,10 +104,21 @@ namespace Jrd { TextType::TextType(TTYPE_ID _type, texttype *_tt, CharSet* _cs) : tt(_tt), cs(_cs), type(_type) { - canonical(cs->getSqlMatchAnyLength(), cs->getSqlMatchAny(), - sizeof(ULONG), reinterpret_cast(&canonicalChars[CHAR_SQL_MATCH_ANY])); - canonical(cs->getSqlMatchOneLength(), cs->getSqlMatchOne(), - sizeof(ULONG), reinterpret_cast(&canonicalChars[CHAR_SQL_MATCH_ONE])); + if (cs->getSqlMatchAnyLength() != 0) + { + canonical(cs->getSqlMatchAnyLength(), cs->getSqlMatchAny(), + sizeof(ULONG), reinterpret_cast(&canonicalChars[CHAR_SQL_MATCH_ANY])); + } + else + memset(&canonicalChars[CHAR_SQL_MATCH_ANY], 0, sizeof(ULONG)); + + if (cs->getSqlMatchOneLength() != 0) + { + canonical(cs->getSqlMatchOneLength(), cs->getSqlMatchOne(), + sizeof(ULONG), reinterpret_cast(&canonicalChars[CHAR_SQL_MATCH_ONE])); + } + else + memset(&canonicalChars[CHAR_SQL_MATCH_ONE], 0, sizeof(ULONG)); struct Conversion { @@ -144,12 +155,19 @@ TextType::TextType(TTYPE_ID _type, texttype *_tt, CharSet* _cs) for (int i = 0; i < FB_NELEM(conversions); i++) { - UCHAR temp[sizeof(ULONG)]; + try + { + UCHAR temp[sizeof(ULONG)]; - ULONG length = getCharSet()->getConvFromUnicode().convert( - sizeof(USHORT), &conversions[i].code, sizeof(temp), temp); - canonical(length, temp, sizeof(ULONG), - reinterpret_cast(&canonicalChars[conversions[i].ch])); + ULONG length = getCharSet()->getConvFromUnicode().convert( + sizeof(USHORT), &conversions[i].code, sizeof(temp), temp); + canonical(length, temp, sizeof(ULONG), + reinterpret_cast(&canonicalChars[conversions[i].ch])); + } + catch (const Firebird::Exception&) + { + memset(&canonicalChars[conversions[i].ch], 0, sizeof(ULONG)); + } } struct Conversion2 diff --git a/src/jrd/evl_string.h b/src/jrd/evl_string.h index 0a27370d79..189baaeaa5 100644 --- a/src/jrd/evl_string.h +++ b/src/jrd/evl_string.h @@ -317,7 +317,9 @@ LikeEvaluator::LikeEvaluator( { c = pattern_str[pattern_pos++]; /* Note: SQL II says is error condition */ - if (c == escape_char || c == sql_match_any || c == sql_match_one) + if (c == escape_char || + (sql_match_any && c == sql_match_any) || + (sql_match_one && c == sql_match_one)) { switch (item->type) { @@ -344,7 +346,7 @@ LikeEvaluator::LikeEvaluator( Firebird::Arg::Gds(isc_escape_invalid).raise(); } // percent sign - if (c == sql_match_any) + if (sql_match_any && c == sql_match_any) { switch (item->type) { @@ -361,7 +363,7 @@ LikeEvaluator::LikeEvaluator( continue; } // underscore - if (c == sql_match_one) + if (sql_match_one && c == sql_match_one) { switch (item->type) { diff --git a/src/jrd/opt.cpp b/src/jrd/opt.cpp index b0fa0938a5..09dd392ad6 100644 --- a/src/jrd/opt.cpp +++ b/src/jrd/opt.cpp @@ -3344,11 +3344,15 @@ static ValueExprNode* optimize_like(thread_db* tdbb, CompilerScratch* csb, Compa const BYTE canWidth = matchTextType->getCanonicalWidth(); + const UCHAR* matchOneChar = matchCharset->getSqlMatchOneLength() != 0 ? + matchTextType->getCanonicalChar(TextType::CHAR_SQL_MATCH_ONE) : NULL; + const UCHAR* matchAnyChar = matchCharset->getSqlMatchAnyLength() != 0 ? + matchTextType->getCanonicalChar(TextType::CHAR_SQL_MATCH_ANY) : NULL; + // If the first character is a wildcard char, forget it. - if ((!escape_node || - (memcmp(first_canonic, escape_canonic, canWidth) != 0)) && - (memcmp(first_canonic, matchTextType->getCanonicalChar(TextType::CHAR_SQL_MATCH_ONE), canWidth) == 0 || - memcmp(first_canonic, matchTextType->getCanonicalChar(TextType::CHAR_SQL_MATCH_ANY), canWidth) == 0)) + if ((!escape_node || memcmp(first_canonic, escape_canonic, canWidth) != 0) && + ((matchOneChar && memcmp(first_canonic, matchOneChar, canWidth) == 0) || + (matchAnyChar && memcmp(first_canonic, matchAnyChar, canWidth) == 0))) { return NULL; } @@ -3386,8 +3390,8 @@ static ValueExprNode* optimize_like(thread_db* tdbb, CompilerScratch* csb, Compa patternPtrStart = patternPtr; patternPtr += canWidth; } - else if (memcmp(patternPtrStart, matchTextType->getCanonicalChar(TextType::CHAR_SQL_MATCH_ONE), canWidth) == 0 || - memcmp(patternPtrStart, matchTextType->getCanonicalChar(TextType::CHAR_SQL_MATCH_ANY), canWidth) == 0) + else if ((matchOneChar && memcmp(patternPtrStart, matchOneChar, canWidth) == 0) || + (matchAnyChar && memcmp(patternPtrStart, matchAnyChar, canWidth) == 0)) { break; }