支持OceanBase数据源

This commit is contained in:
inrgihc
2024-10-09 22:17:21 +08:00
parent 8e71a0fba6
commit 30a96a0b42
19 changed files with 207 additions and 11 deletions

View File

@@ -57,6 +57,7 @@
├── dbswitch-product-elasticsearch // -> elasticsearch方言实现类
├── dbswitch-product-starrocks // -> starrocks方言实现类
├── dbswitch-product-doris // -> doris方言实现类
├── dbswitch-product-oceanbase // -> oceanbase方言实现类
├── dbswitch-data // 工具入口模块,读取配置文件中的参数执行异构迁移同步
├── dbswitch-admin // 在以上模块的基础上引入Quartz的调度服务与接口
├── dbswitch-admin-ui // 基于Vue2的前段WEB交互页面

View File

@@ -103,6 +103,27 @@ jdbc连接地址jdbc:opengauss://172.17.2.10:5866/test
jdbc驱动名称org.opengauss.Driver
```
**StarRocks数据库**
```
jdbc连接地址jdbc:mysql://127.0.0.1:9030/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
jdbc驱动名称com.mysql.jdbc.Driver
```
**Doris数据库**
```
jdbc连接地址jdbc:mysql://127.0.0.1:9030/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
jdbc驱动名称com.mysql.jdbc.Driver
```
**OceanBase数据库**
```
jdbc连接地址jdbc:oceanbase://127.0.0.1:2881/test?pool=false
jdbc驱动名称com.oceanbase.jdbc.Driver
```
**ClickHouse(>=21.0.0.0)数据库**
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@@ -135,6 +135,7 @@
dbswitch-product-greenplum // -> greenplum方言实现类
dbswitch-product-starrocks // -> starrocks方言实现类
dbswitch-product-doris // -> doris方言实现类
dbswitch-product-oceanbase // -> oceanbase方言实现类
dbswitch-product-mongodb // -> mongodb方言实现类
dbswitch-product-elasticsearch // -> elasticsearch方言实现类
dbswitch-data // 工具入口模块,读取配置文件中的参数执行异构迁移同步

View File

@@ -1 +1 @@
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>异构数据迁移工具</title><link href=/static/css/app.48fb2adc31db789f5ffbeccb7b71c011.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.92998aeb1477ccbdd2b0.js></script><script type=text/javascript src=/static/js/vendor.8200341f98478c8f7552.js></script><script type=text/javascript src=/static/js/app.36911b44fc7ed34e7641.js></script></body></html>
<!DOCTYPE html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><title>异构数据迁移工具</title><link href=/static/css/app.48fb2adc31db789f5ffbeccb7b71c011.css rel=stylesheet></head><body><div id=app></div><script type=text/javascript src=/static/js/manifest.125e7b77fc066142d0ea.js></script><script type=text/javascript src=/static/js/vendor.8200341f98478c8f7552.js></script><script type=text/javascript src=/static/js/app.36911b44fc7ed34e7641.js></script></body></html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,2 +1,2 @@
!function(e){var c=window.webpackJsonp;window.webpackJsonp=function(n,f,o){for(var a,d,i,u=0,b=[];u<n.length;u++)d=n[u],r[d]&&b.push(r[d][0]),r[d]=0;for(a in f)Object.prototype.hasOwnProperty.call(f,a)&&(e[a]=f[a]);for(c&&c(n,f,o);b.length;)b.shift()();if(o)for(u=0;u<o.length;u++)i=t(t.s=o[u]);return i};var n={},r={25:0};function t(c){if(n[c])return n[c].exports;var r=n[c]={i:c,l:!1,exports:{}};return e[c].call(r.exports,r,r.exports,t),r.l=!0,r.exports}t.e=function(e){var c=r[e];if(0===c)return new Promise(function(e){e()});if(c)return c[2];var n=new Promise(function(n,t){c=r[e]=[n,t]});c[2]=n;var f=document.getElementsByTagName("head")[0],o=document.createElement("script");o.type="text/javascript",o.charset="utf-8",o.async=!0,o.timeout=12e4,t.nc&&o.setAttribute("nonce",t.nc),o.src=t.p+"static/js/"+e+"."+{0:"537fee2b51442d58d28f",1:"fed755dff73c923d7f16",2:"22e821ec8c9909429f09",3:"ef5e983cf9ad9dc27899",4:"f7c0ea89f712c0335ac9",5:"de32c8bd9fcd7cba61b2",6:"d7f3aa182a9403e7c6f6",7:"2c3ef6028bafee6fbaca",8:"535ff4d6dbb1131433ea",9:"4590fe5acd44e077ba19",10:"1d1a99a89d92bca35121",11:"f1220d9f411fa31f402d",12:"f04608dc3d77cd7fb925",13:"522b8e9b509523953170",14:"5d055f12c2b831e53cd6",15:"9742967c21d37f7c493f",16:"3d8d1b4a2cf253b6dcec",17:"68d3bb07f9efaf16b653",18:"b6bf70f4f372e952d31f",19:"b1e6da86c8a7dcf8425b",20:"beeb2cdb187564a0c9fe",21:"5bf6235c9914a933db4d",22:"c4c6da570159683c5736"}[e]+".js";var a=setTimeout(d,12e4);function d(){o.onerror=o.onload=null,clearTimeout(a);var c=r[e];0!==c&&(c&&c[1](new Error("Loading chunk "+e+" failed.")),r[e]=void 0)}return o.onerror=o.onload=d,f.appendChild(o),n},t.m=e,t.c=n,t.d=function(e,c,n){t.o(e,c)||Object.defineProperty(e,c,{configurable:!1,enumerable:!0,get:n})},t.n=function(e){var c=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(c,"a",c),c},t.o=function(e,c){return Object.prototype.hasOwnProperty.call(e,c)},t.p="/",t.oe=function(e){throw console.error(e),e}}([]);
//# sourceMappingURL=manifest.92998aeb1477ccbdd2b0.js.map
!function(e){var c=window.webpackJsonp;window.webpackJsonp=function(n,f,a){for(var o,d,i,u=0,b=[];u<n.length;u++)d=n[u],r[d]&&b.push(r[d][0]),r[d]=0;for(o in f)Object.prototype.hasOwnProperty.call(f,o)&&(e[o]=f[o]);for(c&&c(n,f,a);b.length;)b.shift()();if(a)for(u=0;u<a.length;u++)i=t(t.s=a[u]);return i};var n={},r={25:0};function t(c){if(n[c])return n[c].exports;var r=n[c]={i:c,l:!1,exports:{}};return e[c].call(r.exports,r,r.exports,t),r.l=!0,r.exports}t.e=function(e){var c=r[e];if(0===c)return new Promise(function(e){e()});if(c)return c[2];var n=new Promise(function(n,t){c=r[e]=[n,t]});c[2]=n;var f=document.getElementsByTagName("head")[0],a=document.createElement("script");a.type="text/javascript",a.charset="utf-8",a.async=!0,a.timeout=12e4,t.nc&&a.setAttribute("nonce",t.nc),a.src=t.p+"static/js/"+e+"."+{0:"9f5c7dfe2e2d505911a3",1:"fed755dff73c923d7f16",2:"22e821ec8c9909429f09",3:"ef5e983cf9ad9dc27899",4:"f7c0ea89f712c0335ac9",5:"de32c8bd9fcd7cba61b2",6:"d7f3aa182a9403e7c6f6",7:"2c3ef6028bafee6fbaca",8:"535ff4d6dbb1131433ea",9:"4590fe5acd44e077ba19",10:"1d1a99a89d92bca35121",11:"f1220d9f411fa31f402d",12:"f04608dc3d77cd7fb925",13:"522b8e9b509523953170",14:"5d055f12c2b831e53cd6",15:"9742967c21d37f7c493f",16:"3d8d1b4a2cf253b6dcec",17:"68d3bb07f9efaf16b653",18:"b6bf70f4f372e952d31f",19:"b1e6da86c8a7dcf8425b",20:"beeb2cdb187564a0c9fe",21:"5bf6235c9914a933db4d",22:"c4c6da570159683c5736"}[e]+".js";var o=setTimeout(d,12e4);function d(){a.onerror=a.onload=null,clearTimeout(o);var c=r[e];0!==c&&(c&&c[1](new Error("Loading chunk "+e+" failed.")),r[e]=void 0)}return a.onerror=a.onload=d,f.appendChild(a),n},t.m=e,t.c=n,t.d=function(e,c,n){t.o(e,c)||Object.defineProperty(e,c,{configurable:!1,enumerable:!0,get:n})},t.n=function(e){var c=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(c,"a",c),c},t.o=function(e,c){return Object.prototype.hasOwnProperty.call(e,c)},t.p="/",t.oe=function(e){throw console.error(e),e}}([]);
//# sourceMappingURL=manifest.125e7b77fc066142d0ea.js.map

View File

@@ -214,6 +214,15 @@ public enum ProductTypeEnum {
new String[]{"jdbc:mysql://{host}[:{port}]/[{database}][\\?{params}]"},
"jdbc:mysql://127.0.0.1:9030/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai&tinyInt1isBit=false&rewriteBatchedStatements=true&useCompression=true"),
/**
* OceanBase数据库类型
*/
OCEANBASE(22, "`", "OceanBase", "com.oceanbase.jdbc.Driver", 2881,
"/* ping */ SELECT 1",
"jdbc:oceanbase://",
new String[]{"jdbc:oceanbase://{host}[:{port}]/[{database}][\\?{params}]"},
"jdbc:oceanbase://127.0.0.1:2881/test?pool=false&useUnicode=true&characterEncoding=utf-8&useSSL=false&"),
;
private int id;

View File

@@ -42,11 +42,11 @@ public final class ProductTypeUtils {
}
public static boolean isStarRocks(Connection connection) {
// 此查询语句是StarRocks查询be节点是否存活可以用来判断是否是StarRocks数据源
String sql = "SHOW BACKENDS";
try (Statement statement = connection.createStatement()) {
// 此查询语句是Starrocks查询be节点是否存活可以用来判断是否是Starrocks数据源
String sql = "SHOW BACKENDS";
return statement.execute(sql);
} catch (Exception sqlException) {
} catch (SQLException sqlException) {
if (log.isDebugEnabled()) {
log.debug("Failed to execute sql :show backends, and guesses it is mysql datasource!");
}
@@ -54,5 +54,31 @@ public final class ProductTypeUtils {
return false;
}
public static boolean isOceanBaseUseMysqlMode(Connection connection) {
String sql = "show global variables where variable_name = 'ob_compatibility_mode'";
try (PreparedStatement statement = connection.prepareStatement(sql)) {
try (ResultSet resultSet = statement.executeQuery()) {
if (resultSet.next()) {
String value = resultSet.getString(2);
if (Objects.nonNull(value)) {
if (value.toUpperCase().contains("MYSQL")) {
return true;
} else {
return false;
}
} else {
throw new RuntimeException();
}
} else {
throw new RuntimeException();
}
}
} catch (SQLException sqlException) {
if (log.isDebugEnabled()) {
log.debug("Failed to execute sql :{}, and guesses OceanBase is MySQL Mode!", sql);
}
}
return true;
}
}

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dbswitch-product</artifactId>
<groupId>com.gitee.dbswitch</groupId>
<version>1.9.9</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dbswitch-product-oceanbase</artifactId>
<dependencies>
<dependency>
<groupId>com.gitee.dbswitch</groupId>
<artifactId>dbswitch-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.gitee.dbswitch</groupId>
<artifactId>dbswitch-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.gitee.dbswitch</groupId>
<artifactId>dbswitch-product-mysql</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.gitee.dbswitch</groupId>
<artifactId>dbswitch-product-oracle</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,91 @@
// Copyright tang. All rights reserved.
// https://gitee.com/inrgihc/dbswitch
//
// Use of this source code is governed by a BSD-style license
//
// Author: tang (inrgihc@126.com)
// Date : 2020/1/2
// Location: beijing , china
/////////////////////////////////////////////////////////////
package com.gitee.dbswitch.product.oceanbase;
import com.gitee.dbswitch.annotation.Product;
import com.gitee.dbswitch.common.type.ProductTypeEnum;
import com.gitee.dbswitch.common.util.ProductTypeUtils;
import com.gitee.dbswitch.features.DefaultProductFeatures;
import com.gitee.dbswitch.features.ProductFeatures;
import com.gitee.dbswitch.product.mysql.MysqlFeatures;
import com.gitee.dbswitch.product.mysql.MysqlMetadataQueryProvider;
import com.gitee.dbswitch.product.oracle.OracleMetadataQueryProvider;
import com.gitee.dbswitch.product.oracle.OracleTableDataSynchronizer;
import com.gitee.dbswitch.product.oracle.OracleTableDataWriteProvider;
import com.gitee.dbswitch.product.oracle.OracleTableManageProvider;
import com.gitee.dbswitch.provider.AbstractFactoryProvider;
import com.gitee.dbswitch.provider.manage.DefaultTableManageProvider;
import com.gitee.dbswitch.provider.manage.TableManageProvider;
import com.gitee.dbswitch.provider.meta.MetadataProvider;
import com.gitee.dbswitch.provider.sync.AutoCastTableDataSynchronizeProvider;
import com.gitee.dbswitch.provider.sync.TableDataSynchronizeProvider;
import com.gitee.dbswitch.provider.write.AutoCastTableDataWriteProvider;
import com.gitee.dbswitch.provider.write.TableDataWriteProvider;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@Product(ProductTypeEnum.OCEANBASE)
public class OceanbaseFactoryProvider extends AbstractFactoryProvider {
private Boolean isMySqlMode;
public OceanbaseFactoryProvider(DataSource dataSource) {
super(dataSource);
try (Connection connection = getDataSource().getConnection()) {
this.isMySqlMode = ProductTypeUtils.isOceanBaseUseMysqlMode(connection);
if (log.isDebugEnabled()) {
if (this.isMySqlMode) {
log.debug("#### Target OceanBase is MySQL Mode ");
} else {
log.debug("#### Target OceanBase is Oracle Mode ");
}
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
@Override
public ProductFeatures getProductFeatures() {
return isMySqlMode ? new MysqlFeatures() : new DefaultProductFeatures();
}
@Override
public MetadataProvider createMetadataQueryProvider() {
return isMySqlMode
? new MysqlMetadataQueryProvider(this)
: new OracleMetadataQueryProvider(this);
}
@Override
public TableDataWriteProvider createTableDataWriteProvider(boolean useInsert) {
return isMySqlMode
? new AutoCastTableDataWriteProvider(this)
: new OracleTableDataWriteProvider(this);
}
@Override
public TableManageProvider createTableManageProvider() {
return isMySqlMode
? new DefaultTableManageProvider(this)
: new OracleTableManageProvider(this);
}
@Override
public TableDataSynchronizeProvider createTableDataSynchronizeProvider() {
return isMySqlMode
? new AutoCastTableDataSynchronizeProvider(this)
: new OracleTableDataSynchronizer(this);
}
}

View File

@@ -0,0 +1 @@
com.gitee.dbswitch.product.oceanbase.OceanbaseFactoryProvider

View File

@@ -118,6 +118,11 @@
<artifactId>dbswitch-product-doris</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.gitee.dbswitch</groupId>
<artifactId>dbswitch-product-oceanbase</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -12,6 +12,7 @@
<packaging>pom</packaging>
<modules>
<module>dbswitch-register-product</module>
<module>dbswitch-product-mysql</module>
<module>dbswitch-product-oracle</module>
<module>dbswitch-product-postgresql</module>
@@ -27,13 +28,13 @@
<module>dbswitch-product-gbase</module>
<module>dbswitch-product-openguass</module>
<module>dbswitch-product-mongodb</module>
<module>dbswitch-register-product</module>
<module>dbswitch-product-clickhouse</module>
<module>dbswitch-product-elasticsearch</module>
<module>dbswitch-product-highgo</module>
<module>dbswitch-product-starrocks</module>
<module>dbswitch-product-greenplum</module>
<module>dbswitch-product-doris</module>
<module>dbswitch-product-oceanbase</module>
</modules>
</project>

Binary file not shown.