Skip to content

Commit 806dab4

Browse files
committed
Fixed privately reported by Pavel Zotov issue with inability to use "gbak -icu" for old databases when ICU version changed
1 parent 6b311b4 commit 806dab4

5 files changed

Lines changed: 84 additions & 33 deletions

File tree

src/common/TextType.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,9 @@ namespace Firebird {
105105
TextType::TextType(TTypeId _type, texttype *_tt, USHORT _attributes, CharSet* _cs)
106106
: tt(_tt), cs(_cs), type(_type), attributes(_attributes)
107107
{
108+
if (!tt)
109+
return;
110+
108111
if (cs->getSqlMatchAnyLength() != 0)
109112
{
110113
canonical(cs->getSqlMatchAnyLength(), cs->getSqlMatchAny(),

src/jrd/Collation.cpp

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,8 +1070,6 @@ class CollationImpl : public Collation
10701070
template <typename T>
10711071
Collation* newCollation(MemoryPool& pool, TTypeId id, texttype* tt, USHORT attributes, CharSet* cs)
10721072
{
1073-
using namespace Firebird;
1074-
10751073
typedef StartsMatcher<UCHAR, NullStrConverter> StartsMatcherUCharDirect;
10761074
typedef StartsMatcher<UCHAR, CanonicalConverter<> > StartsMatcherUCharCanonical;
10771075
typedef ContainsMatcher<UCHAR, UpcaseConverter<> > ContainsMatcherUCharDirect;
@@ -1092,6 +1090,9 @@ Collation* newCollation(MemoryPool& pool, TTypeId id, texttype* tt, USHORT attri
10921090
SleuthMatcher<T>
10931091
> NonDirectImpl;
10941092

1093+
if (!tt)
1094+
return FB_NEW_POOL(pool) DirectImpl(id, nullptr, attributes, cs);
1095+
10951096
if (tt->texttype_flags & TEXTTYPE_DIRECT_MATCH)
10961097
return FB_NEW_POOL(pool) DirectImpl(id, tt, attributes, cs);
10971098
else
@@ -1107,8 +1108,17 @@ Collation* newCollation(MemoryPool& pool, TTypeId id, texttype* tt, USHORT attri
11071108
namespace Jrd {
11081109

11091110

1110-
Collation* Collation::createInstance(MemoryPool& pool, TTypeId id, texttype* tt, USHORT attributes, CharSet* cs)
1111+
Collation* Collation::createInstance(MemoryPool& pool, TTypeId id, texttype* tt, Firebird::IStatus* error, USHORT attributes, CharSet* cs)
11111112
{
1113+
if (!tt)
1114+
{
1115+
fb_assert(error);
1116+
auto coll = newCollation<UCHAR>(pool, id, tt, attributes, cs);
1117+
coll->error = error;
1118+
1119+
return coll;
1120+
}
1121+
11121122
switch (tt->texttype_canonical_width)
11131123
{
11141124
case 1:
@@ -1128,12 +1138,24 @@ Collation* Collation::createInstance(MemoryPool& pool, TTypeId id, texttype* tt,
11281138

11291139
void Collation::destroy(thread_db* tdbb)
11301140
{
1131-
if (tt->texttype_fn_destroy)
1132-
tt->texttype_fn_destroy(tt);
1141+
if (tt)
1142+
{
1143+
if (tt->texttype_fn_destroy)
1144+
tt->texttype_fn_destroy(tt);
1145+
1146+
delete tt;
1147+
}
11331148

1134-
delete tt;
1149+
if (error)
1150+
error->dispose();
11351151

11361152
delete this;
11371153
}
11381154

1155+
[[noreturn]] void Collation::raiseError()
1156+
{
1157+
fb_assert(error);
1158+
status_exception::raise(error);
1159+
}
1160+
11391161
} // namespace Jrd

src/jrd/Collation.h

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,12 @@ class PatternMatcher;
5252
class Collation : public Firebird::TextType
5353
{
5454
public:
55-
static Collation* createInstance(MemoryPool& pool, TTypeId id, texttype* tt,
55+
static Collation* createInstance(MemoryPool& pool, TTypeId id, texttype* tt, Firebird::IStatus* error,
5656
USHORT attributes, Firebird::CharSet* cs);
5757

5858
protected:
5959
Collation(TTypeId id, texttype *a_tt, USHORT a_attributes, Firebird::CharSet* a_cs)
60-
: TextType(id, a_tt, a_attributes, a_cs),
61-
obsolete(false)
60+
: TextType(id, a_tt, a_attributes, a_cs)
6261
{
6362
}
6463

@@ -91,8 +90,17 @@ class Collation : public Firebird::TextType
9190
void incUseCount(thread_db* tdbb);
9291
void decUseCount(thread_db* tdbb);
9392

94-
public:
95-
bool obsolete;
93+
Collation* validate()
94+
{
95+
if (tt)
96+
return this;
97+
98+
raiseError();
99+
}
100+
101+
private:
102+
Firebird::IStatus* error = nullptr;
103+
[[noreturn]] void raiseError();
96104
};
97105

98106
} // namespace Jrd

src/jrd/intl.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ CharSetContainer* CharSetContainer::lookupCharset(thread_db* tdbb, TTypeId ttype
167167
if (id == CS_dynamic)
168168
id = tdbb->getCharSet();
169169

170-
return MetadataCache::getPerm<Cached::CharSet>(tdbb, id, CacheFlag::AUTOCREATE);
170+
return MetadataCache::getPerm<Cached::CharSet>(tdbb, id, CacheFlag::AUTOCREATE | CacheFlag::MINISCAN);
171171
}
172172

173173

@@ -265,14 +265,14 @@ Collation* CharSetVers::getCollation(CollId id)
265265
if (USHORT(id) >= charset_collations.getCount() || !charset_collations[id])
266266
return nullptr;
267267

268-
return charset_collations[id];
268+
return charset_collations[id]->validate();
269269
}
270270

271271
Collation* CharSetVers::getCollation(const QualifiedName& name)
272272
{
273273
FB_SIZE_T pos;
274274
if (charset_collations.find([name](Collation* col) { return col->name == name; }, pos))
275-
return charset_collations[pos];
275+
return charset_collations[pos]->validate();
276276

277277
ERR_post(Arg::Gds(isc_text_subtype) << name.toQuotedString());
278278
}

src/jrd/met.epp

Lines changed: 37 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3881,6 +3881,9 @@ ScanResult CharSetVers::scan(thread_db* tdbb, ObjectBase::Flag flags)
38813881
END_FOR
38823882
}
38833883

3884+
if (flags & CacheFlag::MINISCAN)
3885+
return ScanResult::REPEAT;
3886+
38843887
FOR(REQUEST_HANDLE handle2)
38853888
CS IN RDB$CHARACTER_SETS
38863889
CROSS COL IN RDB$COLLATIONS OVER RDB$CHARACTER_SET_ID
@@ -3927,34 +3930,49 @@ ScanResult CharSetVers::scan(thread_db* tdbb, ObjectBase::Flag flags)
39273930
}
39283931
}
39293932

3930-
AutoPtr<texttype> tt = FB_NEW_POOL(perm->getPool()) texttype;
3931-
memset(tt, 0, sizeof(texttype));
3932-
INTL_lookup_texttype(tt, &info);
3933-
39343933
if (charset_collations.getCount() <= colId)
39353934
charset_collations.grow(colId + 1);
39363935

3937-
fb_assert((tt->texttype_canonical_width == 0 && tt->texttype_fn_canonical == NULL) ||
3938-
(tt->texttype_canonical_width != 0 && tt->texttype_fn_canonical != NULL));
3939-
3940-
if (tt->texttype_canonical_width == 0)
3936+
try
39413937
{
3942-
if (charset->isMultiByte())
3943-
tt->texttype_canonical_width = sizeof(ULONG); // UTF-32
3944-
else
3938+
AutoPtr<texttype> tt = FB_NEW_POOL(perm->getPool()) texttype;
3939+
memset(tt, 0, sizeof(texttype));
3940+
INTL_lookup_texttype(tt, &info);
3941+
3942+
fb_assert((tt->texttype_canonical_width == 0 && tt->texttype_fn_canonical == NULL) ||
3943+
(tt->texttype_canonical_width != 0 && tt->texttype_fn_canonical != NULL));
3944+
3945+
if (tt->texttype_canonical_width == 0)
39453946
{
3946-
tt->texttype_canonical_width = charset->minBytesPerChar();
3947-
// canonical is equal to string, then TEXTTYPE_DIRECT_MATCH can be turned on
3948-
tt->texttype_flags |= TEXTTYPE_DIRECT_MATCH;
3947+
if (charset->isMultiByte())
3948+
tt->texttype_canonical_width = sizeof(ULONG); // UTF-32
3949+
else
3950+
{
3951+
tt->texttype_canonical_width = charset->minBytesPerChar();
3952+
// canonical is equal to string, then TEXTTYPE_DIRECT_MATCH can be turned on
3953+
tt->texttype_flags |= TEXTTYPE_DIRECT_MATCH;
3954+
}
39493955
}
3956+
3957+
Collation* collation = Collation::createInstance(perm->getPool(),
3958+
TTypeId(id, colId), tt, nullptr, info.attributes, charset);
3959+
collation->name = info.collationName;
3960+
3961+
tt.release();
3962+
charset_collations[colId] = collation;
39503963
}
3964+
catch (const Exception& ex)
3965+
{
3966+
AutoDispose<IStatus> error = MasterInterfacePtr()->getStatus();
3967+
ex.stuffException(error);
39513968

3952-
Collation* collation = Collation::createInstance(perm->getPool(),
3953-
TTypeId(id, colId), tt, info.attributes, charset);
3954-
collation->name = info.collationName;
3969+
Collation* collation = Collation::createInstance(perm->getPool(),
3970+
TTypeId(id, colId), nullptr, error, info.attributes, charset);
3971+
collation->name = info.collationName;
39553972

3956-
tt.release();
3957-
charset_collations[colId] = collation;
3973+
error.release();
3974+
charset_collations[colId] = collation;
3975+
}
39583976
}
39593977
END_FOR
39603978

0 commit comments

Comments
 (0)