001package gudusoft.gsqlparser.resolver2.namespace; 002 003import gudusoft.gsqlparser.nodes.TTable; 004import gudusoft.gsqlparser.resolver2.ColumnLevel; 005import gudusoft.gsqlparser.resolver2.model.ColumnSource; 006import gudusoft.gsqlparser.resolver2.model.FieldPath; 007import gudusoft.gsqlparser.stmt.TSelectSqlStatement; 008 009import java.util.List; 010import java.util.Map; 011import java.util.Set; 012 013/** 014 * Represents a namespace that exposes columns. 015 * A namespace can be a table, subquery, CTE, etc. 016 * 017 * Key responsibilities: 018 * 1. Provide column existence checks (hasColumn) 019 * 2. Resolve column names to ColumnSource 020 * 3. Support SELECT * expansion 021 * 4. Track data lineage (getFinalTable) 022 * 023 * Design based on Apache Calcite's SqlValidatorNamespace 024 */ 025public interface INamespace { 026 027 /** 028 * Get a display name for this namespace (for debugging/error messages) 029 */ 030 String getDisplayName(); 031 032 /** 033 * Check if a column exists in this namespace. 034 * Returns a three-level answer: EXISTS, MAYBE, NOT_EXISTS 035 * 036 * @param columnName Column name to check 037 * @return Column existence level 038 */ 039 ColumnLevel hasColumn(String columnName); 040 041 /** 042 * Resolve a column name to its source. 043 * 044 * @param columnName Column name to resolve 045 * @return ColumnSource if found, null otherwise 046 */ 047 ColumnSource resolveColumn(String columnName); 048 049 /** 050 * Resolve a column path (column.field.subfield...) to its source. 051 * 052 * <p>This method supports deep/record field access patterns like 053 * {@code customer.address.city} where:</p> 054 * <ul> 055 * <li>path[0] is the base column name (e.g., "customer")</li> 056 * <li>path[1..n] are field paths (e.g., ["address", "city"])</li> 057 * </ul> 058 * 059 * @param path The column path segments 060 * @return ColumnSource with fieldPath set, or null if base column not found 061 */ 062 default ColumnSource resolveColumnPath(List<String> path) { 063 if (path == null || path.isEmpty()) { 064 return null; 065 } 066 067 // Single segment: simple column resolution 068 if (path.size() == 1) { 069 return resolveColumn(path.get(0)); 070 } 071 072 // Multiple segments: resolve base column and attach fieldPath 073 String baseColumnName = path.get(0); 074 ColumnSource baseSource = resolveColumn(baseColumnName); 075 if (baseSource == null) { 076 return null; 077 } 078 079 // Attach field path (segments beyond base column) 080 List<String> fieldSegments = path.subList(1, path.size()); 081 return baseSource.withFieldPath(FieldPath.of(fieldSegments), "struct_field_access"); 082 } 083 084 /** 085 * Get all column sources exposed by this namespace. 086 * Used for SELECT * expansion and smart completion. 087 * 088 * @return Map of column name -> ColumnSource 089 */ 090 Map<String, ColumnSource> getAllColumnSources(); 091 092 /** 093 * Get the final physical table this namespace represents. 094 * For tables: returns the table itself 095 * For subqueries/CTEs: recursively traces back to physical table(s) 096 * 097 * @return Physical table, or null if not determinable 098 */ 099 TTable getFinalTable(); 100 101 /** 102 * Get all final physical tables this namespace depends on. 103 * For simple table namespace: returns single table 104 * For subquery/CTE: returns all tables in the query tree 105 * 106 * @return List of all physical tables 107 */ 108 List<TTable> getAllFinalTables(); 109 110 /** 111 * Check if this namespace is validated/resolved. 112 * Some namespaces require resolution before they can provide column info. 113 * 114 * @return true if validated 115 */ 116 boolean isValidated(); 117 118 /** 119 * Validate/resolve this namespace. 120 * For subqueries: resolve the SELECT list 121 * For tables: load metadata if needed 122 */ 123 void validate(); 124 125 /** 126 * Get the associated AST node (TTable, TSelectSqlStatement, etc.) 127 * 128 * @return AST node, or null if not applicable 129 */ 130 Object getNode(); 131 132 // ========== Star Column Inference Support ========== 133 134 /** 135 * Get the underlying SELECT statement for this namespace. 136 * For CTENamespace: returns the CTE's subquery 137 * For SubqueryNamespace: returns the subquery 138 * For TableNamespace: returns null 139 * 140 * @return the SELECT statement, or null if not applicable 141 */ 142 default TSelectSqlStatement getSelectStatement() { 143 return null; 144 } 145 146 /** 147 * Check if this namespace contains a star column (SELECT *). 148 * Used to identify namespaces that may need star column inference. 149 * 150 * @return true if the namespace has SELECT *, false otherwise 151 */ 152 default boolean hasStarColumn() { 153 return false; 154 } 155 156 /** 157 * Add an inferred column to this namespace. 158 * Used by star column push-down to add columns discovered from outer queries. 159 * 160 * @param columnName the column name to add 161 * @param confidence the confidence score (0.0 to 1.0) 162 * @param evidence description of why this column was inferred 163 * @return true if the column was added, false if already exists 164 */ 165 default boolean addInferredColumn(String columnName, double confidence, String evidence) { 166 // Default implementation does nothing - override in subclasses that support inference 167 return false; 168 } 169 170 /** 171 * Get all columns that were inferred (not from SELECT list directly). 172 * These are columns discovered through star column push-down. 173 * 174 * @return set of inferred column names, empty if none 175 */ 176 default Set<String> getInferredColumns() { 177 return java.util.Collections.emptySet(); 178 } 179 180 /** 181 * Check if this namespace supports dynamic column inference. 182 * DynamicStarSource and similar namespaces return true. 183 * 184 * @return true if this namespace can have columns added dynamically 185 */ 186 default boolean supportsDynamicInference() { 187 return false; 188 } 189 190 /** 191 * Get the star column (SELECT *) from this namespace if one exists. 192 * Used to track the sourceColumn for columns inferred from a star. 193 * 194 * @return The star column TResultColumn, or null if no star column exists 195 */ 196 default gudusoft.gsqlparser.nodes.TResultColumn getStarColumn() { 197 return null; 198 } 199 200 // ========== Legacy Compatibility Support ========== 201 202 /** 203 * Get the TTable that this namespace is associated with. 204 * Used for legacy sync to set TObjectName.sourceTable. 205 * 206 * For TableNamespace: returns the table itself 207 * For SubqueryNamespace: returns the TTable wrapping the subquery 208 * For CTENamespace: returns the CTE referencing table 209 * For others: returns null 210 * 211 * @return The source TTable, or null if not applicable 212 */ 213 default TTable getSourceTable() { 214 return null; 215 } 216}