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> databaseList) throws Exception { String sqlText = ""; try { List targetSqlList = new ArrayList<>(); String dbType = "MYSQL"; if (databaseList !=null && databaseList.size()>0){ for (Map 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 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> parse(String procSql, String dbType, Integer defaultSystem, String defaultModel) throws Exception { try { String sqlText = ""; List> resultList = new ArrayList<>(); List 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 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 parseAlterTable(TCustomSqlStatement stmt) { TAlterTableStatement alterTableStatement=(TAlterTableStatement)stmt; AlterParser parser=new AlterParser(alterTableStatement,parserContext); parser.parse(); return parser.getParseResult(); } private List parseUpdate(TCustomSqlStatement stmt) { TUpdateSqlStatement dStmt=(TUpdateSqlStatement)stmt; UpdateParser parser=new UpdateParser(dStmt,parserContext); parser.parse(); return parser.getParseResult(); } private List parseDelete(TCustomSqlStatement stmt) { TDeleteSqlStatement dStmt=(TDeleteSqlStatement)stmt; DeleteParser parser=new DeleteParser(dStmt,parserContext); parser.parse(); return parser.getParseResult(); } private List 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 parseCreateTable(TCustomSqlStatement stmt) { TCreateTableSqlStatement ctSql=(TCreateTableSqlStatement)stmt; CreateParser parser=new CreateParser(ctSql,parserContext); parser.parse(); return parser.getParseResult(); } public List parseSelect(TCustomSqlStatement stmt) { TSelectSqlStatement selectSqlStatement = (TSelectSqlStatement) stmt; SelectParser parser=new SelectParser(selectSqlStatement,parserContext); parser.parse(); return parser.getParseResult(); } }