mysql->oracle建表语句转换
This commit is contained in:
@@ -1,6 +1,31 @@
|
||||
package com.zyplayer.doc.db.framework.db.sql.dialect.mysql;
|
||||
|
||||
import com.alibaba.druid.DbType;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
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.SQLSelectOrderByItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableElement;
|
||||
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.dialect.oracle.ast.expr.OracleSysdateExpr;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OraclePrimaryKey;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUnique;
|
||||
import com.alibaba.druid.sql.parser.SQLParserUtils;
|
||||
import com.alibaba.druid.util.FnvHash;
|
||||
import com.zyplayer.doc.db.framework.db.sql.dialect.mysql.function.MySqlToOracleFunctionTransform;
|
||||
import com.zyplayer.doc.db.framework.db.sql.dialect.mysql.util.MySqlSQLDataTypeTransformUtil;
|
||||
import com.zyplayer.doc.db.framework.db.sql.dialect.oracle.function.OracleUtil;
|
||||
import com.zyplayer.doc.db.framework.utils.MapCacheUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* mysql转oracle遍历实现
|
||||
@@ -10,6 +35,11 @@ import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
|
||||
*/
|
||||
public class MySqlToOracleOutputVisitor extends MySqlOutputVisitor {
|
||||
|
||||
private final MySqlToOracleFunctionTransform functionTransform = new MySqlToOracleFunctionTransform();
|
||||
|
||||
// 目标数据库类型
|
||||
private final DbType distDbType = DbType.oracle;
|
||||
|
||||
public MySqlToOracleOutputVisitor(Appendable appender) {
|
||||
super(appender);
|
||||
}
|
||||
@@ -18,5 +48,93 @@ public class MySqlToOracleOutputVisitor extends MySqlOutputVisitor {
|
||||
super(appender, parameterized);
|
||||
}
|
||||
|
||||
/**
|
||||
* mysql建表语句遍历
|
||||
* @param x
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public boolean visit(MySqlCreateTableStatement x) {
|
||||
OracleCreateTableStatement oracleCreateTableStatement = new OracleCreateTableStatement();
|
||||
oracleCreateTableStatement.setTableSource(x.getTableSource());
|
||||
String tableName = x.getTableSource().getName().getSimpleName();
|
||||
oracleCreateTableStatement.setName(String.valueOf(x.getName()).replaceAll("\"", ""));
|
||||
oracleCreateTableStatement.setName(String.valueOf(x.getName()).replaceAll("`", ""));
|
||||
oracleCreateTableStatement.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(OracleUtil.containsKeyWords(columnName)){
|
||||
sqlColumnDefinition.setName("\""+columnName+"\"");
|
||||
}
|
||||
sqlColumnDefinition.setDataType(MySqlSQLDataTypeTransformUtil.transformMySqlToOracle(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(expr instanceof SQLIdentifierExpr) {
|
||||
SQLIdentifierExpr sqlIdentifierExpr = (SQLIdentifierExpr) expr;
|
||||
final long nameHashCode64 = sqlIdentifierExpr.nameHashCode64();
|
||||
if(nameHashCode64 == FnvHash.Constants.SYSTIMESTAMP) {
|
||||
SQLIdentifierExpr xx = sqlIdentifierExpr.clone();
|
||||
xx.setName("CURRENT_TIMESTAMP");
|
||||
xx.setParent(sqlIdentifierExpr.getParent());
|
||||
sqlColumnDefinition.setDefaultExpr(xx);
|
||||
if(sqlColumnDefinition.getColumnName().contains("UPDATE_TIME")
|
||||
|| sqlColumnDefinition.getColumnName().contains("MDFY_TIME")) {
|
||||
sqlColumnDefinition.setOnUpdate(xx);
|
||||
}
|
||||
}
|
||||
}else if(expr instanceof OracleSysdateExpr) {
|
||||
SQLIdentifierExpr xx = new SQLIdentifierExpr("CURRENT_TIMESTAMP");
|
||||
xx.setParent(expr.getParent());
|
||||
sqlColumnDefinition.setDefaultExpr(xx);
|
||||
if(sqlColumnDefinition.getColumnName().contains("UPDATE_TIME")
|
||||
|| sqlColumnDefinition.getColumnName().contains("MDFY_TIME")) {
|
||||
sqlColumnDefinition.setOnUpdate(xx);
|
||||
}
|
||||
}
|
||||
}
|
||||
//@TODO 自增转换(oracle没有AUTO_INCREMENT)
|
||||
if(sqlColumnDefinition.isAutoIncrement()){
|
||||
sqlColumnDefinition.setAutoIncrement(false);
|
||||
//SQLIdentifierExpr xx = new SQLIdentifierExpr("sys_guid()");
|
||||
//xx.setName("sys_guid()");
|
||||
//sqlColumnDefinition.setDefaultExpr(xx);
|
||||
}
|
||||
//@TODO 注释待转换
|
||||
if(sqlColumnDefinition.getComment()!= null){
|
||||
sqlColumnDefinition.setComment((String) null);
|
||||
}
|
||||
sqlColumnDefinition.setDbType(distDbType);
|
||||
MapCacheUtil.getInstance().addCacheData(tableName.toUpperCase() + ":" + columnName.toUpperCase(), sqlColumnDefinition.toString().replaceAll(sqlColumnDefinition.getColumnName(), ""));
|
||||
oracleCreateTableStatement.getTableElementList().add(sqlColumnDefinition);
|
||||
}else if(sqlTableElement instanceof MySqlPrimaryKey){
|
||||
OraclePrimaryKey oraclePrimaryKey = new OraclePrimaryKey();
|
||||
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("`", ""));
|
||||
oraclePrimaryKey.addColumn(sQLIdentifierExpr);
|
||||
}
|
||||
oracleCreateTableStatement.getTableElementList().add(oraclePrimaryKey);
|
||||
}else if(sqlTableElement instanceof MySqlUnique) {
|
||||
OracleUnique oracleUnique = new OracleUnique();
|
||||
((MySqlUnique) sqlTableElement).cloneTo(oracleUnique);
|
||||
oracleCreateTableStatement.getTableElementList().add(oracleUnique);
|
||||
}
|
||||
}
|
||||
|
||||
if(Objects.nonNull(x.getSelect())){
|
||||
x.setParent(oracleCreateTableStatement);
|
||||
oracleCreateTableStatement.setSelect(x.getSelect());
|
||||
}
|
||||
println();
|
||||
print(oracleCreateTableStatement.toString());
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
package com.zyplayer.doc.db.framework.db.sql.dialect.mysql.util;
|
||||
|
||||
import com.alibaba.druid.sql.SQLTransformUtils;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLDataType;
|
||||
import com.alibaba.druid.sql.ast.SQLDataTypeImpl;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCharacterDataType;
|
||||
import com.alibaba.druid.util.FnvHash;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* mysql sql转换工具类
|
||||
*
|
||||
* @author diantu
|
||||
* @since 2023年1月30日
|
||||
*/
|
||||
public class MySqlSQLDataTypeTransformUtil extends SQLTransformUtils {
|
||||
|
||||
public static SQLDataType transformMySqlToOracle(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.SMALLINT
|
||||
//|| nameHash == FnvHash.Constants.MEDIUMINT
|
||||
|| nameHash == FnvHash.Constants.INT
|
||||
|| nameHash == FnvHash.Constants.BIGINT
|
||||
|| nameHash == FnvHash.Constants.TINYINT) {
|
||||
if(argumentns.size() > 0){
|
||||
int len;
|
||||
SQLExpr arg0 = argumentns.get(0);
|
||||
if (arg0 instanceof SQLNumericLiteralExpr) {
|
||||
len = ((SQLNumericLiteralExpr) arg0).getNumber().intValue();
|
||||
} else {
|
||||
throw new UnsupportedOperationException(SQLUtils.toMySqlString(x));
|
||||
}
|
||||
dataType = new SQLDataTypeImpl("NUMBER",len);
|
||||
} else {
|
||||
dataType = new SQLCharacterDataType("NUMBER");
|
||||
}
|
||||
|
||||
} else if (nameHash == FnvHash.Constants.FLOAT
|
||||
|| nameHash == FnvHash.Constants.DOUBLE
|
||||
|| nameHash == FnvHash.Constants.DECIMAL) {
|
||||
dataType = new SQLDataTypeImpl("DECIMAL");
|
||||
int precision = 0;
|
||||
if (argumentns.size() > 0) {
|
||||
precision = ((SQLIntegerExpr) argumentns.get(0)).getNumber().intValue();
|
||||
dataType = new SQLDataTypeImpl("DECIMAL",precision);
|
||||
}
|
||||
|
||||
int scale = 0;
|
||||
if (argumentns.size() > 1) {
|
||||
scale = ((SQLIntegerExpr) argumentns.get(1)).getNumber().intValue();
|
||||
dataType = new SQLDataTypeImpl("DECIMAL",precision,scale);
|
||||
}
|
||||
|
||||
} else if (nameHash == FnvHash.Constants.DATE
|
||||
|| nameHash == FnvHash.Constants.DATETIME) {
|
||||
dataType = new SQLDataTypeImpl("DATE");
|
||||
|
||||
} else if (nameHash == FnvHash.Constants.TIMESTAMP) {
|
||||
dataType = new SQLDataTypeImpl("TIMESTAMP");
|
||||
|
||||
} else if (nameHash == FnvHash.Constants.VARCHAR
|
||||
||nameHash == FnvHash.Constants.CHAR) {
|
||||
if(argumentns.size() > 0){
|
||||
int len;
|
||||
SQLExpr arg0 = argumentns.get(0);
|
||||
if (arg0 instanceof SQLNumericLiteralExpr) {
|
||||
len = ((SQLNumericLiteralExpr) arg0).getNumber().intValue();
|
||||
} else {
|
||||
throw new UnsupportedOperationException(SQLUtils.toMySqlString(x));
|
||||
}
|
||||
dataType = new SQLDataTypeImpl("VARCHAR2",len);
|
||||
}else{
|
||||
dataType = new SQLDataTypeImpl("VARCHAR2");
|
||||
}
|
||||
|
||||
} else if (nameHash == FnvHash.Constants.LONGTEXT) {
|
||||
argumentns.clear();
|
||||
dataType = new SQLCharacterDataType("CLOB");
|
||||
|
||||
} else if (nameHash == FnvHash.Constants.BOOLEAN) {
|
||||
dataType = new SQLDataTypeImpl("NUMBER",1);
|
||||
|
||||
} else {
|
||||
dataType = x;
|
||||
}
|
||||
|
||||
if (dataType != x) {
|
||||
dataType.setParent(x.getParent());
|
||||
}
|
||||
|
||||
return dataType;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.zyplayer.doc.db.framework.db.sql.dialect.oracle.function;
|
||||
|
||||
import com.alibaba.druid.sql.dialect.oracle.parser.OracleLexer;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* oracle sql语句相关工具类
|
||||
*
|
||||
* @author diantu
|
||||
* @since 2023年1月30日
|
||||
*/
|
||||
public class OracleUtil {
|
||||
|
||||
/**
|
||||
* 是否包含关键词
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
public static boolean containsKeyWords(String name) {
|
||||
if (StringUtils.isEmpty(name)) {
|
||||
return false;
|
||||
}
|
||||
return OracleLexer.DEFAULT_ORACLE_KEYWORDS.getKeywords().containsKey(name.toUpperCase());
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.zyplayer.doc.db.framework.utils;
|
||||
import com.alibaba.druid.DbType;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.zyplayer.doc.db.framework.db.sql.dialect.mysql.MySqlToOracleOutputVisitor;
|
||||
import com.zyplayer.doc.db.framework.db.sql.dialect.oracle.OracleToMySqlOutputVisitor;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@@ -37,6 +38,24 @@ public class SQLTransformUtils {
|
||||
return mysqlSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* mysql sql语句转换为oracle sql语句
|
||||
* @param sql
|
||||
* @return
|
||||
*/
|
||||
public static String translateMySqlToOracle(String sql) {
|
||||
List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, DbType.mysql);
|
||||
StringBuilder out = new StringBuilder();
|
||||
MySqlToOracleOutputVisitor visitor = new MySqlToOracleOutputVisitor(out, false);
|
||||
|
||||
for(int i = 0; i < stmtList.size(); ++i) {
|
||||
((SQLStatement)stmtList.get(i)).accept(visitor);
|
||||
}
|
||||
|
||||
String oracleSql = out.toString();
|
||||
return oracleSql;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字CLOB转成STRING类型
|
||||
* @param clob
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.zyplayer.doc.db.framework.db.mapper.base.ExecuteParam;
|
||||
import com.zyplayer.doc.db.framework.db.mapper.base.ExecuteResult;
|
||||
import com.zyplayer.doc.db.framework.db.mapper.base.ExecuteType;
|
||||
import com.zyplayer.doc.db.framework.db.mapper.mysql.MysqlMapper;
|
||||
import com.zyplayer.doc.db.framework.utils.SQLTransformUtils;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -109,11 +110,11 @@ public class MysqlServiceImpl extends DbBaseService {
|
||||
List<Map<String, Object>> tableDdlList = baseMapper.getTableDdl(dbName, tableName);
|
||||
TableDdlVo tableDdlVo = new TableDdlVo();
|
||||
tableDdlVo.setCurrent(DatabaseProductEnum.MYSQL.name().toLowerCase());
|
||||
tableDdlVo.setMysql("// 生成失败");
|
||||
tableDdlVo.setOracle("// TODO 等待大佬来实现转换");
|
||||
// TODO 将建表语句转换为其他数据库的,还不知道怎么做,先这样留着,看有没大佬来实现
|
||||
if (CollectionUtils.isNotEmpty(tableDdlList)) {
|
||||
tableDdlVo.setMysql(tableDdlList.get(0).get("Create Table") + ";");
|
||||
String mysqlSql = tableDdlList.get(0).get("Create Table") + ";";
|
||||
tableDdlVo.setMysql(mysqlSql);
|
||||
tableDdlVo.setOracle(SQLTransformUtils.translateMySqlToOracle(mysqlSql));
|
||||
// TODO sqlserver等数据库同理
|
||||
}
|
||||
return tableDdlVo;
|
||||
}
|
||||
|
||||
@@ -84,7 +84,6 @@ public class OracleServiceImpl extends DbBaseService {
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
//String oracleSql = tableDdlList.get(0).get("CREATETABLE") + ";";
|
||||
tableDdlVo.setOracle(oracleSql);
|
||||
//oracle建表语句转换为mysql建表语句
|
||||
String mysqlSql = SQLTransformUtils.translateOracleToMySql(oracleSql);
|
||||
|
||||
Reference in New Issue
Block a user