From e4313007fb8e17410a4004737a8534041e0b607f Mon Sep 17 00:00:00 2001 From: diantu Date: Mon, 6 Feb 2023 11:41:38 +0800 Subject: [PATCH] =?UTF-8?q?mysql->sqlserver=E5=BB=BA=E8=A1=A8=E8=AF=AD?= =?UTF-8?q?=E5=8F=A5=E8=BD=AC=E6=8D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mysql/MySqlToSqlServerOutputVisitor.java | 113 ++++++++++++++++++ ...nction.java => MySqlToOracleFunction.java} | 2 +- .../MySqlToOracleFunctionTransform.java | 2 +- .../function/MySqlToSqlServerFunction.java | 50 ++++++++ .../MySqlToSqlServerFunctionTransform.java | 17 +++ .../util/MySqlSQLDataTypeTransformUtil.java | 47 +++++++- ...nction.java => OracleToMySqlFunction.java} | 2 +- .../OracleToMySqlFunctionTransform.java | 2 +- .../util/OracleSQLDataTypeTransformUtil.java | 5 +- ...ion.java => SqlServerToMySqlFunction.java} | 2 +- .../SqlServerToMySqlFunctionTransform.java | 2 +- .../SqlServerSQLDataTypeTransformUtil.java | 5 +- .../db/framework/utils/SQLTransformUtils.java | 19 +++ .../db/service/database/MysqlServiceImpl.java | 3 +- 14 files changed, 261 insertions(+), 10 deletions(-) create mode 100644 zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/mysql/MySqlToSqlServerOutputVisitor.java rename zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/mysql/function/{MySqlFunction.java => MySqlToOracleFunction.java} (78%) create mode 100644 zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/mysql/function/MySqlToSqlServerFunction.java create mode 100644 zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/mysql/function/MySqlToSqlServerFunctionTransform.java rename zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/oracle/function/{OracleFunction.java => OracleToMySqlFunction.java} (96%) rename zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/sqlserver/function/{SqlServerFunction.java => SqlServerToMySqlFunction.java} (78%) diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/mysql/MySqlToSqlServerOutputVisitor.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/mysql/MySqlToSqlServerOutputVisitor.java new file mode 100644 index 00000000..1ebf61b4 --- /dev/null +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/mysql/MySqlToSqlServerOutputVisitor.java @@ -0,0 +1,113 @@ +package com.zyplayer.doc.db.framework.db.sql.dialect.mysql; + +import com.alibaba.druid.DbType; +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; +import com.alibaba.druid.sql.ast.statement.*; +import com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey; +import com.alibaba.druid.sql.dialect.mysql.ast.MySqlUnique; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor; +import com.alibaba.druid.sql.parser.SQLParserUtils; +import com.zyplayer.doc.db.framework.db.sql.dialect.mysql.function.MySqlToSqlServerFunctionTransform; +import com.zyplayer.doc.db.framework.db.sql.dialect.mysql.util.MySqlSQLDataTypeTransformUtil; +import com.zyplayer.doc.db.framework.utils.MapCacheUtil; +import com.zyplayer.doc.db.framework.utils.SQLTransformUtils; + +import java.util.List; +import java.util.Objects; + +/** + * mysql转sqlserver遍历实现 + * + * @author diantu + * @since 2023年2月6日 + */ +public class MySqlToSqlServerOutputVisitor extends MySqlOutputVisitor { + + private final MySqlToSqlServerFunctionTransform functionTransform = new MySqlToSqlServerFunctionTransform(); + + // 目标数据库类型 + private final DbType distDbType = DbType.sqlserver; + + public MySqlToSqlServerOutputVisitor(Appendable appender) { + super(appender); + } + + public MySqlToSqlServerOutputVisitor(Appendable appender, boolean parameterized) { + super(appender, parameterized); + } + + /** + * mysql建表语句遍历 + * @param x + * @return + */ + @Override + public boolean visit(MySqlCreateTableStatement x) { + SQLCreateTableStatement sQLCreateTableStatement = new SQLCreateTableStatement(); + sQLCreateTableStatement.setTableSource(x.getTableSource()); + String tableName = x.getTableSource().getName().getSimpleName(); + sQLCreateTableStatement.setName(String.valueOf(x.getName()).replaceAll("\"", "")); + sQLCreateTableStatement.setName(String.valueOf(x.getName()).replaceAll("`", "")); + sQLCreateTableStatement.setComment(x.getComment()); + for(SQLTableElement sqlTableElement : x.getTableElementList()){ + if( sqlTableElement instanceof SQLColumnDefinition) { + SQLColumnDefinition sqlColumnDefinition = ((SQLColumnDefinition)sqlTableElement); + String columnName = sqlColumnDefinition.getName().getSimpleName().replaceAll("\"", ""); + columnName = columnName.replaceAll("`", ""); + sqlColumnDefinition.setName(columnName); + if(SQLTransformUtils.containsKeyWords(columnName,DbType.sqlserver)){ + sqlColumnDefinition.setName("\""+columnName+"\""); + } + sqlColumnDefinition.setDataType(MySqlSQLDataTypeTransformUtil.transformMySqlToSqlServer(SQLParserUtils.createExprParser(sqlColumnDefinition.getDataType().toString(), DbType.mysql).parseDataType())); + if(sqlColumnDefinition.getDefaultExpr() != null) { + SQLExpr expr = sqlColumnDefinition.getDefaultExpr(); + if(expr instanceof SQLMethodInvokeExpr) { + functionTransform.methodInvoke((SQLMethodInvokeExpr) sqlColumnDefinition.getDefaultExpr()); + } + }else{ + //自增转换 + if(sqlColumnDefinition.isAutoIncrement()){ + sqlColumnDefinition.setAutoIncrement(false); + SQLColumnDefinition.Identity identity = new SQLColumnDefinition.Identity(); + identity.setCycle(true); + identity.setIncrement(1); + sqlColumnDefinition.setIdentity(identity); + } + } + //@TODO 注释待转换 + if(sqlColumnDefinition.getComment()!= null){ + sqlColumnDefinition.setComment((String) null); + } + + sqlColumnDefinition.setDbType(distDbType); + MapCacheUtil.getInstance().addCacheData(tableName.toUpperCase() + ":" + columnName.toUpperCase(), sqlColumnDefinition.toString().replaceAll(sqlColumnDefinition.getColumnName(), "")); + sQLCreateTableStatement.getTableElementList().add(sqlColumnDefinition); + }else if(sqlTableElement instanceof MySqlPrimaryKey){ + SQLPrimaryKeyImpl sqlserverPrimaryKey = new SQLPrimaryKeyImpl(); + List list = ((MySqlPrimaryKey) sqlTableElement).getIndexDefinition().getColumns(); + for(int i=0;iOracle字段类型转换 + */ public static SQLDataType transformMySqlToOracle(SQLDataType x) { final String name = x.getName(); final long nameHash = x.nameHashCode64(); @@ -101,4 +104,46 @@ public class MySqlSQLDataTypeTransformUtil extends SQLTransformUtils { return dataType; } + + /** + * MySql->SqlServer字段类型转换 + */ + public static SQLDataType transformMySqlToSqlServer(SQLDataType x) { + final String name = x.getName(); + final long nameHash = x.nameHashCode64(); + if (name == null) { + return x; + } + List argumentns = x.getArguments(); + SQLDataType dataType; + if (nameHash == FnvHash.Constants.ENUM) { + argumentns.clear(); + dataType = new SQLCharacterDataType("enum"); + + } else if(nameHash == FnvHash.Constants.SET){ + argumentns.clear(); + dataType = new SQLCharacterDataType("set"); + + }else if(nameHash == FnvHash.Constants.BIGINT){ + dataType = new SQLCharacterDataType("bigint"); + + }else if(nameHash == FnvHash.Constants.INT){ + dataType = new SQLCharacterDataType("int"); + + }else if(nameHash == FnvHash.Constants.TINYINT){ + dataType = new SQLCharacterDataType("tinyint"); + + }else if(nameHash == FnvHash.Constants.SMALLINT){ + dataType = new SQLCharacterDataType("smallint"); + + }else { + dataType = x; + } + + if (dataType != x) { + dataType.setParent(x.getParent()); + } + + return dataType; + } } diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/oracle/function/OracleFunction.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/oracle/function/OracleToMySqlFunction.java similarity index 96% rename from zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/oracle/function/OracleFunction.java rename to zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/oracle/function/OracleToMySqlFunction.java index f7c7d72e..adc55045 100644 --- a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/oracle/function/OracleFunction.java +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/oracle/function/OracleToMySqlFunction.java @@ -14,7 +14,7 @@ import com.zyplayer.doc.db.framework.db.sql.MethodInvoke; * @author diantu * @since 2023年1月29日 */ -public interface OracleFunction extends MethodInvoke { +public interface OracleToMySqlFunction extends MethodInvoke { /** * 转换 sys_guid 函数 diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/oracle/function/OracleToMySqlFunctionTransform.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/oracle/function/OracleToMySqlFunctionTransform.java index 62789cfc..da0afbb8 100644 --- a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/oracle/function/OracleToMySqlFunctionTransform.java +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/oracle/function/OracleToMySqlFunctionTransform.java @@ -8,7 +8,7 @@ import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; * @author diantu * @since 2023年1月29日 */ -public class OracleToMySqlFunctionTransform implements OracleFunction{ +public class OracleToMySqlFunctionTransform implements OracleToMySqlFunction { @Override public void sys_guid(SQLMethodInvokeExpr expr) { diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/oracle/util/OracleSQLDataTypeTransformUtil.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/oracle/util/OracleSQLDataTypeTransformUtil.java index 44afbf7c..aea49b2e 100644 --- a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/oracle/util/OracleSQLDataTypeTransformUtil.java +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/oracle/util/OracleSQLDataTypeTransformUtil.java @@ -15,13 +15,16 @@ import java.util.List; /** - * oracle sql转换工具类 + * oracle sql字段类型转换工具类 * * @author diantu * @since 2023年1月29日 */ public class OracleSQLDataTypeTransformUtil extends SQLTransformUtils { + /** + * Oracle->MySql字段类型转换 + */ public static SQLDataType transformOracleToMySql(SQLDataType x) { final String name = x.getName(); final long nameHash = x.nameHashCode64(); diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/sqlserver/function/SqlServerFunction.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/sqlserver/function/SqlServerToMySqlFunction.java similarity index 78% rename from zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/sqlserver/function/SqlServerFunction.java rename to zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/sqlserver/function/SqlServerToMySqlFunction.java index a9237eeb..55b4a92c 100644 --- a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/sqlserver/function/SqlServerFunction.java +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/sqlserver/function/SqlServerToMySqlFunction.java @@ -8,6 +8,6 @@ import com.zyplayer.doc.db.framework.db.sql.MethodInvoke; * @author diantu * @since 2023年2月2日 */ -public interface SqlServerFunction extends MethodInvoke{ +public interface SqlServerToMySqlFunction extends MethodInvoke{ } diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/sqlserver/function/SqlServerToMySqlFunctionTransform.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/sqlserver/function/SqlServerToMySqlFunctionTransform.java index c94da1f1..8d7fd9c1 100644 --- a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/sqlserver/function/SqlServerToMySqlFunctionTransform.java +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/sqlserver/function/SqlServerToMySqlFunctionTransform.java @@ -6,6 +6,6 @@ package com.zyplayer.doc.db.framework.db.sql.dialect.sqlserver.function; * @author diantu * @since 2023年2月2日 */ -public class SqlServerToMySqlFunctionTransform implements SqlServerFunction { +public class SqlServerToMySqlFunctionTransform implements SqlServerToMySqlFunction { } diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/sqlserver/util/SqlServerSQLDataTypeTransformUtil.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/sqlserver/util/SqlServerSQLDataTypeTransformUtil.java index 53bbe3f3..f0f56b9e 100644 --- a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/sqlserver/util/SqlServerSQLDataTypeTransformUtil.java +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/db/sql/dialect/sqlserver/util/SqlServerSQLDataTypeTransformUtil.java @@ -10,13 +10,16 @@ import com.alibaba.druid.util.FnvHash; import java.util.List; /** - * sqlserver sql转换工具类 + * sqlserver sql字段类型转换工具类 * * @author diantu * @since 2023年2月2日 */ public class SqlServerSQLDataTypeTransformUtil extends SQLTransformUtils { + /** + * SqlServer->MySql字段类型转换 + */ public static SQLDataType transformSqlServerToMySql(SQLDataType x) { final String name = x.getName(); final long nameHash = x.nameHashCode64(); diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/utils/SQLTransformUtils.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/utils/SQLTransformUtils.java index 4f0d21a2..a775b85b 100644 --- a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/utils/SQLTransformUtils.java +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/framework/utils/SQLTransformUtils.java @@ -9,6 +9,7 @@ import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerLexer; import com.alibaba.druid.sql.parser.Keywords; import com.alibaba.druid.sql.parser.Lexer; import com.zyplayer.doc.db.framework.db.sql.dialect.mysql.MySqlToOracleOutputVisitor; +import com.zyplayer.doc.db.framework.db.sql.dialect.mysql.MySqlToSqlServerOutputVisitor; import com.zyplayer.doc.db.framework.db.sql.dialect.oracle.OracleToMySqlOutputVisitor; import com.zyplayer.doc.db.framework.db.sql.dialect.sqlserver.SqlServerToMySqlOutputVisitor; import org.springframework.util.StringUtils; @@ -81,6 +82,24 @@ public class SQLTransformUtils { return oracleSql; } + /** + * mysql sql语句转换为sqlserver sql语句 + * @param sql + * @return + */ + public static String translateMySqlToSqlServer(String sql) { + List stmtList = SQLUtils.toStatementList(sql, DbType.mysql); + StringBuilder out = new StringBuilder(); + MySqlToSqlServerOutputVisitor visitor = new MySqlToSqlServerOutputVisitor(out, false); + + for(int i = 0; i < stmtList.size(); ++i) { + ((SQLStatement)stmtList.get(i)).accept(visitor); + } + + String sqlserverSql = out.toString(); + return sqlserverSql; + } + /** * 将字CLOB转成STRING类型 * @param clob diff --git a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/service/database/MysqlServiceImpl.java b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/service/database/MysqlServiceImpl.java index 96c33cee..b56730b2 100644 --- a/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/service/database/MysqlServiceImpl.java +++ b/zyplayer-doc-db/src/main/java/com/zyplayer/doc/db/service/database/MysqlServiceImpl.java @@ -114,7 +114,8 @@ public class MysqlServiceImpl extends DbBaseService { String mysqlSql = tableDdlList.get(0).get("Create Table") + ";"; tableDdlVo.setMysql(mysqlSql); tableDdlVo.setOracle(SQLTransformUtils.translateMySqlToOracle(mysqlSql)); - // TODO sqlserver等数据库同理 + tableDdlVo.setSqlserver(SQLTransformUtils.translateMySqlToSqlServer(mysqlSql)); + // TODO 其他数据库同理 } return tableDdlVo; }