mysql->sqlserver建表语句转换

This commit is contained in:
diantu
2023-02-06 11:41:38 +08:00
parent 67341e3e92
commit e4313007fb
14 changed files with 261 additions and 10 deletions

View File

@@ -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<SQLSelectOrderByItem> list = ((MySqlPrimaryKey) sqlTableElement).getIndexDefinition().getColumns();
for(int i=0;i<list.size();i++){
SQLIdentifierExpr sQLIdentifierExpr = (SQLIdentifierExpr)list.get(i).getExpr();
sQLIdentifierExpr.setName(sQLIdentifierExpr.getName().replaceAll("`", ""));
sqlserverPrimaryKey.addColumn(sQLIdentifierExpr);
}
sQLCreateTableStatement.getTableElementList().add(sqlserverPrimaryKey);
}else if(sqlTableElement instanceof MySqlUnique) {
SQLUnique sqlserverUnique = new SQLUnique();
((MySqlUnique) sqlTableElement).cloneTo(sqlserverUnique);
sQLCreateTableStatement.getTableElementList().add(sqlserverUnique);
}
}
if(Objects.nonNull(x.getSelect())){
x.setParent(sQLCreateTableStatement);
sQLCreateTableStatement.setSelect(x.getSelect());
}
println();
print(sQLCreateTableStatement.toString());
return false;
}
}

View File

@@ -8,5 +8,5 @@ import com.zyplayer.doc.db.framework.db.sql.MethodInvoke;
* @author diantu
* @since 2023年1月29日
*/
public interface MySqlFunction extends MethodInvoke {
public interface MySqlToOracleFunction extends MethodInvoke {
}

View File

@@ -6,5 +6,5 @@ package com.zyplayer.doc.db.framework.db.sql.dialect.mysql.function;
* @author diantu
* @since 2023年1月29日
*/
public class MySqlToOracleFunctionTransform implements MySqlFunction{
public class MySqlToOracleFunctionTransform implements MySqlToOracleFunction {
}

View File

@@ -0,0 +1,50 @@
package com.zyplayer.doc.db.framework.db.sql.dialect.mysql.function;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.zyplayer.doc.db.framework.db.sql.MethodInvoke;
/**
* mysql2sqlserver需要转换的函数
*
* @author diantu
* @since 2023年2月6日
*/
public interface MySqlToSqlServerFunction extends MethodInvoke {
/**
* 转换 AUTO_INCREMENT 函数
* @author diantu
* @date 2023年2月6日
* @param expr
* @return void
*/
void auto_increment(SQLMethodInvokeExpr expr);
/**
* 整体替换当前类型
* @author diantu
* @date 2023年2月6日
* @param name
* @param expr
* @return void
*/
default void identifierExpr(String name, SQLObject expr) {
SQLIdentifierExpr sqlIdentifierExpr = new SQLIdentifierExpr();
sqlIdentifierExpr.setName(name);
sqlIdentifierExpr.setParent(expr.getParent());
SQLObject parent = expr.getParent();
if (parent instanceof SQLSelectItem) {
((SQLSelectItem) parent).setExpr(sqlIdentifierExpr);
} else if (parent instanceof SQLBinaryOpExpr) {
((SQLBinaryOpExpr) parent).setRight(sqlIdentifierExpr);
}else if(parent instanceof SQLColumnDefinition){
((SQLColumnDefinition) parent).setName(name);
}
}
}

View File

@@ -0,0 +1,17 @@
package com.zyplayer.doc.db.framework.db.sql.dialect.mysql.function;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
/**
* mysql2sqlserver需要转换的函数实现
*
* @author diantu
* @since 2023年2月6日
*/
public class MySqlToSqlServerFunctionTransform implements MySqlToSqlServerFunction{
@Override
public void auto_increment(SQLMethodInvokeExpr expr) {
identifierExpr("identity", expr);
}
}

View File

@@ -13,13 +13,16 @@ import com.alibaba.druid.util.FnvHash;
import java.util.List;
/**
* mysql sql转换工具类
* mysql sql字段类型转换工具类
*
* @author diantu
* @since 2023年1月30日
*/
public class MySqlSQLDataTypeTransformUtil extends SQLTransformUtils {
/**
* MySql->Oracle字段类型转换
*/
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<SQLExpr> 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;
}
}

View File

@@ -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 函数

View File

@@ -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) {

View File

@@ -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();

View File

@@ -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{
}

View File

@@ -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 {
}

View File

@@ -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();

View File

@@ -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<SQLStatement> 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

View File

@@ -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;
}