001package gudusoft.gsqlparser.resolver;
002
003import gudusoft.gsqlparser.TBaseType;
004import gudusoft.gsqlparser.TLog;
005import gudusoft.gsqlparser.TStatementList;
006import gudusoft.gsqlparser.compiler.TContext;
007
008/**
009 * TSQLResolver handles all semantic analysis and resolution steps for SQL statements.
010 * This class consolidates various resolution algorithms to provide a clear, maintainable
011 * structure for SQL semantic analysis.
012 *
013 * 涉及的重要 类有:
014 * @see gudusoft.gsqlparser.TAttributeNode
015 */
016public class TSQLResolver {
017    private final TContext globalContext;
018    private final TStatementList sqlStatements;
019   // private final TLog logger;
020   private int iterationCount;
021   private int newColumnsLastIteration;
022
023    /**
024     * Creates a new SQL resolver instance.
025     * 
026     * @param context The global context containing SQL environment and scope information
027     * @param statements List of SQL statements to analyze
028     */
029    public TSQLResolver(TContext context, TStatementList statements) {
030        this.globalContext = context;
031        this.sqlStatements = statements;
032       // this.logger = new TLog();
033       this.iterationCount = 0;
034       this.newColumnsLastIteration = 0;
035    }
036
037    /**
038     * Performs complete semantic analysis of SQL statements.
039     * Executes all resolution steps in the correct order.
040     * 
041     * @return true if resolution completes successfully, false if errors occurred
042     */
043    public boolean resolve() {
044        TLog.clearLogs();
045        if (!TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){
046            TLog.disableLog();
047        }else{
048            TLog.enableAllLevelLog();
049        }
050
051        try {
052            collectMetadata();
053            resolveDatabaseObjects();
054
055            do {
056                iterationCount++;
057                newColumnsLastIteration = 0;
058
059                if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){
060                    TBaseType.log(String.format("Starting resolve relationships in iteration %d", iterationCount), TLog.DEBUG);
061                }
062                resolveRelationships();  // 更新表属性
063                if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){
064                    TBaseType.log(String.format("Starting expand star columns in iteration %d", iterationCount), TLog.DEBUG);
065                }
066                expandStarColumns();     // 展开星号列
067                if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){
068                    TBaseType.log(String.format("Starting resolve attributes in iteration %d", iterationCount), TLog.DEBUG);
069                }
070                resolveAttributes();     // 先收集列引用
071                if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){
072                    TBaseType.log(String.format("Starting resolve star columns in iteration %d", iterationCount), TLog.DEBUG);
073                }
074
075                resolveStarColumns();    // 推送星号列
076
077                if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){
078                    TBaseType.log(String.format("Iteration %d: %d new columns inferred", iterationCount, newColumnsLastIteration), TLog.DEBUG);
079                }
080            } while (newColumnsLastIteration > 0 && iterationCount < 10);
081            
082        } catch (Exception e) {
083            TBaseType.log("Exception raised in TSQLResolver.resolve(): " + e.getMessage(), TLog.ERROR);
084            throw e;
085        }
086
087
088       if (TBaseType.DUMP_RESOLVER_LOG_TO_CONSOLE){
089           TBaseType.dumpLogs(false);
090       }
091        return true;
092    }
093
094    /**
095     * Collects metadata from DDL statements like CREATE TABLE, CREATE VIEW, etc.
096     * Uses TMetadataCollector to build the metadata repository.
097     */
098    private void collectMetadata() {
099        TMetadataCollector collector = new TMetadataCollector(sqlStatements, globalContext);
100        collector.collect();
101    }
102
103    /**
104     * Resolves database objects by linking references to their definitions.
105     * Handles table names, view names, and other database objects.
106     */
107    private void resolveDatabaseObjects() {
108        TDatabaseObjectResolver resolver = new TDatabaseObjectResolver(sqlStatements,globalContext);
109        resolver.resolve();
110    }
111
112    /**
113     * Resolves relationships between database objects.
114     * This includes JOIN conditions, foreign key relationships, etc.
115     */
116    private void resolveRelationships() {
117        new TRelationResolver(sqlStatements, globalContext, this).resolve();
118    }
119
120    /**
121     * Resolves relationships between database objects.
122     * This includes JOIN conditions, foreign key relationships, etc.
123     */
124    private void resolveRelationships2() {
125        TRelationResolver2 resolver = new TRelationResolver2(sqlStatements,globalContext);
126        resolver.resolve();
127    }
128
129    /**
130     * Expands star columns (*) and processes subqueries.
131     * Converts * to explicit column lists and handles subquery resolution.
132     */
133    private void expandStarColumns() {
134        new TStarColumnExpander(sqlStatements, globalContext,this).resolve();
135    }
136
137    /**
138     * Resolves column attributes including data types, constraints, etc.
139     */
140    private void resolveAttributes() {
141        new TAttributeResolver(sqlStatements, globalContext, this).resolve();
142    }
143
144    /**
145     * Performs final resolution of star columns after all other resolutions.
146     * This handles any remaining star column cases that depend on previous steps.
147     */
148    private void resolveStarColumns() {
149        TStarColumnPushDownResolver starColumnPushDownResolver = new TStarColumnPushDownResolver(sqlStatements,globalContext);
150        starColumnPushDownResolver.resolve();
151    }
152
153    public void reportNewColumns(int count) {
154        newColumnsLastIteration += count;
155    }    
156
157    /**
158     * Gets the log containing resolution messages and errors.
159     * 
160     * @return The resolution log
161     */
162    // public TLog getLog() {
163    //     return logger;
164    // }
165}