Skip to content

Commit 3751122

Browse files
TreeHunter9Artyom Ivanov
andauthored
Fix incorrect behavior of FF1 - FF4 patterns in CAST FORMAT for string to datetime conversion (#8454) (#8459)
* Reimplement FF1 - FF4 patterns in CAST FORMAT from string to datetime conversion * Fix tests for CAST FORMAT FF patterns * Use more appropriate name for variable * Move README.cast.format.md in doc/sql.extension folder --------- Co-authored-by: Artyom Ivanov <[email protected]>
1 parent f00a24c commit 3751122

File tree

3 files changed

+41
-11
lines changed

3 files changed

+41
-11
lines changed
File renamed without changes.

src/common/CvtFormat.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,6 +1194,31 @@ namespace
11941194
return std::string_view(str + startPoint, wordLen);
11951195
}
11961196

1197+
constexpr unsigned getFractionsFromString(const char* str, FB_SIZE_T length, FB_SIZE_T& offset, FB_SIZE_T parseLength)
1198+
{
1199+
constexpr unsigned pow10[] = {1, 10, 100, 1'000, 10'000};
1200+
static_assert(std::size(pow10) > -ISC_TIME_SECONDS_PRECISION_SCALE);
1201+
1202+
if (parseLength > -ISC_TIME_SECONDS_PRECISION_SCALE)
1203+
parseLength = -ISC_TIME_SECONDS_PRECISION_SCALE;
1204+
int currentPrecisionScale = -ISC_TIME_SECONDS_PRECISION_SCALE;
1205+
unsigned fractions = 0;
1206+
1207+
const FB_SIZE_T parseLengthWithOffset = offset + parseLength;
1208+
for (; offset < parseLengthWithOffset && offset < length; offset++)
1209+
{
1210+
const char symbol = str[offset];
1211+
1212+
if (!isDigit(symbol))
1213+
break;
1214+
1215+
fractions = fractions * 10 + (symbol - '0');
1216+
--currentPrecisionScale;
1217+
}
1218+
1219+
return fractions * pow10[currentPrecisionScale];
1220+
}
1221+
11971222
template <typename TIterator>
11981223
constexpr TIterator getPreviousOrCurrentIterator(TIterator it, TIterator begin)
11991224
{
@@ -1499,10 +1524,9 @@ namespace
14991524
case Format::FF3:
15001525
case Format::FF4:
15011526
{
1502-
const int number = patternStr.back() - '0';
1527+
const int precision = patternStr.back() - '0';
15031528

1504-
const int fractions = getIntFromString(str, strLength, strOffset, number);
1505-
outFractions = fractions * pow(10, -ISC_TIME_SECONDS_PRECISION_SCALE - number);
1529+
outFractions = getFractionsFromString(str, strLength, strOffset, precision);
15061530
break;
15071531
}
15081532

src/common/tests/CvtTest.cpp

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -550,25 +550,31 @@ BOOST_AUTO_TEST_CASE(CVTStringToFormatDateTime_TIME)
550550
testCVTStringToFormatDateTimeExpectTime("5", "FF1", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 5000), cb);
551551
testCVTStringToFormatDateTimeExpectTime("9", "FF1", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 9000), cb);
552552

553-
testCVTStringToFormatDateTimeExpectTime("1", "FF2", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 100), cb);
553+
testCVTStringToFormatDateTimeExpectTime("01", "FF2", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 100), cb);
554+
testCVTStringToFormatDateTimeExpectTime("1", "FF2", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb);
554555
testCVTStringToFormatDateTimeExpectTime("10", "FF2", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb);
555556
testCVTStringToFormatDateTimeExpectTime("50", "FF2", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 5000), cb);
556557
testCVTStringToFormatDateTimeExpectTime("99", "FF2", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 9900), cb);
557558

558-
testCVTStringToFormatDateTimeExpectTime("1", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 10), cb);
559-
testCVTStringToFormatDateTimeExpectTime("10", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 100), cb);
559+
testCVTStringToFormatDateTimeExpectTime("01", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 100), cb);
560+
testCVTStringToFormatDateTimeExpectTime("001", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 10), cb);
561+
testCVTStringToFormatDateTimeExpectTime("1", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb);
562+
testCVTStringToFormatDateTimeExpectTime("10", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb);
560563
testCVTStringToFormatDateTimeExpectTime("100", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb);
561564
testCVTStringToFormatDateTimeExpectTime("500", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 5000), cb);
562565
testCVTStringToFormatDateTimeExpectTime("999", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 9990), cb);
563566

564-
testCVTStringToFormatDateTimeExpectTime("1", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1), cb);
565-
testCVTStringToFormatDateTimeExpectTime("10", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 10), cb);
566-
testCVTStringToFormatDateTimeExpectTime("100", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 100), cb);
567+
testCVTStringToFormatDateTimeExpectTime("01", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 100), cb);
568+
testCVTStringToFormatDateTimeExpectTime("001", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 10), cb);
569+
testCVTStringToFormatDateTimeExpectTime("0001", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1), cb);
570+
testCVTStringToFormatDateTimeExpectTime("1", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb);
571+
testCVTStringToFormatDateTimeExpectTime("10", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb);
572+
testCVTStringToFormatDateTimeExpectTime("100", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb);
567573
testCVTStringToFormatDateTimeExpectTime("1000", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb);
568574
testCVTStringToFormatDateTimeExpectTime("5000", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 5000), cb);
569575
testCVTStringToFormatDateTimeExpectTime("9999", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 9999), cb);
570576

571-
testCVTStringToFormatDateTimeExpectTime("1 P.M. - 25 - 45 - 200", "HH P.M. MI.SS.FF4", createTimeStampTZ(0, 0, 0, 13, 25, 45, 0, 200), cb);
577+
testCVTStringToFormatDateTimeExpectTime("1 P.M. - 25 - 45 - 2", "HH P.M. MI.SS.FF4", createTimeStampTZ(0, 0, 0, 13, 25, 45, 0, 2000), cb);
572578
testCVTStringToFormatDateTimeExpectTime("15:0:15:2", "HH24.MI.SS.FF1", createTimeStampTZ(0, 0, 0, 15, 0, 15, 0, 2000), cb);
573579
}
574580

@@ -583,7 +589,7 @@ BOOST_AUTO_TEST_CASE(CVTStringToFormatDateTime_TZ)
583589

584590
BOOST_AUTO_TEST_CASE(CVTStringToFormatDateTime_SOLID_PATTERNS)
585591
{
586-
testCVTStringToFormatDateTimeExpectTime("1 P.M. - 25 - 45 - 200", "HHA.M.MISSFF4", createTimeStampTZ(0, 0, 0, 13, 25, 45, 0, 200), cb);
592+
testCVTStringToFormatDateTimeExpectTime("1 P.M. - 25 - 45 - 2", "HHA.M.MISSFF4", createTimeStampTZ(0, 0, 0, 13, 25, 45, 0, 2000), cb);
587593
testCVTStringToFormatDateTimeExpectDate("1981-8/13", "YEARMMDD", createTimeStampTZ(1981, 8, 13, 0, 0, 0, 0), cb);
588594
}
589595

0 commit comments

Comments
 (0)