From 2c31578373ba145713f0abf5cedf65729c127e92 Mon Sep 17 00:00:00 2001 From: Artyom Ivanov Date: Mon, 3 Mar 2025 16:24:23 +0300 Subject: [PATCH 1/4] Reimplement FF1 - FF4 patterns in CAST FORMAT from string to datetime conversion --- src/common/CvtFormat.cpp | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/common/CvtFormat.cpp b/src/common/CvtFormat.cpp index 301c1e25fb2..cbed12862e7 100644 --- a/src/common/CvtFormat.cpp +++ b/src/common/CvtFormat.cpp @@ -1194,6 +1194,31 @@ namespace return std::string_view(str + startPoint, wordLen); } + constexpr unsigned getFractionsFromString(const char* str, FB_SIZE_T length, FB_SIZE_T& offset, FB_SIZE_T parseLength) + { + constexpr unsigned pow10[] = {1, 10, 100, 1'000, 10'000}; + static_assert(std::size(pow10) > -ISC_TIME_SECONDS_PRECISION_SCALE); + + if (parseLength > -ISC_TIME_SECONDS_PRECISION_SCALE) + parseLength = -ISC_TIME_SECONDS_PRECISION_SCALE; + int currentPrecisionScale = -ISC_TIME_SECONDS_PRECISION_SCALE; + unsigned fractions = 0; + + const FB_SIZE_T parseLengthWithOffset = offset + parseLength; + for (; offset < parseLengthWithOffset && offset < length; offset++) + { + const char symbol = str[offset]; + + if (!isDigit(symbol)) + break; + + fractions = fractions * 10 + (symbol - '0'); + --currentPrecisionScale; + } + + return fractions * pow10[currentPrecisionScale]; + } + template constexpr TIterator getPreviousOrCurrentIterator(TIterator it, TIterator begin) { @@ -1501,8 +1526,7 @@ namespace { const int number = patternStr.back() - '0'; - const int fractions = getIntFromString(str, strLength, strOffset, number); - outFractions = fractions * pow(10, -ISC_TIME_SECONDS_PRECISION_SCALE - number); + outFractions = getFractionsFromString(str, strLength, strOffset, number); break; } From d4a697eb71b9a6964aa3d0a1d0b235cfe62a8d5c Mon Sep 17 00:00:00 2001 From: Artyom Ivanov Date: Mon, 3 Mar 2025 16:24:47 +0300 Subject: [PATCH 2/4] Fix tests for CAST FORMAT FF patterns --- src/common/tests/CvtTest.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/common/tests/CvtTest.cpp b/src/common/tests/CvtTest.cpp index a86f48d7a7b..6a685b891ed 100644 --- a/src/common/tests/CvtTest.cpp +++ b/src/common/tests/CvtTest.cpp @@ -550,25 +550,31 @@ BOOST_AUTO_TEST_CASE(CVTStringToFormatDateTime_TIME) testCVTStringToFormatDateTimeExpectTime("5", "FF1", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 5000), cb); testCVTStringToFormatDateTimeExpectTime("9", "FF1", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 9000), cb); - testCVTStringToFormatDateTimeExpectTime("1", "FF2", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 100), cb); + testCVTStringToFormatDateTimeExpectTime("01", "FF2", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 100), cb); + testCVTStringToFormatDateTimeExpectTime("1", "FF2", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb); testCVTStringToFormatDateTimeExpectTime("10", "FF2", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb); testCVTStringToFormatDateTimeExpectTime("50", "FF2", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 5000), cb); testCVTStringToFormatDateTimeExpectTime("99", "FF2", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 9900), cb); - testCVTStringToFormatDateTimeExpectTime("1", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 10), cb); - testCVTStringToFormatDateTimeExpectTime("10", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 100), cb); + testCVTStringToFormatDateTimeExpectTime("01", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 100), cb); + testCVTStringToFormatDateTimeExpectTime("001", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 10), cb); + testCVTStringToFormatDateTimeExpectTime("1", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb); + testCVTStringToFormatDateTimeExpectTime("10", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb); testCVTStringToFormatDateTimeExpectTime("100", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb); testCVTStringToFormatDateTimeExpectTime("500", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 5000), cb); testCVTStringToFormatDateTimeExpectTime("999", "FF3", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 9990), cb); - testCVTStringToFormatDateTimeExpectTime("1", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1), cb); - testCVTStringToFormatDateTimeExpectTime("10", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 10), cb); - testCVTStringToFormatDateTimeExpectTime("100", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 100), cb); + testCVTStringToFormatDateTimeExpectTime("01", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 100), cb); + testCVTStringToFormatDateTimeExpectTime("001", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 10), cb); + testCVTStringToFormatDateTimeExpectTime("0001", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1), cb); + testCVTStringToFormatDateTimeExpectTime("1", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb); + testCVTStringToFormatDateTimeExpectTime("10", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb); + testCVTStringToFormatDateTimeExpectTime("100", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb); testCVTStringToFormatDateTimeExpectTime("1000", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 1000), cb); testCVTStringToFormatDateTimeExpectTime("5000", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 5000), cb); testCVTStringToFormatDateTimeExpectTime("9999", "FF4", createTimeStampTZ(0, 0, 0, 0, 0, 0, 0, 9999), cb); - testCVTStringToFormatDateTimeExpectTime("1 P.M. - 25 - 45 - 200", "HH P.M. MI.SS.FF4", createTimeStampTZ(0, 0, 0, 13, 25, 45, 0, 200), cb); + testCVTStringToFormatDateTimeExpectTime("1 P.M. - 25 - 45 - 2", "HH P.M. MI.SS.FF4", createTimeStampTZ(0, 0, 0, 13, 25, 45, 0, 2000), cb); testCVTStringToFormatDateTimeExpectTime("15:0:15:2", "HH24.MI.SS.FF1", createTimeStampTZ(0, 0, 0, 15, 0, 15, 0, 2000), cb); } @@ -583,7 +589,7 @@ BOOST_AUTO_TEST_CASE(CVTStringToFormatDateTime_TZ) BOOST_AUTO_TEST_CASE(CVTStringToFormatDateTime_SOLID_PATTERNS) { - testCVTStringToFormatDateTimeExpectTime("1 P.M. - 25 - 45 - 200", "HHA.M.MISSFF4", createTimeStampTZ(0, 0, 0, 13, 25, 45, 0, 200), cb); + testCVTStringToFormatDateTimeExpectTime("1 P.M. - 25 - 45 - 2", "HHA.M.MISSFF4", createTimeStampTZ(0, 0, 0, 13, 25, 45, 0, 2000), cb); testCVTStringToFormatDateTimeExpectDate("1981-8/13", "YEARMMDD", createTimeStampTZ(1981, 8, 13, 0, 0, 0, 0), cb); } From cbdf9b4a58853ad2a000ab3ac763d0bcbd813af5 Mon Sep 17 00:00:00 2001 From: Artyom Ivanov Date: Mon, 3 Mar 2025 16:30:40 +0300 Subject: [PATCH 3/4] Use more appropriate name for variable --- src/common/CvtFormat.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/common/CvtFormat.cpp b/src/common/CvtFormat.cpp index cbed12862e7..ce483c15493 100644 --- a/src/common/CvtFormat.cpp +++ b/src/common/CvtFormat.cpp @@ -1524,9 +1524,9 @@ namespace case Format::FF3: case Format::FF4: { - const int number = patternStr.back() - '0'; + const int precision = patternStr.back() - '0'; - outFractions = getFractionsFromString(str, strLength, strOffset, number); + outFractions = getFractionsFromString(str, strLength, strOffset, precision); break; } From e0a4497964e6f58f4a096cae1543ffe961753deb Mon Sep 17 00:00:00 2001 From: Artyom Ivanov Date: Tue, 4 Mar 2025 09:49:36 +0300 Subject: [PATCH 4/4] Move README.cast.format.md in doc/sql.extension folder --- doc/{ => sql.extensions}/README.cast.format.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename doc/{ => sql.extensions}/README.cast.format.md (100%) diff --git a/doc/README.cast.format.md b/doc/sql.extensions/README.cast.format.md similarity index 100% rename from doc/README.cast.format.md rename to doc/sql.extensions/README.cast.format.md