2006-10-10 21:40:33 +02:00
|
|
|
/*
|
|
|
|
* PROGRAM: JRD Intl
|
|
|
|
* MODULE: Collation.cpp
|
|
|
|
* DESCRIPTION: International text support routines
|
|
|
|
*
|
|
|
|
* copyright (c) 1992, 1993 by Borland International
|
|
|
|
*/
|
|
|
|
|
|
|
|
/************* history ************
|
|
|
|
*
|
|
|
|
* COMPONENT: JRD MODULE: INTL.CPP
|
|
|
|
* generated by Marion V2.5 2/6/90
|
|
|
|
* from dev db on 4-JAN-1995
|
|
|
|
*****************************************************************
|
|
|
|
*
|
|
|
|
* PR 2002-06-02 Added ugly c hack in
|
|
|
|
* intl_back_compat_alloc_func_lookup.
|
|
|
|
* When someone has time we need to change the references to
|
|
|
|
* return (void*) function to something more C++ like
|
|
|
|
*
|
|
|
|
* 42 4711 3 11 17 tamlin 2001
|
|
|
|
* Added silly numbers before my name, and converted it to C++.
|
|
|
|
*
|
|
|
|
* 18850 daves 4-JAN-1995
|
|
|
|
* Fix gds__alloc usage
|
|
|
|
*
|
|
|
|
* 18837 deej 31-DEC-1994
|
|
|
|
* fixing up HARBOR_MERGE
|
|
|
|
*
|
|
|
|
* 18821 deej 27-DEC-1994
|
|
|
|
* HARBOR MERGE
|
|
|
|
*
|
|
|
|
* 18789 jdavid 19-DEC-1994
|
|
|
|
* Cast some functions
|
|
|
|
*
|
|
|
|
* 17508 jdavid 15-JUL-1994
|
|
|
|
* Bring it up to date
|
|
|
|
*
|
|
|
|
* 17500 daves 13-JUL-1994
|
|
|
|
* Bug 6645: Different calculation of partial keys
|
|
|
|
*
|
|
|
|
* 17202 katz 24-MAY-1994
|
|
|
|
* PC_PLATFORM requires the .dll extension
|
|
|
|
*
|
|
|
|
* 17191 katz 23-MAY-1994
|
|
|
|
* OS/2 requires the .dll extension
|
|
|
|
*
|
|
|
|
* 17180 katz 23-MAY-1994
|
|
|
|
* Define location of DLL on OS/2
|
|
|
|
*
|
|
|
|
* 17149 katz 20-MAY-1994
|
|
|
|
* In JRD, isc_arg_number arguments are SLONG's not int's
|
|
|
|
*
|
|
|
|
* 16633 daves 19-APR-1994
|
|
|
|
* Bug 6202: International licensing uses INTERNATIONAL product code
|
|
|
|
*
|
|
|
|
* 16555 katz 17-APR-1994
|
|
|
|
* The last argument of calls to ERR_post should be 0
|
|
|
|
*
|
|
|
|
* 16521 katz 14-APR-1994
|
|
|
|
* Borland C needs a decorated symbol to lookup
|
|
|
|
*
|
|
|
|
* 16403 daves 8-APR-1994
|
|
|
|
* Bug 6441: Emit an error whenever transliteration from ttype_binary attempted
|
|
|
|
*
|
|
|
|
* 16141 katz 28-MAR-1994
|
|
|
|
* Don't declare return value from ISC_lookup_entrypoint as API_ROUTINE
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Interbase Public
|
|
|
|
* License Version 1.0 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy
|
|
|
|
* of the License at http://www.Inprise.com/IPL.html
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an
|
|
|
|
* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
|
|
|
|
* or implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
|
|
|
*
|
|
|
|
* The Original Code was created by Inprise Corporation
|
|
|
|
* and its predecessors. Portions created by Inprise Corporation are
|
|
|
|
* Copyright (C) Inprise Corporation.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
|
|
|
*
|
|
|
|
* 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
|
|
|
|
*
|
|
|
|
* 2002.10.30 Sean Leyne - Removed support for obsolete "PC_PLATFORM" define
|
|
|
|
*
|
|
|
|
* 2006.10.10 Adriano dos Santos Fernandes - refactored from intl.cpp
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "firebird.h"
|
|
|
|
#include "gen/iberror.h"
|
|
|
|
#include "../jrd/jrd.h"
|
2006-10-11 20:18:20 +02:00
|
|
|
#include "../jrd/err_proto.h"
|
2006-10-10 21:40:33 +02:00
|
|
|
#include "../jrd/evl_like.h"
|
|
|
|
#include "../jrd/evl_string.h"
|
|
|
|
#include "../jrd/intl_classes.h"
|
|
|
|
#include "../jrd/lck_proto.h"
|
|
|
|
|
|
|
|
using namespace Jrd;
|
|
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
// Below are templates for functions used in Collation implementation
|
|
|
|
|
|
|
|
class NullStrConverter {
|
|
|
|
public:
|
|
|
|
NullStrConverter(thread_db* tdbb, const TextType* obj, const UCHAR *str, SLONG len) { }
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename PrevConverter>
|
|
|
|
class UpcaseConverter : public PrevConverter {
|
|
|
|
public:
|
|
|
|
UpcaseConverter(thread_db* tdbb, TextType* obj, const UCHAR* &str, SLONG &len) :
|
|
|
|
PrevConverter(tdbb, obj, str, len)
|
|
|
|
{
|
|
|
|
if (len > (int) sizeof(tempBuffer))
|
|
|
|
out_str = FB_NEW(*tdbb->getDefaultPool()) UCHAR[len];
|
|
|
|
else
|
|
|
|
out_str = tempBuffer;
|
|
|
|
obj->str_to_upper(len, str, len, out_str);
|
|
|
|
str = out_str;
|
|
|
|
}
|
|
|
|
~UpcaseConverter() {
|
|
|
|
if (out_str != tempBuffer)
|
|
|
|
delete[] out_str;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
UCHAR tempBuffer[100], *out_str;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename PrevConverter>
|
|
|
|
class CanonicalConverter : public PrevConverter {
|
|
|
|
public:
|
|
|
|
CanonicalConverter(thread_db* tdbb, TextType* obj, const UCHAR* &str, SLONG &len) :
|
|
|
|
PrevConverter(tdbb, obj, str, len)
|
|
|
|
{
|
|
|
|
SLONG out_len = len / obj->getCharSet()->minBytesPerChar() * obj->getCanonicalWidth();
|
|
|
|
|
|
|
|
if (out_len > (int) sizeof(tempBuffer))
|
|
|
|
out_str = FB_NEW(*tdbb->getDefaultPool()) UCHAR[out_len];
|
|
|
|
else
|
|
|
|
out_str = tempBuffer;
|
|
|
|
|
|
|
|
if (str)
|
|
|
|
{
|
|
|
|
len = obj->canonical(len, str, out_len, out_str) * obj->getCanonicalWidth();
|
|
|
|
str = out_str;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
len = 0;
|
|
|
|
}
|
|
|
|
~CanonicalConverter() {
|
|
|
|
if (out_str != tempBuffer)
|
|
|
|
delete[] out_str;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
UCHAR tempBuffer[100], *out_str;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename StrConverter, typename CharType>
|
|
|
|
class LikeObjectImpl : public LikeObject {
|
|
|
|
public:
|
|
|
|
LikeObjectImpl(MemoryPool& pool, const CharType* str, SLONG str_len,
|
|
|
|
CharType escape, bool use_escape,
|
|
|
|
CharType sql_match_any, CharType sql_match_one)
|
|
|
|
: evaluator(pool, str, str_len, escape, use_escape, sql_match_any, sql_match_one)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
void reset() { evaluator.reset(); }
|
|
|
|
|
|
|
|
bool result() { return evaluator.getResult(); }
|
|
|
|
|
|
|
|
bool process(thread_db* tdbb, Jrd::TextType* ttype, const UCHAR* str, SLONG length) {
|
|
|
|
StrConverter cvt(tdbb, ttype, str, length);
|
|
|
|
fb_assert(length % sizeof(CharType) == 0);
|
|
|
|
return evaluator.processNextChunk(
|
|
|
|
reinterpret_cast<const CharType*>(str), length / sizeof(CharType));
|
|
|
|
}
|
|
|
|
|
|
|
|
~LikeObjectImpl() {}
|
|
|
|
|
|
|
|
static LikeObject* create(thread_db* tdbb, TextType* ttype, const UCHAR* str, SLONG length,
|
|
|
|
const UCHAR* escape, SLONG escape_length,
|
|
|
|
const UCHAR* sql_match_any, SLONG match_any_length,
|
|
|
|
const UCHAR* sql_match_one, SLONG match_one_length)
|
|
|
|
{
|
|
|
|
StrConverter cvt(tdbb, ttype, str, length),
|
|
|
|
cvt_escape(tdbb, ttype, escape, escape_length),
|
|
|
|
cvt_match_any(tdbb, ttype, sql_match_any, match_any_length),
|
|
|
|
cvt_match_one(tdbb, ttype, sql_match_one, match_one_length);
|
|
|
|
|
|
|
|
fb_assert(length % sizeof(CharType) == 0);
|
|
|
|
return FB_NEW(*tdbb->getDefaultPool()) LikeObjectImpl(*tdbb->getDefaultPool(),
|
|
|
|
reinterpret_cast<const CharType*>(str), length / sizeof(CharType),
|
|
|
|
(escape ? *reinterpret_cast<const CharType*>(escape) : 0), escape_length != 0,
|
|
|
|
*reinterpret_cast<const CharType*>(sql_match_any),
|
|
|
|
*reinterpret_cast<const CharType*>(sql_match_one));
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool evaluate(thread_db* tdbb, TextType* ttype, const UCHAR* s, SLONG sl,
|
|
|
|
const UCHAR* p, SLONG pl, const UCHAR* escape, SLONG escape_length, const UCHAR* sql_match_any, SLONG match_any_length, const UCHAR* sql_match_one, SLONG match_one_length)
|
|
|
|
{
|
|
|
|
StrConverter cvt1(tdbb, ttype, p, pl),
|
|
|
|
cvt2(tdbb, ttype, s, sl),
|
|
|
|
cvt_escape(tdbb, ttype, escape, escape_length),
|
|
|
|
cvt_match_any(tdbb, ttype, sql_match_any, match_any_length),
|
|
|
|
cvt_match_one(tdbb, ttype, sql_match_one, match_one_length);
|
|
|
|
|
|
|
|
fb_assert(pl % sizeof(CharType) == 0);
|
|
|
|
fb_assert(sl % sizeof(CharType) == 0);
|
|
|
|
Firebird::LikeEvaluator<CharType> evaluator(*tdbb->getDefaultPool(),
|
|
|
|
reinterpret_cast<const CharType*>(p), pl / sizeof(CharType),
|
|
|
|
(escape ? *reinterpret_cast<const CharType*>(escape) : 0), escape_length != 0,
|
|
|
|
*reinterpret_cast<const CharType*>(sql_match_any),
|
|
|
|
*reinterpret_cast<const CharType*>(sql_match_one));
|
|
|
|
evaluator.processNextChunk(reinterpret_cast<const CharType*>(s), sl / sizeof(CharType));
|
|
|
|
return evaluator.getResult();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
Firebird::LikeEvaluator<CharType> evaluator;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename StrConverter, typename CharType>
|
|
|
|
class ContainsObjectImpl : public ContainsObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ContainsObjectImpl(MemoryPool& pool, const CharType* str, SLONG str_len)
|
|
|
|
: evaluator(pool, str, str_len)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
void reset() { evaluator.reset(); }
|
|
|
|
|
|
|
|
bool result() { return evaluator.getResult(); }
|
|
|
|
|
|
|
|
bool process(thread_db* tdbb, Jrd::TextType* ttype, const UCHAR* str, SLONG length) {
|
|
|
|
StrConverter cvt(tdbb, ttype, str, length);
|
|
|
|
fb_assert(length % sizeof(CharType) == 0);
|
|
|
|
return evaluator.processNextChunk(
|
|
|
|
reinterpret_cast<const CharType*>(str), length / sizeof(CharType));
|
|
|
|
}
|
|
|
|
|
|
|
|
~ContainsObjectImpl() {}
|
|
|
|
|
|
|
|
static ContainsObject* create(thread_db* tdbb, TextType* ttype, const UCHAR* str, SLONG length) {
|
|
|
|
StrConverter cvt(tdbb, ttype, str, length);
|
|
|
|
fb_assert(length % sizeof(CharType) == 0);
|
|
|
|
return FB_NEW(*tdbb->getDefaultPool()) ContainsObjectImpl(*tdbb->getDefaultPool(),
|
|
|
|
reinterpret_cast<const CharType*>(str), length / sizeof(CharType));
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool evaluate(thread_db* tdbb, TextType* ttype, const UCHAR* s, SLONG sl,
|
|
|
|
const UCHAR* p, SLONG pl)
|
|
|
|
{
|
|
|
|
StrConverter cvt1(tdbb, ttype, p, pl), cvt2(tdbb, ttype, s, sl);
|
|
|
|
fb_assert(pl % sizeof(CharType) == 0);
|
|
|
|
fb_assert(sl % sizeof(CharType) == 0);
|
|
|
|
Firebird::ContainsEvaluator<CharType> evaluator(*tdbb->getDefaultPool(),
|
|
|
|
reinterpret_cast<const CharType*>(p), pl / sizeof(CharType));
|
|
|
|
evaluator.processNextChunk(reinterpret_cast<const CharType*>(s), sl / sizeof(CharType));
|
|
|
|
return evaluator.getResult();
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
Firebird::ContainsEvaluator<CharType> evaluator;
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename StrConverter, typename CharType>
|
|
|
|
class MatchesObjectImpl
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static bool evaluate(thread_db* tdbb, TextType* ttype, const UCHAR* s, SLONG sl,
|
|
|
|
const UCHAR* p, SLONG pl)
|
|
|
|
{
|
|
|
|
StrConverter cvt1(tdbb, ttype, p, pl), cvt2(tdbb, ttype, s, sl);
|
|
|
|
fb_assert(pl % sizeof(CharType) == 0);
|
|
|
|
fb_assert(sl % sizeof(CharType) == 0);
|
|
|
|
return MATCHESNAME(tdbb, ttype, reinterpret_cast<const CharType*>(s), sl,
|
|
|
|
reinterpret_cast<const CharType*>(p), pl);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename StrConverter, typename CharType>
|
|
|
|
class SleuthObjectImpl
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static bool check(thread_db* tdbb, TextType* ttype, USHORT flags,
|
|
|
|
const UCHAR* search, SLONG search_len,
|
|
|
|
const UCHAR* match, SLONG match_len)
|
|
|
|
{
|
|
|
|
StrConverter cvt1(tdbb, ttype, search, search_len);//, cvt2(tdbb, ttype, match, match_len);
|
|
|
|
fb_assert(search_len % sizeof(CharType) == 0);
|
|
|
|
fb_assert(match_len % sizeof(CharType) == 0);
|
|
|
|
return SLEUTHNAME(tdbb, ttype, flags,
|
|
|
|
reinterpret_cast<const CharType*>(search), search_len,
|
|
|
|
reinterpret_cast<const CharType*>(match), match_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
static ULONG merge(thread_db* tdbb, TextType* ttype,
|
|
|
|
const UCHAR* match, SLONG match_bytes,
|
|
|
|
const UCHAR* control, SLONG control_bytes,
|
|
|
|
UCHAR* combined, SLONG combined_bytes)
|
|
|
|
{
|
|
|
|
StrConverter cvt1(tdbb, ttype, match, match_bytes), cvt2(tdbb, ttype, control, control_bytes);
|
|
|
|
fb_assert(match_bytes % sizeof(CharType) == 0);
|
|
|
|
fb_assert(control_bytes % sizeof(CharType) == 0);
|
|
|
|
return SLEUTH_MERGE_NAME(tdbb, ttype,
|
|
|
|
reinterpret_cast<const CharType*>(match), match_bytes,
|
|
|
|
reinterpret_cast<const CharType*>(control), control_bytes,
|
|
|
|
reinterpret_cast<CharType*>(combined), combined_bytes);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template <typename pContainsObjectImpl, typename pLikeObjectImpl,
|
|
|
|
typename pMatchesObjectImpl, typename pSleuthObjectImpl>
|
|
|
|
class CollationImpl : public Collation
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CollationImpl(TTYPE_ID a_type, texttype* a_tt, CharSet* a_cs) : Collation(a_type, a_tt, a_cs) {}
|
|
|
|
|
|
|
|
virtual bool matches(thread_db* tdbb, const UCHAR* a, SLONG b, const UCHAR* c, SLONG d)
|
|
|
|
{
|
|
|
|
return pMatchesObjectImpl::evaluate(tdbb, this, a, b, c, d);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool sleuth_check(thread_db* tdbb, USHORT a, const UCHAR* b, SLONG c, const UCHAR* d, SLONG e)
|
|
|
|
{
|
|
|
|
return pSleuthObjectImpl::check(tdbb, this, a, b, c, d, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ULONG sleuth_merge(thread_db* tdbb, const UCHAR* a, SLONG b, const UCHAR* c, SLONG d, UCHAR* e, SLONG f)
|
|
|
|
{
|
|
|
|
return pSleuthObjectImpl::merge(tdbb, this, a, b, c, d, e, f);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool like(thread_db* tdbb, const UCHAR* s, SLONG sl, const UCHAR* p, SLONG pl, const UCHAR* escape, SLONG escape_length)
|
|
|
|
{
|
|
|
|
return pLikeObjectImpl::evaluate(tdbb, this, s, sl, p, pl, escape, escape_length, getCharSet()->getSqlMatchAny(), getCharSet()->getSqlMatchAnyLength(), getCharSet()->getSqlMatchOne(), getCharSet()->getSqlMatchOneLength());
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual LikeObject *like_create(thread_db* tdbb, const UCHAR* p, SLONG pl, const UCHAR* escape, SLONG escape_length)
|
|
|
|
{
|
|
|
|
return pLikeObjectImpl::create(tdbb, this, p, pl, escape, escape_length, getCharSet()->getSqlMatchAny(), getCharSet()->getSqlMatchAnyLength(), getCharSet()->getSqlMatchOne(), getCharSet()->getSqlMatchOneLength());
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool contains(thread_db* tdbb, const UCHAR* s, SLONG sl, const UCHAR* p, SLONG pl)
|
|
|
|
{
|
|
|
|
return pContainsObjectImpl::evaluate(tdbb, this, s, sl, p, pl);
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual ContainsObject *contains_create(thread_db* tdbb, const UCHAR* p, SLONG pl)
|
|
|
|
{
|
|
|
|
return pContainsObjectImpl::create(tdbb, this, p, pl);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef ContainsObjectImpl<UpcaseConverter<NullStrConverter>, UCHAR> uchar_contains_direct;
|
|
|
|
typedef ContainsObjectImpl<UpcaseConverter<NullStrConverter>, USHORT> ushort_contains_direct;
|
|
|
|
typedef ContainsObjectImpl<UpcaseConverter<NullStrConverter>, ULONG> ulong_contains_direct;
|
|
|
|
|
|
|
|
typedef MatchesObjectImpl<CanonicalConverter<NullStrConverter>, UCHAR> uchar_matches_canonical;
|
|
|
|
typedef SleuthObjectImpl<CanonicalConverter<NullStrConverter>, UCHAR> uchar_sleuth_canonical;
|
|
|
|
typedef LikeObjectImpl<CanonicalConverter<NullStrConverter>, UCHAR> uchar_like_canonical;
|
|
|
|
typedef ContainsObjectImpl<CanonicalConverter<UpcaseConverter<NullStrConverter> >, UCHAR> uchar_contains_canonical;
|
|
|
|
|
|
|
|
typedef MatchesObjectImpl<CanonicalConverter<NullStrConverter>, USHORT> ushort_matches_canonical;
|
|
|
|
typedef SleuthObjectImpl<CanonicalConverter<NullStrConverter>, USHORT> ushort_sleuth_canonical;
|
|
|
|
typedef LikeObjectImpl<CanonicalConverter<NullStrConverter>, USHORT> ushort_like_canonical;
|
|
|
|
typedef ContainsObjectImpl<CanonicalConverter<UpcaseConverter<NullStrConverter> >, USHORT> ushort_contains_canonical;
|
|
|
|
|
|
|
|
typedef MatchesObjectImpl<CanonicalConverter<NullStrConverter>, ULONG> ulong_matches_canonical;
|
|
|
|
typedef SleuthObjectImpl<CanonicalConverter<NullStrConverter>, ULONG> ulong_sleuth_canonical;
|
|
|
|
typedef LikeObjectImpl<CanonicalConverter<NullStrConverter>, ULONG> ulong_like_canonical;
|
|
|
|
typedef ContainsObjectImpl<CanonicalConverter<UpcaseConverter<NullStrConverter> >, ULONG> ulong_contains_canonical;
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
|
|
//-------------
|
|
|
|
|
|
|
|
|
|
|
|
namespace Jrd {
|
|
|
|
|
|
|
|
|
|
|
|
Collation* Collation::createInstance(MemoryPool& pool, TTYPE_ID id, texttype* tt, CharSet* cs)
|
|
|
|
{
|
|
|
|
fb_assert(tt->texttype_canonical_width == 1 ||
|
|
|
|
tt->texttype_canonical_width == 2 ||
|
|
|
|
tt->texttype_canonical_width == 4);
|
|
|
|
|
|
|
|
switch (tt->texttype_canonical_width)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
if (tt->texttype_flags & TEXTTYPE_DIRECT_MATCH)
|
|
|
|
{
|
|
|
|
return FB_NEW(pool) CollationImpl<uchar_contains_direct, uchar_like_canonical,
|
|
|
|
uchar_matches_canonical, uchar_sleuth_canonical>(id, tt, cs);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return FB_NEW(pool) CollationImpl<uchar_contains_canonical, uchar_like_canonical,
|
|
|
|
uchar_matches_canonical, uchar_sleuth_canonical>(id, tt, cs);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
if (tt->texttype_flags & TEXTTYPE_DIRECT_MATCH)
|
|
|
|
{
|
|
|
|
return FB_NEW(pool) CollationImpl<uchar_contains_direct, ushort_like_canonical,
|
|
|
|
ushort_matches_canonical, ushort_sleuth_canonical>(id, tt, cs);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return FB_NEW(pool) CollationImpl<ushort_contains_canonical, ushort_like_canonical,
|
|
|
|
ushort_matches_canonical, ushort_sleuth_canonical>(id, tt, cs);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
if (tt->texttype_flags & TEXTTYPE_DIRECT_MATCH)
|
|
|
|
{
|
|
|
|
return FB_NEW(pool) CollationImpl<uchar_contains_direct, ulong_like_canonical,
|
|
|
|
ulong_matches_canonical, ulong_sleuth_canonical>(id, tt, cs);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return FB_NEW(pool) CollationImpl<ulong_contains_canonical, ulong_like_canonical,
|
|
|
|
ulong_matches_canonical, ulong_sleuth_canonical>(id, tt, cs);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2006-10-29 11:19:28 +01:00
|
|
|
fb_assert(false);
|
|
|
|
return NULL; // compiler silencer
|
2006-10-10 21:40:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Collation::destroy()
|
|
|
|
{
|
|
|
|
if (tt->texttype_fn_destroy)
|
|
|
|
tt->texttype_fn_destroy(tt);
|
|
|
|
|
|
|
|
delete tt;
|
|
|
|
delete existenceLock;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Collation::incUseCount(thread_db* tdbb)
|
|
|
|
{
|
|
|
|
++useCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Collation::decUseCount(thread_db* tdbb)
|
|
|
|
{
|
|
|
|
if (--useCount == 0)
|
|
|
|
{
|
|
|
|
if (existenceLock)
|
|
|
|
LCK_re_post(existenceLock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace Jrd
|