sql翻译框架基础搭建完成(基于Druid SQL Parser解析SQL实现不同数据库间sql语句互转)
目前已实现oracle->mysql建表语句转换
This commit is contained in:
@@ -16,7 +16,7 @@ import java.util.Map;
|
||||
* @since 2018年8月8日
|
||||
*/
|
||||
public interface BaseMapper {
|
||||
|
||||
|
||||
/**
|
||||
* 获取库列表
|
||||
*
|
||||
@@ -24,8 +24,8 @@ public interface BaseMapper {
|
||||
* @author 暮光:城中城
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* 获取库列表
|
||||
*
|
||||
@@ -34,7 +34,7 @@ public interface BaseMapper {
|
||||
* @since 2018年8月8日
|
||||
*/
|
||||
List<DatabaseInfoDto> getDatabaseList();
|
||||
|
||||
|
||||
/**
|
||||
* 获取表列表
|
||||
*
|
||||
@@ -44,7 +44,7 @@ public interface BaseMapper {
|
||||
* @since 2018年8月8日
|
||||
*/
|
||||
List<TableInfoDto> getTableList(@Param("dbName") String dbName);
|
||||
|
||||
|
||||
/**
|
||||
* 获取字段列表
|
||||
*
|
||||
@@ -55,7 +55,7 @@ public interface BaseMapper {
|
||||
* @since 2018年8月8日
|
||||
*/
|
||||
List<TableColumnDescDto> getTableColumnList(@Param("dbName") String dbName, @Param("tableName") String tableName);
|
||||
|
||||
|
||||
/**
|
||||
* 模糊搜索表和字段
|
||||
*
|
||||
@@ -66,7 +66,7 @@ public interface BaseMapper {
|
||||
* @since 2018年8月8日
|
||||
*/
|
||||
List<QueryTableColumnDescDto> getTableAndColumnBySearch(@Param("dbName") String dbName, @Param("searchText") String searchText);
|
||||
|
||||
|
||||
/**
|
||||
* 获取表注释
|
||||
*
|
||||
@@ -76,7 +76,7 @@ public interface BaseMapper {
|
||||
* @since 2018年8月8日
|
||||
*/
|
||||
List<TableDescDto> getTableDescList(@Param("dbName") String dbName, @Param("tableName") String tableName);
|
||||
|
||||
|
||||
/**
|
||||
* 增加表注释
|
||||
*
|
||||
@@ -86,7 +86,7 @@ public interface BaseMapper {
|
||||
* @since 2018年8月8日
|
||||
*/
|
||||
void updateTableDesc(@Param("dbName") String dbName, @Param("tableName") String tableName, @Param("newDesc") String newDesc);
|
||||
|
||||
|
||||
/**
|
||||
* 增加字段注释
|
||||
*
|
||||
@@ -101,7 +101,7 @@ public interface BaseMapper {
|
||||
void updateTableColumnDesc(@Param("dbName") String dbName, @Param("tableName") String tableName,
|
||||
@Param("columnName") String columnName, @Param("newDesc") String newDesc,
|
||||
@Param("columnInfo") ColumnInfoDto columnInfo);
|
||||
|
||||
|
||||
/**
|
||||
* 获取表基本信息
|
||||
*
|
||||
@@ -111,7 +111,7 @@ public interface BaseMapper {
|
||||
* @since 2019年9月1日
|
||||
*/
|
||||
TableStatusVo getTableStatus(@Param("dbName") String dbName, @Param("tableName") String tableName);
|
||||
|
||||
|
||||
/**
|
||||
* 获取存储过程总条数
|
||||
*
|
||||
@@ -120,7 +120,7 @@ public interface BaseMapper {
|
||||
* @since 2020年4月24日
|
||||
*/
|
||||
Long getProcedureCount(@Param("param") ProcedureListParam procedureParam);
|
||||
|
||||
|
||||
/**
|
||||
* 获取存储过程列表
|
||||
*
|
||||
@@ -129,7 +129,7 @@ public interface BaseMapper {
|
||||
* @since 2020年4月24日
|
||||
*/
|
||||
List<ProcedureDto> getProcedureList(@Param("param") ProcedureListParam procedureParam);
|
||||
|
||||
|
||||
/**
|
||||
* 获取存储过程详情
|
||||
*
|
||||
@@ -140,7 +140,7 @@ public interface BaseMapper {
|
||||
* @since 2020年4月24日
|
||||
*/
|
||||
ProcedureDto getProcedureDetail(@Param("dbName") String dbName, @Param("typeName") String typeName, @Param("procName") String procName);
|
||||
|
||||
|
||||
/**
|
||||
* 删除存储过程
|
||||
*
|
||||
@@ -151,7 +151,7 @@ public interface BaseMapper {
|
||||
* @since 2020年4月24日
|
||||
*/
|
||||
void deleteProcedure(@Param("dbName") String dbName, @Param("typeName") String typeName, @Param("procName") String procName);
|
||||
|
||||
|
||||
/**
|
||||
* 删除行数
|
||||
* @author 暮光:城中城
|
||||
|
||||
@@ -71,6 +71,10 @@
|
||||
</where>
|
||||
</select>
|
||||
|
||||
<select id="getTableDdl" resultType="java.util.Map">
|
||||
SELECT DBMS_METADATA.GET_DDL('TABLE','${tableName}','${dbName}') createTable FROM DUAL
|
||||
</select>
|
||||
|
||||
<!-- 增加表注释 -->
|
||||
<insert id="updateTableDesc">
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -22,12 +22,12 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
@Service
|
||||
public class HiveServiceImpl extends DbBaseService {
|
||||
|
||||
|
||||
@Override
|
||||
public DatabaseProductEnum getDatabaseProduct() {
|
||||
return DatabaseProductEnum.HIVE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<TableInfoDto> getTableList(Long sourceId, String dbName) {
|
||||
BaseMapper baseMapper = this.getViewAuthBaseMapper(sourceId);
|
||||
@@ -37,40 +37,40 @@ public class HiveServiceImpl extends DbBaseService {
|
||||
}
|
||||
return tableList;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TableDdlVo getTableDdl(Long sourceId, String dbName, String tableName) {
|
||||
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.setCurrent(DatabaseProductEnum.HIVE.name().toLowerCase());
|
||||
if (CollectionUtils.isNotEmpty(tableDdlList)) {
|
||||
// hive和impala结果集不一样
|
||||
if (tableDdlList.size() == 1) {
|
||||
tableDdlVo.setHive(tableDdlList.get(0).get("result"));
|
||||
tableDdlVo.setHive(tableDdlList.get(0).get("result").toString());
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
return tableDdlVo;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<QueryTableColumnDescDto> getTableAndColumnBySearch(Long sourceId, String dbName, String searchText) {
|
||||
throw new ConfirmException("不支持的操作");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<TableDescDto> getTableDescList(Long sourceId, String dbName, String tableName) {
|
||||
throw new ConfirmException("不支持的操作");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateTableDesc(Long sourceId, String dbName, String tableName, String newDesc) {
|
||||
throw new ConfirmException("不支持的操作");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void updateTableColumnDesc(Long sourceId, String dbName, String tableName, String columnName, String newDesc) {
|
||||
throw new ConfirmException("不支持的操作");
|
||||
|
||||
@@ -106,7 +106,7 @@ public class MysqlServiceImpl extends DbBaseService {
|
||||
@Override
|
||||
public TableDdlVo getTableDdl(Long sourceId, String dbName, String tableName) {
|
||||
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.setCurrent(DatabaseProductEnum.MYSQL.name().toLowerCase());
|
||||
tableDdlVo.setMysql("// 生成失败");
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
package com.zyplayer.doc.db.service.database;
|
||||
|
||||
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.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.springframework.stereotype.Service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.Clob;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 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));
|
||||
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