Skip to main content

polyglot_sql/optimizer/
annotate_types.rs

1//! Type Annotation for SQL Expressions
2//!
3//! This module provides type inference and annotation for SQL AST nodes.
4//! It walks the expression tree and assigns data types to expressions based on:
5//! - Literal values (strings, numbers, booleans)
6//! - Column references (from schema)
7//! - Function return types
8//! - Operator result types (with coercion rules)
9//!
10//! Based on SQLGlot's optimizer/annotate_types.py
11
12use std::collections::{HashMap, HashSet};
13
14use crate::dialects::DialectType;
15use crate::expressions::{
16    BinaryOp, DataType, Expression, Function, IfFunc, ListAggOverflow, Literal, Map, Nvl2Func,
17    Struct, StructField, Subscript,
18};
19use crate::schema::{normalize_name, Schema, SchemaError, SchemaResult, TABLE_PARTS};
20
21/// Type coercion class for determining result types in binary operations.
22/// Higher-priority classes win during coercion.
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
24pub enum TypeCoercionClass {
25    /// Text types (CHAR, VARCHAR, TEXT)
26    Text = 0,
27    /// Numeric types (INT, FLOAT, DECIMAL, etc.)
28    Numeric = 1,
29    /// Time-like types (DATE, TIME, TIMESTAMP, INTERVAL)
30    Timelike = 2,
31}
32
33impl TypeCoercionClass {
34    /// Get the coercion class for a data type
35    pub fn from_data_type(dt: &DataType) -> Option<Self> {
36        match dt {
37            // Text types
38            DataType::Char { .. }
39            | DataType::VarChar { .. }
40            | DataType::Text
41            | DataType::Binary { .. }
42            | DataType::VarBinary { .. }
43            | DataType::Blob => Some(TypeCoercionClass::Text),
44
45            // Numeric types
46            DataType::Boolean
47            | DataType::TinyInt { .. }
48            | DataType::SmallInt { .. }
49            | DataType::Int { .. }
50            | DataType::BigInt { .. }
51            | DataType::Float { .. }
52            | DataType::Double { .. }
53            | DataType::Decimal { .. } => Some(TypeCoercionClass::Numeric),
54
55            // Timelike types
56            DataType::Date
57            | DataType::Time { .. }
58            | DataType::Timestamp { .. }
59            | DataType::Interval { .. } => Some(TypeCoercionClass::Timelike),
60
61            // Other types don't have a coercion class
62            _ => None,
63        }
64    }
65}
66
67/// Type annotation configuration and state
68pub struct TypeAnnotator<'a> {
69    /// Schema for looking up column types
70    _schema: Option<&'a dyn Schema>,
71    /// Dialect for dialect-specific type rules
72    _dialect: Option<DialectType>,
73    /// Whether to annotate types for all expressions
74    annotate_aggregates: bool,
75    /// Function return type mappings
76    function_return_types: HashMap<String, DataType>,
77}
78
79impl<'a> TypeAnnotator<'a> {
80    /// Create a new type annotator
81    pub fn new(schema: Option<&'a dyn Schema>, dialect: Option<DialectType>) -> Self {
82        let mut annotator = Self {
83            _schema: schema,
84            _dialect: dialect,
85            annotate_aggregates: true,
86            function_return_types: HashMap::new(),
87        };
88        annotator.init_function_return_types();
89        annotator
90    }
91
92    /// Initialize function return type mappings
93    fn init_function_return_types(&mut self) {
94        // Aggregate functions
95        self.function_return_types
96            .insert("COUNT".to_string(), DataType::BigInt { length: None });
97        self.function_return_types.insert(
98            "SUM".to_string(),
99            DataType::Decimal {
100                precision: None,
101                scale: None,
102            },
103        );
104        self.function_return_types.insert(
105            "AVG".to_string(),
106            DataType::Double {
107                precision: None,
108                scale: None,
109            },
110        );
111
112        // String functions
113        self.function_return_types.insert(
114            "CONCAT".to_string(),
115            DataType::VarChar {
116                length: None,
117                parenthesized_length: false,
118            },
119        );
120        self.function_return_types.insert(
121            "UPPER".to_string(),
122            DataType::VarChar {
123                length: None,
124                parenthesized_length: false,
125            },
126        );
127        self.function_return_types.insert(
128            "LOWER".to_string(),
129            DataType::VarChar {
130                length: None,
131                parenthesized_length: false,
132            },
133        );
134        self.function_return_types.insert(
135            "TRIM".to_string(),
136            DataType::VarChar {
137                length: None,
138                parenthesized_length: false,
139            },
140        );
141        self.function_return_types.insert(
142            "LTRIM".to_string(),
143            DataType::VarChar {
144                length: None,
145                parenthesized_length: false,
146            },
147        );
148        self.function_return_types.insert(
149            "RTRIM".to_string(),
150            DataType::VarChar {
151                length: None,
152                parenthesized_length: false,
153            },
154        );
155        self.function_return_types.insert(
156            "SUBSTRING".to_string(),
157            DataType::VarChar {
158                length: None,
159                parenthesized_length: false,
160            },
161        );
162        self.function_return_types.insert(
163            "SUBSTR".to_string(),
164            DataType::VarChar {
165                length: None,
166                parenthesized_length: false,
167            },
168        );
169        self.function_return_types.insert(
170            "REPLACE".to_string(),
171            DataType::VarChar {
172                length: None,
173                parenthesized_length: false,
174            },
175        );
176        self.function_return_types.insert(
177            "LENGTH".to_string(),
178            DataType::Int {
179                length: None,
180                integer_spelling: false,
181            },
182        );
183        self.function_return_types.insert(
184            "CHAR_LENGTH".to_string(),
185            DataType::Int {
186                length: None,
187                integer_spelling: false,
188            },
189        );
190
191        // Date/Time functions
192        self.function_return_types.insert(
193            "NOW".to_string(),
194            DataType::Timestamp {
195                precision: None,
196                timezone: false,
197            },
198        );
199        self.function_return_types.insert(
200            "CURRENT_TIMESTAMP".to_string(),
201            DataType::Timestamp {
202                precision: None,
203                timezone: false,
204            },
205        );
206        self.function_return_types
207            .insert("CURRENT_DATE".to_string(), DataType::Date);
208        self.function_return_types.insert(
209            "CURRENT_TIME".to_string(),
210            DataType::Time {
211                precision: None,
212                timezone: false,
213            },
214        );
215        self.function_return_types
216            .insert("DATE".to_string(), DataType::Date);
217        self.function_return_types.insert(
218            "YEAR".to_string(),
219            DataType::Int {
220                length: None,
221                integer_spelling: false,
222            },
223        );
224        self.function_return_types.insert(
225            "MONTH".to_string(),
226            DataType::Int {
227                length: None,
228                integer_spelling: false,
229            },
230        );
231        self.function_return_types.insert(
232            "DAY".to_string(),
233            DataType::Int {
234                length: None,
235                integer_spelling: false,
236            },
237        );
238        self.function_return_types.insert(
239            "HOUR".to_string(),
240            DataType::Int {
241                length: None,
242                integer_spelling: false,
243            },
244        );
245        self.function_return_types.insert(
246            "MINUTE".to_string(),
247            DataType::Int {
248                length: None,
249                integer_spelling: false,
250            },
251        );
252        self.function_return_types.insert(
253            "SECOND".to_string(),
254            DataType::Int {
255                length: None,
256                integer_spelling: false,
257            },
258        );
259        self.function_return_types.insert(
260            "EXTRACT".to_string(),
261            DataType::Int {
262                length: None,
263                integer_spelling: false,
264            },
265        );
266        self.function_return_types.insert(
267            "DATE_DIFF".to_string(),
268            DataType::Int {
269                length: None,
270                integer_spelling: false,
271            },
272        );
273        self.function_return_types.insert(
274            "DATEDIFF".to_string(),
275            DataType::Int {
276                length: None,
277                integer_spelling: false,
278            },
279        );
280
281        // Math functions
282        self.function_return_types.insert(
283            "ABS".to_string(),
284            DataType::Double {
285                precision: None,
286                scale: None,
287            },
288        );
289        self.function_return_types.insert(
290            "ROUND".to_string(),
291            DataType::Double {
292                precision: None,
293                scale: None,
294            },
295        );
296        self.function_return_types.insert(
297            "DATE_FORMAT".to_string(),
298            DataType::VarChar {
299                length: None,
300                parenthesized_length: false,
301            },
302        );
303        self.function_return_types.insert(
304            "FORMAT_DATE".to_string(),
305            DataType::VarChar {
306                length: None,
307                parenthesized_length: false,
308            },
309        );
310        self.function_return_types.insert(
311            "TIME_TO_STR".to_string(),
312            DataType::VarChar {
313                length: None,
314                parenthesized_length: false,
315            },
316        );
317        self.function_return_types.insert(
318            "SQRT".to_string(),
319            DataType::Double {
320                precision: None,
321                scale: None,
322            },
323        );
324        self.function_return_types.insert(
325            "POWER".to_string(),
326            DataType::Double {
327                precision: None,
328                scale: None,
329            },
330        );
331        self.function_return_types.insert(
332            "MOD".to_string(),
333            DataType::Int {
334                length: None,
335                integer_spelling: false,
336            },
337        );
338        self.function_return_types.insert(
339            "LOG".to_string(),
340            DataType::Double {
341                precision: None,
342                scale: None,
343            },
344        );
345        self.function_return_types.insert(
346            "LN".to_string(),
347            DataType::Double {
348                precision: None,
349                scale: None,
350            },
351        );
352        self.function_return_types.insert(
353            "EXP".to_string(),
354            DataType::Double {
355                precision: None,
356                scale: None,
357            },
358        );
359
360        // Null-handling functions return Unknown (infer from args)
361        self.function_return_types
362            .insert("COALESCE".to_string(), DataType::Unknown);
363        self.function_return_types
364            .insert("NULLIF".to_string(), DataType::Unknown);
365        self.function_return_types
366            .insert("GREATEST".to_string(), DataType::Unknown);
367        self.function_return_types
368            .insert("LEAST".to_string(), DataType::Unknown);
369    }
370
371    /// Annotate types for an expression tree
372    pub fn annotate(&mut self, expr: &Expression) -> Option<DataType> {
373        match expr {
374            // Literals
375            Expression::Literal(lit) => self.annotate_literal(lit),
376            Expression::Boolean(_) => Some(DataType::Boolean),
377            Expression::Null(_) => None, // NULL has no type
378
379            // Arithmetic binary operations
380            Expression::Add(op)
381            | Expression::Sub(op)
382            | Expression::Mul(op)
383            | Expression::Div(op)
384            | Expression::Mod(op) => self.annotate_arithmetic(op),
385
386            // Comparison operations - always boolean
387            Expression::Eq(_)
388            | Expression::Neq(_)
389            | Expression::Lt(_)
390            | Expression::Lte(_)
391            | Expression::Gt(_)
392            | Expression::Gte(_)
393            | Expression::Like(_)
394            | Expression::ILike(_) => Some(DataType::Boolean),
395
396            // Logical operations - always boolean
397            Expression::And(_) | Expression::Or(_) | Expression::Not(_) => Some(DataType::Boolean),
398
399            // Predicates - always boolean
400            Expression::Between(_)
401            | Expression::In(_)
402            | Expression::IsNull(_)
403            | Expression::IsTrue(_)
404            | Expression::IsFalse(_)
405            | Expression::Is(_)
406            | Expression::Exists(_) => Some(DataType::Boolean),
407
408            // String concatenation
409            Expression::Concat(_) => Some(DataType::VarChar {
410                length: None,
411                parenthesized_length: false,
412            }),
413
414            // Bitwise operations - integer
415            Expression::BitwiseAnd(_)
416            | Expression::BitwiseOr(_)
417            | Expression::BitwiseXor(_)
418            | Expression::BitwiseNot(_) => Some(DataType::BigInt { length: None }),
419
420            // Negation preserves type
421            Expression::Neg(op) => self.annotate(&op.this),
422
423            // Functions
424            Expression::Function(func) => self.annotate_function(func),
425            Expression::IfFunc(if_func) => self.annotate_if_func(if_func),
426            Expression::Nvl2(nvl2) => self.annotate_nvl2(nvl2),
427
428            // Typed aggregate functions
429            Expression::Count(_) => Some(DataType::BigInt { length: None }),
430            Expression::Sum(agg) => self.annotate_sum(&agg.this),
431            Expression::SumIf(f) => self.annotate_sum(&f.this),
432            Expression::Avg(_) => Some(DataType::Double {
433                precision: None,
434                scale: None,
435            }),
436            Expression::Min(agg) => self.annotate(&agg.this),
437            Expression::Max(agg) => self.annotate(&agg.this),
438            Expression::GroupConcat(_) | Expression::StringAgg(_) | Expression::ListAgg(_) => {
439                Some(DataType::VarChar {
440                    length: None,
441                    parenthesized_length: false,
442                })
443            }
444
445            // Generic aggregate function
446            Expression::AggregateFunction(agg) => {
447                if !self.annotate_aggregates {
448                    return None;
449                }
450                let func_name = agg.name.to_uppercase();
451                self.get_aggregate_return_type(&func_name, &agg.args)
452            }
453
454            // Column references - look up type from schema if available
455            Expression::Column(col) => {
456                if let Some(schema) = &self._schema {
457                    let table_name = col.table.as_ref().map(|t| t.name.as_str()).unwrap_or("");
458                    schema.get_column_type(table_name, &col.name.name).ok()
459                } else {
460                    None
461                }
462            }
463
464            // Cast expressions
465            Expression::Cast(cast) => Some(cast.to.clone()),
466            Expression::SafeCast(cast) => Some(cast.to.clone()),
467            Expression::TryCast(cast) => Some(cast.to.clone()),
468
469            // Subqueries - type is the type of the first SELECT expression
470            Expression::Subquery(subq) => {
471                if let Expression::Select(select) = &subq.this {
472                    if let Some(first) = select.expressions.first() {
473                        self.annotate(first)
474                    } else {
475                        None
476                    }
477                } else {
478                    None
479                }
480            }
481
482            // CASE expression - type of the first THEN/ELSE
483            Expression::Case(case) => {
484                if let Some(else_expr) = &case.else_ {
485                    self.annotate(else_expr)
486                } else if let Some((_, then_expr)) = case.whens.first() {
487                    self.annotate(then_expr)
488                } else {
489                    None
490                }
491            }
492
493            // Array expressions
494            Expression::Array(arr) => {
495                if let Some(first) = arr.expressions.first() {
496                    if let Some(elem_type) = self.annotate(first) {
497                        Some(DataType::Array {
498                            element_type: Box::new(elem_type),
499                            dimension: None,
500                        })
501                    } else {
502                        Some(DataType::Array {
503                            element_type: Box::new(DataType::Unknown),
504                            dimension: None,
505                        })
506                    }
507                } else {
508                    Some(DataType::Array {
509                        element_type: Box::new(DataType::Unknown),
510                        dimension: None,
511                    })
512                }
513            }
514
515            // Interval expressions
516            Expression::Interval(_) => Some(DataType::Interval {
517                unit: None,
518                to: None,
519            }),
520
521            // Window functions inherit type from their function
522            Expression::WindowFunction(window) => self.annotate(&window.this),
523
524            // Date/time expressions
525            Expression::CurrentDate(_) => Some(DataType::Date),
526            Expression::CurrentTime(_) => Some(DataType::Time {
527                precision: None,
528                timezone: false,
529            }),
530            Expression::CurrentTimestamp(_) | Expression::CurrentTimestampLTZ(_) => {
531                Some(DataType::Timestamp {
532                    precision: None,
533                    timezone: false,
534                })
535            }
536
537            // Date functions
538            Expression::DateAdd(_)
539            | Expression::DateSub(_)
540            | Expression::ToDate(_)
541            | Expression::Date(_) => Some(DataType::Date),
542            Expression::DateDiff(_) | Expression::Extract(_) => Some(DataType::Int {
543                length: None,
544                integer_spelling: false,
545            }),
546            Expression::ToTimestamp(_) => Some(DataType::Timestamp {
547                precision: None,
548                timezone: false,
549            }),
550
551            // String functions
552            Expression::Upper(_)
553            | Expression::Lower(_)
554            | Expression::Trim(_)
555            | Expression::LTrim(_)
556            | Expression::RTrim(_)
557            | Expression::Replace(_)
558            | Expression::Substring(_)
559            | Expression::Reverse(_)
560            | Expression::Left(_)
561            | Expression::Right(_)
562            | Expression::Repeat(_)
563            | Expression::Lpad(_)
564            | Expression::Rpad(_)
565            | Expression::ConcatWs(_)
566            | Expression::Overlay(_) => Some(DataType::VarChar {
567                length: None,
568                parenthesized_length: false,
569            }),
570            Expression::Length(_) => Some(DataType::Int {
571                length: None,
572                integer_spelling: false,
573            }),
574
575            // Math functions
576            Expression::Abs(_)
577            | Expression::Sqrt(_)
578            | Expression::Cbrt(_)
579            | Expression::Ln(_)
580            | Expression::Exp(_)
581            | Expression::Power(_)
582            | Expression::Log(_) => Some(DataType::Double {
583                precision: None,
584                scale: None,
585            }),
586            Expression::Round(_) => Some(DataType::Double {
587                precision: None,
588                scale: None,
589            }),
590            Expression::Floor(f) => self.annotate_math_function(&f.this),
591            Expression::Ceil(f) => self.annotate_math_function(&f.this),
592            Expression::Sign(s) => self.annotate(&s.this),
593            Expression::DateFormat(_) | Expression::FormatDate(_) | Expression::TimeToStr(_) => {
594                Some(DataType::VarChar {
595                    length: None,
596                    parenthesized_length: false,
597                })
598            }
599
600            // Greatest/Least - coerce argument types
601            Expression::Greatest(v) | Expression::Least(v) => self.coerce_arg_types(&v.expressions),
602
603            // Alias - type of the inner expression
604            Expression::Alias(alias) => self.annotate(&alias.this),
605
606            // SELECT expressions - no scalar type
607            Expression::Select(_) => None,
608
609            // ============================================
610            // 3.1.8: Array/Map Indexing (Subscript/Bracket)
611            // ============================================
612            Expression::Subscript(sub) => self.annotate_subscript(sub),
613
614            // Dot access (struct.field) - returns Unknown without schema
615            Expression::Dot(_) => None,
616
617            // ============================================
618            // 3.1.9: STRUCT Construction
619            // ============================================
620            Expression::Struct(s) => self.annotate_struct(s),
621
622            // ============================================
623            // 3.1.10: MAP Construction
624            // ============================================
625            Expression::Map(map) => self.annotate_map(map),
626            Expression::MapFromEntries(mfe) => {
627                // MAP_FROM_ENTRIES(array_of_pairs) - infer from array element type
628                if let Some(DataType::Array { element_type, .. }) = self.annotate(&mfe.this) {
629                    if let DataType::Struct { fields, .. } = *element_type {
630                        if fields.len() >= 2 {
631                            return Some(DataType::Map {
632                                key_type: Box::new(fields[0].data_type.clone()),
633                                value_type: Box::new(fields[1].data_type.clone()),
634                            });
635                        }
636                    }
637                }
638                Some(DataType::Map {
639                    key_type: Box::new(DataType::Unknown),
640                    value_type: Box::new(DataType::Unknown),
641                })
642            }
643
644            // ============================================
645            // 3.1.11: SetOperation Type Coercion
646            // ============================================
647            Expression::Union(union) => self.annotate_set_operation(&union.left, &union.right),
648            Expression::Intersect(intersect) => {
649                self.annotate_set_operation(&intersect.left, &intersect.right)
650            }
651            Expression::Except(except) => self.annotate_set_operation(&except.left, &except.right),
652
653            // ============================================
654            // 3.1.12: UDTF Type Handling
655            // ============================================
656            Expression::Lateral(lateral) => {
657                // LATERAL subquery - type is the subquery's type
658                self.annotate(&lateral.this)
659            }
660            Expression::LateralView(lv) => {
661                // LATERAL VIEW - returns the exploded type
662                self.annotate_lateral_view(lv)
663            }
664            Expression::Unnest(unnest) => {
665                // UNNEST(array) - returns the element type of the array
666                if let Some(DataType::Array { element_type, .. }) = self.annotate(&unnest.this) {
667                    Some(*element_type)
668                } else {
669                    None
670                }
671            }
672            Expression::Explode(explode) => {
673                // EXPLODE(array) - returns the element type
674                if let Some(DataType::Array { element_type, .. }) = self.annotate(&explode.this) {
675                    Some(*element_type)
676                } else if let Some(DataType::Map {
677                    key_type,
678                    value_type,
679                }) = self.annotate(&explode.this)
680                {
681                    // EXPLODE(map) returns struct(key, value)
682                    Some(DataType::Struct {
683                        fields: vec![
684                            StructField::new("key".to_string(), *key_type),
685                            StructField::new("value".to_string(), *value_type),
686                        ],
687                        nested: false,
688                    })
689                } else {
690                    None
691                }
692            }
693            Expression::ExplodeOuter(explode) => {
694                // EXPLODE_OUTER - same as EXPLODE but preserves nulls
695                if let Some(DataType::Array { element_type, .. }) = self.annotate(&explode.this) {
696                    Some(*element_type)
697                } else {
698                    None
699                }
700            }
701            Expression::GenerateSeries(gs) => {
702                // GENERATE_SERIES returns the type of start/end
703                if let Some(ref start) = gs.start {
704                    self.annotate(start)
705                } else if let Some(ref end) = gs.end {
706                    self.annotate(end)
707                } else {
708                    Some(DataType::Int {
709                        length: None,
710                        integer_spelling: false,
711                    })
712                }
713            }
714
715            // Other expressions - unknown
716            _ => None,
717        }
718    }
719
720    /// Annotate types in-place on the expression tree (bottom-up).
721    ///
722    /// First recurses into children, then computes this node's type using the
723    /// read-only `annotate` method, and finally stores the result via
724    /// `set_inferred_type`.
725    pub fn annotate_in_place(&mut self, expr: &mut Expression) {
726        // 1. Recurse into children (bottom-up)
727        self.annotate_children_in_place(expr);
728
729        // 2. Compute this node's type using the read-only method
730        //    (children already have their types set, but `annotate` re-derives
731        //    from structure, which is fine since the structure hasn't changed)
732        let dt = self.annotate(expr);
733
734        // 3. Store on the node
735        if let Some(data_type) = dt {
736            expr.set_inferred_type(data_type);
737        }
738    }
739
740    /// Recursively annotate children of an expression in-place.
741    fn annotate_children_in_place(&mut self, expr: &mut Expression) {
742        match expr {
743            // Binary operations
744            Expression::And(op)
745            | Expression::Or(op)
746            | Expression::Add(op)
747            | Expression::Sub(op)
748            | Expression::Mul(op)
749            | Expression::Div(op)
750            | Expression::Mod(op)
751            | Expression::Eq(op)
752            | Expression::Neq(op)
753            | Expression::Lt(op)
754            | Expression::Lte(op)
755            | Expression::Gt(op)
756            | Expression::Gte(op)
757            | Expression::Concat(op)
758            | Expression::BitwiseAnd(op)
759            | Expression::BitwiseOr(op)
760            | Expression::BitwiseXor(op)
761            | Expression::Adjacent(op)
762            | Expression::TsMatch(op)
763            | Expression::PropertyEQ(op)
764            | Expression::ArrayContainsAll(op)
765            | Expression::ArrayContainedBy(op)
766            | Expression::ArrayOverlaps(op)
767            | Expression::JSONBContainsAllTopKeys(op)
768            | Expression::JSONBContainsAnyTopKeys(op)
769            | Expression::JSONBDeleteAtPath(op)
770            | Expression::ExtendsLeft(op)
771            | Expression::ExtendsRight(op)
772            | Expression::Is(op)
773            | Expression::MemberOf(op)
774            | Expression::Match(op)
775            | Expression::NullSafeEq(op)
776            | Expression::NullSafeNeq(op)
777            | Expression::Glob(op)
778            | Expression::BitwiseLeftShift(op)
779            | Expression::BitwiseRightShift(op) => {
780                self.annotate_in_place(&mut op.left);
781                self.annotate_in_place(&mut op.right);
782            }
783
784            // Like operations
785            Expression::Like(op) | Expression::ILike(op) => {
786                self.annotate_in_place(&mut op.left);
787                self.annotate_in_place(&mut op.right);
788            }
789
790            // Unary operations
791            Expression::Not(op) | Expression::Neg(op) | Expression::BitwiseNot(op) => {
792                self.annotate_in_place(&mut op.this);
793            }
794
795            // Cast
796            Expression::Cast(c) | Expression::TryCast(c) | Expression::SafeCast(c) => {
797                self.annotate_in_place(&mut c.this);
798            }
799
800            // Case
801            Expression::Case(c) => {
802                if let Some(ref mut operand) = c.operand {
803                    self.annotate_in_place(operand);
804                }
805                for (cond, then_expr) in &mut c.whens {
806                    self.annotate_in_place(cond);
807                    self.annotate_in_place(then_expr);
808                }
809                if let Some(ref mut else_expr) = c.else_ {
810                    self.annotate_in_place(else_expr);
811                }
812            }
813
814            // Alias
815            Expression::Alias(a) => {
816                self.annotate_in_place(&mut a.this);
817            }
818
819            // Column - leaf node, no children to recurse
820            Expression::Column(_) => {}
821
822            // Function
823            Expression::Function(f) => {
824                for arg in &mut f.args {
825                    self.annotate_in_place(arg);
826                }
827            }
828            Expression::Unnest(unnest) => {
829                self.annotate_in_place(&mut unnest.this);
830                for expression in &mut unnest.expressions {
831                    self.annotate_in_place(expression);
832                }
833            }
834
835            // Dedicated conditional functions
836            Expression::IfFunc(f) => {
837                self.annotate_in_place(&mut f.condition);
838                self.annotate_in_place(&mut f.true_value);
839                if let Some(false_value) = &mut f.false_value {
840                    self.annotate_in_place(false_value);
841                }
842            }
843            Expression::Nvl2(f) => {
844                self.annotate_in_place(&mut f.this);
845                self.annotate_in_place(&mut f.true_value);
846                self.annotate_in_place(&mut f.false_value);
847            }
848
849            // AggregateFunction
850            Expression::AggregateFunction(f) => {
851                for arg in &mut f.args {
852                    self.annotate_in_place(arg);
853                }
854            }
855
856            // Dedicated aggregate / string functions
857            Expression::Count(f) => {
858                if let Some(this) = &mut f.this {
859                    self.annotate_in_place(this);
860                }
861                if let Some(filter) = &mut f.filter {
862                    self.annotate_in_place(filter);
863                }
864            }
865            Expression::GroupConcat(f) => {
866                self.annotate_in_place(&mut f.this);
867                if let Some(separator) = &mut f.separator {
868                    self.annotate_in_place(separator);
869                }
870                if let Some(order_by) = &mut f.order_by {
871                    for ordered in order_by {
872                        self.annotate_in_place(&mut ordered.this);
873                    }
874                }
875                if let Some(filter) = &mut f.filter {
876                    self.annotate_in_place(filter);
877                }
878            }
879            Expression::StringAgg(f) => {
880                self.annotate_in_place(&mut f.this);
881                if let Some(separator) = &mut f.separator {
882                    self.annotate_in_place(separator);
883                }
884                if let Some(order_by) = &mut f.order_by {
885                    for ordered in order_by {
886                        self.annotate_in_place(&mut ordered.this);
887                    }
888                }
889                if let Some(filter) = &mut f.filter {
890                    self.annotate_in_place(filter);
891                }
892                if let Some(limit) = &mut f.limit {
893                    self.annotate_in_place(limit);
894                }
895            }
896            Expression::ListAgg(f) => {
897                self.annotate_in_place(&mut f.this);
898                if let Some(separator) = &mut f.separator {
899                    self.annotate_in_place(separator);
900                }
901                if let Some(order_by) = &mut f.order_by {
902                    for ordered in order_by {
903                        self.annotate_in_place(&mut ordered.this);
904                    }
905                }
906                if let Some(filter) = &mut f.filter {
907                    self.annotate_in_place(filter);
908                }
909                if let Some(ListAggOverflow::Truncate {
910                    filler: Some(filler),
911                    ..
912                }) = &mut f.on_overflow
913                {
914                    self.annotate_in_place(filler);
915                }
916            }
917            Expression::SumIf(f) => {
918                self.annotate_in_place(&mut f.this);
919                self.annotate_in_place(&mut f.condition);
920                if let Some(filter) = &mut f.filter {
921                    self.annotate_in_place(filter);
922                }
923            }
924
925            // WindowFunction
926            Expression::WindowFunction(w) => {
927                self.annotate_in_place(&mut w.this);
928            }
929
930            // Subquery
931            Expression::Subquery(s) => {
932                self.annotate_in_place(&mut s.this);
933            }
934
935            // UnaryFunc variants
936            Expression::Upper(f)
937            | Expression::Lower(f)
938            | Expression::Length(f)
939            | Expression::LTrim(f)
940            | Expression::RTrim(f)
941            | Expression::Reverse(f)
942            | Expression::Abs(f)
943            | Expression::Sqrt(f)
944            | Expression::Cbrt(f)
945            | Expression::Ln(f)
946            | Expression::Exp(f)
947            | Expression::Sign(f)
948            | Expression::Date(f)
949            | Expression::Time(f)
950            | Expression::Explode(f)
951            | Expression::ExplodeOuter(f)
952            | Expression::MapFromEntries(f)
953            | Expression::MapKeys(f)
954            | Expression::MapValues(f)
955            | Expression::ArrayLength(f)
956            | Expression::ArraySize(f)
957            | Expression::Cardinality(f)
958            | Expression::ArrayReverse(f)
959            | Expression::ArrayDistinct(f)
960            | Expression::ArrayFlatten(f)
961            | Expression::ArrayCompact(f)
962            | Expression::ToArray(f)
963            | Expression::JsonArrayLength(f)
964            | Expression::JsonKeys(f)
965            | Expression::JsonType(f)
966            | Expression::ParseJson(f)
967            | Expression::ToJson(f)
968            | Expression::Year(f)
969            | Expression::Month(f)
970            | Expression::Day(f)
971            | Expression::Hour(f)
972            | Expression::Minute(f)
973            | Expression::Second(f)
974            | Expression::Initcap(f)
975            | Expression::Ascii(f)
976            | Expression::Chr(f)
977            | Expression::Soundex(f)
978            | Expression::ByteLength(f)
979            | Expression::Hex(f)
980            | Expression::LowerHex(f)
981            | Expression::Unicode(f)
982            | Expression::Typeof(f)
983            | Expression::BitwiseCount(f)
984            | Expression::Epoch(f)
985            | Expression::EpochMs(f)
986            | Expression::Radians(f)
987            | Expression::Degrees(f)
988            | Expression::Sin(f)
989            | Expression::Cos(f)
990            | Expression::Tan(f)
991            | Expression::Asin(f)
992            | Expression::Acos(f)
993            | Expression::Atan(f)
994            | Expression::IsNan(f)
995            | Expression::IsInf(f) => {
996                self.annotate_in_place(&mut f.this);
997            }
998
999            // BinaryFunc variants
1000            Expression::Power(f)
1001            | Expression::NullIf(f)
1002            | Expression::IfNull(f)
1003            | Expression::Nvl(f)
1004            | Expression::Contains(f)
1005            | Expression::StartsWith(f)
1006            | Expression::EndsWith(f)
1007            | Expression::Levenshtein(f)
1008            | Expression::ModFunc(f)
1009            | Expression::IntDiv(f)
1010            | Expression::Atan2(f)
1011            | Expression::AddMonths(f)
1012            | Expression::MonthsBetween(f)
1013            | Expression::NextDay(f)
1014            | Expression::UnixToTimeStr(f)
1015            | Expression::ArrayContains(f)
1016            | Expression::ArrayPosition(f)
1017            | Expression::ArrayAppend(f)
1018            | Expression::ArrayPrepend(f)
1019            | Expression::ArrayUnion(f)
1020            | Expression::ArrayExcept(f)
1021            | Expression::ArrayRemove(f)
1022            | Expression::StarMap(f)
1023            | Expression::MapFromArrays(f)
1024            | Expression::MapContainsKey(f)
1025            | Expression::ElementAt(f)
1026            | Expression::JsonMergePatch(f) => {
1027                self.annotate_in_place(&mut f.this);
1028                self.annotate_in_place(&mut f.expression);
1029            }
1030
1031            // VarArgFunc variants
1032            Expression::Coalesce(f)
1033            | Expression::Greatest(f)
1034            | Expression::Least(f)
1035            | Expression::ArrayConcat(f)
1036            | Expression::ArrayIntersect(f)
1037            | Expression::ArrayZip(f)
1038            | Expression::MapConcat(f)
1039            | Expression::JsonArray(f) => {
1040                for e in &mut f.expressions {
1041                    self.annotate_in_place(e);
1042                }
1043            }
1044
1045            // AggFunc variants
1046            Expression::Sum(f)
1047            | Expression::Avg(f)
1048            | Expression::Min(f)
1049            | Expression::Max(f)
1050            | Expression::ArrayAgg(f)
1051            | Expression::CountIf(f)
1052            | Expression::Stddev(f)
1053            | Expression::StddevPop(f)
1054            | Expression::StddevSamp(f)
1055            | Expression::Variance(f)
1056            | Expression::VarPop(f)
1057            | Expression::VarSamp(f)
1058            | Expression::Median(f)
1059            | Expression::Mode(f)
1060            | Expression::First(f)
1061            | Expression::Last(f)
1062            | Expression::AnyValue(f)
1063            | Expression::ApproxDistinct(f)
1064            | Expression::ApproxCountDistinct(f)
1065            | Expression::LogicalAnd(f)
1066            | Expression::LogicalOr(f)
1067            | Expression::Skewness(f)
1068            | Expression::ArrayConcatAgg(f)
1069            | Expression::ArrayUniqueAgg(f)
1070            | Expression::BoolXorAgg(f)
1071            | Expression::BitwiseAndAgg(f)
1072            | Expression::BitwiseOrAgg(f)
1073            | Expression::BitwiseXorAgg(f) => {
1074                self.annotate_in_place(&mut f.this);
1075            }
1076
1077            // Select - recurse into expressions
1078            Expression::Select(s) => {
1079                for e in &mut s.expressions {
1080                    self.annotate_in_place(e);
1081                }
1082            }
1083
1084            // Everything else - no children to recurse or not value-producing
1085            _ => {}
1086        }
1087    }
1088
1089    /// Annotate math functions like FLOOR/CEIL that return Double for integer inputs
1090    /// and preserve the input type otherwise (matching sqlglot's _annotate_math_functions).
1091    fn annotate_math_function(&mut self, arg: &Expression) -> Option<DataType> {
1092        let input_type = self.annotate(arg)?;
1093        match input_type {
1094            DataType::TinyInt { .. }
1095            | DataType::SmallInt { .. }
1096            | DataType::Int { .. }
1097            | DataType::BigInt { .. } => Some(DataType::Double {
1098                precision: None,
1099                scale: None,
1100            }),
1101            other => Some(other),
1102        }
1103    }
1104
1105    /// Annotate a subscript/bracket expression (array[index] or map[key])
1106    fn annotate_subscript(&mut self, sub: &Subscript) -> Option<DataType> {
1107        let base_type = self.annotate(&sub.this)?;
1108
1109        match base_type {
1110            DataType::Array { element_type, .. } => Some(*element_type),
1111            DataType::Map { value_type, .. } => Some(*value_type),
1112            DataType::Json | DataType::JsonB => Some(DataType::Json), // JSON indexing returns JSON
1113            DataType::VarChar { .. } | DataType::Text => {
1114                // String indexing returns a character
1115                Some(DataType::VarChar {
1116                    length: Some(1),
1117                    parenthesized_length: false,
1118                })
1119            }
1120            _ => None,
1121        }
1122    }
1123
1124    /// Annotate a STRUCT literal
1125    fn annotate_struct(&mut self, s: &Struct) -> Option<DataType> {
1126        let fields: Vec<StructField> = s
1127            .fields
1128            .iter()
1129            .map(|(name, expr)| {
1130                let field_type = self.annotate(expr).unwrap_or(DataType::Unknown);
1131                StructField::new(name.clone().unwrap_or_default(), field_type)
1132            })
1133            .collect();
1134        Some(DataType::Struct {
1135            fields,
1136            nested: false,
1137        })
1138    }
1139
1140    /// Annotate a MAP literal
1141    fn annotate_map(&mut self, map: &Map) -> Option<DataType> {
1142        let key_type = if let Some(first_key) = map.keys.first() {
1143            self.annotate(first_key).unwrap_or(DataType::Unknown)
1144        } else {
1145            DataType::Unknown
1146        };
1147
1148        let value_type = if let Some(first_value) = map.values.first() {
1149            self.annotate(first_value).unwrap_or(DataType::Unknown)
1150        } else {
1151            DataType::Unknown
1152        };
1153
1154        Some(DataType::Map {
1155            key_type: Box::new(key_type),
1156            value_type: Box::new(value_type),
1157        })
1158    }
1159
1160    /// Annotate a SetOperation (UNION/INTERSECT/EXCEPT)
1161    /// Returns None since set operations produce relation types, not scalar types
1162    fn annotate_set_operation(
1163        &mut self,
1164        _left: &Expression,
1165        _right: &Expression,
1166    ) -> Option<DataType> {
1167        // Set operations produce relations, not scalar types
1168        // The column types would be coerced between left and right
1169        // For now, return None as this is a relation-level type
1170        None
1171    }
1172
1173    /// Annotate a LATERAL VIEW expression
1174    fn annotate_lateral_view(&mut self, lv: &crate::expressions::LateralView) -> Option<DataType> {
1175        // The type depends on the table-generating function
1176        self.annotate(&lv.this)
1177    }
1178
1179    /// Annotate a literal value
1180    fn annotate_literal(&self, lit: &Literal) -> Option<DataType> {
1181        match lit {
1182            Literal::String(_)
1183            | Literal::NationalString(_)
1184            | Literal::TripleQuotedString(_, _)
1185            | Literal::EscapeString(_)
1186            | Literal::DollarString(_)
1187            | Literal::RawString(_) => Some(DataType::VarChar {
1188                length: None,
1189                parenthesized_length: false,
1190            }),
1191            Literal::Number(n) => {
1192                // Try to determine if it's an integer or float
1193                if n.contains('.') || n.contains('e') || n.contains('E') {
1194                    Some(DataType::Double {
1195                        precision: None,
1196                        scale: None,
1197                    })
1198                } else {
1199                    // Check if it fits in an Int or needs BigInt
1200                    if let Ok(_) = n.parse::<i32>() {
1201                        Some(DataType::Int {
1202                            length: None,
1203                            integer_spelling: false,
1204                        })
1205                    } else {
1206                        Some(DataType::BigInt { length: None })
1207                    }
1208                }
1209            }
1210            Literal::HexString(_) | Literal::BitString(_) | Literal::ByteString(_) => {
1211                Some(DataType::VarBinary { length: None })
1212            }
1213            Literal::HexNumber(_) => Some(DataType::BigInt { length: None }),
1214            Literal::Date(_) => Some(DataType::Date),
1215            Literal::Time(_) => Some(DataType::Time {
1216                precision: None,
1217                timezone: false,
1218            }),
1219            Literal::Timestamp(_) => Some(DataType::Timestamp {
1220                precision: None,
1221                timezone: false,
1222            }),
1223            Literal::Datetime(_) => Some(DataType::Custom {
1224                name: "DATETIME".to_string(),
1225            }),
1226        }
1227    }
1228
1229    /// Annotate an arithmetic binary operation
1230    fn annotate_arithmetic(&mut self, op: &BinaryOp) -> Option<DataType> {
1231        let left_type = self.annotate(&op.left);
1232        let right_type = self.annotate(&op.right);
1233
1234        match (left_type, right_type) {
1235            (Some(l), Some(r)) => self.coerce_types(&l, &r),
1236            (Some(t), None) | (None, Some(t)) => Some(t),
1237            (None, None) => None,
1238        }
1239    }
1240
1241    /// Annotate a function call
1242    fn annotate_function(&mut self, func: &Function) -> Option<DataType> {
1243        let func_name = func.name.to_uppercase();
1244
1245        // Check known function return types
1246        if let Some(return_type) = self.function_return_types.get(&func_name) {
1247            if *return_type != DataType::Unknown {
1248                return Some(return_type.clone());
1249            }
1250        }
1251
1252        // For functions with Unknown return type, infer from arguments
1253        match func_name.as_str() {
1254            "UNNEST" => func.args.first().and_then(|arg| match self.annotate(arg) {
1255                Some(DataType::Array { element_type, .. }) => Some(*element_type),
1256                _ => None,
1257            }),
1258            "COALESCE" | "IFNULL" | "NVL" | "ISNULL" => {
1259                // Return type of first non-null argument
1260                for arg in &func.args {
1261                    if let Some(arg_type) = self.annotate(arg) {
1262                        return Some(arg_type);
1263                    }
1264                }
1265                None
1266            }
1267            "NULLIF" => {
1268                // Return type of first argument
1269                func.args.first().and_then(|arg| self.annotate(arg))
1270            }
1271            "GREATEST" | "LEAST" => {
1272                // Coerce all argument types
1273                self.coerce_arg_types(&func.args)
1274            }
1275            "IF" | "IIF" => {
1276                // Return type of THEN/ELSE branches
1277                if func.args.len() >= 2 {
1278                    self.annotate(&func.args[1])
1279                } else {
1280                    None
1281                }
1282            }
1283            _ => {
1284                // Unknown function - try to infer from first argument
1285                func.args.first().and_then(|arg| self.annotate(arg))
1286            }
1287        }
1288    }
1289
1290    /// Annotate IF/IIF/IFF conditional function
1291    fn annotate_if_func(&mut self, func: &IfFunc) -> Option<DataType> {
1292        let true_type = self.annotate(&func.true_value);
1293        let false_type = func
1294            .false_value
1295            .as_ref()
1296            .and_then(|expr| self.annotate(expr));
1297
1298        match (true_type, false_type) {
1299            (Some(left), Some(right)) => self.coerce_types(&left, &right),
1300            (Some(dt), None) | (None, Some(dt)) => Some(dt),
1301            (None, None) => None,
1302        }
1303    }
1304
1305    /// Annotate NVL2 conditional function from its true/false branches
1306    fn annotate_nvl2(&mut self, func: &Nvl2Func) -> Option<DataType> {
1307        let true_type = self.annotate(&func.true_value);
1308        let false_type = self.annotate(&func.false_value);
1309
1310        match (true_type, false_type) {
1311            (Some(left), Some(right)) => self.coerce_types(&left, &right),
1312            (Some(dt), None) | (None, Some(dt)) => Some(dt),
1313            (None, None) => None,
1314        }
1315    }
1316
1317    /// Get return type for aggregate functions
1318    fn get_aggregate_return_type(
1319        &mut self,
1320        func_name: &str,
1321        args: &[Expression],
1322    ) -> Option<DataType> {
1323        match func_name {
1324            "COUNT" | "COUNT_IF" => Some(DataType::BigInt { length: None }),
1325            "SUM_IF" => {
1326                if let Some(arg) = args.first() {
1327                    self.annotate_sum(arg)
1328                } else {
1329                    Some(DataType::Decimal {
1330                        precision: None,
1331                        scale: None,
1332                    })
1333                }
1334            }
1335            "SUM" => {
1336                if let Some(arg) = args.first() {
1337                    self.annotate_sum(arg)
1338                } else {
1339                    Some(DataType::Decimal {
1340                        precision: None,
1341                        scale: None,
1342                    })
1343                }
1344            }
1345            "AVG" => Some(DataType::Double {
1346                precision: None,
1347                scale: None,
1348            }),
1349            "MIN" | "MAX" => {
1350                // Preserves input type
1351                args.first().and_then(|arg| self.annotate(arg))
1352            }
1353            "STRING_AGG" | "GROUP_CONCAT" | "LISTAGG" | "ARRAY_AGG" => Some(DataType::VarChar {
1354                length: None,
1355                parenthesized_length: false,
1356            }),
1357            "BOOL_AND" | "BOOL_OR" | "EVERY" | "ANY" | "SOME" => Some(DataType::Boolean),
1358            "BIT_AND" | "BIT_OR" | "BIT_XOR" => Some(DataType::BigInt { length: None }),
1359            "STDDEV" | "STDDEV_POP" | "STDDEV_SAMP" | "VARIANCE" | "VAR_POP" | "VAR_SAMP" => {
1360                Some(DataType::Double {
1361                    precision: None,
1362                    scale: None,
1363                })
1364            }
1365            "PERCENTILE_CONT" | "PERCENTILE_DISC" | "MEDIAN" => {
1366                args.first().and_then(|arg| self.annotate(arg))
1367            }
1368            _ => None,
1369        }
1370    }
1371
1372    /// Annotate SUM function - promotes to at least BigInt
1373    fn annotate_sum(&mut self, arg: &Expression) -> Option<DataType> {
1374        match self.annotate(arg) {
1375            Some(DataType::TinyInt { .. })
1376            | Some(DataType::SmallInt { .. })
1377            | Some(DataType::Int { .. }) => Some(DataType::BigInt { length: None }),
1378            Some(DataType::BigInt { .. }) => Some(DataType::BigInt { length: None }),
1379            Some(DataType::Float { .. }) | Some(DataType::Double { .. }) => {
1380                Some(DataType::Double {
1381                    precision: None,
1382                    scale: None,
1383                })
1384            }
1385            Some(DataType::Decimal { precision, scale }) => {
1386                Some(DataType::Decimal { precision, scale })
1387            }
1388            _ => Some(DataType::Decimal {
1389                precision: None,
1390                scale: None,
1391            }),
1392        }
1393    }
1394
1395    /// Coerce multiple argument types to a common type
1396    fn coerce_arg_types(&mut self, args: &[Expression]) -> Option<DataType> {
1397        let mut result_type: Option<DataType> = None;
1398        for arg in args {
1399            if let Some(arg_type) = self.annotate(arg) {
1400                result_type = match result_type {
1401                    Some(t) => self.coerce_types(&t, &arg_type),
1402                    None => Some(arg_type),
1403                };
1404            }
1405        }
1406        result_type
1407    }
1408
1409    /// Coerce two types to a common type
1410    fn coerce_types(&self, left: &DataType, right: &DataType) -> Option<DataType> {
1411        // If types are the same, return that type
1412        if left == right {
1413            return Some(left.clone());
1414        }
1415
1416        // Special case: Interval + Date/Timestamp
1417        match (left, right) {
1418            (DataType::Date, DataType::Interval { .. })
1419            | (DataType::Interval { .. }, DataType::Date) => return Some(DataType::Date),
1420            (
1421                DataType::Timestamp {
1422                    precision,
1423                    timezone,
1424                },
1425                DataType::Interval { .. },
1426            )
1427            | (
1428                DataType::Interval { .. },
1429                DataType::Timestamp {
1430                    precision,
1431                    timezone,
1432                },
1433            ) => {
1434                return Some(DataType::Timestamp {
1435                    precision: *precision,
1436                    timezone: *timezone,
1437                });
1438            }
1439            _ => {}
1440        }
1441
1442        // Coerce based on class
1443        let left_class = TypeCoercionClass::from_data_type(left);
1444        let right_class = TypeCoercionClass::from_data_type(right);
1445
1446        match (left_class, right_class) {
1447            // Same class: use higher-precision type within class
1448            (Some(lc), Some(rc)) if lc == rc => {
1449                // For numeric, choose wider type
1450                if lc == TypeCoercionClass::Numeric {
1451                    Some(self.wider_numeric_type(left, right))
1452                } else {
1453                    // For text and timelike, left wins by default
1454                    Some(left.clone())
1455                }
1456            }
1457            // Different classes: higher-priority class wins
1458            (Some(lc), Some(rc)) => {
1459                if lc > rc {
1460                    Some(left.clone())
1461                } else {
1462                    Some(right.clone())
1463                }
1464            }
1465            // One unknown: use the known type
1466            (Some(_), None) => Some(left.clone()),
1467            (None, Some(_)) => Some(right.clone()),
1468            // Both unknown: return unknown
1469            (None, None) => Some(DataType::Unknown),
1470        }
1471    }
1472
1473    /// Get the wider numeric type
1474    fn wider_numeric_type(&self, left: &DataType, right: &DataType) -> DataType {
1475        let order = |dt: &DataType| -> u8 {
1476            match dt {
1477                DataType::Boolean => 0,
1478                DataType::TinyInt { .. } => 1,
1479                DataType::SmallInt { .. } => 2,
1480                DataType::Int { .. } => 3,
1481                DataType::BigInt { .. } => 4,
1482                DataType::Float { .. } => 5,
1483                DataType::Double { .. } => 6,
1484                DataType::Decimal { .. } => 7,
1485                _ => 0,
1486            }
1487        };
1488
1489        if order(left) >= order(right) {
1490            left.clone()
1491        } else {
1492            right.clone()
1493        }
1494    }
1495}
1496
1497/// A schema layer whose entries are visible only while annotating one query
1498/// scope. The parent contains physical tables and any correlated outer scope;
1499/// CTE, derived-table, table-alias, and table-valued-function outputs stay in
1500/// this layer and therefore cannot leak into sibling scopes.
1501struct ScopedSchema<'a> {
1502    parent: Option<&'a dyn Schema>,
1503    tables: HashMap<String, HashMap<String, DataType>>,
1504    dialect: Option<DialectType>,
1505}
1506
1507impl<'a> ScopedSchema<'a> {
1508    fn new(parent: Option<&'a dyn Schema>, dialect: Option<DialectType>) -> Self {
1509        Self {
1510            parent,
1511            tables: HashMap::new(),
1512            dialect,
1513        }
1514    }
1515
1516    fn normalized(&self, name: &str, is_table: bool) -> String {
1517        normalize_name(name, self.dialect, is_table, true)
1518    }
1519
1520    fn local_column_type(&self, table: &str, column: &str) -> Option<DataType> {
1521        let table = self.normalized(table, true);
1522        let column = self.normalized(column, false);
1523        self.tables
1524            .get(&table)
1525            .and_then(|columns| columns.get(&column))
1526            .cloned()
1527    }
1528
1529    fn local_tables_for_column(&self, column: &str) -> Vec<String> {
1530        let column = self.normalized(column, false);
1531        self.tables
1532            .iter()
1533            .filter_map(|(table, columns)| columns.contains_key(&column).then(|| table.clone()))
1534            .collect()
1535    }
1536}
1537
1538impl Schema for ScopedSchema<'_> {
1539    fn dialect(&self) -> Option<DialectType> {
1540        self.dialect
1541            .or_else(|| self.parent.and_then(Schema::dialect))
1542    }
1543
1544    fn add_table(
1545        &mut self,
1546        table: &str,
1547        columns: &[(String, DataType)],
1548        _dialect: Option<DialectType>,
1549    ) -> SchemaResult<()> {
1550        let table = self.normalized(table, true);
1551        let columns = columns
1552            .iter()
1553            .map(|(name, data_type)| (self.normalized(name, false), data_type.clone()))
1554            .collect();
1555        self.tables.insert(table, columns);
1556        Ok(())
1557    }
1558
1559    fn column_names(&self, table: &str) -> SchemaResult<Vec<String>> {
1560        let table = self.normalized(table, true);
1561        if let Some(columns) = self.tables.get(&table) {
1562            return Ok(columns.keys().cloned().collect());
1563        }
1564        self.parent
1565            .ok_or_else(|| SchemaError::TableNotFound(table.clone()))?
1566            .column_names(&table)
1567    }
1568
1569    fn get_column_type(&self, table: &str, column: &str) -> SchemaResult<DataType> {
1570        if table.is_empty() {
1571            let local_tables = self.local_tables_for_column(column);
1572            return match local_tables.as_slice() {
1573                [local_table] => self.get_column_type(local_table, column),
1574                [] => self
1575                    .parent
1576                    .ok_or_else(|| SchemaError::ColumnNotFound {
1577                        table: String::new(),
1578                        column: column.to_string(),
1579                    })?
1580                    .get_column_type(table, column),
1581                _ => Err(SchemaError::AmbiguousTable {
1582                    table: String::new(),
1583                    matches: local_tables.join(", "),
1584                }),
1585            };
1586        }
1587
1588        let normalized_table = self.normalized(table, true);
1589        if self.tables.contains_key(&normalized_table) {
1590            return self.local_column_type(table, column).ok_or_else(|| {
1591                SchemaError::ColumnNotFound {
1592                    table: table.to_string(),
1593                    column: column.to_string(),
1594                }
1595            });
1596        }
1597
1598        self.parent
1599            .ok_or_else(|| SchemaError::ColumnNotFound {
1600                table: table.to_string(),
1601                column: column.to_string(),
1602            })?
1603            .get_column_type(table, column)
1604    }
1605
1606    fn has_column(&self, table: &str, column: &str) -> bool {
1607        self.get_column_type(table, column).is_ok()
1608    }
1609
1610    fn supported_table_args(&self) -> &[&str] {
1611        TABLE_PARTS
1612    }
1613
1614    fn is_empty(&self) -> bool {
1615        self.tables.is_empty() && self.parent.is_none_or(Schema::is_empty)
1616    }
1617
1618    fn depth(&self) -> usize {
1619        self.parent.map_or(1, |schema| schema.depth().max(1))
1620    }
1621
1622    fn find_tables_for_column(&self, column: &str) -> Vec<String> {
1623        let mut tables = self.local_tables_for_column(column);
1624        if let Some(parent) = self.parent {
1625            tables.extend(parent.find_tables_for_column(column));
1626        }
1627        let mut seen = HashSet::new();
1628        tables.retain(|table| seen.insert(table.clone()));
1629        tables
1630    }
1631}
1632
1633type OutputColumns = Vec<(String, DataType)>;
1634
1635fn table_name(table: &crate::expressions::TableRef) -> String {
1636    let mut parts = Vec::new();
1637    if let Some(catalog) = &table.catalog {
1638        parts.push(catalog.name.as_str());
1639    }
1640    if let Some(schema) = &table.schema {
1641        parts.push(schema.name.as_str());
1642    }
1643    parts.push(table.name.name.as_str());
1644    parts.join(".")
1645}
1646
1647fn table_columns(schema: &dyn Schema, table: &str) -> OutputColumns {
1648    schema
1649        .column_names(table)
1650        .unwrap_or_default()
1651        .into_iter()
1652        .map(|column| {
1653            let data_type = schema
1654                .get_column_type(table, &column)
1655                .unwrap_or(DataType::Unknown);
1656            (column, data_type)
1657        })
1658        .collect()
1659}
1660
1661fn apply_column_aliases(
1662    mut columns: OutputColumns,
1663    aliases: &[crate::expressions::Identifier],
1664) -> OutputColumns {
1665    for ((name, _), alias) in columns.iter_mut().zip(aliases) {
1666        *name = alias.name.clone();
1667    }
1668    columns
1669}
1670
1671fn projection_name(expression: &Expression) -> Option<String> {
1672    match expression {
1673        Expression::Alias(alias) => Some(alias.alias.name.clone()),
1674        Expression::Column(column) => Some(column.name.name.clone()),
1675        Expression::Identifier(identifier) => Some(identifier.name.clone()),
1676        _ => None,
1677    }
1678}
1679
1680fn projection_type(expression: &Expression) -> DataType {
1681    expression
1682        .inferred_type()
1683        .or_else(|| match expression {
1684            Expression::Alias(alias) => alias.this.inferred_type(),
1685            _ => None,
1686        })
1687        .cloned()
1688        .unwrap_or(DataType::Unknown)
1689}
1690
1691fn query_outputs(expressions: &[Expression]) -> OutputColumns {
1692    expressions
1693        .iter()
1694        .filter_map(|expression| {
1695            projection_name(expression).map(|name| (name, projection_type(expression)))
1696        })
1697        .collect()
1698}
1699
1700fn array_element_type(data_type: Option<&DataType>) -> DataType {
1701    match data_type {
1702        Some(DataType::Array { element_type, .. }) => (**element_type).clone(),
1703        _ => DataType::Unknown,
1704    }
1705}
1706
1707fn unnest_output_types(unnest: &crate::expressions::UnnestFunc) -> Vec<DataType> {
1708    let mut types = vec![array_element_type(unnest.this.inferred_type())];
1709    types.extend(
1710        unnest
1711            .expressions
1712            .iter()
1713            .map(|expression| array_element_type(expression.inferred_type())),
1714    );
1715    if unnest.with_ordinality || unnest.offset_alias.is_some() {
1716        types.push(DataType::BigInt { length: None });
1717    }
1718    types
1719}
1720
1721fn virtual_output_columns(
1722    expression: &Expression,
1723    source_alias: &str,
1724    column_aliases: &[crate::expressions::Identifier],
1725) -> OutputColumns {
1726    let (types, offset_alias) = match expression {
1727        Expression::Unnest(unnest) => (unnest_output_types(unnest), unnest.offset_alias.as_ref()),
1728        Expression::Explode(explode) | Expression::ExplodeOuter(explode) => {
1729            (vec![array_element_type(explode.this.inferred_type())], None)
1730        }
1731        Expression::Function(function) if function.name.eq_ignore_ascii_case("UNNEST") => (
1732            function
1733                .args
1734                .iter()
1735                .map(|argument| array_element_type(argument.inferred_type()))
1736                .collect(),
1737            None,
1738        ),
1739        _ => return Vec::new(),
1740    };
1741
1742    if column_aliases.is_empty() {
1743        let mut columns = Vec::new();
1744        if let Some(data_type) = types.first() {
1745            columns.push((source_alias.to_string(), data_type.clone()));
1746        }
1747        if let Some(offset_alias) = offset_alias {
1748            columns.push((offset_alias.name.clone(), DataType::BigInt { length: None }));
1749        }
1750        columns
1751    } else {
1752        column_aliases
1753            .iter()
1754            .zip(types)
1755            .map(|(alias, data_type)| (alias.name.clone(), data_type))
1756            .collect()
1757    }
1758}
1759
1760fn annotate_relation_source(
1761    expression: &mut Expression,
1762    schema: &mut ScopedSchema<'_>,
1763    dialect: Option<DialectType>,
1764) {
1765    match expression {
1766        Expression::Table(table) => {
1767            let source_table = table_name(table);
1768            let mut columns = table_columns(schema, &source_table);
1769            columns = apply_column_aliases(columns, &table.column_aliases);
1770            let visible_name = table
1771                .alias
1772                .as_ref()
1773                .map(|alias| alias.name.as_str())
1774                .unwrap_or(table.name.name.as_str());
1775            let _ = schema.add_table(visible_name, &columns, dialect);
1776        }
1777        Expression::Subquery(subquery) => {
1778            let mut columns = annotate_scoped_expression(&mut subquery.this, Some(schema), dialect);
1779            columns = apply_column_aliases(columns, &subquery.column_aliases);
1780            if let Some((_, first_type)) = columns.first() {
1781                subquery.inferred_type = Some(first_type.clone());
1782            }
1783            if let Some(alias) = &subquery.alias {
1784                let _ = schema.add_table(&alias.name, &columns, dialect);
1785            }
1786        }
1787        Expression::Alias(alias) => {
1788            match &mut alias.this {
1789                Expression::Subquery(subquery) => {
1790                    let columns =
1791                        annotate_scoped_expression(&mut subquery.this, Some(schema), dialect);
1792                    let columns = apply_column_aliases(columns, &alias.column_aliases);
1793                    let _ = schema.add_table(&alias.alias.name, &columns, dialect);
1794                    return;
1795                }
1796                _ => {
1797                    let mut annotator = TypeAnnotator::new(Some(schema), dialect);
1798                    annotator.annotate_in_place(&mut alias.this);
1799                }
1800            }
1801            let columns =
1802                virtual_output_columns(&alias.this, &alias.alias.name, &alias.column_aliases);
1803            if !columns.is_empty() {
1804                let _ = schema.add_table(&alias.alias.name, &columns, dialect);
1805            }
1806        }
1807        Expression::Unnest(_) => {
1808            let mut annotator = TypeAnnotator::new(Some(schema), dialect);
1809            annotator.annotate_in_place(expression);
1810            if let Expression::Unnest(unnest) = expression {
1811                if let Some(alias) = &unnest.alias {
1812                    let alias_name = alias.name.clone();
1813                    let columns = unnest_output_types(unnest)
1814                        .into_iter()
1815                        .next()
1816                        .map(|data_type| vec![(alias_name.clone(), data_type)])
1817                        .unwrap_or_default();
1818                    let _ = schema.add_table(&alias_name, &columns, dialect);
1819                }
1820            }
1821        }
1822        Expression::Lateral(lateral) => {
1823            let mut annotator = TypeAnnotator::new(Some(schema), dialect);
1824            annotator.annotate_in_place(&mut lateral.this);
1825            if let Some(alias) = &lateral.alias {
1826                let aliases: Vec<_> = lateral
1827                    .column_aliases
1828                    .iter()
1829                    .map(crate::expressions::Identifier::new)
1830                    .collect();
1831                let columns = virtual_output_columns(&lateral.this, alias, &aliases);
1832                if !columns.is_empty() {
1833                    let _ = schema.add_table(alias, &columns, dialect);
1834                }
1835            }
1836        }
1837        Expression::Paren(paren) => annotate_relation_source(&mut paren.this, schema, dialect),
1838        _ => {
1839            let mut annotator = TypeAnnotator::new(Some(schema), dialect);
1840            annotator.annotate_in_place(expression);
1841        }
1842    }
1843}
1844
1845fn annotate_with(
1846    with: &mut Option<crate::expressions::With>,
1847    schema: &mut ScopedSchema<'_>,
1848    dialect: Option<DialectType>,
1849) {
1850    if let Some(with) = with {
1851        for cte in &mut with.ctes {
1852            let columns = annotate_scoped_expression(&mut cte.this, Some(schema), dialect);
1853            let columns = apply_column_aliases(columns, &cte.columns);
1854            let _ = schema.add_table(&cte.alias.name, &columns, dialect);
1855        }
1856    }
1857}
1858
1859fn annotate_select(
1860    select: &mut crate::expressions::Select,
1861    parent: Option<&dyn Schema>,
1862    dialect: Option<DialectType>,
1863) -> OutputColumns {
1864    let mut schema = ScopedSchema::new(parent, dialect);
1865    annotate_with(&mut select.with, &mut schema, dialect);
1866
1867    if let Some(from) = &mut select.from {
1868        for source in &mut from.expressions {
1869            annotate_relation_source(source, &mut schema, dialect);
1870        }
1871    }
1872    for join in &mut select.joins {
1873        annotate_relation_source(&mut join.this, &mut schema, dialect);
1874    }
1875
1876    let mut annotator = TypeAnnotator::new(Some(&schema), dialect);
1877    for expression in &mut select.expressions {
1878        annotator.annotate_in_place(expression);
1879    }
1880    query_outputs(&select.expressions)
1881}
1882
1883fn annotate_scoped_expression(
1884    expression: &mut Expression,
1885    parent: Option<&dyn Schema>,
1886    dialect: Option<DialectType>,
1887) -> OutputColumns {
1888    match expression {
1889        Expression::Select(select) => annotate_select(select, parent, dialect),
1890        Expression::Subquery(subquery) => {
1891            let columns = annotate_scoped_expression(&mut subquery.this, parent, dialect);
1892            if let Some((_, first_type)) = columns.first() {
1893                subquery.inferred_type = Some(first_type.clone());
1894            }
1895            columns
1896        }
1897        Expression::Cte(cte) => annotate_scoped_expression(&mut cte.this, parent, dialect),
1898        Expression::Paren(paren) => annotate_scoped_expression(&mut paren.this, parent, dialect),
1899        Expression::Union(union) => {
1900            let mut schema = ScopedSchema::new(parent, dialect);
1901            annotate_with(&mut union.with, &mut schema, dialect);
1902            let columns = annotate_scoped_expression(&mut union.left, Some(&schema), dialect);
1903            annotate_scoped_expression(&mut union.right, Some(&schema), dialect);
1904            columns
1905        }
1906        Expression::Intersect(intersect) => {
1907            let mut schema = ScopedSchema::new(parent, dialect);
1908            annotate_with(&mut intersect.with, &mut schema, dialect);
1909            let columns = annotate_scoped_expression(&mut intersect.left, Some(&schema), dialect);
1910            annotate_scoped_expression(&mut intersect.right, Some(&schema), dialect);
1911            columns
1912        }
1913        Expression::Except(except) => {
1914            let mut schema = ScopedSchema::new(parent, dialect);
1915            annotate_with(&mut except.with, &mut schema, dialect);
1916            let columns = annotate_scoped_expression(&mut except.left, Some(&schema), dialect);
1917            annotate_scoped_expression(&mut except.right, Some(&schema), dialect);
1918            columns
1919        }
1920        _ => {
1921            let mut annotator = TypeAnnotator::new(parent, dialect);
1922            annotator.annotate_in_place(expression);
1923            Vec::new()
1924        }
1925    }
1926}
1927
1928/// Annotate types in-place on the expression tree.
1929///
1930/// Walks the AST bottom-up and sets `inferred_type` on each value-producing
1931/// node. After this call, `expr.inferred_type()` (and the same on any child
1932/// node) returns the inferred type.
1933pub fn annotate_types(
1934    expr: &mut Expression,
1935    schema: Option<&dyn Schema>,
1936    dialect: Option<DialectType>,
1937) {
1938    annotate_scoped_expression(expr, schema, dialect);
1939}
1940
1941#[cfg(test)]
1942mod tests {
1943    use super::*;
1944    use crate::expressions::{BooleanLiteral, Cast, Null};
1945    use crate::{parse_one, DialectType, MappingSchema, Schema};
1946
1947    fn make_int_literal(val: i64) -> Expression {
1948        Expression::Literal(Box::new(Literal::Number(val.to_string())))
1949    }
1950
1951    fn make_float_literal(val: f64) -> Expression {
1952        Expression::Literal(Box::new(Literal::Number(val.to_string())))
1953    }
1954
1955    fn make_string_literal(val: &str) -> Expression {
1956        Expression::Literal(Box::new(Literal::String(val.to_string())))
1957    }
1958
1959    fn make_bool_literal(val: bool) -> Expression {
1960        Expression::Boolean(BooleanLiteral { value: val })
1961    }
1962
1963    #[test]
1964    fn test_literal_types() {
1965        let mut annotator = TypeAnnotator::new(None, None);
1966
1967        // Integer literal
1968        let int_expr = make_int_literal(42);
1969        assert_eq!(
1970            annotator.annotate(&int_expr),
1971            Some(DataType::Int {
1972                length: None,
1973                integer_spelling: false
1974            })
1975        );
1976
1977        // Float literal
1978        let float_expr = make_float_literal(3.14);
1979        assert_eq!(
1980            annotator.annotate(&float_expr),
1981            Some(DataType::Double {
1982                precision: None,
1983                scale: None
1984            })
1985        );
1986
1987        // String literal
1988        let string_expr = make_string_literal("hello");
1989        assert_eq!(
1990            annotator.annotate(&string_expr),
1991            Some(DataType::VarChar {
1992                length: None,
1993                parenthesized_length: false
1994            })
1995        );
1996
1997        // Boolean literal
1998        let bool_expr = make_bool_literal(true);
1999        assert_eq!(annotator.annotate(&bool_expr), Some(DataType::Boolean));
2000
2001        // Null literal
2002        let null_expr = Expression::Null(Null);
2003        assert_eq!(annotator.annotate(&null_expr), None);
2004    }
2005
2006    #[test]
2007    fn test_comparison_types() {
2008        let mut annotator = TypeAnnotator::new(None, None);
2009
2010        // Comparison returns boolean
2011        let cmp = Expression::Gt(Box::new(BinaryOp::new(
2012            make_int_literal(1),
2013            make_int_literal(2),
2014        )));
2015        assert_eq!(annotator.annotate(&cmp), Some(DataType::Boolean));
2016
2017        // Equality returns boolean
2018        let eq = Expression::Eq(Box::new(BinaryOp::new(
2019            make_string_literal("a"),
2020            make_string_literal("b"),
2021        )));
2022        assert_eq!(annotator.annotate(&eq), Some(DataType::Boolean));
2023    }
2024
2025    #[test]
2026    fn test_arithmetic_types() {
2027        let mut annotator = TypeAnnotator::new(None, None);
2028
2029        // Int + Int = Int
2030        let add_int = Expression::Add(Box::new(BinaryOp::new(
2031            make_int_literal(1),
2032            make_int_literal(2),
2033        )));
2034        assert_eq!(
2035            annotator.annotate(&add_int),
2036            Some(DataType::Int {
2037                length: None,
2038                integer_spelling: false
2039            })
2040        );
2041
2042        // Int + Float = Double (wider type)
2043        let add_mixed = Expression::Add(Box::new(BinaryOp::new(
2044            make_int_literal(1),
2045            make_float_literal(2.5), // Use 2.5 so the string has a decimal point
2046        )));
2047        assert_eq!(
2048            annotator.annotate(&add_mixed),
2049            Some(DataType::Double {
2050                precision: None,
2051                scale: None
2052            })
2053        );
2054    }
2055
2056    #[test]
2057    fn test_string_concat_type() {
2058        let mut annotator = TypeAnnotator::new(None, None);
2059
2060        // String || String = VarChar
2061        let concat = Expression::Concat(Box::new(BinaryOp::new(
2062            make_string_literal("hello"),
2063            make_string_literal(" world"),
2064        )));
2065        assert_eq!(
2066            annotator.annotate(&concat),
2067            Some(DataType::VarChar {
2068                length: None,
2069                parenthesized_length: false
2070            })
2071        );
2072    }
2073
2074    #[test]
2075    fn test_cast_type() {
2076        let mut annotator = TypeAnnotator::new(None, None);
2077
2078        // CAST(1 AS VARCHAR)
2079        let cast = Expression::Cast(Box::new(Cast {
2080            this: make_int_literal(1),
2081            to: DataType::VarChar {
2082                length: Some(10),
2083                parenthesized_length: false,
2084            },
2085            trailing_comments: vec![],
2086            double_colon_syntax: false,
2087            format: None,
2088            default: None,
2089            inferred_type: None,
2090        }));
2091        assert_eq!(
2092            annotator.annotate(&cast),
2093            Some(DataType::VarChar {
2094                length: Some(10),
2095                parenthesized_length: false
2096            })
2097        );
2098    }
2099
2100    #[test]
2101    fn test_function_types() {
2102        let mut annotator = TypeAnnotator::new(None, None);
2103
2104        // COUNT returns BigInt
2105        let count =
2106            Expression::Function(Box::new(Function::new("COUNT", vec![make_int_literal(1)])));
2107        assert_eq!(
2108            annotator.annotate(&count),
2109            Some(DataType::BigInt { length: None })
2110        );
2111
2112        // UPPER returns VarChar
2113        let upper = Expression::Function(Box::new(Function::new(
2114            "UPPER",
2115            vec![make_string_literal("hello")],
2116        )));
2117        assert_eq!(
2118            annotator.annotate(&upper),
2119            Some(DataType::VarChar {
2120                length: None,
2121                parenthesized_length: false
2122            })
2123        );
2124
2125        // NOW returns Timestamp
2126        let now = Expression::Function(Box::new(Function::new("NOW", vec![])));
2127        assert_eq!(
2128            annotator.annotate(&now),
2129            Some(DataType::Timestamp {
2130                precision: None,
2131                timezone: false
2132            })
2133        );
2134    }
2135
2136    #[test]
2137    fn test_coalesce_type_inference() {
2138        let mut annotator = TypeAnnotator::new(None, None);
2139
2140        // COALESCE(NULL, 1) returns Int (type of first non-null arg)
2141        let coalesce = Expression::Function(Box::new(Function::new(
2142            "COALESCE",
2143            vec![Expression::Null(Null), make_int_literal(1)],
2144        )));
2145        assert_eq!(
2146            annotator.annotate(&coalesce),
2147            Some(DataType::Int {
2148                length: None,
2149                integer_spelling: false
2150            })
2151        );
2152    }
2153
2154    #[test]
2155    fn test_type_coercion_class() {
2156        // Text types
2157        assert_eq!(
2158            TypeCoercionClass::from_data_type(&DataType::VarChar {
2159                length: None,
2160                parenthesized_length: false
2161            }),
2162            Some(TypeCoercionClass::Text)
2163        );
2164        assert_eq!(
2165            TypeCoercionClass::from_data_type(&DataType::Text),
2166            Some(TypeCoercionClass::Text)
2167        );
2168
2169        // Numeric types
2170        assert_eq!(
2171            TypeCoercionClass::from_data_type(&DataType::Int {
2172                length: None,
2173                integer_spelling: false
2174            }),
2175            Some(TypeCoercionClass::Numeric)
2176        );
2177        assert_eq!(
2178            TypeCoercionClass::from_data_type(&DataType::Double {
2179                precision: None,
2180                scale: None
2181            }),
2182            Some(TypeCoercionClass::Numeric)
2183        );
2184
2185        // Timelike types
2186        assert_eq!(
2187            TypeCoercionClass::from_data_type(&DataType::Date),
2188            Some(TypeCoercionClass::Timelike)
2189        );
2190        assert_eq!(
2191            TypeCoercionClass::from_data_type(&DataType::Timestamp {
2192                precision: None,
2193                timezone: false
2194            }),
2195            Some(TypeCoercionClass::Timelike)
2196        );
2197
2198        // Unknown types
2199        assert_eq!(TypeCoercionClass::from_data_type(&DataType::Json), None);
2200    }
2201
2202    #[test]
2203    fn test_wider_numeric_type() {
2204        let annotator = TypeAnnotator::new(None, None);
2205
2206        // Int vs BigInt -> BigInt
2207        let result = annotator.wider_numeric_type(
2208            &DataType::Int {
2209                length: None,
2210                integer_spelling: false,
2211            },
2212            &DataType::BigInt { length: None },
2213        );
2214        assert_eq!(result, DataType::BigInt { length: None });
2215
2216        // Float vs Double -> Double
2217        let result = annotator.wider_numeric_type(
2218            &DataType::Float {
2219                precision: None,
2220                scale: None,
2221                real_spelling: false,
2222            },
2223            &DataType::Double {
2224                precision: None,
2225                scale: None,
2226            },
2227        );
2228        assert_eq!(
2229            result,
2230            DataType::Double {
2231                precision: None,
2232                scale: None
2233            }
2234        );
2235
2236        // Int vs Double -> Double
2237        let result = annotator.wider_numeric_type(
2238            &DataType::Int {
2239                length: None,
2240                integer_spelling: false,
2241            },
2242            &DataType::Double {
2243                precision: None,
2244                scale: None,
2245            },
2246        );
2247        assert_eq!(
2248            result,
2249            DataType::Double {
2250                precision: None,
2251                scale: None
2252            }
2253        );
2254    }
2255
2256    #[test]
2257    fn test_aggregate_return_types() {
2258        let mut annotator = TypeAnnotator::new(None, None);
2259
2260        // SUM(int) returns BigInt
2261        let sum_type = annotator.get_aggregate_return_type("SUM", &[make_int_literal(1)]);
2262        assert_eq!(sum_type, Some(DataType::BigInt { length: None }));
2263
2264        // AVG always returns Double
2265        let avg_type = annotator.get_aggregate_return_type("AVG", &[make_int_literal(1)]);
2266        assert_eq!(
2267            avg_type,
2268            Some(DataType::Double {
2269                precision: None,
2270                scale: None
2271            })
2272        );
2273
2274        // MIN/MAX preserve input type
2275        let min_type = annotator.get_aggregate_return_type("MIN", &[make_string_literal("a")]);
2276        assert_eq!(
2277            min_type,
2278            Some(DataType::VarChar {
2279                length: None,
2280                parenthesized_length: false
2281            })
2282        );
2283    }
2284
2285    #[test]
2286    fn test_date_literal_types() {
2287        let mut annotator = TypeAnnotator::new(None, None);
2288
2289        // DATE literal
2290        let date_expr = Expression::Literal(Box::new(Literal::Date("2024-01-15".to_string())));
2291        assert_eq!(annotator.annotate(&date_expr), Some(DataType::Date));
2292
2293        // TIME literal
2294        let time_expr = Expression::Literal(Box::new(Literal::Time("10:30:00".to_string())));
2295        assert_eq!(
2296            annotator.annotate(&time_expr),
2297            Some(DataType::Time {
2298                precision: None,
2299                timezone: false
2300            })
2301        );
2302
2303        // TIMESTAMP literal
2304        let ts_expr = Expression::Literal(Box::new(Literal::Timestamp(
2305            "2024-01-15 10:30:00".to_string(),
2306        )));
2307        assert_eq!(
2308            annotator.annotate(&ts_expr),
2309            Some(DataType::Timestamp {
2310                precision: None,
2311                timezone: false
2312            })
2313        );
2314    }
2315
2316    #[test]
2317    fn test_logical_operations() {
2318        let mut annotator = TypeAnnotator::new(None, None);
2319
2320        // AND returns boolean
2321        let and_expr = Expression::And(Box::new(BinaryOp::new(
2322            make_bool_literal(true),
2323            make_bool_literal(false),
2324        )));
2325        assert_eq!(annotator.annotate(&and_expr), Some(DataType::Boolean));
2326
2327        // OR returns boolean
2328        let or_expr = Expression::Or(Box::new(BinaryOp::new(
2329            make_bool_literal(true),
2330            make_bool_literal(false),
2331        )));
2332        assert_eq!(annotator.annotate(&or_expr), Some(DataType::Boolean));
2333
2334        // NOT returns boolean
2335        let not_expr = Expression::Not(Box::new(crate::expressions::UnaryOp::new(
2336            make_bool_literal(true),
2337        )));
2338        assert_eq!(annotator.annotate(&not_expr), Some(DataType::Boolean));
2339    }
2340
2341    // ========================================
2342    // Tests for newly implemented features
2343    // ========================================
2344
2345    #[test]
2346    fn test_subscript_array_type() {
2347        let mut annotator = TypeAnnotator::new(None, None);
2348
2349        // Array[index] returns element type
2350        let arr = Expression::Array(Box::new(crate::expressions::Array {
2351            expressions: vec![make_int_literal(1), make_int_literal(2)],
2352        }));
2353        let subscript = Expression::Subscript(Box::new(crate::expressions::Subscript {
2354            this: arr,
2355            index: make_int_literal(0),
2356        }));
2357        assert_eq!(
2358            annotator.annotate(&subscript),
2359            Some(DataType::Int {
2360                length: None,
2361                integer_spelling: false
2362            })
2363        );
2364    }
2365
2366    #[test]
2367    fn test_subscript_map_type() {
2368        let mut annotator = TypeAnnotator::new(None, None);
2369
2370        // Map[key] returns value type
2371        let map = Expression::Map(Box::new(crate::expressions::Map {
2372            keys: vec![make_string_literal("a")],
2373            values: vec![make_int_literal(1)],
2374        }));
2375        let subscript = Expression::Subscript(Box::new(crate::expressions::Subscript {
2376            this: map,
2377            index: make_string_literal("a"),
2378        }));
2379        assert_eq!(
2380            annotator.annotate(&subscript),
2381            Some(DataType::Int {
2382                length: None,
2383                integer_spelling: false
2384            })
2385        );
2386    }
2387
2388    #[test]
2389    fn test_struct_type() {
2390        let mut annotator = TypeAnnotator::new(None, None);
2391
2392        // STRUCT literal
2393        let struct_expr = Expression::Struct(Box::new(crate::expressions::Struct {
2394            fields: vec![
2395                (Some("name".to_string()), make_string_literal("Alice")),
2396                (Some("age".to_string()), make_int_literal(30)),
2397            ],
2398        }));
2399        let result = annotator.annotate(&struct_expr);
2400        assert!(matches!(result, Some(DataType::Struct { fields, .. }) if fields.len() == 2));
2401    }
2402
2403    #[test]
2404    fn test_map_type() {
2405        let mut annotator = TypeAnnotator::new(None, None);
2406
2407        // MAP literal
2408        let map_expr = Expression::Map(Box::new(crate::expressions::Map {
2409            keys: vec![make_string_literal("a"), make_string_literal("b")],
2410            values: vec![make_int_literal(1), make_int_literal(2)],
2411        }));
2412        let result = annotator.annotate(&map_expr);
2413        assert!(matches!(
2414            result,
2415            Some(DataType::Map { key_type, value_type })
2416            if matches!(*key_type, DataType::VarChar { .. })
2417               && matches!(*value_type, DataType::Int { .. })
2418        ));
2419    }
2420
2421    #[test]
2422    fn test_explode_array_type() {
2423        let mut annotator = TypeAnnotator::new(None, None);
2424
2425        // EXPLODE(array) returns element type
2426        let arr = Expression::Array(Box::new(crate::expressions::Array {
2427            expressions: vec![make_int_literal(1), make_int_literal(2)],
2428        }));
2429        let explode = Expression::Explode(Box::new(crate::expressions::UnaryFunc {
2430            this: arr,
2431            original_name: None,
2432            inferred_type: None,
2433        }));
2434        assert_eq!(
2435            annotator.annotate(&explode),
2436            Some(DataType::Int {
2437                length: None,
2438                integer_spelling: false
2439            })
2440        );
2441    }
2442
2443    #[test]
2444    fn test_unnest_array_type() {
2445        let mut annotator = TypeAnnotator::new(None, None);
2446
2447        // UNNEST(array) returns element type
2448        let arr = Expression::Array(Box::new(crate::expressions::Array {
2449            expressions: vec![make_string_literal("a"), make_string_literal("b")],
2450        }));
2451        let unnest = Expression::Unnest(Box::new(crate::expressions::UnnestFunc {
2452            this: arr,
2453            expressions: Vec::new(),
2454            with_ordinality: false,
2455            alias: None,
2456            offset_alias: None,
2457            inferred_type: None,
2458        }));
2459        assert_eq!(
2460            annotator.annotate(&unnest),
2461            Some(DataType::VarChar {
2462                length: None,
2463                parenthesized_length: false
2464            })
2465        );
2466    }
2467
2468    #[test]
2469    fn test_set_operation_type() {
2470        let mut annotator = TypeAnnotator::new(None, None);
2471
2472        // UNION/INTERSECT/EXCEPT return None (they produce relations, not scalars)
2473        let select = Expression::Select(Box::new(crate::expressions::Select::default()));
2474        let union = Expression::Union(Box::new(crate::expressions::Union {
2475            left: select.clone(),
2476            right: select.clone(),
2477            all: false,
2478            distinct: false,
2479            with: None,
2480            order_by: None,
2481            limit: None,
2482            offset: None,
2483            by_name: false,
2484            side: None,
2485            kind: None,
2486            corresponding: false,
2487            strict: false,
2488            on_columns: Vec::new(),
2489            distribute_by: None,
2490            sort_by: None,
2491            cluster_by: None,
2492        }));
2493        assert_eq!(annotator.annotate(&union), None);
2494    }
2495
2496    #[test]
2497    fn test_floor_ceil_input_dependent_types() {
2498        use crate::expressions::{CeilFunc, FloorFunc};
2499
2500        let mut annotator = TypeAnnotator::new(None, None);
2501
2502        // FLOOR/CEIL with integer literal → Double (integers get promoted)
2503        let floor_int = Expression::Floor(Box::new(FloorFunc {
2504            this: make_int_literal(42),
2505            scale: None,
2506            to: None,
2507        }));
2508        assert_eq!(
2509            annotator.annotate(&floor_int),
2510            Some(DataType::Double {
2511                precision: None,
2512                scale: None,
2513            })
2514        );
2515
2516        let ceil_int = Expression::Ceil(Box::new(CeilFunc {
2517            this: make_int_literal(42),
2518            decimals: None,
2519            to: None,
2520        }));
2521        assert_eq!(
2522            annotator.annotate(&ceil_int),
2523            Some(DataType::Double {
2524                precision: None,
2525                scale: None,
2526            })
2527        );
2528
2529        // FLOOR with float literal → Double (literals are always Double)
2530        let floor_float = Expression::Floor(Box::new(FloorFunc {
2531            this: make_float_literal(3.14),
2532            scale: None,
2533            to: None,
2534        }));
2535        assert_eq!(
2536            annotator.annotate(&floor_float),
2537            Some(DataType::Double {
2538                precision: None,
2539                scale: None,
2540            })
2541        );
2542
2543        // FLOOR via Function("FLOOR") path → falls through to arg-based inference
2544        let floor_fn =
2545            Expression::Function(Box::new(Function::new("FLOOR", vec![make_int_literal(1)])));
2546        assert_eq!(
2547            annotator.annotate(&floor_fn),
2548            Some(DataType::Int {
2549                length: None,
2550                integer_spelling: false,
2551            })
2552        );
2553    }
2554
2555    #[test]
2556    fn test_sign_preserves_input_type() {
2557        use crate::expressions::UnaryFunc;
2558
2559        let mut annotator = TypeAnnotator::new(None, None);
2560
2561        // SIGN with integer literal → Int (preserves input type)
2562        let sign_int = Expression::Sign(Box::new(UnaryFunc {
2563            this: make_int_literal(42),
2564            original_name: None,
2565            inferred_type: None,
2566        }));
2567        assert_eq!(
2568            annotator.annotate(&sign_int),
2569            Some(DataType::Int {
2570                length: None,
2571                integer_spelling: false,
2572            })
2573        );
2574
2575        // SIGN with float literal → Double (preserves input type)
2576        let sign_float = Expression::Sign(Box::new(UnaryFunc {
2577            this: make_float_literal(3.14),
2578            original_name: None,
2579            inferred_type: None,
2580        }));
2581        assert_eq!(
2582            annotator.annotate(&sign_float),
2583            Some(DataType::Double {
2584                precision: None,
2585                scale: None,
2586            })
2587        );
2588
2589        // SIGN with a CAST to INT → Int (preserves input type)
2590        let sign_cast = Expression::Sign(Box::new(UnaryFunc {
2591            this: Expression::Cast(Box::new(Cast {
2592                this: make_int_literal(42),
2593                to: DataType::Int {
2594                    length: None,
2595                    integer_spelling: false,
2596                },
2597                format: None,
2598                trailing_comments: Vec::new(),
2599                double_colon_syntax: false,
2600                default: None,
2601                inferred_type: None,
2602            })),
2603            original_name: None,
2604            inferred_type: None,
2605        }));
2606        assert_eq!(
2607            annotator.annotate(&sign_cast),
2608            Some(DataType::Int {
2609                length: None,
2610                integer_spelling: false,
2611            })
2612        );
2613    }
2614
2615    #[test]
2616    fn test_date_format_types() {
2617        use crate::expressions::{DateFormatFunc, TimeToStr};
2618
2619        let mut annotator = TypeAnnotator::new(None, None);
2620
2621        // DateFormat → VarChar
2622        let date_fmt = Expression::DateFormat(Box::new(DateFormatFunc {
2623            this: make_string_literal("2024-01-01"),
2624            format: make_string_literal("%Y-%m-%d"),
2625        }));
2626        assert_eq!(
2627            annotator.annotate(&date_fmt),
2628            Some(DataType::VarChar {
2629                length: None,
2630                parenthesized_length: false,
2631            })
2632        );
2633
2634        // FormatDate → VarChar
2635        let format_date = Expression::FormatDate(Box::new(DateFormatFunc {
2636            this: make_string_literal("2024-01-01"),
2637            format: make_string_literal("%Y-%m-%d"),
2638        }));
2639        assert_eq!(
2640            annotator.annotate(&format_date),
2641            Some(DataType::VarChar {
2642                length: None,
2643                parenthesized_length: false,
2644            })
2645        );
2646
2647        // TimeToStr → VarChar
2648        let time_to_str = Expression::TimeToStr(Box::new(TimeToStr {
2649            this: Box::new(make_string_literal("2024-01-01")),
2650            format: "%Y-%m-%d".to_string(),
2651            culture: None,
2652            zone: None,
2653        }));
2654        assert_eq!(
2655            annotator.annotate(&time_to_str),
2656            Some(DataType::VarChar {
2657                length: None,
2658                parenthesized_length: false,
2659            })
2660        );
2661
2662        // DATE_FORMAT via Function path → VarChar (uses function_return_types)
2663        let date_fmt_fn = Expression::Function(Box::new(Function::new(
2664            "DATE_FORMAT",
2665            vec![
2666                make_string_literal("2024-01-01"),
2667                make_string_literal("%Y-%m-%d"),
2668            ],
2669        )));
2670        assert_eq!(
2671            annotator.annotate(&date_fmt_fn),
2672            Some(DataType::VarChar {
2673                length: None,
2674                parenthesized_length: false,
2675            })
2676        );
2677    }
2678
2679    // ===== In-place annotation tests (Step 9) =====
2680
2681    #[test]
2682    fn test_annotate_in_place_sets_type_on_root() {
2683        // Literals don't have inferred_type field, so test with a BinaryOp
2684        let mut expr = Expression::Add(Box::new(BinaryOp::new(
2685            make_int_literal(1),
2686            make_int_literal(2),
2687        )));
2688        annotate_types(&mut expr, None, None);
2689        assert_eq!(
2690            expr.inferred_type(),
2691            Some(&DataType::Int {
2692                length: None,
2693                integer_spelling: false,
2694            })
2695        );
2696    }
2697
2698    #[test]
2699    fn test_annotate_in_place_sets_types_on_children() {
2700        // (a + b) + (c - d) where all are ints
2701        // This tests that inner BinaryOp children also get annotated
2702        let inner_add = Expression::Add(Box::new(BinaryOp::new(
2703            make_int_literal(1),
2704            make_float_literal(2.5),
2705        )));
2706        let inner_sub = Expression::Sub(Box::new(BinaryOp::new(
2707            make_int_literal(3),
2708            make_int_literal(4),
2709        )));
2710        let mut expr = Expression::Add(Box::new(BinaryOp::new(inner_add, inner_sub)));
2711        annotate_types(&mut expr, None, None);
2712
2713        // Root (Add) should be Double (wider of Double and Int)
2714        assert_eq!(
2715            expr.inferred_type(),
2716            Some(&DataType::Double {
2717                precision: None,
2718                scale: None,
2719            })
2720        );
2721
2722        // Children should also have types
2723        if let Expression::Add(op) = &expr {
2724            // Left child (1 + 2.5) should be Double
2725            assert_eq!(
2726                op.left.inferred_type(),
2727                Some(&DataType::Double {
2728                    precision: None,
2729                    scale: None,
2730                })
2731            );
2732            // Right child (3 - 4) should be Int
2733            assert_eq!(
2734                op.right.inferred_type(),
2735                Some(&DataType::Int {
2736                    length: None,
2737                    integer_spelling: false,
2738                })
2739            );
2740        } else {
2741            panic!("Expected Add expression");
2742        }
2743    }
2744
2745    #[test]
2746    fn test_annotate_in_place_comparison() {
2747        let mut expr = Expression::Eq(Box::new(BinaryOp::new(
2748            make_int_literal(1),
2749            make_int_literal(2),
2750        )));
2751        annotate_types(&mut expr, None, None);
2752        assert_eq!(expr.inferred_type(), Some(&DataType::Boolean));
2753    }
2754
2755    #[test]
2756    fn test_annotate_in_place_cast() {
2757        let mut expr = Expression::Cast(Box::new(Cast {
2758            this: make_int_literal(42),
2759            to: DataType::VarChar {
2760                length: None,
2761                parenthesized_length: false,
2762            },
2763            trailing_comments: vec![],
2764            double_colon_syntax: false,
2765            format: None,
2766            default: None,
2767            inferred_type: None,
2768        }));
2769        annotate_types(&mut expr, None, None);
2770        assert_eq!(
2771            expr.inferred_type(),
2772            Some(&DataType::VarChar {
2773                length: None,
2774                parenthesized_length: false,
2775            })
2776        );
2777    }
2778
2779    #[test]
2780    fn test_annotate_in_place_nested_expression() {
2781        // (1 + 2) > 0  -> should be Boolean at root, Int for the Add
2782        let add = Expression::Add(Box::new(BinaryOp::new(
2783            make_int_literal(1),
2784            make_int_literal(2),
2785        )));
2786        let mut expr = Expression::Gt(Box::new(BinaryOp::new(add, make_int_literal(0))));
2787        annotate_types(&mut expr, None, None);
2788
2789        assert_eq!(expr.inferred_type(), Some(&DataType::Boolean));
2790
2791        // The left child (Add) should be Int
2792        if let Expression::Gt(op) = &expr {
2793            assert_eq!(
2794                op.left.inferred_type(),
2795                Some(&DataType::Int {
2796                    length: None,
2797                    integer_spelling: false,
2798                })
2799            );
2800        }
2801    }
2802
2803    #[test]
2804    fn test_annotate_in_place_parsed_sql() {
2805        use crate::parser::Parser;
2806        let mut expr =
2807            Parser::parse_sql("SELECT 1 + 2.0, 'hello', TRUE").expect("parse failed")[0].clone();
2808        annotate_types(&mut expr, None, None);
2809
2810        // The expression tree should have types annotated throughout
2811        // We can't easily inspect deep inside a parsed Select, but at minimum
2812        // the root Select itself won't have a type (it's not value-producing)
2813        assert!(expr.inferred_type().is_none());
2814    }
2815
2816    #[test]
2817    fn test_inferred_type_json_roundtrip() {
2818        let mut expr = Expression::Add(Box::new(BinaryOp::new(
2819            make_int_literal(1),
2820            make_int_literal(2),
2821        )));
2822        annotate_types(&mut expr, None, None);
2823
2824        // Serialize to JSON
2825        let json = serde_json::to_string(&expr).expect("serialize failed");
2826        // The JSON should contain the inferred_type
2827        assert!(json.contains("inferred_type"));
2828
2829        // Deserialize back
2830        let deserialized: Expression = serde_json::from_str(&json).expect("deserialize failed");
2831        assert_eq!(
2832            deserialized.inferred_type(),
2833            Some(&DataType::Int {
2834                length: None,
2835                integer_spelling: false,
2836            })
2837        );
2838    }
2839
2840    #[test]
2841    fn test_inferred_type_none_not_serialized() {
2842        // When inferred_type is None, it should not appear in JSON
2843        let expr = Expression::Add(Box::new(BinaryOp::new(
2844            make_int_literal(1),
2845            make_int_literal(2),
2846        )));
2847        let json = serde_json::to_string(&expr).expect("serialize failed");
2848        assert!(!json.contains("inferred_type"));
2849    }
2850
2851    #[test]
2852    fn test_annotate_if_func_bigquery_node_and_alias_type() {
2853        let mut schema = MappingSchema::with_dialect(DialectType::BigQuery);
2854        schema
2855            .add_table(
2856                "t",
2857                &[("col1".to_string(), DataType::String { length: None })],
2858                None,
2859            )
2860            .unwrap();
2861
2862        let mut expr = parse_one(
2863            "SELECT IF(col1 IS NOT NULL, 1, 0) AS x FROM t",
2864            DialectType::BigQuery,
2865        )
2866        .unwrap();
2867        annotate_types(&mut expr, Some(&schema), Some(DialectType::BigQuery));
2868
2869        let Expression::Select(select) = &expr else {
2870            panic!("expected select");
2871        };
2872        let Expression::Alias(alias) = &select.expressions[0] else {
2873            panic!("expected alias");
2874        };
2875
2876        assert_eq!(
2877            alias.this.inferred_type(),
2878            Some(&DataType::Int {
2879                length: None,
2880                integer_spelling: false,
2881            })
2882        );
2883        assert_eq!(
2884            select.expressions[0].inferred_type(),
2885            Some(&DataType::Int {
2886                length: None,
2887                integer_spelling: false,
2888            })
2889        );
2890    }
2891
2892    #[test]
2893    fn test_annotate_nvl2_node_type() {
2894        let mut expr = parse_one("SELECT NVL2(a, 1, 0) AS x", DialectType::Generic).unwrap();
2895        annotate_types(&mut expr, None, None);
2896
2897        let Expression::Select(select) = &expr else {
2898            panic!("expected select");
2899        };
2900        let Expression::Alias(alias) = &select.expressions[0] else {
2901            panic!("expected alias");
2902        };
2903
2904        assert_eq!(
2905            alias.this.inferred_type(),
2906            Some(&DataType::Int {
2907                length: None,
2908                integer_spelling: false,
2909            })
2910        );
2911    }
2912
2913    #[test]
2914    fn test_annotate_count_node_type() {
2915        let mut expr = parse_one("SELECT COUNT(1) AS x", DialectType::Generic).unwrap();
2916        annotate_types(&mut expr, None, None);
2917
2918        let Expression::Select(select) = &expr else {
2919            panic!("expected select");
2920        };
2921        let Expression::Alias(alias) = &select.expressions[0] else {
2922            panic!("expected alias");
2923        };
2924
2925        assert_eq!(
2926            alias.this.inferred_type(),
2927            Some(&DataType::BigInt { length: None })
2928        );
2929    }
2930
2931    #[test]
2932    fn test_annotate_group_concat_node_type() {
2933        let mut expr = parse_one("SELECT GROUP_CONCAT(a) AS x", DialectType::Generic).unwrap();
2934        annotate_types(&mut expr, None, None);
2935
2936        let Expression::Select(select) = &expr else {
2937            panic!("expected select");
2938        };
2939        let Expression::Alias(alias) = &select.expressions[0] else {
2940            panic!("expected alias");
2941        };
2942
2943        assert_eq!(
2944            alias.this.inferred_type(),
2945            Some(&DataType::VarChar {
2946                length: None,
2947                parenthesized_length: false,
2948            })
2949        );
2950    }
2951
2952    #[test]
2953    fn test_annotate_sum_if_generic_aggregate_type() {
2954        let mut expr =
2955            parse_one("SELECT SUM_IF(1, a > 0) AS x FROM t", DialectType::Generic).unwrap();
2956        annotate_types(&mut expr, None, None);
2957
2958        let Expression::Select(select) = &expr else {
2959            panic!("expected select");
2960        };
2961        let Expression::Alias(alias) = &select.expressions[0] else {
2962            panic!("expected alias");
2963        };
2964
2965        assert_eq!(
2966            select.expressions[0].inferred_type(),
2967            Some(&DataType::BigInt { length: None })
2968        );
2969        assert_eq!(
2970            alias.this.inferred_type(),
2971            Some(&DataType::BigInt { length: None })
2972        );
2973    }
2974}