001package gudusoft.gsqlparser.ir.builder.postgresql; 002 003import gudusoft.gsqlparser.TCustomSqlStatement; 004import gudusoft.gsqlparser.TStatementList; 005import gudusoft.gsqlparser.analyzer.v2.AnalyzerV2Config; 006import gudusoft.gsqlparser.ir.bound.BoundProgram; 007import gudusoft.gsqlparser.ir.bound.BoundScope; 008import gudusoft.gsqlparser.ir.bound.EScopeKind; 009import gudusoft.gsqlparser.ir.builder.IBoundIRBuilder; 010 011import java.util.Arrays; 012import java.util.List; 013 014/** 015 * PostgreSQL PL/pgSQL implementation of {@link IBoundIRBuilder}. 016 * <p> 017 * Orchestrates three internal phases: 018 * <ol> 019 * <li>Create global scope</li> 020 * <li>Run {@link PostgresqlSymbolCollector} (visitor) to extract 021 * routines, variables, table refs, and call refs</li> 022 * <li>Run {@link PostgresqlRoutineRefResolver} with search_path 023 * to match refs to symbols</li> 024 * </ol> 025 */ 026public class PostgresqlBoundIRBuilder implements IBoundIRBuilder { 027 028 private final List<String> searchPath; 029 030 public PostgresqlBoundIRBuilder() { 031 this(Arrays.asList("public")); 032 } 033 034 public PostgresqlBoundIRBuilder(List<String> searchPath) { 035 this.searchPath = searchPath; 036 } 037 038 @Override 039 public BoundProgram build(TStatementList stmts, AnalyzerV2Config config) { 040 return build(stmts, config, ""); 041 } 042 043 public BoundProgram build(TStatementList stmts, AnalyzerV2Config config, String fileId) { 044 BoundProgram program = new BoundProgram(); 045 046 BoundScope globalScope = new BoundScope(EScopeKind.GLOBAL, null, null); 047 program.addScope(globalScope); 048 049 if (stmts == null || stmts.size() == 0) { 050 return program; 051 } 052 053 // Phase 2: Walk AST 054 PostgresqlSymbolCollector collector = 055 new PostgresqlSymbolCollector(program, globalScope, config, fileId, searchPath); 056 for (int i = 0; i < stmts.size(); i++) { 057 TCustomSqlStatement stmt = stmts.get(i); 058 if (stmt != null) { 059 stmt.acceptChildren(collector); 060 } 061 } 062 063 // Phase 3: Resolve routine references 064 PostgresqlRoutineRefResolver resolver = new PostgresqlRoutineRefResolver(searchPath); 065 resolver.resolve(program); 066 067 return program; 068 } 069}