@@ -40,26 +40,91 @@ def get_conditions_by_type(self, field_type: str) -> list[Condition]:
4040
4141class Analyzer :
4242 """Analyzes parsed SQL queries with schema context."""
43-
43+
4444 def __init__ (self , schemas : dict [str , dict [str , str ]]):
4545 """Initialize analyzer with schema registry data.
46-
46+
4747 Args:
4848 schemas: Dict mapping index names to field->type dicts.
4949 """
5050 self ._schemas = schemas
51-
51+
5252 def analyze (self , parsed : ParsedQuery ) -> AnalyzedQuery :
5353 """Analyze a parsed query, resolving field types.
54-
54+
5555 Args:
5656 parsed: The parsed SQL query.
57-
57+
5858 Returns:
5959 An AnalyzedQuery with field types resolved.
60-
60+
6161 Raises:
6262 ValueError: If the index or a field is unknown.
6363 """
64- raise NotImplementedError ("Analyzer.analyze is not yet implemented" )
64+ # Validate index exists
65+ if parsed .index not in self ._schemas :
66+ raise ValueError (f"Unknown index: { parsed .index } " )
67+
68+ schema = self ._schemas [parsed .index ]
69+ result = AnalyzedQuery (parsed = parsed )
70+
71+ # Collect all fields referenced in the query
72+ referenced_fields : set [str ] = set ()
73+
74+ # Fields from SELECT
75+ for field_name in parsed .fields :
76+ if field_name != "*" :
77+ referenced_fields .add (field_name )
78+
79+ # Fields from conditions
80+ for condition in parsed .conditions :
81+ referenced_fields .add (condition .field )
82+
83+ # Fields from aggregations
84+ for agg in parsed .aggregations :
85+ if agg .field :
86+ referenced_fields .add (agg .field )
87+
88+ # Fields from computed fields (extract field references from expressions)
89+ for computed in parsed .computed_fields :
90+ # Simple extraction - look for field names in the expression
91+ for field_name in schema .keys ():
92+ if field_name in computed .expression :
93+ referenced_fields .add (field_name )
94+
95+ # Fields from vector search
96+ if parsed .vector_search :
97+ referenced_fields .add (parsed .vector_search .field )
98+
99+ # Fields from GROUP BY
100+ for field_name in parsed .groupby_fields :
101+ referenced_fields .add (field_name )
102+
103+ # Resolve field types
104+ for field_name in referenced_fields :
105+ if field_name not in schema :
106+ raise ValueError (f"Unknown field: { field_name } " )
107+ result .field_types [field_name ] = schema [field_name ]
108+
109+ # Copy aggregations and computed fields
110+ result .aggregations = parsed .aggregations
111+ result .computed_fields = parsed .computed_fields
112+ result .groupby_fields = parsed .groupby_fields
113+
114+ # Determine if this is a global aggregation
115+ result .is_global_aggregation = (
116+ len (parsed .aggregations ) > 0 and len (parsed .groupby_fields ) == 0
117+ )
118+
119+ # Analyze vector search
120+ if parsed .vector_search :
121+ result .vector_search = VectorSearchAnalysis (
122+ field = parsed .vector_search .field ,
123+ k = parsed .limit or parsed .vector_search .k or 10 ,
124+ alias = parsed .vector_search .alias ,
125+ )
126+ # Has prefilter if there are conditions
127+ result .has_prefilter = len (parsed .conditions ) > 0
128+
129+ return result
65130
0 commit comments