This is an automated email from the ASF dual-hosted git repository.

zhangstar333 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 0c5703fd129 [fix](function) Fix wrong result of week/yearweek in 
constant folding (#37376)
0c5703fd129 is described below

commit 0c5703fd12928a5751c832ee495bbbd06ed3991a
Author: zclllyybb <[email protected]>
AuthorDate: Mon Jul 8 11:47:09 2024 +0800

    [fix](function) Fix wrong result of week/yearweek in constant folding 
(#37376)
    
    ## Proposed changes
    
    Issue Number: close #xxx
    
    Java doesn't support the calculation of `0000-01-01`(0000 year is 1 B.C.
    which ISO-8601 defines). so some of our calc was wrong in FE. now fixed
    them.
    
    new result:
    ```sql
    mysql> select week('0000-01-01', 0),week('0000-01-01', 
1),week('0000-01-01', 2),week('0000-01-01', 3),week('0000-01-01', 4), 
week('0000-01-01', 5), week('0000-01-01', 6), week('0000-01-01', 7);
    +------+------+------+------+------+------+------+------+
    | 1    | 0    | 1    | 52   | 1    | 0    | 1    | 52   |
    +------+------+------+------+------+------+------+------+
    |    1 |    0 |    1 |   52 |    1 |    0 |    1 |   52 |
    +------+------+------+------+------+------+------+------+
    1 row in set (0.10 sec)
    
    mysql> select week('0000-01-02', 0),week('0000-01-02', 
1),week('0000-01-02', 2),week('0000-01-02', 3),week('0000-01-02', 4), 
week('0000-01-02', 5), week('0000-01-02', 6), week('0000-01-02', 7);
    +------+------+------+------+------+------+------+------+
    | 1    | 1    | 1    | 1    | 1    | 1    | 1    | 1    |
    +------+------+------+------+------+------+------+------+
    |    1 |    1 |    1 |    1 |    1 |    1 |    1 |    1 |
    +------+------+------+------+------+------+------+------+
    1 row in set (0.10 sec)
    ```
    same with `yearweek`
---
 .../executable/DateTimeExtractAndTransform.java    | 43 +++++++-------
 .../functions/DateTimeExtractAndTransformTest.java | 65 +++++++++++++---------
 2 files changed, 60 insertions(+), 48 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeExtractAndTransform.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeExtractAndTransform.java
index a5cffe3dabd..f719eea44b3 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeExtractAndTransform.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeExtractAndTransform.java
@@ -707,6 +707,15 @@ public class DateTimeExtractAndTransform {
      * the impl of function week(date/datetime, mode)
      */
     public static Expression week(LocalDateTime localDateTime, int mode) {
+        final byte[] resultOfFirstDayBC1 = new byte[] { 1, 0, 1, 52, 1, 0, 1, 
52 };
+        if (isSpecificDate(localDateTime) && mode >= 0 && mode <= 7) { // 
0000-01-01/02
+            if (localDateTime.getDayOfMonth() == 1) {
+                return new TinyIntLiteral(resultOfFirstDayBC1[mode]);
+            } else { // 0001-01-02
+                return new TinyIntLiteral((byte) 1);
+            }
+        }
+
         switch (mode) {
             case 0: {
                 return new TinyIntLiteral(
@@ -716,13 +725,6 @@ public class DateTimeExtractAndTransform {
                 return new TinyIntLiteral((byte) 
localDateTime.get(WeekFields.ISO.weekOfYear()));
             }
             case 2: {
-                // 
https://dev.mysql.com/doc/refman/8.4/en/date-and-time-functions.html#function_week
-                // mode 2 is start with a Sunday day as first week in this 
year.
-                // and special case for 0000-01-01, as it's SATURDAY, 
calculate result of 52 is
-                // last year, so it's meaningless.
-                if (checkIsSpecificDate(localDateTime)) {
-                    return new TinyIntLiteral((byte) 1);
-                }
                 return new TinyIntLiteral(
                         (byte) 
localDateTime.get(WeekFields.of(DayOfWeek.SUNDAY, 7).weekOfWeekBasedYear()));
             }
@@ -753,6 +755,14 @@ public class DateTimeExtractAndTransform {
         }
     }
 
+    /**
+     * 0000-01-01/02 are specific dates, sometime need handle them alone.
+     */
+    private static boolean isSpecificDate(LocalDateTime localDateTime) {
+        return localDateTime.getYear() == 0 && localDateTime.getMonthValue() 
== 1
+                && (localDateTime.getDayOfMonth() == 1 || 
localDateTime.getDayOfMonth() == 2);
+    }
+
     @ExecFunction(name = "yearweek", argTypes = {"DATEV2", "INT"}, returnType 
= "INT")
     public static Expression yearWeek(DateV2Literal date, IntegerLiteral mode) 
{
         return yearWeek(date.toJavaDateType(), mode.getIntValue());
@@ -787,11 +797,12 @@ public class DateTimeExtractAndTransform {
      * the impl of function yearWeek(date/datetime, mode)
      */
     public static Expression yearWeek(LocalDateTime localDateTime, int mode) {
+        if (localDateTime.getYear() == 0) {
+            return week(localDateTime, mode);
+        }
+
         switch (mode) {
             case 0: {
-                if (checkIsSpecificDate(localDateTime)) {
-                    return new IntegerLiteral(1);
-                }
                 return new IntegerLiteral(
                         localDateTime.get(WeekFields.of(DayOfWeek.SUNDAY, 
7).weekBasedYear()) * 100
                                 + localDateTime.get(
@@ -802,9 +813,6 @@ public class DateTimeExtractAndTransform {
                         + 
localDateTime.get(WeekFields.ISO.weekOfWeekBasedYear()));
             }
             case 2: {
-                if (checkIsSpecificDate(localDateTime)) {
-                    return new IntegerLiteral(1);
-                }
                 return new IntegerLiteral(
                         localDateTime.get(WeekFields.of(DayOfWeek.SUNDAY, 
7).weekBasedYear()) * 100
                                 + localDateTime.get(
@@ -840,18 +848,11 @@ public class DateTimeExtractAndTransform {
             }
             default: {
                 throw new AnalysisException(
-                        String.format("unknown mode %d in week function", 
mode));
+                        String.format("unknown mode %d in yearweek function", 
mode));
             }
         }
     }
 
-    /**
-     * 0000-01-01 is specific date, sometime need handle it alone.
-     */
-    private static boolean checkIsSpecificDate(LocalDateTime localDateTime) {
-        return localDateTime.getYear() == 0 && localDateTime.getMonthValue() 
== 1 && localDateTime.getDayOfMonth() == 1;
-    }
-
     @ExecFunction(name = "weekofyear", argTypes = {"DATETIMEV2"}, returnType = 
"TINYINT")
     public static Expression weekOfYear(DateTimeV2Literal dateTime) {
         return new TinyIntLiteral((byte) 
dateTime.toJavaDateType().get(WeekFields.ISO.weekOfWeekBasedYear()));
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/DateTimeExtractAndTransformTest.java
 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/DateTimeExtractAndTransformTest.java
index 10aa5939e31..51e77e3feda 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/DateTimeExtractAndTransformTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/nereids/trees/expressions/functions/DateTimeExtractAndTransformTest.java
@@ -18,7 +18,6 @@
 package org.apache.doris.nereids.trees.expressions.functions;
 
 import 
org.apache.doris.nereids.trees.expressions.functions.executable.DateTimeExtractAndTransform;
-import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral;
 import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral;
 
 import org.junit.jupiter.api.Assertions;
@@ -28,32 +27,44 @@ import java.time.LocalDateTime;
 
 class DateTimeExtractAndTransformTest {
     @Test
-    void testWeekMode2Function() {
-        LocalDateTime localDateTime = LocalDateTime.of(0, 1, 1, 0, 0, 0, 0);
-        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.week(localDateTime, 2));
-        LocalDateTime localDateTime2 = localDateTime.plusDays(1);
-        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.week(localDateTime2, 2));
-        LocalDateTime localDateTime3 = LocalDateTime.of(0, 1, 9, 0, 0, 0, 0);
-        Assertions.assertEquals(new TinyIntLiteral((byte) 2), 
DateTimeExtractAndTransform.week(localDateTime3, 2));
-
-        LocalDateTime localDateTime4 = LocalDateTime.of(0, 12, 30, 0, 0, 0, 0);
-        Assertions.assertEquals(new TinyIntLiteral((byte) 52), 
DateTimeExtractAndTransform.week(localDateTime4, 2));
-        LocalDateTime localDateTime5 = localDateTime4.plusDays(1);
-        Assertions.assertEquals(new TinyIntLiteral((byte) 53), 
DateTimeExtractAndTransform.week(localDateTime5, 2));
-    }
+    void testSpecialDateWeeks() {
+        // test week/yearweek for 0000-01-01/02
+        LocalDateTime time1 = LocalDateTime.of(0, 1, 1, 0, 0, 0, 0);
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.week(time1, 0));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 0), 
DateTimeExtractAndTransform.week(time1, 1));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.week(time1, 2));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 52), 
DateTimeExtractAndTransform.week(time1, 3));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.week(time1, 4));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 0), 
DateTimeExtractAndTransform.week(time1, 5));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.week(time1, 6));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 52), 
DateTimeExtractAndTransform.week(time1, 7));
 
-    @Test
-    void testYearWeekMode2Function() {
-        LocalDateTime localDateTime = LocalDateTime.of(0, 1, 1, 0, 0, 0, 0);
-        Assertions.assertEquals(new IntegerLiteral(1), 
DateTimeExtractAndTransform.yearWeek(localDateTime, 2));
-        LocalDateTime localDateTime2 = localDateTime.plusDays(1);
-        Assertions.assertEquals(new IntegerLiteral(1), 
DateTimeExtractAndTransform.yearWeek(localDateTime2, 2));
-        LocalDateTime localDateTime3 = LocalDateTime.of(0, 1, 9, 0, 0, 0, 0);
-        Assertions.assertEquals(new IntegerLiteral(2), 
DateTimeExtractAndTransform.yearWeek(localDateTime3, 2));
-
-        LocalDateTime localDateTime4 = LocalDateTime.of(0, 12, 30, 0, 0, 0, 0);
-        Assertions.assertEquals(new IntegerLiteral(52), 
DateTimeExtractAndTransform.yearWeek(localDateTime4, 2));
-        LocalDateTime localDateTime5 = localDateTime4.plusDays(1);
-        Assertions.assertEquals(new IntegerLiteral(53), 
DateTimeExtractAndTransform.yearWeek(localDateTime5, 2));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.yearWeek(time1, 0));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 0), 
DateTimeExtractAndTransform.yearWeek(time1, 1));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.yearWeek(time1, 2));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 52), 
DateTimeExtractAndTransform.yearWeek(time1, 3));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.yearWeek(time1, 4));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 0), 
DateTimeExtractAndTransform.yearWeek(time1, 5));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.yearWeek(time1, 6));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 52), 
DateTimeExtractAndTransform.yearWeek(time1, 7));
+
+        LocalDateTime time2 = LocalDateTime.of(0, 1, 2, 0, 0, 0, 0);
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.week(time2, 0));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.week(time2, 1));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.week(time2, 2));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.week(time2, 3));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.week(time2, 4));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.week(time2, 5));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.week(time2, 6));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.week(time2, 7));
+
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.yearWeek(time2, 0));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.yearWeek(time2, 1));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.yearWeek(time2, 2));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.yearWeek(time2, 3));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.yearWeek(time2, 4));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.yearWeek(time2, 5));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.yearWeek(time2, 6));
+        Assertions.assertEquals(new TinyIntLiteral((byte) 1), 
DateTimeExtractAndTransform.yearWeek(time2, 7));
     }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to