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

zykkk 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 f4d05e03adf [enhancement](jdbc catalog) Enhance function pushdown of 
Jdbc Oracle Catalog (#29972)
f4d05e03adf is described below

commit f4d05e03adfafd5e6f8165dda9bd8c3895a880a0
Author: zy-kkk <zhongy...@gmail.com>
AuthorDate: Tue Jan 16 15:55:43 2024 +0800

    [enhancement](jdbc catalog) Enhance function pushdown of Jdbc Oracle 
Catalog (#29972)
---
 docs/en/docs/lakehouse/multi-catalog/jdbc.md       |  6 +++++-
 docs/zh-CN/docs/lakehouse/multi-catalog/jdbc.md    |  6 +++++-
 .../external/jdbc/JdbcFunctionPushDownRule.java    | 25 ++++++++++++++++++++++
 .../doris/planner/external/jdbc/JdbcScanNode.java  |  3 ++-
 .../jdbc/test_oracle_jdbc_catalog.groovy           |  6 ++++++
 5 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/docs/en/docs/lakehouse/multi-catalog/jdbc.md 
b/docs/en/docs/lakehouse/multi-catalog/jdbc.md
index 11a02b049a6..662fcc81118 100644
--- a/docs/en/docs/lakehouse/multi-catalog/jdbc.md
+++ b/docs/en/docs/lakehouse/multi-catalog/jdbc.md
@@ -114,7 +114,7 @@ In some cases, the keywords in the database might be used 
as the field names. Fo
 
 1. When executing a query like `where dt = '2022-01-01'`, Doris can push down 
these filtering conditions to the external data source, thereby directly 
excluding data that does not meet the conditions at the data source level, 
reducing the number of unqualified Necessary data acquisition and transfer. 
This greatly improves query performance while also reducing the load on 
external data sources.
 
-2. When `enable_func_pushdown` is set to true, the function conditions after 
where will also be pushed down to the external data source. Currently, only 
MySQL and ClickHouse are supported. If you encounter a function that is not 
supported by MySQL or ClickHouse, you can set this parameter to false. , 
currently Doris will automatically identify some functions not supported by 
MySQL and functions supported by CLickHouse for push-down condition filtering, 
which can be viewed through explain sql.
+2. When `enable_func_pushdown` is set to true, the function conditions after 
where will also be pushed down to the external data source. Currently, only 
MySQL, ClickHouse, and Oracle are supported. If you encounter functions that 
are not supported by MySQL, ClickHouse, and Oracle, you can use this The 
parameter is set to false. At present, Doris will automatically identify some 
functions that are not supported by MySQL and functions supported by CLickHouse 
and Oracle for push-down condit [...]
 
 Functions that are currently not pushed down include:
 
@@ -130,6 +130,10 @@ Functions that are currently pushed down include:
 | FROM_UNIXTIME  |
 | UNIX_TIMESTAMP |
 
+| Oracle |
+|:------:|
+|  NVL   |
+
 ### Line Limit
 
 If there is a limit keyword in the query, Doris will translate it into 
semantics suitable for different data sources.
diff --git a/docs/zh-CN/docs/lakehouse/multi-catalog/jdbc.md 
b/docs/zh-CN/docs/lakehouse/multi-catalog/jdbc.md
index e57acbe688f..e3eb90d7f40 100644
--- a/docs/zh-CN/docs/lakehouse/multi-catalog/jdbc.md
+++ b/docs/zh-CN/docs/lakehouse/multi-catalog/jdbc.md
@@ -114,7 +114,7 @@ select * from mysql_catalog.mysql_database.mysql_table 
where k1 > 1000 and k3 ='
 
 1. 当执行类似于 `where dt = '2022-01-01'` 这样的查询时,Doris 
能够将这些过滤条件下推到外部数据源,从而直接在数据源层面排除不符合条件的数据,减少了不必要的数据获取和传输。这大大提高了查询性能,同时也降低了对外部数据源的负载。
    
-2. 当 `enable_func_pushdown` 设置为true,会将 where 之后的函数条件也下推到外部数据源,目前仅支持 MySQL 以及 
ClickHouse,如遇到 MySQL 或 ClickHouse 不支持的函数,可以将此参数设置为 false,目前 Doris 会自动识别部分 MySQL 
不支持的函数以及 CLickHouse 支持的函数进行下推条件过滤,可通过 explain sql 查看。
+2. 当 `enable_func_pushdown` 设置为true,会将 where 之后的函数条件也下推到外部数据源,目前仅支持 
MySQL、ClickHouse、Oracle,如遇到 MySQL、ClickHouse、Oracle 不支持的函数,可以将此参数设置为 false,目前 
Doris 会自动识别部分 MySQL 不支持的函数以及 CLickHouse、Oracle 支持的函数进行下推条件过滤,可通过 explain sql 查看。
 
 目前不会下推的函数有:
 
@@ -130,6 +130,10 @@ select * from mysql_catalog.mysql_database.mysql_table 
where k1 > 1000 and k3 ='
 | FROM_UNIXTIME  |
 | UNIX_TIMESTAMP |
 
+| Oracle |
+|:------:|
+|  NVL   |
+
 ### 行数限制
 
 如果在查询中带有 limit 关键字,Doris 会将其转译成适合不同数据源的语义。
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 4fb8788bb0b..d328952593f 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
@@ -49,6 +49,13 @@ public class JdbcFunctionPushDownRule {
         CLICKHOUSE_SUPPORTED_FUNCTIONS.add("unix_timestamp");
     }
 
+    private static final TreeSet<String> ORACLE_SUPPORTED_FUNCTIONS = new 
TreeSet<>(String.CASE_INSENSITIVE_ORDER);
+
+    static {
+        ORACLE_SUPPORTED_FUNCTIONS.add("nvl");
+        ORACLE_SUPPORTED_FUNCTIONS.add("ifnull");
+    }
+
     private static boolean isMySQLFunctionUnsupported(String functionName) {
         return 
MYSQL_UNSUPPORTED_FUNCTIONS.contains(functionName.toLowerCase());
     }
@@ -57,6 +64,9 @@ public class JdbcFunctionPushDownRule {
         return 
!CLICKHOUSE_SUPPORTED_FUNCTIONS.contains(functionName.toLowerCase());
     }
 
+    private static boolean isOracleFunctionUnsupported(String functionName) {
+        return 
!ORACLE_SUPPORTED_FUNCTIONS.contains(functionName.toLowerCase());
+    }
 
     private static final Map<String, String> REPLACE_MYSQL_FUNCTIONS = 
Maps.newHashMap();
 
@@ -80,6 +90,16 @@ public class JdbcFunctionPushDownRule {
         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 isReplaceOracleFunctions(String functionName) {
+        return 
REPLACE_ORACLE_FUNCTIONS.containsKey(functionName.toLowerCase());
+    }
+
     public static Expr processFunctions(TOdbcTableType tableType, Expr expr, 
List<String> errors) {
         if (tableType == null || expr == null) {
             return expr;
@@ -94,6 +114,9 @@ public class JdbcFunctionPushDownRule {
         } else if (TOdbcTableType.CLICKHOUSE.equals(tableType)) {
             replaceFunction = 
JdbcFunctionPushDownRule::isReplaceClickHouseFunctions;
             checkFunction = 
JdbcFunctionPushDownRule::isClickHouseFunctionUnsupported;
+        } else if (TOdbcTableType.ORACLE.equals(tableType)) {
+            replaceFunction = 
JdbcFunctionPushDownRule::isReplaceOracleFunctions;
+            checkFunction = 
JdbcFunctionPushDownRule::isOracleFunctionUnsupported;
         } else {
             return expr;
         }
@@ -138,6 +161,8 @@ public class JdbcFunctionPushDownRule {
                 newFunc = REPLACE_MYSQL_FUNCTIONS.get(func.toLowerCase());
             } else if (TOdbcTableType.CLICKHOUSE.equals(tableType)) {
                 newFunc = REPLACE_CLICKHOUSE_FUNCTIONS.get(func);
+            } else if (TOdbcTableType.ORACLE.equals(tableType)) {
+                newFunc = REPLACE_ORACLE_FUNCTIONS.get(func);
             } else {
                 newFunc = null;
             }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/planner/external/jdbc/JdbcScanNode.java
 
b/fe/fe-core/src/main/java/org/apache/doris/planner/external/jdbc/JdbcScanNode.java
index 76dbd40abab..774d4284bce 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/planner/external/jdbc/JdbcScanNode.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/planner/external/jdbc/JdbcScanNode.java
@@ -311,7 +311,8 @@ public class JdbcScanNode extends ExternalScanNode {
 
     private static boolean shouldPushDownConjunct(TOdbcTableType tableType, 
Expr expr) {
         if (containsFunctionCallExpr(expr)) {
-            if (tableType.equals(TOdbcTableType.MYSQL) || 
tableType.equals(TOdbcTableType.CLICKHOUSE)) {
+            if (tableType.equals(TOdbcTableType.MYSQL) || 
tableType.equals(TOdbcTableType.CLICKHOUSE)
+                    || tableType.equals(TOdbcTableType.ORACLE)) {
                 return Config.enable_func_pushdown;
             } else {
                 return false;
diff --git 
a/regression-test/suites/external_table_p0/jdbc/test_oracle_jdbc_catalog.groovy 
b/regression-test/suites/external_table_p0/jdbc/test_oracle_jdbc_catalog.groovy
index 136b785bb51..75ce7175df5 100644
--- 
a/regression-test/suites/external_table_p0/jdbc/test_oracle_jdbc_catalog.groovy
+++ 
b/regression-test/suites/external_table_p0/jdbc/test_oracle_jdbc_catalog.groovy
@@ -134,6 +134,12 @@ suite("test_oracle_jdbc_catalog", 
"p0,external,oracle,external_docker,external_d
         order_qt_date6  """ select * from TEST_DATE where (T1 < '2022-01-22 
00:00:00' or T1 > '2022-01-20 00:00:00') and (T1 < '2022-01-23 00:00:00' or T1 
> '2022-01-19 00:00:00'); """
         order_qt_date7  """select * from TEST_TIMESTAMP where T2 < 
str_to_date('2020-12-21 12:34:56', '%Y-%m-%d %H:%i:%s');"""
 
+        // test nvl
+        explain {
+            sql("SELECT * FROM STUDENT WHERE nvl(score, 0) < 95;")
+            contains """SELECT "ID", "NAME", "AGE", "SCORE" FROM 
"DORIS_TEST"."STUDENT" WHERE (nvl("SCORE", 0.0) < 95.0)"""
+        }
+
         // for old planner
         order_qt_filter4_old_plan  """ select /*+ 
SET_VAR(enable_nereids_planner=false) */ * from STUDENT where NAME NOT like 
'%bob%' order by ID; """
         order_qt_filter5_old_plan  """ select /*+ 
SET_VAR(enable_nereids_planner=false) */ * from STUDENT where NAME NOT like 
'%bob%' or NAME NOT LIKE '%jerry%' order by ID; """


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

Reply via email to