You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by zh...@apache.org on 2019/11/08 10:57:28 UTC

[incubator-doris] branch master updated: Support date_add function to support partition prune (#2154)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 48d9318  Support date_add function to support partition prune (#2154)
48d9318 is described below

commit 48d9318d07488895261305bdb512985134d7db75
Author: HangyuanLiu <46...@qq.com>
AuthorDate: Fri Nov 8 18:57:21 2019 +0800

    Support date_add function to support partition prune (#2154)
    
    Currently in the date_add/date_sub functions (DATE_ADD(DATETIME date,INTERVAL expr type)), the expr parameter is the interval you want to add.
    Doris will convert these functions to xxx_sub/xxx_add. However, there is only the days_add function in fe, which causes other date_add formats, such as select date_add('2010-11-30 23:59:59', INTERVAL 2 DAY), cannot be pruned.
    
    So I've added other functions to support fe partition prune
---
 .../org/apache/doris/analysis/DateLiteral.java     | 49 +++++++++++++---
 .../apache/doris/analysis/ExpressionFunctions.java |  3 +-
 .../java/org/apache/doris/rewrite/FEFunctions.java | 68 ++++++++++++++++++++--
 .../org/apache/doris/rewrite/FEFunctionsTest.java  | 41 +++++++++++++
 4 files changed, 147 insertions(+), 14 deletions(-)

diff --git a/fe/src/main/java/org/apache/doris/analysis/DateLiteral.java b/fe/src/main/java/org/apache/doris/analysis/DateLiteral.java
index 8bbedfe..7042ad8 100644
--- a/fe/src/main/java/org/apache/doris/analysis/DateLiteral.java
+++ b/fe/src/main/java/org/apache/doris/analysis/DateLiteral.java
@@ -161,6 +161,16 @@ public class DateLiteral extends LiteralExpr {
         this.type = Type.DATETIME;
     }
 
+    public DateLiteral(LocalDateTime dateTime, Type type) {
+        this.year = dateTime.getYear();
+        this.month = dateTime.getMonthOfYear();
+        this.day = dateTime.getDayOfMonth();
+        this.hour = dateTime.getHourOfDay();
+        this.minute = dateTime.getMinuteOfHour();
+        this.second = dateTime.getSecondOfMinute();
+        this.type = type;                                                            
+    }
+
     public DateLiteral(DateLiteral other) {
         super(other);
         hour = other.hour;
@@ -542,17 +552,38 @@ public class DateLiteral extends LiteralExpr {
         return builder;
     }
 
-    public DateLiteral plusDays(int day) throws AnalysisException {
-        LocalDateTime dateTime;
+    public LocalDateTime getTimeFormatter() throws AnalysisException {
         if (type == Type.DATE) {
-            dateTime = DATE_FORMATTER.parseLocalDateTime(getStringValue()).plusDays(day);                                        
+            return DATE_FORMATTER.parseLocalDateTime(getStringValue());                        
+        } else if (type == Type.DATETIME) {
+            return DATE_TIME_FORMATTER.parseLocalDateTime(getStringValue());
         } else {
-            dateTime = DATE_TIME_FORMATTER.parseLocalDateTime(getStringValue()).plusDays(day);
-        }
-        DateLiteral dateLiteral = new DateLiteral(dateTime.getYear(), dateTime.getMonthOfYear(), dateTime.getDayOfMonth(),
-                dateTime.getHourOfDay(), dateTime.getMinuteOfHour(), dateTime.getSecondOfMinute());                                
-        dateLiteral.setType(type);
-        return dateLiteral;
+            throw new AnalysisException("Not support date literal type");
+        }        
+    }
+
+    public DateLiteral plusYears(int year) throws AnalysisException {
+        return new DateLiteral(getTimeFormatter().plusYears(year), type);
+    }
+
+    public DateLiteral plusMonths(int month) throws AnalysisException {
+        return new DateLiteral(getTimeFormatter().plusMonths(month), type);
+    }
+
+    public DateLiteral plusDays(int day) throws AnalysisException {
+        return new DateLiteral(getTimeFormatter().plusDays(day), type);
+    }
+
+    public DateLiteral plusHours(int hour) throws AnalysisException {
+        return new DateLiteral(getTimeFormatter().plusHours(hour), type);
+    }
+
+    public DateLiteral plusMinutes(int minute) throws AnalysisException {
+        return new DateLiteral(getTimeFormatter().plusMinutes(minute), type);
+    }
+
+    public DateLiteral plusSeconds(int second) throws AnalysisException {
+        return new DateLiteral(getTimeFormatter().plusSeconds(second), type);
     }
 
     public long getYear() {
diff --git a/fe/src/main/java/org/apache/doris/analysis/ExpressionFunctions.java b/fe/src/main/java/org/apache/doris/analysis/ExpressionFunctions.java
index 2ceb86f..e81e75b 100644
--- a/fe/src/main/java/org/apache/doris/analysis/ExpressionFunctions.java
+++ b/fe/src/main/java/org/apache/doris/analysis/ExpressionFunctions.java
@@ -66,7 +66,8 @@ public enum ExpressionFunctions {
         }
 
         if (constExpr instanceof ArithmeticExpr
-                || constExpr instanceof FunctionCallExpr) {
+                || constExpr instanceof FunctionCallExpr 
+                || constExpr instanceof TimestampArithmeticExpr) {
             Function fn = constExpr.getFn();
             
             Preconditions.checkNotNull(fn, "Expr's fn can't be null.");
diff --git a/fe/src/main/java/org/apache/doris/rewrite/FEFunctions.java b/fe/src/main/java/org/apache/doris/rewrite/FEFunctions.java
index a8b7c57..6786f72 100644
--- a/fe/src/main/java/org/apache/doris/rewrite/FEFunctions.java
+++ b/fe/src/main/java/org/apache/doris/rewrite/FEFunctions.java
@@ -66,18 +66,48 @@ public class FEFunctions {
 
     @FEFunction(name = "date_add", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
     public static DateLiteral dateAdd(LiteralExpr date, LiteralExpr day) throws AnalysisException {
-        DateLiteral dateLiteral = (DateLiteral) date;
-        return dateLiteral.plusDays((int) day.getLongValue());
+        return daysAdd(date, day);
     }
 
     @FEFunction(name = "adddate", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
     public static DateLiteral addDate(LiteralExpr date, LiteralExpr day) throws AnalysisException {
-        return dateAdd(date, day);
+        return daysAdd(date, day);
+    }
+
+    @FEFunction(name = "years_add", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
+    public static DateLiteral yearsAdd(LiteralExpr date, LiteralExpr year) throws AnalysisException {
+        DateLiteral dateLiteral = (DateLiteral) date;
+        return dateLiteral.plusYears((int) year.getLongValue());
+    }
+
+    @FEFunction(name = "months_add", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
+    public static DateLiteral monthsAdd(LiteralExpr date, LiteralExpr month) throws AnalysisException {
+        DateLiteral dateLiteral = (DateLiteral) date;
+        return dateLiteral.plusMonths((int) month.getLongValue());
     }
 
     @FEFunction(name = "days_add", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
     public static DateLiteral daysAdd(LiteralExpr date, LiteralExpr day) throws AnalysisException {
-        return dateAdd(date, day);
+        DateLiteral dateLiteral = (DateLiteral) date;
+        return dateLiteral.plusDays((int) day.getLongValue());
+    }
+
+    @FEFunction(name = "hours_add", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
+    public static DateLiteral hoursAdd(LiteralExpr date, LiteralExpr hour) throws AnalysisException {
+        DateLiteral dateLiteral = (DateLiteral) date;
+        return dateLiteral.plusHours((int) hour.getLongValue());
+    }
+
+    @FEFunction(name = "minutes_add", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
+    public static DateLiteral minutesAdd(LiteralExpr date, LiteralExpr minute) throws AnalysisException {
+        DateLiteral dateLiteral = (DateLiteral) date;
+        return dateLiteral.plusMinutes((int) minute.getLongValue());
+    }
+
+    @FEFunction(name = "seconds_add", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
+     public static DateLiteral secondsAdd(LiteralExpr date, LiteralExpr second) throws AnalysisException {
+        DateLiteral dateLiteral = (DateLiteral) date;
+        return dateLiteral.plusSeconds((int) second.getLongValue());
     }
 
     @FEFunction(name = "date_format", argTypes = { "DATETIME", "VARCHAR" }, returnType = "VARCHAR")
@@ -96,6 +126,36 @@ public class FEFunctions {
         return dateAdd(date, new IntLiteral(-(int) day.getLongValue()));
     }
 
+    @FEFunction(name = "years_sub", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
+    public static DateLiteral yearsSub(LiteralExpr date, LiteralExpr year) throws AnalysisException {
+        return yearsAdd(date, new IntLiteral(-(int) year.getLongValue()));
+    }
+
+    @FEFunction(name = "months_sub", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
+    public static DateLiteral monthsSub(LiteralExpr date, LiteralExpr month) throws AnalysisException {
+        return monthsAdd(date, new IntLiteral(-(int) month.getLongValue()));
+    }
+
+    @FEFunction(name = "days_sub", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
+    public static DateLiteral daysSub(LiteralExpr date, LiteralExpr day) throws AnalysisException {
+        return daysAdd(date, new IntLiteral(-(int) day.getLongValue()));
+    }
+
+    @FEFunction(name = "hours_sub", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
+    public static DateLiteral hoursSub(LiteralExpr date, LiteralExpr hour) throws AnalysisException {
+        return hoursAdd(date, new IntLiteral(-(int) hour.getLongValue()));
+    }
+
+    @FEFunction(name = "minutes_sub", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
+    public static DateLiteral minutesSub(LiteralExpr date, LiteralExpr minute) throws AnalysisException {
+        return minutesAdd(date, new IntLiteral(-(int) minute.getLongValue()));
+    }
+
+    @FEFunction(name = "seconds_sub", argTypes = { "DATETIME", "INT" }, returnType = "DATETIME")
+    public static DateLiteral secondsSub(LiteralExpr date, LiteralExpr second) throws AnalysisException {
+        return secondsAdd(date, new IntLiteral(-(int) second.getLongValue()));
+    }
+
     @FEFunction(name = "year", argTypes = { "DATETIME" }, returnType = "INT")
     public static IntLiteral year(LiteralExpr arg) throws AnalysisException {
         return new IntLiteral(((DateLiteral) arg).getYear(), Type.INT);
diff --git a/fe/src/test/java/org/apache/doris/rewrite/FEFunctionsTest.java b/fe/src/test/java/org/apache/doris/rewrite/FEFunctionsTest.java
index b54a9f0..276952d 100644
--- a/fe/src/test/java/org/apache/doris/rewrite/FEFunctionsTest.java
+++ b/fe/src/test/java/org/apache/doris/rewrite/FEFunctionsTest.java
@@ -518,4 +518,45 @@ public class FEFunctionsTest {
         Assert.assertEquals(31559414743L, FEFunctions.timeDiff(d3, d1).getLongValue());
         Assert.assertEquals(2419200, FEFunctions.timeDiff(d3, d2).getLongValue());
     }
+
+    @Test
+    public void datePlusAndSubTest() throws AnalysisException {
+        DateLiteral dateLiteral = new DateLiteral("2019-11-11 00:00:00", Type.DATETIME);
+
+        Assert.assertEquals(new DateLiteral("2020-11-11 00:00:00", Type.DATETIME),
+                FEFunctions.yearsAdd(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2018-11-11 00:00:00", Type.DATETIME),
+                FEFunctions.yearsSub(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-12-11 00:00:00", Type.DATETIME),
+                FEFunctions.monthsAdd(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-10-11 00:00:00", Type.DATETIME),
+                FEFunctions.monthsSub(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-11-12 00:00:00", Type.DATETIME),
+                FEFunctions.daysAdd(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-11-10 00:00:00", Type.DATETIME),
+                FEFunctions.daysSub(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-11-11 01:00:00", Type.DATETIME),
+                FEFunctions.hoursAdd(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-11-10 23:00:00", Type.DATETIME),
+                FEFunctions.hoursSub(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-11-11 00:01:00", Type.DATETIME),
+                FEFunctions.minutesAdd(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-11-10 23:59:00", Type.DATETIME),
+                FEFunctions.minutesSub(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-11-11 00:00:01", Type.DATETIME),
+                FEFunctions.secondsAdd(dateLiteral, new IntLiteral(1)));
+
+        Assert.assertEquals(new DateLiteral("2019-11-10 23:59:59", Type.DATETIME),
+                FEFunctions.secondsSub(dateLiteral, new IntLiteral(1)));
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@doris.apache.org
For additional commands, e-mail: commits-help@doris.apache.org