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

zykkk pushed a commit to branch branch-2.0
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-2.0 by this push:
     new 5c19ae070ec [pick][fix](catalog) fix data_sub/data_add func pushdown 
in jdbcscan (#30882)
5c19ae070ec is described below

commit 5c19ae070ecf9934b177b24b20603a22540d9d8f
Author: zy-kkk <zhongy...@gmail.com>
AuthorDate: Tue Feb 6 15:49:31 2024 +0800

    [pick][fix](catalog) fix data_sub/data_add func pushdown in jdbcscan 
(#30882)
---
 .../external/jdbc/JdbcFunctionPushDownRule.java    | 64 +++++++++++++---
 .../jdbc/test_mysql_jdbc_catalog.out               | 42 +++++++++++
 .../jdbc/test_mysql_jdbc_catalog.groovy            | 88 ++++++++++++++++++++++
 3 files changed, 183 insertions(+), 11 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/planner/external/jdbc/JdbcFunctionPushDownRule.java
 
b/fe/fe-core/src/main/java/org/apache/doris/planner/external/jdbc/JdbcFunctionPushDownRule.java
index d328952593f..74e04256f43 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/planner/external/jdbc/JdbcFunctionPushDownRule.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/planner/external/jdbc/JdbcFunctionPushDownRule.java
@@ -20,6 +20,7 @@ package org.apache.doris.planner.external.jdbc;
 import org.apache.doris.analysis.Expr;
 import org.apache.doris.analysis.FunctionCallExpr;
 import org.apache.doris.analysis.FunctionName;
+import org.apache.doris.analysis.TimestampArithmeticExpr;
 import org.apache.doris.catalog.TableIf.TableType;
 import org.apache.doris.thrift.TOdbcTableType;
 
@@ -75,10 +76,6 @@ public class JdbcFunctionPushDownRule {
         REPLACE_MYSQL_FUNCTIONS.put("to_date", "date");
     }
 
-    private static boolean isReplaceMysqlFunctions(String functionName) {
-        return REPLACE_MYSQL_FUNCTIONS.containsKey(functionName.toLowerCase());
-    }
-
     private static final Map<String, String> REPLACE_CLICKHOUSE_FUNCTIONS = 
Maps.newHashMap();
 
     static {
@@ -86,16 +83,20 @@ public class JdbcFunctionPushDownRule {
         REPLACE_CLICKHOUSE_FUNCTIONS.put("unix_timestamp", "toUnixTimestamp");
     }
 
-    private static boolean isReplaceClickHouseFunctions(String functionName) {
-        return 
REPLACE_CLICKHOUSE_FUNCTIONS.containsKey(functionName.toLowerCase());
-    }
-
     private static final Map<String, String> REPLACE_ORACLE_FUNCTIONS = 
Maps.newHashMap();
 
     static {
         REPLACE_ORACLE_FUNCTIONS.put("ifnull", "nvl");
     }
 
+    private static boolean isReplaceMysqlFunctions(String functionName) {
+        return REPLACE_MYSQL_FUNCTIONS.containsKey(functionName.toLowerCase());
+    }
+
+    private static boolean isReplaceClickHouseFunctions(String functionName) {
+        return 
REPLACE_CLICKHOUSE_FUNCTIONS.containsKey(functionName.toLowerCase());
+    }
+
     private static boolean isReplaceOracleFunctions(String functionName) {
         return 
REPLACE_ORACLE_FUNCTIONS.containsKey(functionName.toLowerCase());
     }
@@ -141,6 +142,8 @@ public class JdbcFunctionPushDownRule {
             }
 
             replaceFunctionNameIfNecessary(func, replaceFunction, 
functionCallExpr, tableType);
+
+            expr = replaceGenericFunctionExpr(functionCallExpr, func);
         }
 
         List<Expr> children = expr.getChildren();
@@ -153,7 +156,7 @@ public class JdbcFunctionPushDownRule {
         return expr;
     }
 
-    private static String replaceFunctionNameIfNecessary(String func, 
Predicate<String> replaceFunction,
+    private static void replaceFunctionNameIfNecessary(String func, 
Predicate<String> replaceFunction,
             FunctionCallExpr functionCallExpr, TOdbcTableType tableType) {
         if (replaceFunction.test(func)) {
             String newFunc;
@@ -168,9 +171,48 @@ public class JdbcFunctionPushDownRule {
             }
             if (newFunc != null) {
                 
functionCallExpr.setFnName(FunctionName.createBuiltinName(newFunc));
-                func = functionCallExpr.getFnName().getFunction();
             }
         }
-        return func;
+    }
+
+    // Function used to convert nereids planner's function to old planner's 
function
+    private static Expr replaceGenericFunctionExpr(FunctionCallExpr 
functionCallExpr, String func) {
+        Map<String, String> supportedTimeUnits = Maps.newHashMap();
+        supportedTimeUnits.put("years", "YEAR");
+        supportedTimeUnits.put("months", "MONTH");
+        supportedTimeUnits.put("weeks", "WEEK");
+        supportedTimeUnits.put("days", "DAY");
+        supportedTimeUnits.put("hours", "HOUR");
+        supportedTimeUnits.put("minutes", "MINUTE");
+        supportedTimeUnits.put("seconds", "SECOND");
+
+        String baseFuncName = null;
+        String timeUnit = null;
+
+        for (Map.Entry<String, String> entry : supportedTimeUnits.entrySet()) {
+            if (func.endsWith(entry.getKey() + "_add")) {
+                baseFuncName = "date_add";
+                timeUnit = entry.getValue();
+                break;
+            } else if (func.endsWith(entry.getKey() + "_sub")) {
+                baseFuncName = "date_sub";
+                timeUnit = entry.getValue();
+                break;
+            }
+        }
+
+        if (baseFuncName != null && timeUnit != null) {
+            if (functionCallExpr.getChildren().size() == 2) {
+                Expr child1 = functionCallExpr.getChild(0);
+                Expr child2 = functionCallExpr.getChild(1);
+                return new TimestampArithmeticExpr(
+                        baseFuncName,
+                        child1,
+                        child2,
+                        timeUnit
+                );
+            }
+        }
+        return functionCallExpr;
     }
 }
diff --git 
a/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_catalog.out 
b/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_catalog.out
index af836d95c02..b02db0b1ee6 100644
--- a/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_catalog.out
+++ b/regression-test/data/external_table_p0/jdbc/test_mysql_jdbc_catalog.out
@@ -399,3 +399,45 @@ year       SMALLINT        Yes     false   \N      NONE
 -- !money_format --
 1
 
+-- !date_add_year --
+2      2022-01-01
+
+-- !date_add_month --
+2      2022-01-01
+
+-- !date_add_week --
+2      2022-01-01
+
+-- !date_add_day --
+2      2022-01-01
+
+-- !date_add_hour --
+2      2022-01-01
+
+-- !date_add_min --
+2      2022-01-01
+
+-- !date_add_sec --
+2      2022-01-01
+
+-- !date_sub_year --
+2      2022-01-01
+
+-- !date_sub_month --
+2      2022-01-01
+
+-- !date_sub_week --
+2      2022-01-01
+
+-- !date_sub_day --
+2      2022-01-01
+
+-- !date_sub_hour --
+2      2022-01-01
+
+-- !date_sub_min --
+2      2022-01-01
+
+-- !date_sub_sec --
+2      2022-01-01
+
diff --git 
a/regression-test/suites/external_table_p0/jdbc/test_mysql_jdbc_catalog.groovy 
b/regression-test/suites/external_table_p0/jdbc/test_mysql_jdbc_catalog.groovy
index fdc1f84e382..08590d08fea 100644
--- 
a/regression-test/suites/external_table_p0/jdbc/test_mysql_jdbc_catalog.groovy
+++ 
b/regression-test/suites/external_table_p0/jdbc/test_mysql_jdbc_catalog.groovy
@@ -416,6 +416,94 @@ suite("test_mysql_jdbc_catalog", 
"p0,external,mysql,external_docker,external_doc
                 contains "QUERY: SELECT `k6`, `k8` FROM `doris_test`.`test1` 
WHERE (`k8` = 1)"
             }
             sql """ admin set frontend config ("enable_func_pushdown" = 
"true"); """
+            // test date_add
+            sql """ set disable_nereids_rules='NORMALIZE_REWRITE_RULES'; """
+            order_qt_date_add_year """ select * from test_zd where 
date_add(d_z,interval 1 year) = '2023-01-01' order by 1; """
+            explain {
+                sql("select * from test_zd where date_add(d_z,interval 1 year) 
= '2023-01-01' order by 1;")
+
+                contains " QUERY: SELECT `id`, `d_z` FROM 
`doris_test`.`test_zd` WHERE (date_add(`d_z`, INTERVAL 1 YEAR) = '2023-01-01')"
+            }
+            order_qt_date_add_month """ select * from test_zd where 
date_add(d_z,interval 1 month) = '2022-02-01' order by 1; """
+            explain {
+                sql("select * from test_zd where date_add(d_z,interval 1 
month) = '2022-02-01' order by 1;")
+
+                contains " QUERY: SELECT `id`, `d_z` FROM 
`doris_test`.`test_zd` WHERE (date_add(`d_z`, INTERVAL 1 MONTH) = '2022-02-01')"
+            }
+            order_qt_date_add_week """ select * from test_zd where 
date_add(d_z,interval 1 week) = '2022-01-08' order by 1; """
+            explain {
+                sql("select * from test_zd where date_add(d_z,interval 1 week) 
= '2022-01-08' order by 1;")
+
+                contains " QUERY: SELECT `id`, `d_z` FROM 
`doris_test`.`test_zd` WHERE (date_add(`d_z`, INTERVAL 1 WEEK) = '2022-01-08')"
+            }
+            order_qt_date_add_day """ select * from test_zd where 
date_add(d_z,interval 1 day) = '2022-01-02' order by 1; """
+            explain {
+                sql("select * from test_zd where date_add(d_z,interval 1 day) 
= '2022-01-02' order by 1;")
+
+                contains " QUERY: SELECT `id`, `d_z` FROM 
`doris_test`.`test_zd` WHERE (date_add(`d_z`, INTERVAL 1 DAY) = '2022-01-02')"
+            }
+            order_qt_date_add_hour """ select * from test_zd where 
date_add(d_z,interval 1 hour) = '2022-01-01 01:00:00' order by 1; """
+            explain {
+                sql("select * from test_zd where date_add(d_z,interval 1 hour) 
= '2022-01-01 01:00:00' order by 1;")
+
+                contains " QUERY: SELECT `id`, `d_z` FROM 
`doris_test`.`test_zd` WHERE (date_add(`d_z`, INTERVAL 1 HOUR) = '2022-01-01 
01:00:00')"
+            }
+            order_qt_date_add_min """ select * from test_zd where 
date_add(d_z,interval 1 minute) = '2022-01-01 00:01:00' order by 1; """
+            explain {
+                sql("select * from test_zd where date_add(d_z,interval 1 
minute) = '2022-01-01 00:01:00' order by 1;")
+
+                contains " QUERY: SELECT `id`, `d_z` FROM 
`doris_test`.`test_zd` WHERE (date_add(`d_z`, INTERVAL 1 MINUTE) = '2022-01-01 
00:01:00')"
+            }
+            order_qt_date_add_sec """ select * from test_zd where 
date_add(d_z,interval 1 second) = '2022-01-01 00:00:01' order by 1; """
+            explain {
+                sql("select * from test_zd where date_add(d_z,interval 1 
second) = '2022-01-01 00:00:01' order by 1;")
+
+                contains " QUERY: SELECT `id`, `d_z` FROM 
`doris_test`.`test_zd` WHERE (date_add(`d_z`, INTERVAL 1 SECOND) = '2022-01-01 
00:00:01')"
+            }
+            // date_sub
+            order_qt_date_sub_year """ select * from test_zd where 
date_sub(d_z,interval 1 year) = '2021-01-01' order by 1; """
+            explain {
+                sql("select * from test_zd where date_sub(d_z,interval 1 year) 
= '2021-01-01' order by 1;")
+
+                contains " QUERY: SELECT `id`, `d_z` FROM 
`doris_test`.`test_zd` WHERE (date_sub(`d_z`, INTERVAL 1 YEAR) = '2021-01-01')"
+            }
+            order_qt_date_sub_month """ select * from test_zd where 
date_sub(d_z,interval 1 month) = '2021-12-01' order by 1; """
+            explain {
+                sql("select * from test_zd where date_sub(d_z,interval 1 
month) = '2021-12-01' order by 1;")
+
+                contains " QUERY: SELECT `id`, `d_z` FROM 
`doris_test`.`test_zd` WHERE (date_sub(`d_z`, INTERVAL 1 MONTH) = '2021-12-01')"
+            }
+            order_qt_date_sub_week """ select * from test_zd where 
date_sub(d_z,interval 1 week) = '2021-12-25' order by 1; """
+            explain {
+                sql("select * from test_zd where date_sub(d_z,interval 1 week) 
= '2021-12-25' order by 1;")
+
+                contains " QUERY: SELECT `id`, `d_z` FROM 
`doris_test`.`test_zd` WHERE (date_sub(`d_z`, INTERVAL 1 WEEK) = '2021-12-25')"
+            }
+            order_qt_date_sub_day """ select * from test_zd where 
date_sub(d_z,interval 1 day) = '2021-12-31' order by 1; """
+            explain {
+                sql("select * from test_zd where date_sub(d_z,interval 1 day) 
= '2021-12-31' order by 1;")
+
+                contains " QUERY: SELECT `id`, `d_z` FROM 
`doris_test`.`test_zd` WHERE (date_sub(`d_z`, INTERVAL 1 DAY) = '2021-12-31')"
+            }
+            order_qt_date_sub_hour """ select * from test_zd where 
date_sub(d_z,interval 1 hour) = '2021-12-31 23:00:00' order by 1; """
+            explain {
+                sql("select * from test_zd where date_sub(d_z,interval 1 hour) 
= '2021-12-31 23:00:00' order by 1;")
+
+                contains " QUERY: SELECT `id`, `d_z` FROM 
`doris_test`.`test_zd` WHERE (date_sub(`d_z`, INTERVAL 1 HOUR) = '2021-12-31 
23:00:00')"
+            }
+            order_qt_date_sub_min """ select * from test_zd where 
date_sub(d_z,interval 1 minute) = '2021-12-31 23:59:00' order by 1; """
+            explain {
+                sql("select * from test_zd where date_sub(d_z,interval 1 
minute) = '2021-12-31 23:59:00' order by 1;")
+
+                contains " QUERY: SELECT `id`, `d_z` FROM 
`doris_test`.`test_zd` WHERE (date_sub(`d_z`, INTERVAL 1 MINUTE) = '2021-12-31 
23:59:00')"
+            }
+            order_qt_date_sub_sec """ select * from test_zd where 
date_sub(d_z,interval 1 second) = '2021-12-31 23:59:59' order by 1; """
+            explain {
+                sql("select * from test_zd where date_sub(d_z,interval 1 
second) = '2021-12-31 23:59:59' order by 1;")
+
+                contains " QUERY: SELECT `id`, `d_z` FROM 
`doris_test`.`test_zd` WHERE (date_sub(`d_z`, INTERVAL 1 SECOND) = '2021-12-31 
23:59:59')"
+            }
+            sql """ set disable_nereids_rules=''; """
         } finally {
                        res_dbs_log = sql "show databases;"
                        for(int i = 0;i < res_dbs_log.size();i++) {


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

Reply via email to