diff options
author | imunkin <imunkin@yandex-team.com> | 2025-02-27 19:38:40 +0300 |
---|---|---|
committer | imunkin <imunkin@yandex-team.com> | 2025-02-27 19:58:57 +0300 |
commit | b2829f5d95e52ba54c76f0c6358c21ff9e409290 (patch) | |
tree | ce8e1cf447679c7289e2fc6f2f8e870ea282ce09 | |
parent | 9a43d8d1ed58c0ad4d545d888e0e0d37a2af59d7 (diff) | |
download | ydb-b2829f5d95e52ba54c76f0c6358c21ff9e409290.tar.gz |
Fix parsing ofinterval literals
commit_hash:a5558c14a89e996bafff7c980065e2280278f294
8 files changed, 112 insertions, 24 deletions
diff --git a/yql/essentials/minikql/mkql_type_ops.cpp b/yql/essentials/minikql/mkql_type_ops.cpp index 8fba53831a..8900eba74b 100644 --- a/yql/essentials/minikql/mkql_type_ops.cpp +++ b/yql/essentials/minikql/mkql_type_ops.cpp @@ -2223,8 +2223,8 @@ NUdf::TUnboxedValuePod ParseTzTimestamp(NUdf::TStringRef str) { } } -template <bool DecimalPart = false, i8 MaxDigits = 6> -bool ParseNumber(std::string_view::const_iterator& pos, const std::string_view& buf, ui32& value) { +template <bool DecimalPart, ui8 MaxDigits> +bool ParseNumber(std::string_view::const_iterator& pos, const std::string_view& buf, ui64& value) { value = 0U; if (buf.cend() == pos || !std::isdigit(*pos)) { @@ -2263,10 +2263,16 @@ NUdf::TUnboxedValuePod ParseInterval(const std::string_view& buf) { return NUdf::TUnboxedValuePod(); } - std::optional<ui32> days, hours, minutes, seconds, microseconds; - ui32 num; + std::optional<ui64> days, hours, minutes, seconds, microseconds; + ui64 num; if (*pos != 'T') { + // Estimated upper bound for number of digits in the + // numeric representation of days (weeks need less). + // * Interval: MAX_DATE (49673) = 5 digits. + // * Interval64: MAX_DATE32 - MIN_DATE32 (106751616) = 9 digits. + // So, 9 digits is maximum for any interval component with + // granularity more than a day. if (!ParseNumber<false, 9>(pos, buf, num)) { return NUdf::TUnboxedValuePod(); } @@ -2289,7 +2295,14 @@ NUdf::TUnboxedValuePod ParseInterval(const std::string_view& buf) { if (buf.cend() != pos) // TODO: Remove this line later. do { - if (!ParseNumber(pos, buf, num)) { + // Estimated upper bound for number of digits in the + // numeric representation of seconds (hours, minutes, + // microseconds need less). + // * Interval: MAX_DATETIME (4291747200) = 10 digits. + // * Interval64: MAX_DATETIME64 - MIN_DATETIME64 (9223339708799) = 13 digits. + // So, 13 digits is maximum for any interval component with + // granularity less than a day. + if (!ParseNumber<false, 13>(pos, buf, num)) { return NUdf::TUnboxedValuePod(); } @@ -2317,7 +2330,8 @@ NUdf::TUnboxedValuePod ParseInterval(const std::string_view& buf) { return NUdf::TUnboxedValuePod(); } seconds = num; - if (!ParseNumber<true>(pos, buf, num) || *pos++ != 'S') { + // 6 digits is maximum for microseconds representation. + if (!ParseNumber<true, 6>(pos, buf, num) || *pos++ != 'S') { return NUdf::TUnboxedValuePod(); } microseconds = num; diff --git a/yql/essentials/tests/sql/minirun/part8/canondata/result.json b/yql/essentials/tests/sql/minirun/part8/canondata/result.json index 53cd1141ef..6d3cbc281d 100644 --- a/yql/essentials/tests/sql/minirun/part8/canondata/result.json +++ b/yql/essentials/tests/sql/minirun/part8/canondata/result.json @@ -298,16 +298,16 @@ ], "test.test[bigdate-input_interval64-default.txt-Debug]": [ { - "checksum": "632ffcd579b1f6bbf48e367ec38e0f27", - "size": 6397, - "uri": "https://{canondata_backend}/1031349/5d9a68084ecc9d27b7e5271088a725bb2d294cc6/resource.tar.gz#test.test_bigdate-input_interval64-default.txt-Debug_/opt.yql" + "checksum": "ed3ffc93b25ff8a71b6e6659ce05acd7", + "size": 7477, + "uri": "https://{canondata_backend}/1031349/aa434f3964bbcd36b9d29e1bd64ac6be96249ceb/resource.tar.gz#test.test_bigdate-input_interval64-default.txt-Debug_/opt.yql" } ], "test.test[bigdate-input_interval64-default.txt-Results]": [ { - "checksum": "c78332dfea021a025164772dffe9ba99", - "size": 48883, - "uri": "https://{canondata_backend}/1031349/5d9a68084ecc9d27b7e5271088a725bb2d294cc6/resource.tar.gz#test.test_bigdate-input_interval64-default.txt-Results_/results.txt" + "checksum": "5f8fd7865d7554bf3849cf7408f7b752", + "size": 57256, + "uri": "https://{canondata_backend}/1031349/aa434f3964bbcd36b9d29e1bd64ac6be96249ceb/resource.tar.gz#test.test_bigdate-input_interval64-default.txt-Results_/results.txt" } ], "test.test[bigdate-output_timestamp64-default.txt-Debug]": [ diff --git a/yql/essentials/tests/sql/minirun/part9/canondata/result.json b/yql/essentials/tests/sql/minirun/part9/canondata/result.json index 011e1f94a1..26102a2ad1 100644 --- a/yql/essentials/tests/sql/minirun/part9/canondata/result.json +++ b/yql/essentials/tests/sql/minirun/part9/canondata/result.json @@ -358,16 +358,16 @@ ], "test.test[datetime-date_in-default.txt-Debug]": [ { - "checksum": "d0c478d299d9317c9796a5a5689ea5ea", - "size": 5307, - "uri": "https://{canondata_backend}/1946324/ea335e4b9e4a11417f24b451ef1085a63908db10/resource.tar.gz#test.test_datetime-date_in-default.txt-Debug_/opt.yql" + "checksum": "3e6ba7312997f15d807aa25613e84db6", + "size": 6390, + "uri": "https://{canondata_backend}/1689644/ad5d4ca8c2d76550a459d4741259163b48e36d05/resource.tar.gz#test.test_datetime-date_in-default.txt-Debug_/opt.yql" } ], "test.test[datetime-date_in-default.txt-Results]": [ { - "checksum": "ec449bd5df1be1823e71d727d04cc6a0", - "size": 38190, - "uri": "https://{canondata_backend}/1946324/ea335e4b9e4a11417f24b451ef1085a63908db10/resource.tar.gz#test.test_datetime-date_in-default.txt-Results_/results.txt" + "checksum": "2a6bd274cc5f3511fd4c04b0b023a275", + "size": 46190, + "uri": "https://{canondata_backend}/1689644/ad5d4ca8c2d76550a459d4741259163b48e36d05/resource.tar.gz#test.test_datetime-date_in-default.txt-Results_/results.txt" } ], "test.test[datetime-date_tz_bounds_scale-default.txt-Debug]": [ diff --git a/yql/essentials/tests/sql/sql2yql/canondata/result.json b/yql/essentials/tests/sql/sql2yql/canondata/result.json index 96ad2ba4f9..f345b0e389 100644 --- a/yql/essentials/tests/sql/sql2yql/canondata/result.json +++ b/yql/essentials/tests/sql/sql2yql/canondata/result.json @@ -1135,9 +1135,9 @@ ], "test_sql2yql.test[bigdate-input_interval64]": [ { - "checksum": "46d987122b7fe9750e1b1f0ce5e4fc84", - "size": 37353, - "uri": "https://{canondata_backend}/1942173/99e88108149e222741552e7e6cddef041d6a2846/resource.tar.gz#test_sql2yql.test_bigdate-input_interval64_/sql.yql" + "checksum": "b4321aecb81505bfab6638a0d276e6a0", + "size": 43605, + "uri": "https://{canondata_backend}/1689644/d756eb6544cfd8c72af37ed4481b21fa67255f71/resource.tar.gz#test_sql2yql.test_bigdate-input_interval64_/sql.yql" } ], "test_sql2yql.test[bigdate-input_timestamp64]": [ @@ -2094,9 +2094,9 @@ ], "test_sql2yql.test[datetime-date_in]": [ { - "checksum": "68c9e3557926f3a6b12d602e682e9558", - "size": 29101, - "uri": "https://{canondata_backend}/1942173/99e88108149e222741552e7e6cddef041d6a2846/resource.tar.gz#test_sql2yql.test_datetime-date_in_/sql.yql" + "checksum": "f042635815e0ece3c9aa69a5cc35c44f", + "size": 35323, + "uri": "https://{canondata_backend}/1809005/d23a86a41976b5deadc93862c9d4b33c732d638d/resource.tar.gz#test_sql2yql.test_datetime-date_in_/sql.yql" } ], "test_sql2yql.test[datetime-date_out]": [ diff --git a/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_bigdate-input_interval64_/formatted.sql b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_bigdate-input_interval64_/formatted.sql index fd9bb1ad40..8afe7e3265 100644 --- a/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_bigdate-input_interval64_/formatted.sql +++ b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_bigdate-input_interval64_/formatted.sql @@ -89,11 +89,21 @@ SELECT ; SELECT + CAST('-P106751616D' AS interval64), + CAST(CAST('-P106751616D' AS interval64) AS string) +; + +SELECT CAST('P106751617D' AS interval64), CAST(CAST('P106751617D' AS interval64) AS string) ; SELECT + CAST('-P106751617D' AS interval64), + CAST(CAST('-P106751617D' AS interval64) AS string) +; + +SELECT CAST('P15250230W' AS interval64), CAST(CAST('P15250230W' AS interval64) AS string) ; @@ -104,6 +114,26 @@ SELECT ; SELECT + CAST('PT9223339708799S' AS interval64), + CAST(CAST('PT9223339708799S' AS interval64) AS string) +; + +SELECT + CAST('-PT9223339708799S' AS interval64), + CAST(CAST('-PT9223339708799S' AS interval64) AS string) +; + +SELECT + CAST('PT9223339708800S' AS interval64), + CAST(CAST('PT9223339708800S' AS interval64) AS string) +; + +SELECT + CAST('-PT9223339708800S' AS interval64), + CAST(CAST('-PT9223339708800S' AS interval64) AS string) +; + +SELECT CAST('PT0000000S' AS interval64), CAST(CAST('PT0000000S' AS interval64) AS string) ; diff --git a/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_datetime-date_in_/formatted.sql b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_datetime-date_in_/formatted.sql index ee14d8206b..e9923597fe 100644 --- a/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_datetime-date_in_/formatted.sql +++ b/yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_datetime-date_in_/formatted.sql @@ -135,6 +135,36 @@ SELECT ; SELECT + CAST('-P49672DT23H59M59.999999S' AS interval), + CAST(CAST('-P49672DT23H59M59.999999S' AS interval) AS string) +; + +SELECT CAST('P49673D' AS interval), CAST(CAST('P49673D' AS interval) AS string) ; + +SELECT + CAST('-P49673D' AS interval), + CAST(CAST('-P49673D' AS interval) AS string) +; + +SELECT + CAST('PT4291747199S' AS interval), + CAST(CAST('PT4291747199S' AS interval) AS string) +; + +SELECT + CAST('-PT4291747199S' AS interval), + CAST(CAST('-PT4291747199S' AS interval) AS string) +; + +SELECT + CAST('PT4291747200S' AS interval), + CAST(CAST('PT4291747200S' AS interval) AS string) +; + +SELECT + CAST('-PT4291747200S' AS interval), + CAST(CAST('-PT4291747200S' AS interval) AS string) +; diff --git a/yql/essentials/tests/sql/suites/bigdate/input_interval64.sql b/yql/essentials/tests/sql/suites/bigdate/input_interval64.sql index 47627b6003..052bf2a126 100644 --- a/yql/essentials/tests/sql/suites/bigdate/input_interval64.sql +++ b/yql/essentials/tests/sql/suites/bigdate/input_interval64.sql @@ -21,10 +21,17 @@ select cast("PT999999M" as interval64), cast(cast("PT999999M" as interval64) as select cast("PT999999H" as interval64), cast(cast("PT999999H" as interval64) as string); select cast("P106751616D" as interval64), cast(cast("P106751616D" as interval64) as string); +select cast("-P106751616D" as interval64), cast(cast("-P106751616D" as interval64) as string); select cast("P106751617D" as interval64), cast(cast("P106751617D" as interval64) as string); +select cast("-P106751617D" as interval64), cast(cast("-P106751617D" as interval64) as string); select cast("P15250230W" as interval64), cast(cast("P15250230W" as interval64) as string); select cast("P15250231W" as interval64), cast(cast("P15250231W" as interval64) as string); +select cast("PT9223339708799S" as interval64), cast(cast("PT9223339708799S" as interval64) as string); +select cast("-PT9223339708799S" as interval64), cast(cast("-PT9223339708799S" as interval64) as string); +select cast("PT9223339708800S" as interval64), cast(cast("PT9223339708800S" as interval64) as string); +select cast("-PT9223339708800S" as interval64), cast(cast("-PT9223339708800S" as interval64) as string); + select cast("PT0000000S" as interval64), cast(cast("PT0000000S" as interval64) as string); select cast("PT0000000M" as interval64), cast(cast("PT0000000M" as interval64) as string); select cast("PT0000000H" as interval64), cast(cast("PT0000000H" as interval64) as string); diff --git a/yql/essentials/tests/sql/suites/datetime/date_in.sql b/yql/essentials/tests/sql/suites/datetime/date_in.sql index 158c08c964..45a0d0d63f 100644 --- a/yql/essentials/tests/sql/suites/datetime/date_in.sql +++ b/yql/essentials/tests/sql/suites/datetime/date_in.sql @@ -32,4 +32,11 @@ select cast("2105-12-31T23:59:59.999999Z" as timestamp),cast(cast("2105-12-31T23 select cast("2106-01-01T00:00:00.000000Z" as timestamp),cast(cast("2106-01-01T00:00:00.000000Z" as timestamp) as string); select cast("P49672DT23H59M59.999999S" as interval),cast(cast("P49672DT23H59M59.999999S" as interval) as string); +select cast("-P49672DT23H59M59.999999S" as interval),cast(cast("-P49672DT23H59M59.999999S" as interval) as string); select cast("P49673D" as interval),cast(cast("P49673D" as interval) as string); +select cast("-P49673D" as interval),cast(cast("-P49673D" as interval) as string); + +select cast("PT4291747199S" as interval),cast(cast("PT4291747199S" as interval) as string); +select cast("-PT4291747199S" as interval),cast(cast("-PT4291747199S" as interval) as string); +select cast("PT4291747200S" as interval),cast(cast("PT4291747200S" as interval) as string); +select cast("-PT4291747200S" as interval),cast(cast("-PT4291747200S" as interval) as string); |