sql翻译框架基础搭建完成(基于Druid SQL Parser解析SQL实现不同数据库间sql语句互转)
目前已实现oracle->mysql建表语句转换
This commit is contained in:
@@ -24,7 +24,7 @@ public interface BaseMapper {
|
|||||||
* @author 暮光:城中城
|
* @author 暮光:城中城
|
||||||
* @since 2018年8月8日
|
* @since 2018年8月8日
|
||||||
*/
|
*/
|
||||||
List<Map<String, String>> getTableDdl(@Param("dbName") String dbName, @Param("tableName") String tableName);
|
List<Map<String, Object>> getTableDdl(@Param("dbName") String dbName, @Param("tableName") String tableName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取库列表
|
* 获取库列表
|
||||||
|
|||||||
@@ -71,6 +71,10 @@
|
|||||||
</where>
|
</where>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="getTableDdl" resultType="java.util.Map">
|
||||||
|
SELECT DBMS_METADATA.GET_DDL('TABLE','${tableName}','${dbName}') createTable FROM DUAL
|
||||||
|
</select>
|
||||||
|
|
||||||
<!-- 增加表注释 -->
|
<!-- 增加表注释 -->
|
||||||
<insert id="updateTableDesc">
|
<insert id="updateTableDesc">
|
||||||
comment on table ${dbName}.${tableName} is #{new Desc}
|
comment on table ${dbName}.${tableName} is #{new Desc}
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package com.zyplayer.doc.db.framework.db.sql;
|
||||||
|
|
||||||
|
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||||
|
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sql方法反射实现
|
||||||
|
*
|
||||||
|
* @author diantu
|
||||||
|
* @since 2023年1月29日
|
||||||
|
*/
|
||||||
|
public interface MethodInvoke {
|
||||||
|
|
||||||
|
Logger log = LoggerFactory.getLogger(MethodInvoke.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 方法转换
|
||||||
|
* @param expr
|
||||||
|
*/
|
||||||
|
default void methodInvoke(SQLMethodInvokeExpr expr){
|
||||||
|
if (ObjectUtils.isEmpty(expr)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Method method = ReflectionUtils.findMethod(this.getClass(), expr.getMethodName().toLowerCase(), SQLMethodInvokeExpr.class);
|
||||||
|
if (null != method) {
|
||||||
|
try {
|
||||||
|
method.invoke(this, new Object[]{expr});
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("method invoke error", e);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理嵌套函数
|
||||||
|
* @param sqlExpr
|
||||||
|
*/
|
||||||
|
default void forEachMethod(SQLExpr sqlExpr) {
|
||||||
|
if (sqlExpr instanceof SQLMethodInvokeExpr) {
|
||||||
|
methodInvoke((SQLMethodInvokeExpr) sqlExpr);
|
||||||
|
}
|
||||||
|
Optional.ofNullable(sqlExpr.getChildren()).orElse(new ArrayList<>()).forEach(e -> {
|
||||||
|
if (e instanceof SQLMethodInvokeExpr) {
|
||||||
|
forEachMethod((SQLMethodInvokeExpr) e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.zyplayer.doc.db.framework.db.sql.dialect.mysql;
|
||||||
|
|
||||||
|
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mysql转oracle遍历实现
|
||||||
|
*
|
||||||
|
* @author diantu
|
||||||
|
* @since 2023年1月29日
|
||||||
|
*/
|
||||||
|
public class MySqlToOracleOutputVisitor extends MySqlOutputVisitor {
|
||||||
|
|
||||||
|
public MySqlToOracleOutputVisitor(Appendable appender) {
|
||||||
|
super(appender);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MySqlToOracleOutputVisitor(Appendable appender, boolean parameterized) {
|
||||||
|
super(appender, parameterized);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.zyplayer.doc.db.framework.db.sql.dialect.mysql.function;
|
||||||
|
|
||||||
|
import com.zyplayer.doc.db.framework.db.sql.MethodInvoke;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mysql2oracle需要转换的函数
|
||||||
|
*
|
||||||
|
* @author diantu
|
||||||
|
* @since 2023年1月29日
|
||||||
|
*/
|
||||||
|
public interface MySqlFunction extends MethodInvoke {
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.zyplayer.doc.db.framework.db.sql.dialect.mysql.function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mysql2oracle需要转换的函数实现
|
||||||
|
*
|
||||||
|
* @author diantu
|
||||||
|
* @since 2023年1月29日
|
||||||
|
*/
|
||||||
|
public class MySqlToOracleFunctionTransform implements MySqlFunction{
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.zyplayer.doc.db.framework.db.sql.dialect.mysql.util;
|
||||||
|
|
||||||
|
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlLexer;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mysql sql语句相关工具类
|
||||||
|
*
|
||||||
|
* @author diantu
|
||||||
|
* @since 2023年1月29日
|
||||||
|
*/
|
||||||
|
public class MySqlUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否包含关键词
|
||||||
|
* @param name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean containsKeyWords(String name) {
|
||||||
|
if (StringUtils.isEmpty(name)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return MySqlLexer.DEFAULT_MYSQL_KEYWORDS.getKeywords().containsKey(name.toUpperCase());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
package com.zyplayer.doc.db.framework.db.sql.dialect.oracle;
|
||||||
|
|
||||||
|
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.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.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.dialect.oracle.visitor.OracleOutputVisitor;
|
||||||
|
import com.alibaba.druid.sql.parser.SQLParserUtils;
|
||||||
|
import com.alibaba.druid.util.FnvHash;
|
||||||
|
import com.zyplayer.doc.db.framework.db.sql.dialect.mysql.util.MySqlUtil;
|
||||||
|
import com.zyplayer.doc.db.framework.db.sql.dialect.oracle.function.OracleToMySqlFunctionTransform;
|
||||||
|
import com.zyplayer.doc.db.framework.db.sql.dialect.oracle.util.OracleSQLDataTypeTransformUtil;
|
||||||
|
import com.zyplayer.doc.db.framework.utils.MapCacheUtil;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oracle转mysql遍历实现
|
||||||
|
*
|
||||||
|
* @author diantu
|
||||||
|
* @since 2023年1月29日
|
||||||
|
*/
|
||||||
|
public class OracleToMySqlOutputVisitor extends OracleOutputVisitor {
|
||||||
|
|
||||||
|
private final OracleToMySqlFunctionTransform functionTransform = new OracleToMySqlFunctionTransform();
|
||||||
|
|
||||||
|
// 目标数据库类型
|
||||||
|
private final DbType distDbType = DbType.mysql;
|
||||||
|
|
||||||
|
public OracleToMySqlOutputVisitor(Appendable appender) {
|
||||||
|
super(appender);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OracleToMySqlOutputVisitor(Appendable appender, boolean printPostSemi) {
|
||||||
|
super(appender, printPostSemi);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oracle建表语句遍历
|
||||||
|
* @param x
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean visit(OracleCreateTableStatement x) {
|
||||||
|
MySqlCreateTableStatement mySqlCreateTableStatement = new MySqlCreateTableStatement();
|
||||||
|
mySqlCreateTableStatement.setTableSource(x.getTableSource());
|
||||||
|
String tableName = x.getTableSource().getName().getSimpleName();
|
||||||
|
mySqlCreateTableStatement.setName(String.valueOf(x.getName()).replaceAll("\"", ""));
|
||||||
|
for(SQLTableElement sqlTableElement : x.getTableElementList()){
|
||||||
|
if( sqlTableElement instanceof SQLColumnDefinition) {
|
||||||
|
SQLColumnDefinition sqlColumnDefinition = ((SQLColumnDefinition)sqlTableElement);
|
||||||
|
String columnName = sqlColumnDefinition.getName().getSimpleName().replaceAll("\"", "");
|
||||||
|
sqlColumnDefinition.setName(columnName);
|
||||||
|
if(MySqlUtil.containsKeyWords(columnName)){
|
||||||
|
sqlColumnDefinition.setName("`"+columnName+"`");
|
||||||
|
}
|
||||||
|
sqlColumnDefinition.setDataType(OracleSQLDataTypeTransformUtil.transformOracleToMySql(SQLParserUtils.createExprParser(sqlColumnDefinition.getDataType().toString(), DbType.oracle).parseDataType()));
|
||||||
|
if(sqlColumnDefinition.getDefaultExpr() != null) {
|
||||||
|
SQLExpr expr = sqlColumnDefinition.getDefaultExpr();
|
||||||
|
if(expr instanceof SQLMethodInvokeExpr) {
|
||||||
|
SQLMethodInvokeExpr sqlMethodInvokeExpr = (SQLMethodInvokeExpr) expr;
|
||||||
|
final long nameHashCode64 = sqlMethodInvokeExpr.methodNameHashCode64();
|
||||||
|
//mysql默认值只能为常量
|
||||||
|
if (nameHashCode64 == FnvHash.Constants.SYS_GUID || nameHashCode64 == FnvHash.Constants.TO_CHAR) {
|
||||||
|
sqlColumnDefinition.setDefaultExpr(null);
|
||||||
|
}else {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sqlColumnDefinition.setDbType(distDbType);
|
||||||
|
MapCacheUtil.getInstance().addCacheData(tableName.toUpperCase() + ":" + columnName.toUpperCase(), sqlColumnDefinition.toString().replaceAll(sqlColumnDefinition.getColumnName(), ""));
|
||||||
|
mySqlCreateTableStatement.getTableElementList().add(sqlColumnDefinition);
|
||||||
|
}else if(sqlTableElement instanceof OraclePrimaryKey){
|
||||||
|
MySqlPrimaryKey mySqlPrimaryKey = new MySqlPrimaryKey();
|
||||||
|
mySqlPrimaryKey.setName("primary key");
|
||||||
|
List<SQLSelectOrderByItem> list = ((OraclePrimaryKey) sqlTableElement).getIndexDefinition().getColumns();
|
||||||
|
for(int i=0;i<list.size();i++){
|
||||||
|
mySqlPrimaryKey.addColumn(list.get(i));
|
||||||
|
}
|
||||||
|
mySqlCreateTableStatement.getTableElementList().add(mySqlPrimaryKey);
|
||||||
|
}else if(sqlTableElement instanceof OracleUnique) {
|
||||||
|
MySqlUnique mySqlUnique = new MySqlUnique();
|
||||||
|
((OracleUnique) sqlTableElement).cloneTo(mySqlUnique);
|
||||||
|
mySqlCreateTableStatement.getTableElementList().add(mySqlUnique);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Objects.nonNull(x.getSelect())){
|
||||||
|
x.setParent(mySqlCreateTableStatement);
|
||||||
|
mySqlCreateTableStatement.setSelect(x.getSelect());
|
||||||
|
}
|
||||||
|
println();
|
||||||
|
print(mySqlCreateTableStatement.toString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package com.zyplayer.doc.db.framework.db.sql.dialect.oracle.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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oracle2mysql需要转换的函数
|
||||||
|
*
|
||||||
|
* @author diantu
|
||||||
|
* @since 2023年1月29日
|
||||||
|
*/
|
||||||
|
public interface OracleFunction extends MethodInvoke {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换 sys_guid 函数
|
||||||
|
* @author diantu
|
||||||
|
* @date 2023年1月29日
|
||||||
|
* @param expr
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
void sys_guid(SQLMethodInvokeExpr expr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 整体替换当前类型
|
||||||
|
* @author diantu
|
||||||
|
* @date 2023年1月29日
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.zyplayer.doc.db.framework.db.sql.dialect.oracle.function;
|
||||||
|
|
||||||
|
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oracle2mysql需要转换的函数实现
|
||||||
|
*
|
||||||
|
* @author diantu
|
||||||
|
* @since 2023年1月29日
|
||||||
|
*/
|
||||||
|
public class OracleToMySqlFunctionTransform implements OracleFunction{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sys_guid(SQLMethodInvokeExpr expr) {
|
||||||
|
identifierExpr("replace(uuid(), '-', '')", expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,268 @@
|
|||||||
|
package com.zyplayer.doc.db.framework.db.sql.dialect.oracle.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.SQLAllColumnExpr;
|
||||||
|
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;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oracle sql转换工具类
|
||||||
|
*
|
||||||
|
* @author diantu
|
||||||
|
* @since 2023年1月29日
|
||||||
|
*/
|
||||||
|
public class OracleSQLDataTypeTransformUtil extends SQLTransformUtils {
|
||||||
|
|
||||||
|
public static SQLDataType transformOracleToMySql(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.UROWID) {
|
||||||
|
int len = 4000;
|
||||||
|
if (argumentns.size() == 1) {
|
||||||
|
SQLExpr arg0 = argumentns.get(0);
|
||||||
|
if (arg0 instanceof SQLIntegerExpr) {
|
||||||
|
len = ((SQLIntegerExpr) arg0).getNumber().intValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dataType = new SQLDataTypeImpl("varchar", len);
|
||||||
|
} else if (nameHash == FnvHash.Constants.ROWID) {
|
||||||
|
dataType = new SQLDataTypeImpl("char", 10);
|
||||||
|
|
||||||
|
} else if (nameHash == FnvHash.Constants.BOOLEAN) {
|
||||||
|
dataType = new SQLDataTypeImpl("tinyint");
|
||||||
|
|
||||||
|
} else if (nameHash == FnvHash.Constants.INTEGER) {
|
||||||
|
dataType = new SQLDataTypeImpl("int");
|
||||||
|
|
||||||
|
} else if (nameHash == FnvHash.Constants.FLOAT
|
||||||
|
|| nameHash == FnvHash.Constants.BINARY_FLOAT) {
|
||||||
|
dataType = new SQLDataTypeImpl("float");
|
||||||
|
|
||||||
|
} else if (nameHash == FnvHash.Constants.REAL
|
||||||
|
|| nameHash == FnvHash.Constants.BINARY_DOUBLE
|
||||||
|
|| nameHash == FnvHash.Constants.DOUBLE_PRECISION) {
|
||||||
|
dataType = new SQLDataTypeImpl("double");
|
||||||
|
|
||||||
|
} else if (nameHash == FnvHash.Constants.NUMBER) {
|
||||||
|
if (argumentns.size() == 0) {
|
||||||
|
dataType = new SQLDataTypeImpl("decimal", 38);
|
||||||
|
} else {
|
||||||
|
SQLExpr arg0 = argumentns.get(0);
|
||||||
|
|
||||||
|
int precision, scale = 0;
|
||||||
|
if (arg0 instanceof SQLAllColumnExpr) {
|
||||||
|
precision = 9;
|
||||||
|
} else {
|
||||||
|
precision = ((SQLIntegerExpr) arg0).getNumber().intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argumentns.size() > 1) {
|
||||||
|
scale = ((SQLIntegerExpr) argumentns.get(1)).getNumber().intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scale > precision) {
|
||||||
|
if (arg0 instanceof SQLAllColumnExpr) {
|
||||||
|
precision = 19;
|
||||||
|
if (scale > precision) {
|
||||||
|
precision = scale;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
precision = scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scale == 0) {
|
||||||
|
if (precision < 3) {
|
||||||
|
dataType = new SQLDataTypeImpl("tinyint");
|
||||||
|
} else if (precision < 5) {
|
||||||
|
dataType = new SQLDataTypeImpl("smallint");
|
||||||
|
} else if (precision < 9) {
|
||||||
|
dataType = new SQLDataTypeImpl("int");
|
||||||
|
} else if (precision <= 20) {
|
||||||
|
dataType = new SQLDataTypeImpl("bigint");
|
||||||
|
} else {
|
||||||
|
dataType = new SQLDataTypeImpl("decimal", precision);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dataType = new SQLDataTypeImpl("decimal", precision, scale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (nameHash == FnvHash.Constants.DEC
|
||||||
|
|| nameHash == FnvHash.Constants.DECIMAL) {
|
||||||
|
|
||||||
|
dataType = x.clone();
|
||||||
|
dataType.setName("decimal");
|
||||||
|
|
||||||
|
int precision = 0;
|
||||||
|
if (argumentns.size() > 0) {
|
||||||
|
precision = ((SQLIntegerExpr) argumentns.get(0)).getNumber().intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
int scale = 0;
|
||||||
|
if (argumentns.size() > 1) {
|
||||||
|
scale = ((SQLIntegerExpr) argumentns.get(1)).getNumber().intValue();
|
||||||
|
if (precision < scale) {
|
||||||
|
((SQLIntegerExpr) dataType.getArguments().get(1)).setNumber(precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (nameHash == FnvHash.Constants.RAW) {
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (argumentns.size() == 0) {
|
||||||
|
len = -1;
|
||||||
|
} else if (argumentns.size() == 1) {
|
||||||
|
SQLExpr arg0 = argumentns.get(0);
|
||||||
|
if (arg0 instanceof SQLNumericLiteralExpr) {
|
||||||
|
len = ((SQLNumericLiteralExpr) arg0).getNumber().intValue();
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException(SQLUtils.toOracleString(x));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException(SQLUtils.toOracleString(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == -1) {
|
||||||
|
dataType = new SQLDataTypeImpl("binary");
|
||||||
|
} else if (len <= 255) {
|
||||||
|
dataType = new SQLDataTypeImpl("binary", len);
|
||||||
|
} else {
|
||||||
|
dataType = new SQLDataTypeImpl("varbinary", len);
|
||||||
|
}
|
||||||
|
} else if (nameHash == FnvHash.Constants.CHAR
|
||||||
|
|| nameHash == FnvHash.Constants.CHARACTER) {
|
||||||
|
if (argumentns.size() == 1) {
|
||||||
|
SQLExpr arg0 = argumentns.get(0);
|
||||||
|
|
||||||
|
int len;
|
||||||
|
if (arg0 instanceof SQLNumericLiteralExpr) {
|
||||||
|
len = ((SQLNumericLiteralExpr) arg0).getNumber().intValue();
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException(SQLUtils.toOracleString(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len <= 255) {
|
||||||
|
dataType = new SQLCharacterDataType("char", len);
|
||||||
|
} else {
|
||||||
|
dataType = new SQLCharacterDataType("varchar", len);
|
||||||
|
}
|
||||||
|
} else if (argumentns.size() == 0) {
|
||||||
|
dataType = new SQLCharacterDataType("char");
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException(SQLUtils.toOracleString(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (nameHash == FnvHash.Constants.NCHAR) {
|
||||||
|
if (argumentns.size() == 1) {
|
||||||
|
SQLExpr arg0 = argumentns.get(0);
|
||||||
|
|
||||||
|
int len;
|
||||||
|
if (arg0 instanceof SQLNumericLiteralExpr) {
|
||||||
|
len = ((SQLNumericLiteralExpr) arg0).getNumber().intValue();
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException(SQLUtils.toOracleString(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len <= 255) {
|
||||||
|
dataType = new SQLCharacterDataType("nchar", len);
|
||||||
|
} else {
|
||||||
|
dataType = new SQLCharacterDataType("nvarchar", len);
|
||||||
|
}
|
||||||
|
} else if (argumentns.size() == 0) {
|
||||||
|
dataType = new SQLCharacterDataType("nchar");
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException(SQLUtils.toOracleString(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (nameHash == FnvHash.Constants.VARCHAR2) {
|
||||||
|
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.toOracleString(x));
|
||||||
|
}
|
||||||
|
if(len >= 4000) {
|
||||||
|
dataType = new SQLCharacterDataType("text");
|
||||||
|
}else {
|
||||||
|
dataType = new SQLCharacterDataType("varchar", len);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dataType = new SQLCharacterDataType("varchar");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (nameHash == FnvHash.Constants.NVARCHAR2) {
|
||||||
|
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.toOracleString(x));
|
||||||
|
}
|
||||||
|
dataType = new SQLCharacterDataType("nvarchar", len);
|
||||||
|
} else {
|
||||||
|
dataType = new SQLCharacterDataType("nvarchar");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (nameHash == FnvHash.Constants.BFILE) {
|
||||||
|
dataType = new SQLCharacterDataType("varchar", 255);
|
||||||
|
|
||||||
|
} else if (nameHash == FnvHash.Constants.DATE
|
||||||
|
|| nameHash == FnvHash.Constants.TIMESTAMP) {
|
||||||
|
int len = -1;
|
||||||
|
if (argumentns.size() > 0) {
|
||||||
|
SQLExpr arg0 = argumentns.get(0);
|
||||||
|
if (arg0 instanceof SQLNumericLiteralExpr) {
|
||||||
|
len = ((SQLNumericLiteralExpr) arg0).getNumber().intValue();
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException(SQLUtils.toOracleString(x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if (len >= 0) {
|
||||||
|
if (len > 6) {
|
||||||
|
len = 6;
|
||||||
|
}
|
||||||
|
dataType = new SQLDataTypeImpl("datetime", len);
|
||||||
|
} else {*/
|
||||||
|
dataType = new SQLDataTypeImpl("datetime");
|
||||||
|
/* }*/
|
||||||
|
} else if (nameHash == FnvHash.Constants.BLOB
|
||||||
|
|| nameHash == FnvHash.Constants.LONG_RAW) {
|
||||||
|
argumentns.clear();
|
||||||
|
dataType = new SQLDataTypeImpl("LONGBLOB");
|
||||||
|
|
||||||
|
} else if (nameHash == FnvHash.Constants.CLOB
|
||||||
|
|| nameHash == FnvHash.Constants.NCLOB
|
||||||
|
|| nameHash == FnvHash.Constants.LONG
|
||||||
|
|| nameHash == FnvHash.Constants.XMLTYPE) {
|
||||||
|
argumentns.clear();
|
||||||
|
dataType = new SQLCharacterDataType("LONGTEXT");
|
||||||
|
} else {
|
||||||
|
dataType = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dataType != x) {
|
||||||
|
dataType.setParent(x.getParent());
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.zyplayer.doc.db.framework.utils;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基于Map实现内存缓存
|
||||||
|
*
|
||||||
|
* @author diantu
|
||||||
|
* @since 2023年1月29日
|
||||||
|
*/
|
||||||
|
public class MapCacheUtil {
|
||||||
|
|
||||||
|
private static MapCacheUtil cacheUtil;
|
||||||
|
private static Map<String,Object> cacheMap;
|
||||||
|
|
||||||
|
private MapCacheUtil(){
|
||||||
|
cacheMap = new HashMap<String, Object>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MapCacheUtil getInstance(){
|
||||||
|
if (cacheUtil == null){
|
||||||
|
cacheUtil = new MapCacheUtil();
|
||||||
|
}
|
||||||
|
return cacheUtil;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加缓存
|
||||||
|
*/
|
||||||
|
public void addCacheData(String key,Object obj){
|
||||||
|
cacheMap.put(key,obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取出缓存
|
||||||
|
*/
|
||||||
|
public Object getCacheData(String key){
|
||||||
|
return cacheMap.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清楚缓存
|
||||||
|
*/
|
||||||
|
public void removeCacheData(String key){
|
||||||
|
cacheMap.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map cacheMap() {
|
||||||
|
return cacheMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
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.oracle.OracleToMySqlOutputVisitor;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.sql.Clob;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sql语句转换工具类
|
||||||
|
*
|
||||||
|
* @author diantu
|
||||||
|
* @since 2023年1月29日
|
||||||
|
*/
|
||||||
|
public class SQLTransformUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* oracle sql语句转换为mysql sql语句
|
||||||
|
* @param sql
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String translateOracleToMySql(String sql) {
|
||||||
|
List<SQLStatement> stmtList = SQLUtils.toStatementList(sql, DbType.oracle);
|
||||||
|
StringBuilder out = new StringBuilder();
|
||||||
|
OracleToMySqlOutputVisitor visitor = new OracleToMySqlOutputVisitor(out, false);
|
||||||
|
|
||||||
|
for(int i = 0; i < stmtList.size(); ++i) {
|
||||||
|
((SQLStatement)stmtList.get(i)).accept(visitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
String mysqlSql = out.toString();
|
||||||
|
return mysqlSql;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将字CLOB转成STRING类型
|
||||||
|
* @param clob
|
||||||
|
* @return
|
||||||
|
* @throws SQLException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public static String ClobToString(Clob clob) throws SQLException, IOException {
|
||||||
|
|
||||||
|
String reString = "";
|
||||||
|
// 得到流
|
||||||
|
java.io.Reader is = clob.getCharacterStream();
|
||||||
|
BufferedReader br = new BufferedReader(is);
|
||||||
|
String s = br.readLine();
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
// 执行循环将字符串全部取出付值给StringBuffer由StringBuffer转成STRING
|
||||||
|
while (s != null) {
|
||||||
|
sb.append(s);
|
||||||
|
s = br.readLine();
|
||||||
|
}
|
||||||
|
reString = sb.toString();
|
||||||
|
return reString;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,15 +41,15 @@ public class HiveServiceImpl extends DbBaseService {
|
|||||||
@Override
|
@Override
|
||||||
public TableDdlVo getTableDdl(Long sourceId, String dbName, String tableName) {
|
public TableDdlVo getTableDdl(Long sourceId, String dbName, String tableName) {
|
||||||
BaseMapper baseMapper = this.getViewAuthBaseMapper(sourceId);
|
BaseMapper baseMapper = this.getViewAuthBaseMapper(sourceId);
|
||||||
List<Map<String, String>> 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.HIVE.name().toLowerCase());
|
tableDdlVo.setCurrent(DatabaseProductEnum.HIVE.name().toLowerCase());
|
||||||
if (CollectionUtils.isNotEmpty(tableDdlList)) {
|
if (CollectionUtils.isNotEmpty(tableDdlList)) {
|
||||||
// hive和impala结果集不一样
|
// hive和impala结果集不一样
|
||||||
if (tableDdlList.size() == 1) {
|
if (tableDdlList.size() == 1) {
|
||||||
tableDdlVo.setHive(tableDdlList.get(0).get("result"));
|
tableDdlVo.setHive(tableDdlList.get(0).get("result").toString());
|
||||||
} else {
|
} else {
|
||||||
String createTabStmt = tableDdlList.stream().map(map -> map.get("createtab_stmt")).collect(Collectors.joining("\n"));
|
String createTabStmt = tableDdlList.stream().map(map -> map.get("createtab_stmt").toString()).collect(Collectors.joining("\n"));
|
||||||
tableDdlVo.setHive(createTabStmt);
|
tableDdlVo.setHive(createTabStmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ public class MysqlServiceImpl extends DbBaseService {
|
|||||||
@Override
|
@Override
|
||||||
public TableDdlVo getTableDdl(Long sourceId, String dbName, String tableName) {
|
public TableDdlVo getTableDdl(Long sourceId, String dbName, String tableName) {
|
||||||
BaseMapper baseMapper = this.getViewAuthBaseMapper(sourceId);
|
BaseMapper baseMapper = this.getViewAuthBaseMapper(sourceId);
|
||||||
List<Map<String, String>> 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.setMysql("// 生成失败");
|
||||||
|
|||||||
@@ -1,10 +1,20 @@
|
|||||||
package com.zyplayer.doc.db.service.database;
|
package com.zyplayer.doc.db.service.database;
|
||||||
|
|
||||||
import com.zyplayer.doc.db.controller.param.DataViewParam;
|
import com.zyplayer.doc.db.controller.param.DataViewParam;
|
||||||
|
import com.zyplayer.doc.db.controller.vo.TableDdlVo;
|
||||||
import com.zyplayer.doc.db.framework.db.enums.DatabaseProductEnum;
|
import com.zyplayer.doc.db.framework.db.enums.DatabaseProductEnum;
|
||||||
|
import com.zyplayer.doc.db.framework.db.mapper.base.BaseMapper;
|
||||||
|
import com.zyplayer.doc.db.framework.utils.SQLTransformUtils;
|
||||||
|
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;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.sql.Clob;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Oracle数据查询服务实现类
|
* Oracle数据查询服务实现类
|
||||||
*
|
*
|
||||||
@@ -52,4 +62,35 @@ public class OracleServiceImpl extends DbBaseService {
|
|||||||
sqlSbFinal.append(String.format("select * from ( select %s from %s", queryColumns + ",rownum rn", "(" + sqlSb + ") where rownum<=" + pageSize + " ) t2 where t2.rn >=" + pageNum));
|
sqlSbFinal.append(String.format("select * from ( select %s from %s", queryColumns + ",rownum rn", "(" + sqlSb + ") where rownum<=" + pageSize + " ) t2 where t2.rn >=" + pageNum));
|
||||||
return sqlSbFinal.toString();
|
return sqlSbFinal.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取建表语句
|
||||||
|
*
|
||||||
|
* @author diantu
|
||||||
|
* @since 2023年1月29日
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public TableDdlVo getTableDdl(Long sourceId, String dbName, String tableName) {
|
||||||
|
BaseMapper baseMapper = this.getViewAuthBaseMapper(sourceId);
|
||||||
|
List<Map<String, Object>> tableDdlList = baseMapper.getTableDdl(dbName, tableName);
|
||||||
|
TableDdlVo tableDdlVo = new TableDdlVo();
|
||||||
|
tableDdlVo.setCurrent(DatabaseProductEnum.MYSQL.name().toLowerCase());
|
||||||
|
if (CollectionUtils.isNotEmpty(tableDdlList)) {
|
||||||
|
String oracleSql = "";
|
||||||
|
try {
|
||||||
|
oracleSql = SQLTransformUtils.ClobToString((Clob)tableDdlList.get(0).get("CREATETABLE"));
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
//String oracleSql = tableDdlList.get(0).get("CREATETABLE") + ";";
|
||||||
|
tableDdlVo.setOracle(oracleSql);
|
||||||
|
//oracle建表语句转换为mysql建表语句
|
||||||
|
String mysqlSql = SQLTransformUtils.translateOracleToMySql(oracleSql);
|
||||||
|
tableDdlVo.setMysql(mysqlSql);
|
||||||
|
// TODO sqlserver等数据库同理
|
||||||
|
}
|
||||||
|
return tableDdlVo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user