diff --git a/src/common/cvt.cpp b/src/common/cvt.cpp index 1b7a55f7c7f..55cd17f659f 100644 --- a/src/common/cvt.cpp +++ b/src/common/cvt.cpp @@ -2872,6 +2872,16 @@ SSHORT CVT_decompose(const char* str, USHORT len, Int128* val, ErrorFunction err } +Int128 CVT_hex_to_int128(const char* str, USHORT len) +{ + Int128 val; + RetValue value(&val); + hex_to_value(str, str + len, &value); + + return val; +} + + USHORT CVT_get_string_ptr_common(const dsc* desc, USHORT* ttype, UCHAR** address, vary* temp, USHORT length, DecimalStatus decSt, Callbacks* cb) { @@ -3538,7 +3548,7 @@ static void hex_to_value(const char*& string, const char* end, RetPtr* retValue) * Functional description * Convert a hex string to a numeric value. This code only * converts a hex string into a numeric value, and the - * biggest hex string supported must fit into a BIGINT. + * size of biggest hex string depends upon RetPtr. * *************************************/ { diff --git a/src/common/cvt.h b/src/common/cvt.h index f656194fbc8..04923f99b89 100644 --- a/src/common/cvt.h +++ b/src/common/cvt.h @@ -93,6 +93,7 @@ double CVT_get_double(const dsc*, Firebird::DecimalStatus, ErrorFunction, bool* Firebird::Decimal64 CVT_get_dec64(const dsc*, Firebird::DecimalStatus, ErrorFunction); Firebird::Decimal128 CVT_get_dec128(const dsc*, Firebird::DecimalStatus, ErrorFunction); Firebird::Int128 CVT_get_int128(const dsc*, SSHORT, Firebird::DecimalStatus, ErrorFunction); +Firebird::Int128 CVT_hex_to_int128(const char* str, USHORT len); USHORT CVT_make_string(const dsc*, USHORT, const char**, vary*, USHORT, Firebird::DecimalStatus, ErrorFunction); void CVT_make_null_string(const dsc*, USHORT, const char**, vary*, USHORT, Firebird::DecimalStatus, ErrorFunction); void CVT_move_common(const dsc*, dsc*, Firebird::DecimalStatus, Firebird::Callbacks*); diff --git a/src/dsql/Parser.cpp b/src/dsql/Parser.cpp index 7e5eeff2f7b..bacacc63784 100644 --- a/src/dsql/Parser.cpp +++ b/src/dsql/Parser.cpp @@ -861,7 +861,7 @@ int Parser::yylexAux() ++charlen; // Okay, just count 'em ++lex.ptr; // and advance... - if (charlen > 16) // Too many digits... + if (charlen > 32) // Too many digits... { hexerror = true; break; @@ -872,11 +872,24 @@ int Parser::yylexAux() // an NUMBER32BIT or NUMBER64BIT. if (!hexerror) { + if (charlen > 16) + { + // we deal with int128 + fb_assert(charlen <= 32); // charlen is always <= 32, see 10-15 lines upper + + Firebird::string sbuff(hexstring, charlen); + sbuff.insert(0, "0X"); + + yylval.lim64ptr = newLim64String(sbuff, 0); + + return TOK_NUM128; + } + // if charlen > 8 (something like FFFF FFFF 0, w/o the spaces) // then we have to return a NUMBER64BIT. We'll make a string // node here, and let make.cpp worry about converting the // string to a number and building the node later. - if (charlen > 8) + else if (charlen > 8) { char cbuff[32]; fb_assert(charlen <= 16); // charlen is always <= 16, see 10-15 lines upper diff --git a/src/jrd/cvt.cpp b/src/jrd/cvt.cpp index 7eb84425471..04244909689 100644 --- a/src/jrd/cvt.cpp +++ b/src/jrd/cvt.cpp @@ -218,6 +218,13 @@ UCHAR CVT_get_numeric(const UCHAR* string, const USHORT length, SSHORT* scale, v bool digit_seen = false, fraction = false, over = false; const UCHAR* p = string; + if (p[0] == '0' && p[1] == 'X') + { + *(Int128*) ptr = CVT_hex_to_int128(reinterpret_cast(p + 2), length - 2); + *scale = 0; + return dtype_int128; + } + const UCHAR* const end = p + length; for (; p < end; p++) {