diff --git a/src/dsql/dsql.cpp b/src/dsql/dsql.cpp index af93be573e7..f010d119902 100644 --- a/src/dsql/dsql.cpp +++ b/src/dsql/dsql.cpp @@ -2415,14 +2415,14 @@ static UCHAR* var_info(const dsql_msg* message, // Scan sources of coercion rules in reverse order to observe // 'last entered in use' rule. Start with dynamic binding rules ... - if (!attachment->att_bindings.coerce(&desc)) + if (!attachment->att_bindings.coerce(tdbb, &desc)) { // next - given in DPB ... - if (!attachment->getInitialBindings()->coerce(&desc)) + if (!attachment->getInitialBindings()->coerce(tdbb, &desc)) { Database* dbb = tdbb->getDatabase(); // and finally - rules from .conf files. - dbb->getBindings()->coerce(&desc, dbb->dbb_compatibility_index); + dbb->getBindings()->coerce(tdbb, &desc, dbb->dbb_compatibility_index); } } diff --git a/src/jrd/Coercion.cpp b/src/jrd/Coercion.cpp index 2efd29cf28f..72ef7c1f327 100644 --- a/src/jrd/Coercion.cpp +++ b/src/jrd/Coercion.cpp @@ -32,6 +32,7 @@ #include "../dsql/dsql.h" #include "../dsql/make_proto.h" #include "../jrd/align.h" +#include "../jrd/DataTypeUtil.h" using namespace Jrd; using namespace Firebird; @@ -41,12 +42,12 @@ static const USHORT FROM_MASK = FLD_has_len | FLD_has_chset | FLD_has_scale | static const USHORT TO_MASK = FLD_has_len | FLD_has_chset | FLD_has_scale | FLD_legacy | FLD_native | FLD_has_sub | FLD_has_prec | FLD_extended; -bool CoercionArray::coerce(dsc* d, unsigned startItem) const +bool CoercionArray::coerce(thread_db* tdbb, dsc* d, unsigned startItem) const { // move down through array to ensure correct order: newer rule overrides older one for (unsigned n = getCount(); n-- > startItem; ) { - if (getElement(n).coerce(d)) + if (getElement(n).coerce(tdbb, d)) return true; } @@ -224,7 +225,7 @@ static const USHORT subTypeCompatibility[DTYPE_TYPE_MAX] = }; -bool CoercionRule::coerce(dsc* d) const +bool CoercionRule::coerce(thread_db* tdbb, dsc* d) const { // check does descriptor match FROM clause if (! match(d)) @@ -295,6 +296,8 @@ bool CoercionRule::coerce(dsc* d) const // final pass - order is important + const auto srcCharSet = d->getCharSet(); + // scale if (toMask & FLD_has_scale) d->dsc_scale = toDsc.dsc_scale; @@ -330,14 +333,17 @@ bool CoercionRule::coerce(dsc* d) const d->dsc_dtype = toDsc.dsc_dtype; } - // varchar length - if (d->dsc_dtype == dtype_varying) - d->dsc_length += sizeof(USHORT); - // charset if (toMask & FLD_has_chset) d->setTextType(toDsc.getTextType()); + if (d->isText()) + d->dsc_length = DataTypeUtil(tdbb).convertLength(d->dsc_length, srcCharSet, toDsc.getCharSet()); + + // varchar length + if (d->dsc_dtype == dtype_varying) + d->dsc_length += sizeof(USHORT); + // subtype - special processing for BLOBs if (toMask & FLD_has_sub) d->setBlobSubType(toDsc.getBlobSubType()); diff --git a/src/jrd/Coercion.h b/src/jrd/Coercion.h index e4f58d4271a..f0a36824adf 100644 --- a/src/jrd/Coercion.h +++ b/src/jrd/Coercion.h @@ -50,7 +50,7 @@ class CoercionRule void setRule(const TypeClause* from, const TypeClause *to); dsc* makeLegacy(USHORT mask = 0); - bool coerce(dsc* d) const; + bool coerce(thread_db* tdbb, dsc* d) const; bool match(const dsc* d) const; bool operator==(const CoercionRule& rule) const; @@ -68,7 +68,7 @@ class CoercionArray : public Firebird::HalfStaticArray { } - bool coerce(dsc* d, unsigned startItem = 0) const; + bool coerce(thread_db* tdbb, dsc* d, unsigned startItem = 0) const; void setRule(const TypeClause* from, const TypeClause *to); };