sql翻译框架基础搭建完成(基于Druid SQL Parser解析SQL实现不同数据库间sql语句互转)

目前已实现oracle->mysql建表语句转换
This commit is contained in:
diantu
2023-01-30 14:53:37 +08:00
parent adfd8b24e6
commit d8b400189b
16 changed files with 779 additions and 26 deletions

View File

@@ -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 暮光:城中城

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -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("不支持的操作");

View File

@@ -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("// 生成失败");

View File

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