001package gudusoft.gsqlparser.analyzer.v2; 002 003import gudusoft.gsqlparser.EDbVendor; 004import gudusoft.gsqlparser.TGSqlParser; 005import gudusoft.gsqlparser.ir.builder.IBoundIRBuilder; 006import gudusoft.gsqlparser.ir.builder.IRTranslator; 007import gudusoft.gsqlparser.analyzer.v2.callgraph.CallGraph; 008import gudusoft.gsqlparser.ir.bound.BoundProgram; 009 010import java.util.List; 011 012/** 013 * Main entry point for the IR-based Analyzer v2. 014 * <p> 015 * Provides high-level APIs for analyzing SQL/PL/SQL text and producing 016 * structured analysis results (call graphs, impact analysis, lineage). 017 * <p> 018 * Phase A: Parses SQL and produces BoundProgram with routine/object/column refs. 019 * Phase B: Adds CallGraph and impact analysis. 020 * Phase C: Adds CFG/DFG and legacy diff. 021 */ 022public class AnalyzerV2Facade { 023 024 private final IBoundIRBuilder boundBuilder; 025 026 public AnalyzerV2Facade(IBoundIRBuilder boundBuilder) { 027 this.boundBuilder = boundBuilder; 028 } 029 030 /** 031 * Analyzes the given SQL/PL/SQL text and returns the analysis result. 032 * 033 * @param sqlText SQL or PL/SQL text to analyze 034 * @param vendor database vendor 035 * @param config analyzer configuration 036 * @return analysis result 037 */ 038 public AnalysisResult analyze(String sqlText, EDbVendor vendor, AnalyzerV2Config config) { 039 // Gate IR construction behind useIRPath flag 040 if (config != null && !config.useIRPath) { 041 return new AnalysisResult(new IRProgram(new BoundProgram())); 042 } 043 044 TGSqlParser parser = new TGSqlParser(vendor); 045 parser.sqltext = sqlText; 046 int result = parser.parse(); 047 if (result != 0) { 048 // Return empty result on parse failure 049 return new AnalysisResult(new IRProgram(new BoundProgram())); 050 } 051 052 IRTranslator translator = new IRTranslator(config, boundBuilder); 053 IRProgram irProgram = translator.translate(parser.sqlstatements); 054 055 // Build CallGraph from BoundProgram 056 CallGraph callGraph = CallGraph.buildFrom(irProgram.getBoundProgram()); 057 AnalysisResult analysisResult = new AnalysisResult(irProgram, callGraph); 058 analysisResult.setConfig(config); 059 return analysisResult; 060 } 061 062 /** 063 * Analyzes multiple SQL/PL/SQL files. 064 * 065 * @param sqlTexts list of SQL texts (one per file) 066 * @param vendor database vendor 067 * @param config analyzer configuration 068 * @return analysis result combining all files 069 */ 070 public AnalysisResult analyzeMultiple(List<String> sqlTexts, EDbVendor vendor, AnalyzerV2Config config) { 071 // Phase A: analyze each text independently and merge bound programs 072 BoundProgram mergedProgram = new BoundProgram(); 073 074 for (String sqlText : sqlTexts) { 075 TGSqlParser parser = new TGSqlParser(vendor); 076 parser.sqltext = sqlText; 077 int result = parser.parse(); 078 if (result != 0) { 079 continue; 080 } 081 082 BoundProgram partial = boundBuilder.build(parser.sqlstatements, config); 083 mergeBoundPrograms(mergedProgram, partial); 084 } 085 086 CallGraph callGraph = CallGraph.buildFrom(mergedProgram); 087 return new AnalysisResult(new IRProgram(mergedProgram), callGraph); 088 } 089 090 private void mergeBoundPrograms(BoundProgram target, BoundProgram source) { 091 for (gudusoft.gsqlparser.ir.bound.BoundScope scope : source.getScopes()) { 092 target.addScope(scope); 093 } 094 for (java.util.Map.Entry<String, gudusoft.gsqlparser.ir.bound.BoundRoutineSymbol> entry 095 : source.getRoutineIndex().entrySet()) { 096 target.registerRoutine(entry.getValue()); 097 } 098 for (gudusoft.gsqlparser.ir.bound.BoundObjectRef ref : source.getAllObjectRefs()) { 099 target.addObjectRef(ref); 100 } 101 for (gudusoft.gsqlparser.ir.bound.BoundColumnRef ref : source.getAllColumnRefs()) { 102 target.addColumnRef(ref); 103 } 104 for (gudusoft.gsqlparser.ir.bound.BoundRoutineRef ref : source.getAllRoutineRefs()) { 105 target.addRoutineRef(ref); 106 } 107 } 108}