Просмотр исходного кода

Fix parsing ofinterval literals
commit_hash:a5558c14a89e996bafff7c980065e2280278f294

imunkin 1 неделя назад
Родитель
Сommit
b2829f5d95

+ 20 - 6
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;

+ 6 - 6
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]": [

+ 6 - 6
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]": [

+ 6 - 6
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]": [

+ 30 - 0
yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_bigdate-input_interval64_/formatted.sql

@@ -88,11 +88,21 @@ SELECT
     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)
@@ -103,6 +113,26 @@ SELECT
     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)

+ 30 - 0
yql/essentials/tests/sql/sql2yql/canondata/test_sql_format.test_datetime-date_in_/formatted.sql

@@ -134,7 +134,37 @@ SELECT
     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)
+;

+ 7 - 0
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);

+ 7 - 0
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);