mysql->oracle建表语句转换
This commit is contained in:
@@ -1,6 +1,31 @@
|
|||||||
package com.zyplayer.doc.db.framework.db.sql.dialect.mysql;
|
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.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遍历实现
|
* mysql转oracle遍历实现
|
||||||
@@ -10,6 +35,11 @@ import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
|
|||||||
*/
|
*/
|
||||||
public class MySqlToOracleOutputVisitor extends MySqlOutputVisitor {
|
public class MySqlToOracleOutputVisitor extends MySqlOutputVisitor {
|
||||||
|
|
||||||
|
private final MySqlToOracleFunctionTransform functionTransform = new MySqlToOracleFunctionTransform();
|
||||||
|
|
||||||
|
// 目标数据库类型
|
||||||
|
private final DbType distDbType = DbType.oracle;
|
||||||
|
|
||||||
public MySqlToOracleOutputVisitor(Appendable appender) {
|
public MySqlToOracleOutputVisitor(Appendable appender) {
|
||||||
super(appender);
|
super(appender);
|
||||||
}
|
}
|
||||||
@@ -18,5 +48,93 @@ public class MySqlToOracleOutputVisitor extends MySqlOutputVisitor {
|
|||||||
super(appender, parameterized);
|
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.DbType;
|
||||||
import com.alibaba.druid.sql.SQLUtils;
|
import com.alibaba.druid.sql.SQLUtils;
|
||||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
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 com.zyplayer.doc.db.framework.db.sql.dialect.oracle.OracleToMySqlOutputVisitor;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
@@ -37,6 +38,24 @@ public class SQLTransformUtils {
|
|||||||
return mysqlSql;
|
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类型
|
* 将字CLOB转成STRING类型
|
||||||
* @param clob
|
* @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.ExecuteResult;
|
||||||
import com.zyplayer.doc.db.framework.db.mapper.base.ExecuteType;
|
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.db.mapper.mysql.MysqlMapper;
|
||||||
|
import com.zyplayer.doc.db.framework.utils.SQLTransformUtils;
|
||||||
import org.apache.commons.collections.CollectionUtils;
|
import org.apache.commons.collections.CollectionUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -109,11 +110,11 @@ public class MysqlServiceImpl extends DbBaseService {
|
|||||||
List<Map<String, Object>> tableDdlList = baseMapper.getTableDdl(dbName, tableName);
|
List<Map<String, Object>> tableDdlList = baseMapper.getTableDdl(dbName, tableName);
|
||||||
TableDdlVo tableDdlVo = new TableDdlVo();
|
TableDdlVo tableDdlVo = new TableDdlVo();
|
||||||
tableDdlVo.setCurrent(DatabaseProductEnum.MYSQL.name().toLowerCase());
|
tableDdlVo.setCurrent(DatabaseProductEnum.MYSQL.name().toLowerCase());
|
||||||
tableDdlVo.setMysql("// 生成失败");
|
|
||||||
tableDdlVo.setOracle("// TODO 等待大佬来实现转换");
|
|
||||||
// TODO 将建表语句转换为其他数据库的,还不知道怎么做,先这样留着,看有没大佬来实现
|
|
||||||
if (CollectionUtils.isNotEmpty(tableDdlList)) {
|
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;
|
return tableDdlVo;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,6 @@ public class OracleServiceImpl extends DbBaseService {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
//String oracleSql = tableDdlList.get(0).get("CREATETABLE") + ";";
|
|
||||||
tableDdlVo.setOracle(oracleSql);
|
tableDdlVo.setOracle(oracleSql);
|
||||||
//oracle建表语句转换为mysql建表语句
|
//oracle建表语句转换为mysql建表语句
|
||||||
String mysqlSql = SQLTransformUtils.translateOracleToMySql(oracleSql);
|
String mysqlSql = SQLTransformUtils.translateOracleToMySql(oracleSql);
|
||||||
|
|||||||
Reference in New Issue
Block a user