diff --git a/README.md b/README.md index 799b60e2..2925f9ea 100644 --- a/README.md +++ b/README.md @@ -241,14 +241,14 @@ dbswitch: **MySQL/MariaDB数据库** ``` -jdbc连接地址:jdbc:mysql://172.17.2.10:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&tinyInt1isBit=false&rewriteBatchedStatements=true&useCompression=true +jdbc连接地址:jdbc:mysql://172.17.2.10:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai&tinyInt1isBit=false&rewriteBatchedStatements=true&useCompression=true jdbc驱动名称: com.mysql.jdbc.Driver ``` 与: ``` -jdbc连接地址:jdbc:mariadb://172.17.2.10:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&tinyInt1isBit=false&rewriteBatchedStatements=true&useCompression=true +jdbc连接地址:jdbc:mariadb://172.17.2.10:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai&tinyInt1isBit=false&rewriteBatchedStatements=true&useCompression=true jdbc驱动名称: org.mariadb.jdbc.Driver ``` diff --git a/dbswitch-common/src/main/java/com/gitee/dbswitch/common/entity/ResultSetWrapper.java b/dbswitch-common/src/main/java/com/gitee/dbswitch/common/entity/ResultSetWrapper.java index 91258b49..ea2168a7 100644 --- a/dbswitch-common/src/main/java/com/gitee/dbswitch/common/entity/ResultSetWrapper.java +++ b/dbswitch-common/src/main/java/com/gitee/dbswitch/common/entity/ResultSetWrapper.java @@ -8,15 +8,6 @@ // Location: beijing , china ///////////////////////////////////////////////////////////// package com.gitee.dbswitch.common.entity; -// 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 -///////////////////////////////////////////////////////////// import java.sql.Connection; import java.sql.ResultSet; diff --git a/dbswitch-common/src/main/java/com/gitee/dbswitch/common/type/ProductTypeEnum.java b/dbswitch-common/src/main/java/com/gitee/dbswitch/common/type/ProductTypeEnum.java index 94281e64..9da60513 100644 --- a/dbswitch-common/src/main/java/com/gitee/dbswitch/common/type/ProductTypeEnum.java +++ b/dbswitch-common/src/main/java/com/gitee/dbswitch/common/type/ProductTypeEnum.java @@ -148,7 +148,7 @@ public enum ProductTypeEnum { private String[] url; public boolean hasDatabaseName() { - return !Arrays.asList(DM, SQLITE3).contains(this); + return !Arrays.asList(DM, SQLITE3, MYSQL, MARIADB, GBASE8A).contains(this); } public boolean hasFilePath() { diff --git a/dbswitch-common/src/main/java/com/gitee/dbswitch/common/util/ObjectCastUtils.java b/dbswitch-common/src/main/java/com/gitee/dbswitch/common/util/ObjectCastUtils.java index a47fb9bf..7c4b088e 100644 --- a/dbswitch-common/src/main/java/com/gitee/dbswitch/common/util/ObjectCastUtils.java +++ b/dbswitch-common/src/main/java/com/gitee/dbswitch/common/util/ObjectCastUtils.java @@ -6,6 +6,7 @@ import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.SQLException; +import java.sql.Timestamp; import java.sql.Types; import java.time.Instant; import java.time.LocalDate; @@ -667,6 +668,93 @@ public final class ObjectCastUtils { return null; } + /** + * 将任意类型转换为java.time.LocalDateTime类型 + * + * @param in 任意类型的对象实例 + * @return java.sql.Timestamp类型 + */ + public static Timestamp castToTimestamp(final Object in) { + if (in instanceof java.sql.Timestamp) { + return (java.sql.Timestamp) in; + } else if (in instanceof java.sql.Date) { + java.sql.Date date = (java.sql.Date) in; + LocalDate localDate = date.toLocalDate(); + LocalTime localTime = LocalTime.of(0, 0, 0); + LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime); + return Timestamp.valueOf(localDateTime); + } else if (in instanceof java.sql.Time) { + java.sql.Time date = (java.sql.Time) in; + return new java.sql.Timestamp(date.getTime()); + } else if (in instanceof java.util.Date) { + return new java.sql.Timestamp(((java.util.Date) in).getTime()); + } else if (in instanceof java.util.Calendar) { + return new java.sql.Timestamp(((java.util.Calendar) in).getTime().getTime()); + } else if (in instanceof LocalDate) { + LocalDate localDate = (LocalDate) in; + LocalTime localTime = LocalTime.of(0, 0, 0); + LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime); + return Timestamp.valueOf(localDateTime); + } else if (in instanceof LocalTime) { + LocalDate localDate = LocalDate.MIN; + LocalTime localTime = (LocalTime) in; + LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime); + return Timestamp.valueOf(localDateTime); + } else if (in instanceof LocalDateTime) { + return Timestamp.valueOf((LocalDateTime) in); + } else if (in instanceof java.time.OffsetDateTime) { + return Timestamp.valueOf(((java.time.OffsetDateTime) in).toLocalDateTime()); + } else if (in.getClass().getName().equals("oracle.sql.TIMESTAMP")) { + Class clz = in.getClass(); + try { + Method m = clz.getMethod("timestampValue"); + java.sql.Timestamp t = (java.sql.Timestamp) m.invoke(in); + LocalDateTime localDateTime = LocalDateTime + .ofInstant(t.toInstant(), ZoneId.systemDefault()); + return Timestamp.valueOf(localDateTime); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else if (in.getClass().getName().equals("microsoft.sql.DateTimeOffset")) { + Class clz = in.getClass(); + try { + Method m = clz.getMethod("getTimestamp"); + java.sql.Timestamp t = (java.sql.Timestamp) m.invoke(in); + LocalDateTime localDateTime = LocalDateTime + .ofInstant(t.toInstant(), ZoneId.systemDefault()); + return Timestamp.valueOf(localDateTime); + } catch (Exception e) { + throw new RuntimeException(e); + } + } else if (in instanceof String || in instanceof Character) { + try { + java.sql.Timestamp t = java.sql.Timestamp.valueOf(in.toString()); + LocalDateTime localDateTime = LocalDateTime + .ofInstant(t.toInstant(), ZoneId.systemDefault()); + return Timestamp.valueOf(localDateTime); + } catch (IllegalArgumentException e) { + throw new RuntimeException( + String.format("无法将java.lang.String类型转换为java.sql.TimeStamp类型:%s", e.getMessage())); + } + } else if (in instanceof java.sql.Clob) { + try { + java.sql.Timestamp t = java.sql.Timestamp.valueOf(clob2Str((java.sql.Clob) in)); + LocalDateTime localDateTime = LocalDateTime + .ofInstant(t.toInstant(), ZoneId.systemDefault()); + return Timestamp.valueOf(localDateTime); + } catch (NumberFormatException e) { + throw new RuntimeException( + String.format("无法将java.sql.Clob类型转换为java.sql.TimeStamp类型:%s", e.getMessage())); + } + } else if (in instanceof Number) { + java.sql.Timestamp t = new java.sql.Timestamp(((Number) in).longValue()); + LocalDateTime localDateTime = LocalDateTime.ofInstant(t.toInstant(), ZoneId.systemDefault()); + return Timestamp.valueOf(localDateTime); + } + + return null; + } + /** * 将任意类型转换为Boolean类型 * @@ -859,7 +947,7 @@ public final class ObjectCastUtils { case Types.DATE: return convert(value, ObjectCastUtils::castToLocalDate); case Types.TIMESTAMP: - return convert(value, ObjectCastUtils::castToLocalDateTime); + return convert(value, ObjectCastUtils::castToTimestamp); case Types.BINARY: case Types.VARBINARY: case Types.BLOB: diff --git a/dbswitch-core/src/main/java/com/gitee/dbswitch/provider/meta/AbstractMetadataProvider.java b/dbswitch-core/src/main/java/com/gitee/dbswitch/provider/meta/AbstractMetadataProvider.java index b63c1bc0..dd50dce1 100644 --- a/dbswitch-core/src/main/java/com/gitee/dbswitch/provider/meta/AbstractMetadataProvider.java +++ b/dbswitch-core/src/main/java/com/gitee/dbswitch/provider/meta/AbstractMetadataProvider.java @@ -45,6 +45,10 @@ public abstract class AbstractMetadataProvider super(factoryProvider); } + public void setCatalogName(String catalogName) { + this.catalogName = catalogName; + } + @Override public List querySchemaList(Connection connection) { Set ret = new LinkedHashSet<>(); @@ -103,10 +107,10 @@ public abstract class AbstractMetadataProvider while (rs.next()) { columns.add(rs.getString("COLUMN_NAME")); } + return new ArrayList<>(columns); } catch (SQLException e) { throw new RuntimeException(e); } - return new ArrayList<>(columns); } @Override @@ -127,10 +131,10 @@ public abstract class AbstractMetadataProvider } } } + return ret; } catch (SQLException e) { throw new RuntimeException(e); } - return ret; } @Override @@ -191,10 +195,6 @@ public abstract class AbstractMetadataProvider } } - protected void beforeExecuteQuery() { - - } - /************************************** * internal function **************************************/ diff --git a/dbswitch-product/dbswitch-product-gbase/src/main/java/com/gitee/dbswitch/product/gbase/GbaseFactoryProvider.java b/dbswitch-product/dbswitch-product-gbase/src/main/java/com/gitee/dbswitch/product/gbase/GbaseFactoryProvider.java index 9d4b949c..ab561464 100644 --- a/dbswitch-product/dbswitch-product-gbase/src/main/java/com/gitee/dbswitch/product/gbase/GbaseFactoryProvider.java +++ b/dbswitch-product/dbswitch-product-gbase/src/main/java/com/gitee/dbswitch/product/gbase/GbaseFactoryProvider.java @@ -12,6 +12,7 @@ package com.gitee.dbswitch.product.gbase; import com.gitee.dbswitch.annotation.Product; import com.gitee.dbswitch.common.type.ProductTypeEnum; import com.gitee.dbswitch.features.ProductFeatures; +import com.gitee.dbswitch.product.mysql.MysqlMetadataQueryProvider; import com.gitee.dbswitch.provider.AbstractFactoryProvider; import com.gitee.dbswitch.provider.meta.MetadataProvider; import com.gitee.dbswitch.provider.sync.AutoCastTableDataSynchronizer; @@ -33,7 +34,7 @@ public class GbaseFactoryProvider extends AbstractFactoryProvider { @Override public MetadataProvider createMetadataQueryProvider() { - return new GbaseMetadataQueryProvider(this); + return new MysqlMetadataQueryProvider(this); } @Override diff --git a/dbswitch-product/dbswitch-product-gbase/src/main/java/com/gitee/dbswitch/product/gbase/GbaseMetadataQueryProvider.java b/dbswitch-product/dbswitch-product-gbase/src/main/java/com/gitee/dbswitch/product/gbase/GbaseMetadataQueryProvider.java deleted file mode 100644 index f6f9f1d5..00000000 --- a/dbswitch-product/dbswitch-product-gbase/src/main/java/com/gitee/dbswitch/product/gbase/GbaseMetadataQueryProvider.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.gitee.dbswitch.product.gbase; - -import com.gitee.dbswitch.common.util.JdbcUrlUtils; -import com.gitee.dbswitch.product.mysql.MysqlMetadataQueryProvider; -import com.gitee.dbswitch.provider.ProductFactoryProvider; -import java.sql.Connection; -import java.sql.SQLException; -import java.util.Collections; -import java.util.List; -import java.util.regex.Matcher; - -public class GbaseMetadataQueryProvider extends MysqlMetadataQueryProvider { - - public GbaseMetadataQueryProvider(ProductFactoryProvider factoryProvider) { - super(factoryProvider); - } - - @Override - public List querySchemaList(Connection connection) { - try { - final Matcher matcher = JdbcUrlUtils - .getPattern("jdbc:gbase:://{host}[:{port}]/[{database}][\\?{params}]") - .matcher(connection.getMetaData().getURL()); - if (matcher.matches()) { - return Collections.singletonList(matcher.group("database")); - } - throw new RuntimeException("get database name from jdbc url failed!"); - } catch (SQLException e) { - throw new RuntimeException(e); - } catch (RuntimeException e) { - throw e; - } - } - -} diff --git a/dbswitch-product/dbswitch-product-mysql/src/main/java/com/gitee/dbswitch/product/mysql/MysqlMetadataQueryProvider.java b/dbswitch-product/dbswitch-product-mysql/src/main/java/com/gitee/dbswitch/product/mysql/MysqlMetadataQueryProvider.java index d0287242..780b9cdc 100644 --- a/dbswitch-product/dbswitch-product-mysql/src/main/java/com/gitee/dbswitch/product/mysql/MysqlMetadataQueryProvider.java +++ b/dbswitch-product/dbswitch-product-mysql/src/main/java/com/gitee/dbswitch/product/mysql/MysqlMetadataQueryProvider.java @@ -10,7 +10,6 @@ package com.gitee.dbswitch.product.mysql; import com.gitee.dbswitch.common.consts.Constants; -import com.gitee.dbswitch.common.util.JdbcUrlUtils; import com.gitee.dbswitch.provider.ProductFactoryProvider; import com.gitee.dbswitch.provider.meta.AbstractMetadataProvider; import com.gitee.dbswitch.schema.ColumnDescription; @@ -25,7 +24,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.regex.Matcher; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; @@ -44,18 +43,14 @@ public class MysqlMetadataQueryProvider extends AbstractMetadataProvider { @Override public List querySchemaList(Connection connection) { - try { - final Matcher matcher = JdbcUrlUtils - .getPattern("jdbc:mysql://{host}[:{port}]/[{database}][\\?{params}]") - .matcher(connection.getMetaData().getURL()); - if (matcher.matches()) { - return Collections.singletonList(matcher.group("database")); + List result = new ArrayList<>(); + try (ResultSet rs = connection.getMetaData().getCatalogs()) { + while (rs.next()) { + Optional.ofNullable(rs.getString(1)).ifPresent(result::add); } - throw new RuntimeException("get database name from jdbc url failed!"); + return result.stream().distinct().collect(Collectors.toList()); } catch (SQLException e) { throw new RuntimeException(e); - } catch (RuntimeException e) { - throw e; } } @@ -87,6 +82,27 @@ public class MysqlMetadataQueryProvider extends AbstractMetadataProvider { } } + @Override + public synchronized TableDescription queryTableMeta(Connection connection, String schemaName, + String tableName) { + setCatalogName(schemaName); + return super.queryTableMeta(connection, schemaName, tableName); + } + + @Override + public synchronized List queryTableColumnName(Connection connection, String schemaName, + String tableName) { + setCatalogName(schemaName); + return super.queryTableColumnName(connection, schemaName, tableName); + } + + @Override + public synchronized List queryTablePrimaryKeys(Connection connection, String schemaName, + String tableName) { + setCatalogName(schemaName); + return super.queryTablePrimaryKeys(connection, schemaName, tableName); + } + @Override public String getTableDDL(Connection connection, String schemaName, String tableName) { List result = new ArrayList<>();