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

morningman pushed a commit to branch branch-1.2-lts
in repository https://gitbox.apache.org/repos/asf/doris.git

commit ee329692fea3a01f055783087ed3c21eedf893f6
Author: Tiewei Fang <43782773+bepppo...@users.noreply.github.com>
AuthorDate: Sat Jan 14 00:01:33 2023 +0800

    [feature](multi-catalog) support oracle jdbc catalog (#15862)
---
 .../docker-compose/oracle/init/01-drop-user.sql    | 18 ++++++
 .../docker-compose/oracle/init/02-create-user.sql  | 19 ++++++
 .../docker-compose/oracle/init/03-create-table.sql | 70 ++++++++++++++++++++
 .../docker-compose/oracle/init/04-insert.sql       | 48 ++++++++++++++
 .../docker-compose/oracle/oracle-11.env            | 19 ++++++
 .../docker-compose/oracle/oracle-11.yaml           | 49 ++++++++++++++
 docker/thirdparties/start-thirdparties-docker.sh   |  7 ++
 docker/thirdparties/stop-thirdparties-docker.sh    |  3 +
 .../docs/ecosystem/external-table/multi-catalog.md | 45 ++++++++++++-
 .../Create/CREATE-CATALOG.md                       | 28 +++++++-
 .../docs/ecosystem/external-table/multi-catalog.md | 45 ++++++++++++-
 .../Create/CREATE-CATALOG.md                       | 28 +++++++-
 .../org/apache/doris/catalog/JdbcResource.java     |  2 +
 .../org/apache/doris/external/jdbc/JdbcClient.java | 73 ++++++++++++++++++---
 regression-test/conf/regression-conf.groovy        |  1 +
 .../jdbc_catalog_p0/test_oracle_jdbc_catalog.out   | 33 ++++++++++
 .../test_oracle_jdbc_catalog.groovy                | 74 ++++++++++++++++++++++
 17 files changed, 543 insertions(+), 19 deletions(-)

diff --git a/docker/thirdparties/docker-compose/oracle/init/01-drop-user.sql 
b/docker/thirdparties/docker-compose/oracle/init/01-drop-user.sql
new file mode 100644
index 0000000000..a47a923f97
--- /dev/null
+++ b/docker/thirdparties/docker-compose/oracle/init/01-drop-user.sql
@@ -0,0 +1,18 @@
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements.  See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership.  The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License.  You may obtain a copy of the License at
+--
+--   http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied.  See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+
+drop user doris_test CASCADE;
diff --git a/docker/thirdparties/docker-compose/oracle/init/02-create-user.sql 
b/docker/thirdparties/docker-compose/oracle/init/02-create-user.sql
new file mode 100644
index 0000000000..dc59e57b78
--- /dev/null
+++ b/docker/thirdparties/docker-compose/oracle/init/02-create-user.sql
@@ -0,0 +1,19 @@
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements.  See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership.  The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License.  You may obtain a copy of the License at
+--
+--   http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied.  See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+
+create user doris_test identified by 123456;
+grant connect, resource to doris_test;
diff --git a/docker/thirdparties/docker-compose/oracle/init/03-create-table.sql 
b/docker/thirdparties/docker-compose/oracle/init/03-create-table.sql
new file mode 100644
index 0000000000..efd648dff6
--- /dev/null
+++ b/docker/thirdparties/docker-compose/oracle/init/03-create-table.sql
@@ -0,0 +1,70 @@
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements.  See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership.  The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License.  You may obtain a copy of the License at
+--
+--   http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied.  See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+
+create table doris_test.student (
+id number(5),
+name varchar2(20),
+age number(2),
+score number(3,1)
+);
+
+create table doris_test.test_num (
+id int,
+n1 number,
+n2 number(38),
+n3 number(9,2),
+n4 int,
+n5 smallint,
+n6 decimal(5,2),
+n7 float,
+n8 float(2),
+n9 real
+);
+
+create table doris_test.test_int (
+id int,
+tinyint_value1 number(2,0),
+smallint_value1 number(4,0),
+int_value1 number(9,0),
+bigint_value1 number(18,0),
+tinyint_value2 number(3,0),
+smallint_value2 number(5,0),
+int_value2 number(10,0),
+bigint_value2 number(19,0)
+);
+
+create table doris_test.test_char (
+id int,
+country char,
+city nchar(6),
+address varchar2(4000),
+name nvarchar2(6),
+remark long
+);
+
+create table doris_test.test_raw (
+id int,
+raw_value raw(20),
+long_raw_value long raw
+);
+
+create table doris_test.test_date (
+id int,
+t1 date,
+t2 interval year(3) to month,
+t3 interval day(3) to second(6)
+);
diff --git a/docker/thirdparties/docker-compose/oracle/init/04-insert.sql 
b/docker/thirdparties/docker-compose/oracle/init/04-insert.sql
new file mode 100644
index 0000000000..fd6ea2a57c
--- /dev/null
+++ b/docker/thirdparties/docker-compose/oracle/init/04-insert.sql
@@ -0,0 +1,48 @@
+-- Licensed to the Apache Software Foundation (ASF) under one
+-- or more contributor license agreements.  See the NOTICE file
+-- distributed with this work for additional information
+-- regarding copyright ownership.  The ASF licenses this file
+-- to you under the Apache License, Version 2.0 (the
+-- "License"); you may not use this file except in compliance
+-- with the License.  You may obtain a copy of the License at
+--
+--   http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing,
+-- software distributed under the License is distributed on an
+-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+-- KIND, either express or implied.  See the License for the
+-- specific language governing permissions and limitations
+-- under the License.
+
+insert into doris_test.student values (1, 'alice', 20, 99.5);
+insert into doris_test.student values (2, 'bob', 21, 90.5);
+insert into doris_test.student values (3, 'jerry', 23, 88.0);
+insert into doris_test.student values (4, 'andy', 21, 93);
+
+insert into doris_test.test_num values
+(1, 111, 123, 7456123.89, 573, 34, 673.43, 34.1264, 56.2, 23.231);
+
+insert into doris_test.test_int values
+(1, 99, 9999, 999999999, 999999999999999999, 999, 99999, 9999999999, 
9999999999999999999);
+insert into doris_test.test_int values
+(2, -99, -9999, -999999999, -999999999999999999, -999, -99999, -9999999999, 
-9999999999999999999);
+insert into doris_test.test_int values
+(3, 9.9, 99.99, 999999999, 999999999999999999, 999, 99999, 9999999999, 
9999999999999999999);
+
+
+insert into doris_test.test_char values (1, '1', 'china', 'beijing', 'alice', 
'abcdefghrjkmnopq');
+insert into doris_test.test_char values (2, '2', 'china', 'shanghai', 'bob', 
'abcdefghrjkmnopq');
+insert into doris_test.test_char values (3, '3', 'Americ', 'new york', 
'Jerry', 'abcdefghrjkmnopq');
+
+
+insert into doris_test.test_raw values (1, hextoraw('ffff'), hextoraw('aaaa'));
+insert into doris_test.test_raw values (2, utl_raw.cast_to_raw('beijing'), 
utl_raw.cast_to_raw('shanghai'));
+
+insert into doris_test.test_date (id, t1) values (1, to_date('2022-1-21 
5:23:01','yyyy-mm-dd hh24:mi:ss'));
+insert into doris_test.test_date (id, t1) values (2, to_date('20221112203256', 
'yyyymmddhh24miss'));
+insert into doris_test.test_date (id, t2) values (3, interval '11' year);
+insert into doris_test.test_date (id, t2) values (4, interval '223-9' year(3) 
to month);
+insert into doris_test.test_date (id, t3) values (5, interval '12 
10:23:01.1234568' day to second);
+
+commit;
diff --git a/docker/thirdparties/docker-compose/oracle/oracle-11.env 
b/docker/thirdparties/docker-compose/oracle/oracle-11.env
new file mode 100644
index 0000000000..f3d1f22efc
--- /dev/null
+++ b/docker/thirdparties/docker-compose/oracle/oracle-11.env
@@ -0,0 +1,19 @@
+#!/usr/bin/env bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+DOCKER_ORACLE_EXTERNAL_PORT=1521
diff --git a/docker/thirdparties/docker-compose/oracle/oracle-11.yaml 
b/docker/thirdparties/docker-compose/oracle/oracle-11.yaml
new file mode 100644
index 0000000000..93225aacd3
--- /dev/null
+++ b/docker/thirdparties/docker-compose/oracle/oracle-11.yaml
@@ -0,0 +1,49 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+version: '3'
+
+services:
+  doris--oracle_11:
+    image: oracleinanutshell/oracle-xe-11g:latest
+    restart: always
+    ports:
+      - ${DOCKER_ORACLE_EXTERNAL_PORT}:1521
+    privileged: true
+    healthcheck:
+      test: [ "CMD", "bash", "-c", "echo 'select 1 from dual;' | 
ORACLE_HOME=/u01/app/oracle/product/11.2.0/xe 
/u01/app/oracle/product/11.2.0/xe/bin/sqlplus -s DORIS_TEST/123456@localhost"]
+      interval: 20s
+      timeout: 60s
+      retries: 120
+    volumes:
+      - ./init:/docker-entrypoint-initdb.d
+    environment:
+      - ORACLE_ALLOW_REMOTE=true
+      - ORACLE_ENABLE_XDB=true
+      - DBCA_TOTAL_MEMORY=2048
+      - IMPORT_FROM_VOLUME=true
+      - TZ=Asia/Shanghai
+    networks:
+      - doris--oracle_11
+  hello-world:
+    image: hello-world
+    depends_on:
+      doris--oracle_11:
+        condition: service_healthy 
+
+networks:
+  doris--oracle_11:
\ No newline at end of file
diff --git a/docker/thirdparties/start-thirdparties-docker.sh 
b/docker/thirdparties/start-thirdparties-docker.sh
index 986d04da7a..61e0df9713 100755
--- a/docker/thirdparties/start-thirdparties-docker.sh
+++ b/docker/thirdparties/start-thirdparties-docker.sh
@@ -56,6 +56,13 @@ sudo mkdir -p "${ROOT}"/docker-compose/postgresql/data/data
 sudo rm "${ROOT}"/docker-compose/postgresql/data/data/* -rf
 sudo docker compose -f "${ROOT}"/docker-compose/postgresql/postgresql-14.yaml 
--env-file "${ROOT}"/docker-compose/postgresql/postgresql-14.env up -d
 
+# oracle
+sed -i "s/doris--/${CONTAINER_UID}/g" 
"${ROOT}"/docker-compose/oracle/oracle-11.yaml
+sudo docker compose -f "${ROOT}"/docker-compose/oracle/oracle-11.yaml 
--env-file "${ROOT}"/docker-compose/oracle/oracle-11.env down
+sudo mkdir -p "${ROOT}"/docker-compose/oracle/data/
+sudo rm "${ROOT}"/docker-compose/oracle/data/* -rf
+sudo docker compose -f "${ROOT}"/docker-compose/oracle/oracle-11.yaml 
--env-file "${ROOT}"/docker-compose/oracle/oracle-11.env up -d
+
 # hive
 # before start it, you need to download parquet file package, see "README" in 
"docker-compose/hive/scripts/"
 sed -i "s/doris--/${CONTAINER_UID}/g" 
"${ROOT}"/docker-compose/hive/hive-2x.yaml
diff --git a/docker/thirdparties/stop-thirdparties-docker.sh 
b/docker/thirdparties/stop-thirdparties-docker.sh
index 4ed3e78c18..dc2c5773d8 100755
--- a/docker/thirdparties/stop-thirdparties-docker.sh
+++ b/docker/thirdparties/stop-thirdparties-docker.sh
@@ -33,5 +33,8 @@ sudo docker compose -f 
"${ROOT}"/docker-compose/mysql/mysql-5.7.yaml --env-file
 # pg 14
 sudo docker compose -f "${ROOT}"/docker-compose/postgresql/postgresql-14.yaml 
--env-file "${ROOT}"/docker-compose/postgresql/postgresql-14.env down
 
+# oracle 11
+sudo docker compose -f "${ROOT}"/docker-compose/oracle/oracle-11.yaml 
--env-file "${ROOT}"/docker-compose/oracle/oracle-11.env down
+
 # hive
 sudo docker compose -f "${ROOT}"/docker-compose/hive/hive-2x.yaml --env-file 
"${ROOT}"/docker-compose/hive/hadoop-hive.env down
diff --git a/docs/en/docs/ecosystem/external-table/multi-catalog.md 
b/docs/en/docs/ecosystem/external-table/multi-catalog.md
index 0d0439ec2b..89ac6b22e3 100644
--- a/docs/en/docs/ecosystem/external-table/multi-catalog.md
+++ b/docs/en/docs/ecosystem/external-table/multi-catalog.md
@@ -430,7 +430,7 @@ CREATE CATALOG jdbc PROPERTIES (
 **CLICKHOUSE catalog example**
 
 ```sql
--- 1.2.0+ Version
+-- The first way
 CREATE RESOURCE clickhouse_resource PROPERTIES (
     "type"="jdbc",
     "user"="default",
@@ -441,7 +441,7 @@ CREATE RESOURCE clickhouse_resource PROPERTIES (
 )
 CREATE CATALOG jdbc WITH RESOURCE clickhouse_resource;
 
--- 1.2.0 Version
+-- The second way, note: keys have 'jdbc' prefix in front.
 CREATE CATALOG jdbc PROPERTIES (
     "type"="jdbc",
     "jdbc.jdbc_url" = "jdbc:clickhouse://127.0.0.1:8123/demo",
@@ -449,6 +449,31 @@ CREATE CATALOG jdbc PROPERTIES (
 )
 ```
 
+**oracle catalog example**
+
+```sql
+-- The first way
+CREATE RESOURCE oracle_resource PROPERTIES (
+    "type"="jdbc",
+    "user"="doris",
+    "password"="123456",
+    "jdbc_url" = "jdbc:oracle:thin:@127.0.0.1:1521:helowin",
+    "driver_url" = "file:/path/to/ojdbc6.jar",
+    "driver_class" = "oracle.jdbc.driver.OracleDriver"
+);
+CREATE CATALOG jdbc WITH RESOURCE oracle_resource;
+
+-- The second way, note: keys have 'jdbc' prefix in front.
+CREATE CATALOG jdbc PROPERTIES (
+    "type"="jdbc",
+    "jdbc.user"="doris",
+    "jdbc.password"="123456",
+    "jdbc.jdbc_url" = "jdbc:oracle:thin:@127.0.0.1:1521:helowin",
+    "jdbc.driver_url" = "file:/path/to/ojdbc6.jar",
+    "jdbc.driver_class" = "oracle.jdbc.driver.OracleDriver"
+);     
+```
+
 Where `jdbc.driver_url` can be a remote jar package
 
 ```sql
@@ -481,7 +506,9 @@ MySQL [(none)]> show catalogs;
 2 rows in set (0.02 sec)
 ```
 
-> Note: In the `postgresql catalog`, a database for doris corresponds to a 
schema in the postgresql specified catalog (specified in the `jdbc.jdbc_url` 
parameter), tables under this database corresponds to tables under this 
postgresql's schema.
+> Note: 
+> 1. In the `postgresql catalog`, a database for doris corresponds to a schema 
in the postgresql specified catalog (specified in the `jdbc.jdbc_url` 
parameter), tables under this database corresponds to tables under this 
postgresql's schema.
+> 2. In the `oracle catalog`, a database for doris corresponds to a user in 
the oracle, tables under this database corresponds to tables under this 
oracle's user.
 
 Switch to the jdbc catalog with the `SWITCH` command and view the databases in 
it:
 
@@ -764,6 +791,18 @@ For Hive/Iceberge/Hudi
 | DECIMAL                | DECIMAL    | Data that exceeds Doris's maximum 
Decimal precision is mapped to a STRING                                         
                   |
 | Enum/IPv4/IPv6/UUID    | STRING     | In the display of IPv4 and IPv6, an 
extra `/` is displayed before the data, which needs to be processed by the 
`split_part` function |
 
+#### ORACLE
+ ORACLE Type | Doris Type | Comment |
+|---|---|---|
+| number(p) / number(p,0) |  | Doris will choose the corresponding doris type 
based on the p: p<3 -> TINYINT; p<5 -> SMALLINT; p<10 -> INT; p<19 -> BIGINT; 
p>19 -> LARGEINT |
+| number(p,s) | DECIMAL | |
+| decimal | DECIMAL | |
+| float/real | DOUBLE | |
+| DATE | DATETIME | |
+| CHAR/NCHAR | CHAR | |
+| VARCHAR2/NVARCHAR2 | VARCHAR | |
+| LONG/ RAW/ LONG RAW/ INTERVAL | TEXT | |
+
 ## Privilege Management
 
 Using Doris to access the databases and tables in the External Catalog is not 
controlled by the permissions of the external data source itself, but relies on 
Doris's own permission access management.
diff --git 
a/docs/en/docs/sql-manual/sql-reference/Data-Definition-Statements/Create/CREATE-CATALOG.md
 
b/docs/en/docs/sql-manual/sql-reference/Data-Definition-Statements/Create/CREATE-CATALOG.md
index 33e9e4af9a..b659e3a7fc 100644
--- 
a/docs/en/docs/sql-manual/sql-reference/Data-Definition-Statements/Create/CREATE-CATALOG.md
+++ 
b/docs/en/docs/sql-manual/sql-reference/Data-Definition-Statements/Create/CREATE-CATALOG.md
@@ -148,7 +148,7 @@ CREATE CATALOG catalog_name PROPERTIES (
        **postgresql**
 
        ```sql
-       -- 1.2.0+ Version
+       -- The first way
        CREATE RESOURCE pg_resource PROPERTIES (
                "type"="jdbc",
                "user"="postgres",
@@ -159,7 +159,7 @@ CREATE CATALOG catalog_name PROPERTIES (
        );
        CREATE CATALOG jdbc WITH RESOURCE pg_resource;
 
-       -- 1.2.0 Version
+       -- The second way, note: keys have 'jdbc' prefix in front.
        CREATE CATALOG jdbc PROPERTIES (
                "type"="jdbc",
                "jdbc.user"="postgres",
@@ -192,6 +192,30 @@ CREATE CATALOG catalog_name PROPERTIES (
        )
        ```
 
+       **oracle**
+       ```sql
+       -- The first way
+       CREATE RESOURCE oracle_resource PROPERTIES (
+               "type"="jdbc",
+               "user"="doris",
+               "password"="123456",
+               "jdbc_url" = "jdbc:oracle:thin:@127.0.0.1:1521:helowin",
+               "driver_url" = "file:/path/to/ojdbc6.jar",
+               "driver_class" = "oracle.jdbc.driver.OracleDriver"
+       );
+       CREATE CATALOG jdbc WITH RESOURCE oracle_resource;
+
+       -- The second way, note: keys have 'jdbc' prefix in front.
+       CREATE CATALOG jdbc PROPERTIES (
+               "type"="jdbc",
+               "jdbc.user"="doris",
+               "jdbc.password"="123456",
+               "jdbc.jdbc_url" = "jdbc:oracle:thin:@127.0.0.1:1521:helowin",
+               "jdbc.driver_url" = "file:/path/to/ojdbc6.jar",
+               "jdbc.driver_class" = "oracle.jdbc.driver.OracleDriver"
+       );      
+       ```
+
 ### Keywords
 
 CREATE, CATALOG
diff --git a/docs/zh-CN/docs/ecosystem/external-table/multi-catalog.md 
b/docs/zh-CN/docs/ecosystem/external-table/multi-catalog.md
index 8192eea436..ab3974fe30 100644
--- a/docs/zh-CN/docs/ecosystem/external-table/multi-catalog.md
+++ b/docs/zh-CN/docs/ecosystem/external-table/multi-catalog.md
@@ -503,7 +503,7 @@ CREATE CATALOG jdbc PROPERTIES (
 **CLICKHOUSE catalog示例**
 
 ```sql
--- 1.2.0+ 版本
+-- 方式一
 CREATE RESOURCE clickhouse_resource PROPERTIES (
     "type"="jdbc",
     "user"="default",
@@ -514,7 +514,7 @@ CREATE RESOURCE clickhouse_resource PROPERTIES (
 )
 CREATE CATALOG jdbc WITH RESOURCE clickhouse_resource;
 
--- 1.2.0 版本
+-- 方式二,注意有jdbc前缀
 CREATE CATALOG jdbc PROPERTIES (
     "type"="jdbc",
     "jdbc.jdbc_url" = "jdbc:clickhouse://127.0.0.1:8123/demo",
@@ -522,6 +522,31 @@ CREATE CATALOG jdbc PROPERTIES (
 )
 ```
 
+**ORACLE catalog示例**
+
+```sql
+-- 方式一
+CREATE RESOURCE oracle_resource PROPERTIES (
+    "type"="jdbc",
+    "user"="doris",
+    "password"="123456",
+    "jdbc_url" = "jdbc:oracle:thin:@127.0.0.1:1521:helowin",
+    "driver_url" = "file:/path/to/ojdbc6.jar",
+    "driver_class" = "oracle.jdbc.driver.OracleDriver"
+);
+CREATE CATALOG jdbc WITH RESOURCE oracle_resource;
+
+-- 方式二,注意有jdbc前缀
+CREATE CATALOG jdbc PROPERTIES (
+    "type"="jdbc",
+    "jdbc.user"="doris",
+    "jdbc.password"="123456",
+    "jdbc.jdbc_url" = "jdbc:oracle:thin:@127.0.0.1:1521:helowin",
+    "jdbc.driver_url" = "file:/path/to/ojdbc6.jar",
+    "jdbc.driver_class" = "oracle.jdbc.driver.OracleDriver"
+);     
+```
+
 其中`jdbc.driver_url`可以是远程jar包:
 
 ```sql
@@ -576,7 +601,9 @@ MySQL [(none)]> show databases;
 9 rows in set (0.67 sec)
 ```
 
-> 注意:在postgresql 
catalog中,doris的一个database对应于postgresql中指定catalog(`jdbc.jdbc_url`参数中指定的catalog)下的一个schema,database下的tables则对应于postgresql该schema下的tables。
+> 注意:
+> 1. 在postgresql 
catalog中,doris的一个database对应于postgresql中指定catalog(`jdbc.jdbc_url`参数中指定的catalog)下的一个schema,database下的tables则对应于postgresql该schema下的tables。
+> 2. 在oracle 
catalog中,doris的一个database对应于oracle中的一个user,database下的tables则对应于oracle该user下的有权限访问的tables。
 
 查看`db1`数据库下的表,并查询:
 ```sql
@@ -763,6 +790,18 @@ select k1, k4 from table;           // Query OK.
 | DECIMAL                | DECIMAL    | 对于超过了Doris最大的Decimal精度的数据,将映射为STRING   
             |
 | Enum/IPv4/IPv6/UUID    | STRING     | 
在显示上IPv4,IPv6会额外在数据最前面显示一个`/`,需要自己用`split_part`函数处理 |
 
+#### ORACLE
+ ORACLE Type | Doris Type | Comment |
+|---|---|---|
+| number(p) / number(p,0) |  | Doris会根据p的大小来选择对应的类型:p<3 -> TINYINT; p<5 -> 
SMALLINT; p<10 -> INT; p<19 -> BIGINT; p>19 -> LARGEINT |
+| number(p,s) | DECIMAL | |
+| decimal | DECIMAL | |
+| float/real | DOUBLE | |
+| DATE | DATETIME | |
+| CHAR/NCHAR | CHAR | |
+| VARCHAR2/NVARCHAR2 | VARCHAR | |
+| LONG/ RAW/ LONG RAW/ INTERVAL | TEXT | |
+
 ## 权限管理
 
 使用 Doris 对 External Catalog 中库表进行访问,并不受外部数据目录自身的权限控制,而是依赖 Doris 自身的权限访问管理功能。
diff --git 
a/docs/zh-CN/docs/sql-manual/sql-reference/Data-Definition-Statements/Create/CREATE-CATALOG.md
 
b/docs/zh-CN/docs/sql-manual/sql-reference/Data-Definition-Statements/Create/CREATE-CATALOG.md
index 81ee7b30cb..9c71ee73a8 100644
--- 
a/docs/zh-CN/docs/sql-manual/sql-reference/Data-Definition-Statements/Create/CREATE-CATALOG.md
+++ 
b/docs/zh-CN/docs/sql-manual/sql-reference/Data-Definition-Statements/Create/CREATE-CATALOG.md
@@ -154,7 +154,7 @@ CREATE CATALOG catalog_name PROPERTIES (
        **postgresql**
 
        ```sql
-       -- 1.2.0+ 版本
+       -- 方式一
        CREATE RESOURCE pg_resource PROPERTIES (
                "type"="jdbc",
                "user"="postgres",
@@ -165,7 +165,7 @@ CREATE CATALOG catalog_name PROPERTIES (
        );
        CREATE CATALOG jdbc WITH RESOURCE pg_resource;
 
-       -- 1.2.0 版本
+       -- 方式二,注意有jdbc前缀
        CREATE CATALOG jdbc PROPERTIES (
                "type"="jdbc",
                "jdbc.user"="postgres",
@@ -198,6 +198,30 @@ CREATE CATALOG catalog_name PROPERTIES (
    )
    ```
 
+       **oracle**
+       ```sql
+       -- 方式一
+       CREATE RESOURCE oracle_resource PROPERTIES (
+               "type"="jdbc",
+               "user"="doris",
+               "password"="123456",
+               "jdbc_url" = "jdbc:oracle:thin:@127.0.0.1:1521:helowin",
+               "driver_url" = "file:/path/to/ojdbc6.jar",
+               "driver_class" = "oracle.jdbc.driver.OracleDriver"
+       );
+       CREATE CATALOG jdbc WITH RESOURCE oracle_resource;
+
+       -- 方式二,注意有jdbc前缀
+       CREATE CATALOG jdbc PROPERTIES (
+               "type"="jdbc",
+               "jdbc.user"="doris",
+               "jdbc.password"="123456",
+               "jdbc.jdbc_url" = "jdbc:oracle:thin:@127.0.0.1:1521:helowin",
+               "jdbc.driver_url" = "file:/path/to/ojdbc6.jar",
+               "jdbc.driver_class" = "oracle.jdbc.driver.OracleDriver"
+       );      
+       ```
+
 ### Keywords
 
 CREATE, CATALOG
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/catalog/JdbcResource.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/JdbcResource.java
index 3862a38e3b..add3009de8 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/JdbcResource.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/JdbcResource.java
@@ -66,6 +66,7 @@ public class JdbcResource extends Resource {
     public static final String JDBC_ORACLE = "jdbc:oracle";
     public static final String JDBC_SQLSERVER = "jdbc:sqlserver";
     public static final String JDBC_CLICKHOUSE = "jdbc:clickhouse";
+
     public static final String MYSQL = "MYSQL";
     public static final String POSTGRESQL = "POSTGRESQL";
     public static final String ORACLE = "ORACLE";
@@ -253,6 +254,7 @@ public class JdbcResource extends Resource {
             // it will convert to Doris tinyint, not bit.
             newJdbcUrl = checkJdbcUrlParam(newJdbcUrl, "yearIsDateType", 
"true", "false");
             newJdbcUrl = checkJdbcUrlParam(newJdbcUrl, "tinyInt1isBit", 
"true", "false");
+            newJdbcUrl = checkJdbcUrlParam(newJdbcUrl, "useCursorFetch", 
"false", "true");
         }
         return newJdbcUrl;
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/external/jdbc/JdbcClient.java 
b/fe/fe-core/src/main/java/org/apache/doris/external/jdbc/JdbcClient.java
index fa10819a7b..cc8fc80b3d 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/external/jdbc/JdbcClient.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/external/jdbc/JdbcClient.java
@@ -157,17 +157,18 @@ public class JdbcClient {
             stmt = conn.createStatement();
             switch (dbType) {
                 case JdbcResource.MYSQL:
+                case JdbcResource.CLICKHOUSE:
                     rs = stmt.executeQuery("SHOW DATABASES");
                     break;
                 case JdbcResource.POSTGRESQL:
                     rs = stmt.executeQuery("SELECT schema_name FROM 
information_schema.schemata "
                             + "where schema_owner='" + jdbcUser + "';");
                     break;
-                case JdbcResource.CLICKHOUSE:
-                    rs = stmt.executeQuery("SHOW DATABASES");
+                case JdbcResource.ORACLE:
+                    rs = stmt.executeQuery("SELECT DISTINCT OWNER FROM 
all_tables");
                     break;
                 default:
-                    throw  new JdbcClientException("Not supported jdbc type");
+                    throw new JdbcClientException("Not supported jdbc type");
             }
 
             while (rs.next()) {
@@ -196,8 +197,7 @@ public class JdbcClient {
                     rs = databaseMetaData.getTables(dbName, null, null, types);
                     break;
                 case JdbcResource.POSTGRESQL:
-                    rs = databaseMetaData.getTables(null, dbName, null, types);
-                    break;
+                case JdbcResource.ORACLE:
                 case JdbcResource.CLICKHOUSE:
                     rs = databaseMetaData.getTables(null, dbName, null, types);
                     break;
@@ -226,8 +226,7 @@ public class JdbcClient {
                     rs = databaseMetaData.getTables(dbName, null, tableName, 
types);
                     break;
                 case JdbcResource.POSTGRESQL:
-                    rs = databaseMetaData.getTables(null, dbName, null, types);
-                    break;
+                case JdbcResource.ORACLE:
                 case JdbcResource.CLICKHOUSE:
                     rs = databaseMetaData.getTables(null, dbName, null, types);
                     break;
@@ -297,8 +296,7 @@ public class JdbcClient {
                     rs = databaseMetaData.getColumns(dbName, null, tableName, 
null);
                     break;
                 case JdbcResource.POSTGRESQL:
-                    rs = databaseMetaData.getColumns(null, dbName, tableName, 
null);
-                    break;
+                case JdbcResource.ORACLE:
                 case JdbcResource.CLICKHOUSE:
                     rs = databaseMetaData.getColumns(null, dbName, tableName, 
null);
                     break;
@@ -334,6 +332,8 @@ public class JdbcClient {
                 return postgresqlTypeToDoris(fieldSchema);
             case JdbcResource.CLICKHOUSE:
                 return clickhouseTypeToDoris(fieldSchema);
+            case JdbcResource.ORACLE:
+                return oracleTypeToDoris(fieldSchema);
             default:
                 throw new JdbcClientException("Unknown database type");
         }
@@ -563,6 +563,61 @@ public class JdbcClient {
         // Todo(zyk): Wait the JDBC external table support the array type then 
supported clickhouse array type
     }
 
+    public Type oracleTypeToDoris(JdbcFieldSchema fieldSchema) {
+        String oracleType = fieldSchema.getDataTypeName();
+        if (oracleType.startsWith("INTERVAL")) {
+            oracleType = oracleType.substring(0, 8);
+        }
+        switch (oracleType) {
+            case "NUMBER":
+                int precision = fieldSchema.getColumnSize();
+                int scale = fieldSchema.getDecimalDigits();
+                if (scale == 0) {
+                    if (precision < 3) {
+                        return Type.TINYINT;
+                    } else if (precision < 5) {
+                        return Type.SMALLINT;
+                    } else if (precision < 10) {
+                        return Type.INT;
+                    } else if (precision < 19) {
+                        return Type.BIGINT;
+                    } else if (precision < 39) {
+                        return Type.LARGEINT;
+                    }
+                    return ScalarType.createStringType();
+                }
+                if (precision <= ScalarType.MAX_DECIMAL128_PRECISION) {
+                    if (!Config.enable_decimal_conversion && precision > 
ScalarType.MAX_DECIMALV2_PRECISION) {
+                        return ScalarType.createStringType();
+                    }
+                    return ScalarType.createDecimalType(precision, scale);
+                } else {
+                    return ScalarType.createStringType();
+                }
+            case "FLOAT":
+                return Type.DOUBLE;
+            case "DATE":
+                return ScalarType.getDefaultDateType(Type.DATETIME);
+            case "VARCHAR2":
+            case "NVARCHAR2":
+            case "CHAR":
+            case "NCHAR":
+            case "LONG":
+            case "RAW":
+            case "LONG RAW":
+            case "INTERVAL":
+                return ScalarType.createStringType();
+            case "BLOB":
+            case "CLOB":
+            case "NCLOB":
+            case "BFILE":
+            case "BINARY_FLOAT":
+            case "BINARY_DOUBLE":
+            default:
+                return Type.UNSUPPORTED;
+        }
+    }
+
     public List<Column> getColumnsFromJdbc(String dbName, String tableName) {
         List<JdbcFieldSchema> jdbcTableSchema = getJdbcColumnsInfo(dbName, 
tableName);
         List<Column> dorisTableSchema = 
Lists.newArrayListWithCapacity(jdbcTableSchema.size());
diff --git a/regression-test/conf/regression-conf.groovy 
b/regression-test/conf/regression-conf.groovy
index cc07c068c4..0b743fe9dd 100644
--- a/regression-test/conf/regression-conf.groovy
+++ b/regression-test/conf/regression-conf.groovy
@@ -75,6 +75,7 @@ sk=""
 enableJdbcTest=false
 mysql_57_port=3316
 pg_14_port=5442
+oracle_11_port=1521
 
 // hive catalog test config
 // To enable jdbc test, you need first start hive container.
diff --git a/regression-test/data/jdbc_catalog_p0/test_oracle_jdbc_catalog.out 
b/regression-test/data/jdbc_catalog_p0/test_oracle_jdbc_catalog.out
new file mode 100644
index 0000000000..0fe8aa929c
--- /dev/null
+++ b/regression-test/data/jdbc_catalog_p0/test_oracle_jdbc_catalog.out
@@ -0,0 +1,33 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !test0 --
+1      alice   20      99.5
+2      bob     21      90.5
+3      jerry   23      88.0
+4      andy    21      93.0
+
+-- !in_tb --
+1      alice   20
+2      bob     21
+3      jerry   23
+4      andy    21
+
+-- !test1 --
+1      111     123     7456123.89      573     34      673.43  34.1264 60.0    
23.231
+
+-- !test2 --
+1      1       china   beijing alice   abcdefghrjkmnopq
+2      2       china   shanghai        bob     abcdefghrjkmnopq
+3      3       Americ  new york        Jerry   abcdefghrjkmnopq
+
+-- !test3 --
+1      99      9999    999999999       999999999999999999      999     99999   
9999999999      9999999999999999999
+2      -99     -9999   -999999999      -999999999999999999     -999    -99999  
-9999999999     -9999999999999999999
+3      10      100     999999999       999999999999999999      999     99999   
9999999999      9999999999999999999
+
+-- !test5 --
+1      2022-01-21T05:23:01     \N      \N
+2      2022-11-12T20:32:56     \N      \N
+3      \N      11-0    \N
+4      \N      223-9   \N
+5      \N      \N      12 10:23:1.123457000
+
diff --git 
a/regression-test/suites/jdbc_catalog_p0/test_oracle_jdbc_catalog.groovy 
b/regression-test/suites/jdbc_catalog_p0/test_oracle_jdbc_catalog.groovy
new file mode 100644
index 0000000000..9d473e7598
--- /dev/null
+++ b/regression-test/suites/jdbc_catalog_p0/test_oracle_jdbc_catalog.groovy
@@ -0,0 +1,74 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+suite("test_oracle_jdbc_catalog", "p0") {
+    String enabled = context.config.otherConfigs.get("enableJdbcTest");
+    if (enabled != null && enabled.equalsIgnoreCase("true")) {
+        String resource_name = "oracle_catalog_resource";
+        String catalog_name = "oracle_catalog";
+        String internal_db_name = "regression_test_jdbc_catalog_p0";
+        String ex_db_name = "DORIS_TEST";
+        String oracle_port = context.config.otherConfigs.get("oracle_11_port");
+        String SID = "XE"
+
+        String inDorisTable = "doris_in_tb";
+
+        sql """drop catalog if exists ${catalog_name} """
+        sql """drop resource if exists ${resource_name}"""
+
+        sql """create resource if not exists ${resource_name} properties(
+                    "type"="jdbc",
+                    "user"="doris_test",
+                    "password"="123456",
+                    "jdbc_url" = 
"jdbc:oracle:thin:@127.0.0.1:${oracle_port}:${SID}",
+                    "driver_url" = 
"https://doris-community-test-1308700295.cos.ap-hongkong.myqcloud.com/jdbc_driver/ojdbc6.jar";,
+                    "driver_class" = "oracle.jdbc.driver.OracleDriver"
+        );"""
+
+        sql """CREATE CATALOG ${catalog_name} WITH RESOURCE ${resource_name}"""
+
+        sql  """ drop table if exists ${inDorisTable} """
+        sql  """
+              CREATE TABLE ${inDorisTable} (
+                `id` INT NULL COMMENT "主键id",
+                `name` string NULL COMMENT "名字",
+                `age` INT NULL COMMENT "年龄"
+                ) DISTRIBUTED BY HASH(id) BUCKETS 10
+                PROPERTIES("replication_num" = "1");
+        """
+
+        sql """switch ${catalog_name}"""
+        sql """ use ${ex_db_name}"""
+
+        order_qt_test0  """ select * from STUDENT order by ID; """
+        sql  """ insert into internal.${internal_db_name}.${inDorisTable} 
select ID, NAME, AGE from STUDENT; """
+        order_qt_in_tb  """ select id, name, age from 
internal.${internal_db_name}.${inDorisTable} order by id; """
+
+        order_qt_test1  """ select * from TEST_NUM order by ID; """
+        order_qt_test2  """ select * from TEST_CHAR order by ID; """
+        order_qt_test3  """ select * from TEST_INT order by ID; """
+        order_qt_test5  """ select * from TEST_DATE order by ID; """
+
+        // The result of TEST_RAW will change
+        // So instead of qt, we're using sql here.
+        sql  """ select * from TEST_RAW order by ID; """
+
+
+        sql """drop catalog if exists ${catalog_name} """
+        sql """drop resource if exists jdbc_resource_catalog_pg"""
+    }
+}


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


Reply via email to