血缘解析
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

412 lines
13 KiB

package com.guozhi.bloodanalysis.parser;
import com.guozhi.bloodanalysis.entity.DataLineageInfo;
import com.guozhi.bloodanalysis.exception.BusinessException;
import com.guozhi.bloodanalysis.parser.clean.GenericLogNormalizer;
import com.guozhi.bloodanalysis.parser.common.*;
import com.guozhi.bloodanalysis.parser.utils.ExportParseResultUtil;
import com.guozhi.bloodanalysis.parser.vo.KColumn;
import gudusoft.gsqlparser.EDbVendor;
import gudusoft.gsqlparser.TCustomSqlStatement;
import gudusoft.gsqlparser.TGSqlParser;
import gudusoft.gsqlparser.TStatementList;
import gudusoft.gsqlparser.stmt.TAlterTableStatement;
import gudusoft.gsqlparser.stmt.TCreateTableSqlStatement;
import gudusoft.gsqlparser.stmt.TDeleteSqlStatement;
import gudusoft.gsqlparser.stmt.TInsertSqlStatement;
import gudusoft.gsqlparser.stmt.TSelectSqlStatement;
import gudusoft.gsqlparser.stmt.TUpdateSqlStatement;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static com.guozhi.bloodanalysis.parser.utils.DatabaseType.Oracle;
@Slf4j
@Component
@Data
@NoArgsConstructor
@Scope("prototype")
public class SqlParser {
//解析器对象
private TGSqlParser sqlParser = null;
//sql解析器上下文
private ParserContext parserContext = new ParserContext();
@Autowired
ExportParseResultUtil exportParseResultUtil;
@Autowired
ApplicationContext applicationContext;
public void parse(DataLineageInfo dataLineageInfo, List<Map<Integer, String>> databaseList) throws Exception {
String sqlText = "";
try {
List<String> targetSqlList = new ArrayList<>();
String dbType = "MYSQL";
if (databaseList !=null && databaseList.size()>0){
for (Map<Integer, String> map : databaseList) {
String type = map.get(dataLineageInfo.getSsysId());
if (type != null) {
dbType = type;
}
}
}
String sql = new GenericLogNormalizer().normalizer(dataLineageInfo.getProcText(),dbType);
sql = optDeclare(sql,dataLineageInfo.getProcName());
sql = optDeclare2(sql);
if(sql.trim().equals("")){
throw new BusinessException("errorSQLparse:"+dataLineageInfo.getProcName());
}
targetSqlList.add(sql);
String defaultSchema = dataLineageInfo.getMdlName();
Integer defaultSystem = dataLineageInfo.getSsysId();
this.parserContext.setDefaultDb(defaultSystem);
this.parserContext.setDefaultSchema(defaultSchema);
int length = targetSqlList.size();
for (String s : targetSqlList) {
sqlText = s;
if ("ORACLE".equals(dbType)) {
if (Objects.equals(dbType, Oracle.toString())) {
if (sqlText != null) {
sqlText = sqlText.toUpperCase();
}
}
sqlParser = new TGSqlParser(EDbVendor.dbvoracle);
}
if ("MYSQL".equals(dbType)) {
sqlParser = new TGSqlParser(EDbVendor.dbvmysql);
}
if ("SQLSERVER".equals(dbType)) {
sqlParser = new TGSqlParser(EDbVendor.dbvmssql);
}
if ("TERADATA".equals(dbType)) {
sqlParser = new TGSqlParser(EDbVendor.dbvteradata);
}
if ("POSTGRESQL".equals(dbType)) {
sqlParser = new TGSqlParser(EDbVendor.dbvpostgresql);
}
if ("DB2".equals(dbType)) {
sqlParser = new TGSqlParser(EDbVendor.dbvdb2);
}
sqlParser.sqltext = sqlText;
int ret = sqlParser.parse();
List<KColumn> result = new ArrayList<>();
if (ret == 0) {
TStatementList statementList = sqlParser.getSqlstatements();
while (statementList.hasNext()) {
TCustomSqlStatement stmt = statementList.next();
parserContext.getTableInCurrentStatement().clear();
switch (stmt.sqlstatementtype) {
case sstselect:
result = parseSelect(stmt);
break;
case sstdelete:
result = parseDelete(stmt);
break;
case sstupdate:
result = parseUpdate(stmt);
break;
case sstinsert:
result = parseInsert(stmt);
break;
case sstcreatetable:
result = parseCreateTable(stmt);
break;
case sstcreateview:
break;
case sstoraclealtertablespace:
// parseAlterTable(stmt);
break;
case sstdroptable:
// parseDropTable(stmt);
break;
case sstmerge:
log.error("sstmerge["
+ stmt.sqlstatementtype
+ "][unknow sql type]sqltext:"
);
default:
log.error("[" + stmt.sqlstatementtype
+ "][unknow sql type]sqltext:"
);
break;
}
}
} else {
log.error(sqlParser.sqltext + sqlParser.getErrormessage());
}
if (result.size() > 0) {
exportParseResultUtil.expResult(result, dataLineageInfo);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public List<Map<String,Object>> parse(String procSql, String dbType, Integer defaultSystem, String defaultModel) throws Exception {
try {
String sqlText = "";
List<Map<String,Object>> resultList = new ArrayList<>();
List<String> targetSqlList = new ArrayList<>();
String sql = new GenericLogNormalizer().normalizer(procSql,dbType);
sql = optDeclare(sql,null);
sql = optDeclare2(sql);
if(sql.trim().equals("")){
throw new BusinessException("errorSQLparse");
}
targetSqlList.add(sql);
this.parserContext.setDefaultDb(defaultSystem);
this.parserContext.setDefaultSchema(defaultModel);
for (String s : targetSqlList) {
sqlText = s;
if ("ORACLE".equals(dbType)) {
if (Objects.equals(dbType, Oracle.toString())) {
if (sqlText != null) {
sqlText = sqlText.toUpperCase();
}
}
sqlParser = new TGSqlParser(EDbVendor.dbvoracle);
}
if ("MYSQL".equals(dbType)) {
sqlParser = new TGSqlParser(EDbVendor.dbvmysql);
}
if ("SQLSERVER".equals(dbType)) {
sqlParser = new TGSqlParser(EDbVendor.dbvmssql);
}
if ("TERADATA".equals(dbType)) {
sqlParser = new TGSqlParser(EDbVendor.dbvteradata);
}
if ("POSTGRESQL".equals(dbType)) {
sqlParser = new TGSqlParser(EDbVendor.dbvpostgresql);
}
if ("DB2".equals(dbType)) {
sqlParser = new TGSqlParser(EDbVendor.dbvdb2);
}
sqlParser.sqltext = sqlText;
int ret = sqlParser.parse();
List<KColumn> result = new ArrayList<>();
if (ret == 0) {
TStatementList statementList = sqlParser.getSqlstatements();
while (statementList.hasNext()) {
TCustomSqlStatement stmt = statementList.next();
parserContext.getTableInCurrentStatement().clear();
switch (stmt.sqlstatementtype) {
case sstselect:
result = parseSelect(stmt);
break;
case sstdelete:
result = parseDelete(stmt);
break;
case sstupdate:
result = parseUpdate(stmt);
break;
case sstinsert:
result = parseInsert(stmt);
break;
case sstcreatetable:
result = parseCreateTable(stmt);
break;
case sstcreateview:
break;
case sstoraclealtertablespace:
// parseAlterTable(stmt);
break;
case sstdroptable:
// parseDropTable(stmt);
break;
case sstmerge:
log.error("sstmerge["
+ stmt.sqlstatementtype
+ "][unknow sql type]sqltext:"
);
default:
log.error("[" + stmt.sqlstatementtype
+ "][unknow sql type]sqltext:"
);
break;
}
}
} else {
log.error(sqlParser.sqltext + sqlParser.getErrormessage());
}
if (result.size() > 0) {
resultList = exportParseResultUtil.expResult(result);
}
}
return resultList;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private String optDeclare(String sql,String procName) {
String returnSql=sql;
if(StringUtils.isNotEmpty(sql)){
//储存过程名称
String[] sqls = sql.split(";");
for(String sql2:sqls){
sql2 = sql2.trim();
//去掉set和 truncate和delete语句 还有引用其他存储过程的语句
if(sql2.startsWith("SET")||sql2.startsWith("TRUNCATE")||sql2.startsWith("DELETE")||sql2.startsWith("PERFORM")){
sql = sql.replace(sql2+";", "");
}
// String dd = sql2.replaceAll(" ", "");
// int startIndex = dd.toUpperCase().lastIndexOf("PROCEDURE");
// if(startIndex >= 0){
// startIndex += "PROCEDURE".length();
// int endIndex = dd.indexOf("(");
// if(endIndex >= 0){
// procName = dd.substring(startIndex, endIndex);
// }
// }
/*
Pattern pat = Pattern.compile("(DECLARE)(\\s*)");
Matcher mat = pat.matcher(sql2);
if (mat.find()) {
sql2 = mat.replaceAll("");
String sub = sql2.substring(0,sql2.indexOf(" ")).trim();
if(sql.contains(sub)){
sql = sql.replaceAll(sub, "'88888888'");
}
}*/
}
Pattern pat = Pattern.compile("(DECLARE)(\\s).*");
Matcher mat = pat.matcher(sql);
while (mat.find()) {
sql = mat.replaceAll("");
}
//找出脚本结束的位置
if (procName != null && procName.length()>0){
Pattern lastPattern = Pattern.compile("(END)(\\s)+"+("".equals(procName)?";":procName));
Matcher lastMatcher = lastPattern.matcher(sql);
if(lastMatcher.find()){
int lastIndex = lastMatcher.start();
if(sql.contains("BEGIN")){
returnSql = sql.substring(sql.indexOf("BEGIN")+5, lastIndex);
}else{
returnSql = sql.substring(0, lastIndex);
}
}else{
Pattern tempPattern = Pattern.compile("(END)(\\s)*;");
Matcher tempMatcher = tempPattern.matcher(sql);
Pattern tempPatternBegin = Pattern.compile("(\\s)(BEGIN)(\\s)");
Matcher tempMatcherBegin = tempPatternBegin.matcher(sql);
if(tempMatcher.find()){
int tempIndex = tempMatcher.start();
int tempIndexBegin = 0;
if(tempMatcherBegin.find()){
tempIndexBegin = tempMatcherBegin.start();
}
returnSql = sql.substring(tempIndexBegin+6, tempIndex);
}
}
}else {
Pattern tempPattern = Pattern.compile("(END)(\\s)*;");
Matcher tempMatcher = tempPattern.matcher(sql);
Pattern tempPatternBegin = Pattern.compile("(\\s)(BEGIN)(\\s)");
Matcher tempMatcherBegin = tempPatternBegin.matcher(sql);
if(tempMatcher.find()){
int tempIndex = tempMatcher.start();
int tempIndexBegin = 0;
if(tempMatcherBegin.find()){
tempIndexBegin = tempMatcherBegin.start();
}
returnSql = sql.substring(tempIndexBegin+6, tempIndex);
}
}
}
return returnSql;
}
private String optDeclare2(String sql) {
StringBuilder returnVal = new StringBuilder();
if(StringUtils.isNotEmpty(sql)){
String[] sqls = sql.split(";");
for(String sql2:sqls){
sql2 = sql2.trim();
//去掉set和 truncate和delete语句 还有引用其他存储过程的语句
if(sql2.toUpperCase().trim().startsWith("INSERT")){
returnVal.append(sql2.substring(sql2.toUpperCase().indexOf("INSERT"))).append(";\r\n");
}else if(sql2.toUpperCase().trim().startsWith("UPDATE")){
returnVal.append(sql2.substring(sql2.toUpperCase().indexOf("UPDATE"))).append(";\r\n");
}else if(sql2.toUpperCase().trim().startsWith("MERGE")){
//TODO wxl merge语句的解析暂时不支持,导致报错
// returnVal.append(sql2.substring(sql2.toUpperCase().indexOf("MERGE"))+";\r\n");
}else if(sql2.toUpperCase().trim().startsWith("CREATE")){
returnVal.append(sql2.substring(sql2.toUpperCase().indexOf("CREATE"))).append(";\r\n");
}
}
}
return returnVal.toString();
}
private List<KColumn> parseAlterTable(TCustomSqlStatement stmt) {
TAlterTableStatement alterTableStatement=(TAlterTableStatement)stmt;
AlterParser parser=new AlterParser(alterTableStatement,parserContext);
parser.parse();
return parser.getParseResult();
}
private List<KColumn> parseUpdate(TCustomSqlStatement stmt) {
TUpdateSqlStatement dStmt=(TUpdateSqlStatement)stmt;
UpdateParser parser=new UpdateParser(dStmt,parserContext);
parser.parse();
return parser.getParseResult();
}
private List<KColumn> parseDelete(TCustomSqlStatement stmt) {
TDeleteSqlStatement dStmt=(TDeleteSqlStatement)stmt;
DeleteParser parser=new DeleteParser(dStmt,parserContext);
parser.parse();
return parser.getParseResult();
}
private List<KColumn> parseInsert(TCustomSqlStatement stmt) {
InsertParser parser = applicationContext.getBean(InsertParser.class);
parser.setMInsertSql((TInsertSqlStatement)stmt);
parser.setMParserContext(this.parserContext);
parser.parse();
return parser.getParseResult();
}
// private void parseDropTable(TCustomSqlStatement stmt) {
// DropParser dp=new DropParser(stmt,parserContext);
// dp.parse();
// }
public List<KColumn> parseCreateTable(TCustomSqlStatement stmt) {
TCreateTableSqlStatement ctSql=(TCreateTableSqlStatement)stmt;
CreateParser parser=new CreateParser(ctSql,parserContext);
parser.parse();
return parser.getParseResult();
}
public List<KColumn> parseSelect(TCustomSqlStatement stmt) {
TSelectSqlStatement selectSqlStatement = (TSelectSqlStatement) stmt;
SelectParser parser=new SelectParser(selectSqlStatement,parserContext);
parser.parse();
return parser.getParseResult();
}
}