aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorimunkin <imunkin@yandex-team.com>2025-02-27 19:38:40 +0300
committerimunkin <imunkin@yandex-team.com>2025-02-27 19:58:57 +0300
commitb2829f5d95e52ba54c76f0c6358c21ff9e409290 (patch)
treece8e1cf447679c7289e2fc6f2f8e870ea282ce09
parent9a43d8d1ed58c0ad4d545d888e0e0d37a2af59d7 (diff)
downloadydb-b2829f5d95e52ba54c76f0c6358c21ff9e409290.tar.gz
Fix parsing ofinterval literals
commit_hash:a5558c14a89e996bafff7c980065e2280278f294
-rw-r--r--yql/essentials/minikql/mkql_type_ops.cpp26
-rw-r--r--yql/essentials/tests/sql/minirun/part8/canondata/result.json12
-rw-r--r--yql/essentials/tests/sql/minirun/part9/canondata/result.json12
-rw-r--r--yql/essentials/tests/sql/sql2yql/canondata/result.json12
-rw-r--r--yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_bigdate-input_interval64_/formatted.sql30
-rw-r--r--yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_datetime-date_in_/formatted.sql30
-rw-r--r--yql/essentials/tests/sql/suites/bigdate/input_interval64.sql7
-rw-r--r--yql/essentials/tests/sql/suites/datetime/date_in.sql7
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);