Skip to content

Commit 9109eb2

Browse files
committed
Reuse existing string validation instead of another one
1 parent 8cd3ba6 commit 9109eb2

File tree

2 files changed

+11
-39
lines changed

2 files changed

+11
-39
lines changed

src/common/cvt.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1669,7 +1669,11 @@ void CVT_move_common(const dsc* from, dsc* to, DecimalStatus decSt, Callbacks* c
16691669
// optimal, it would cost more to find the fast move than the
16701670
// fast move would gain.
16711671

1672-
if (DSC_EQUIV(from, to, false))
1672+
// But do not do it for strings because their length has not been validated until this moment
1673+
// (real source length must be validated against target maximum length
1674+
// and this is the first common place where both are present).
1675+
1676+
if (DSC_EQUIV(from, to, false) && !DTYPE_IS_TEXT(from->dsc_dtype))
16731677
{
16741678
if (length) {
16751679
memcpy(p, q, length);

src/jrd/exe.cpp

Lines changed: 6 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -462,44 +462,7 @@ void EXE_assignment(thread_db* tdbb, const ValueExprNode* to, dsc* from_desc, bo
462462
}
463463
}
464464

465-
// Validate text length
466-
467-
if (DTYPE_IS_TEXT(from_desc->dsc_dtype) && DTYPE_IS_TEXT(to_desc->dsc_dtype))
468-
{
469-
const CharSet* srcCharSet = INTL_charset_lookup(tdbb, from_desc->getCharSet());
470-
const CharSet* tgtCharSet = INTL_charset_lookup(tdbb, to_desc->getCharSet());
471-
472-
// SQL Standard 4.3.1 Introduction to character strings:
473-
// "If a store assignment would result in the loss of non-<truncating whitespace> characters due to truncation, then an exception condition is raised."
474-
// Do not count trailing spaces in source.
475-
476-
// EngineCallbacks::instance->validateLength() cannot be used here because its current implementation ignores charSetId parameter
477-
// which (I guess) is supposed to be target's charset
478-
const UCHAR* p = from_desc->dsc_address;
479-
USHORT len = from_desc->dsc_length;
480-
481-
switch (from_desc->dsc_dtype)
482-
{
483-
case dtype_cstring:
484-
len = static_cast<USHORT>(strnlen((const char*) p, len));
485-
break;
486-
487-
case dtype_varying:
488-
len = reinterpret_cast<const vary*>(p)->vary_length;
489-
p += sizeof(USHORT);
490-
break;
491-
}
492-
493-
const ULONG srcCharLength = srcCharSet->length(len, p, false);
494-
// Here would be better `target->getMaxCharLength()`...
495-
const ULONG destCharLength = to_desc->getStringLength() / tgtCharSet->maxBytesPerChar();
496-
497-
if (srcCharLength > destCharLength)
498-
{
499-
ERR_post(Arg::Gds(isc_arith_except) << Arg::Gds(isc_string_truncation) <<
500-
Arg::Gds(isc_trunc_limits) << Arg::Num(destCharLength) << Arg::Num(srcCharLength));
501-
}
502-
}
465+
// Strings will be validated in CVT_move()
503466

504467
if (DTYPE_IS_BLOB_OR_QUAD(from_desc->dsc_dtype) || DTYPE_IS_BLOB_OR_QUAD(to_desc->dsc_dtype))
505468
{
@@ -532,6 +495,11 @@ void EXE_assignment(thread_db* tdbb, const ValueExprNode* to, dsc* from_desc, bo
532495
{
533496
MOV_move(tdbb, from_desc, to_desc);
534497
}
498+
else if (DTYPE_IS_TEXT(from_desc->dsc_dtype))
499+
{
500+
// Force slow move to properly handle the case when source string is provided with real length instead of padded length
501+
MOV_move(tdbb, from_desc, to_desc);
502+
}
535503
else if (from_desc->dsc_dtype == dtype_short)
536504
{
537505
*((SSHORT*) to_desc->dsc_address) = *((SSHORT*) from_desc->dsc_address);

0 commit comments

Comments
 (0)