Edit on GitHub

sqlglot.optimizer.annotate_types

  1from __future__ import annotations
  2
  3import functools
  4import typing as t
  5
  6from sqlglot import exp
  7from sqlglot.helper import (
  8    ensure_list,
  9    is_date_unit,
 10    is_iso_date,
 11    is_iso_datetime,
 12    seq_get,
 13)
 14from sqlglot.optimizer.scope import Scope, traverse_scope
 15from sqlglot.schema import Schema, ensure_schema
 16from sqlglot.dialects.dialect import Dialect
 17
 18if t.TYPE_CHECKING:
 19    from sqlglot._typing import B, E
 20
 21    BinaryCoercionFunc = t.Callable[[exp.Expression, exp.Expression], exp.DataType.Type]
 22    BinaryCoercions = t.Dict[
 23        t.Tuple[exp.DataType.Type, exp.DataType.Type],
 24        BinaryCoercionFunc,
 25    ]
 26
 27    from sqlglot.dialects.dialect import DialectType, AnnotatorsType
 28
 29
 30def annotate_types(
 31    expression: E,
 32    schema: t.Optional[t.Dict | Schema] = None,
 33    annotators: t.Optional[AnnotatorsType] = None,
 34    coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None,
 35    dialect: t.Optional[DialectType] = None,
 36) -> E:
 37    """
 38    Infers the types of an expression, annotating its AST accordingly.
 39
 40    Example:
 41        >>> import sqlglot
 42        >>> schema = {"y": {"cola": "SMALLINT"}}
 43        >>> sql = "SELECT x.cola + 2.5 AS cola FROM (SELECT y.cola AS cola FROM y AS y) AS x"
 44        >>> annotated_expr = annotate_types(sqlglot.parse_one(sql), schema=schema)
 45        >>> annotated_expr.expressions[0].type.this  # Get the type of "x.cola + 2.5 AS cola"
 46        <Type.DOUBLE: 'DOUBLE'>
 47
 48    Args:
 49        expression: Expression to annotate.
 50        schema: Database schema.
 51        annotators: Maps expression type to corresponding annotation function.
 52        coerces_to: Maps expression type to set of types that it can be coerced into.
 53
 54    Returns:
 55        The expression annotated with types.
 56    """
 57
 58    schema = ensure_schema(schema)
 59
 60    return TypeAnnotator(schema, annotators, coerces_to, dialect=dialect).annotate(expression)
 61
 62
 63def _coerce_date_literal(l: exp.Expression, unit: t.Optional[exp.Expression]) -> exp.DataType.Type:
 64    date_text = l.name
 65    is_iso_date_ = is_iso_date(date_text)
 66
 67    if is_iso_date_ and is_date_unit(unit):
 68        return exp.DataType.Type.DATE
 69
 70    # An ISO date is also an ISO datetime, but not vice versa
 71    if is_iso_date_ or is_iso_datetime(date_text):
 72        return exp.DataType.Type.DATETIME
 73
 74    return exp.DataType.Type.UNKNOWN
 75
 76
 77def _coerce_date(l: exp.Expression, unit: t.Optional[exp.Expression]) -> exp.DataType.Type:
 78    if not is_date_unit(unit):
 79        return exp.DataType.Type.DATETIME
 80    return l.type.this if l.type else exp.DataType.Type.UNKNOWN
 81
 82
 83def swap_args(func: BinaryCoercionFunc) -> BinaryCoercionFunc:
 84    @functools.wraps(func)
 85    def _swapped(l: exp.Expression, r: exp.Expression) -> exp.DataType.Type:
 86        return func(r, l)
 87
 88    return _swapped
 89
 90
 91def swap_all(coercions: BinaryCoercions) -> BinaryCoercions:
 92    return {**coercions, **{(b, a): swap_args(func) for (a, b), func in coercions.items()}}
 93
 94
 95class _TypeAnnotator(type):
 96    def __new__(cls, clsname, bases, attrs):
 97        klass = super().__new__(cls, clsname, bases, attrs)
 98
 99        # Highest-to-lowest type precedence, as specified in Spark's docs (ANSI):
100        # https://spark.apache.org/docs/3.2.0/sql-ref-ansi-compliance.html
101        text_precedence = (
102            exp.DataType.Type.TEXT,
103            exp.DataType.Type.NVARCHAR,
104            exp.DataType.Type.VARCHAR,
105            exp.DataType.Type.NCHAR,
106            exp.DataType.Type.CHAR,
107        )
108        numeric_precedence = (
109            exp.DataType.Type.DOUBLE,
110            exp.DataType.Type.FLOAT,
111            exp.DataType.Type.DECIMAL,
112            exp.DataType.Type.BIGINT,
113            exp.DataType.Type.INT,
114            exp.DataType.Type.SMALLINT,
115            exp.DataType.Type.TINYINT,
116        )
117        timelike_precedence = (
118            exp.DataType.Type.TIMESTAMPLTZ,
119            exp.DataType.Type.TIMESTAMPTZ,
120            exp.DataType.Type.TIMESTAMP,
121            exp.DataType.Type.DATETIME,
122            exp.DataType.Type.DATE,
123        )
124
125        for type_precedence in (text_precedence, numeric_precedence, timelike_precedence):
126            coerces_to = set()
127            for data_type in type_precedence:
128                klass.COERCES_TO[data_type] = coerces_to.copy()
129                coerces_to |= {data_type}
130
131        return klass
132
133
134class TypeAnnotator(metaclass=_TypeAnnotator):
135    NESTED_TYPES = {
136        exp.DataType.Type.ARRAY,
137    }
138
139    # Specifies what types a given type can be coerced into (autofilled)
140    COERCES_TO: t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]] = {}
141
142    # Coercion functions for binary operations.
143    # Map of type pairs to a callable that takes both sides of the binary operation and returns the resulting type.
144    BINARY_COERCIONS: BinaryCoercions = {
145        **swap_all(
146            {
147                (t, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date_literal(
148                    l, r.args.get("unit")
149                )
150                for t in exp.DataType.TEXT_TYPES
151            }
152        ),
153        **swap_all(
154            {
155                # text + numeric will yield the numeric type to match most dialects' semantics
156                (text, numeric): lambda l, r: t.cast(
157                    exp.DataType.Type, l.type if l.type in exp.DataType.NUMERIC_TYPES else r.type
158                )
159                for text in exp.DataType.TEXT_TYPES
160                for numeric in exp.DataType.NUMERIC_TYPES
161            }
162        ),
163        **swap_all(
164            {
165                (exp.DataType.Type.DATE, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date(
166                    l, r.args.get("unit")
167                ),
168            }
169        ),
170    }
171
172    def __init__(
173        self,
174        schema: Schema,
175        annotators: t.Optional[AnnotatorsType] = None,
176        coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None,
177        binary_coercions: t.Optional[BinaryCoercions] = None,
178        dialect: t.Optional[DialectType] = None,
179    ) -> None:
180        self.schema = schema
181        self.annotators = annotators or Dialect.get_or_raise(dialect).ANNOTATORS
182        self.coerces_to = coerces_to or self.COERCES_TO
183        self.binary_coercions = binary_coercions or self.BINARY_COERCIONS
184
185        # Caches the ids of annotated sub-Expressions, to ensure we only visit them once
186        self._visited: t.Set[int] = set()
187
188    def _set_type(
189        self, expression: exp.Expression, target_type: t.Optional[exp.DataType | exp.DataType.Type]
190    ) -> None:
191        expression.type = target_type or exp.DataType.Type.UNKNOWN  # type: ignore
192        self._visited.add(id(expression))
193
194    def annotate(self, expression: E) -> E:
195        for scope in traverse_scope(expression):
196            self.annotate_scope(scope)
197        return self._maybe_annotate(expression)  # This takes care of non-traversable expressions
198
199    def annotate_scope(self, scope: Scope) -> None:
200        selects = {}
201        for name, source in scope.sources.items():
202            if not isinstance(source, Scope):
203                continue
204            if isinstance(source.expression, exp.UDTF):
205                values = []
206
207                if isinstance(source.expression, exp.Lateral):
208                    if isinstance(source.expression.this, exp.Explode):
209                        values = [source.expression.this.this]
210                elif isinstance(source.expression, exp.Unnest):
211                    values = [source.expression]
212                else:
213                    values = source.expression.expressions[0].expressions
214
215                if not values:
216                    continue
217
218                selects[name] = {
219                    alias: column
220                    for alias, column in zip(
221                        source.expression.alias_column_names,
222                        values,
223                    )
224                }
225            else:
226                selects[name] = {
227                    select.alias_or_name: select for select in source.expression.selects
228                }
229
230        # First annotate the current scope's column references
231        for col in scope.columns:
232            if not col.table:
233                continue
234
235            source = scope.sources.get(col.table)
236            if isinstance(source, exp.Table):
237                self._set_type(col, self.schema.get_column_type(source, col))
238            elif source:
239                if col.table in selects and col.name in selects[col.table]:
240                    self._set_type(col, selects[col.table][col.name].type)
241                elif isinstance(source.expression, exp.Unnest):
242                    self._set_type(col, source.expression.type)
243
244        # Then (possibly) annotate the remaining expressions in the scope
245        self._maybe_annotate(scope.expression)
246
247    def _maybe_annotate(self, expression: E) -> E:
248        if id(expression) in self._visited:
249            return expression  # We've already inferred the expression's type
250
251        annotator = self.annotators.get(expression.__class__)
252
253        return (
254            annotator(self, expression)
255            if annotator
256            else self._annotate_with_type(expression, exp.DataType.Type.UNKNOWN)
257        )
258
259    def _annotate_args(self, expression: E) -> E:
260        for value in expression.iter_expressions():
261            self._maybe_annotate(value)
262
263        return expression
264
265    def _maybe_coerce(
266        self, type1: exp.DataType | exp.DataType.Type, type2: exp.DataType | exp.DataType.Type
267    ) -> exp.DataType | exp.DataType.Type:
268        type1_value = type1.this if isinstance(type1, exp.DataType) else type1
269        type2_value = type2.this if isinstance(type2, exp.DataType) else type2
270
271        # We propagate the NULL / UNKNOWN types upwards if found
272        if exp.DataType.Type.NULL in (type1_value, type2_value):
273            return exp.DataType.Type.NULL
274        if exp.DataType.Type.UNKNOWN in (type1_value, type2_value):
275            return exp.DataType.Type.UNKNOWN
276
277        return type2_value if type2_value in self.coerces_to.get(type1_value, {}) else type1_value
278
279    def _annotate_binary(self, expression: B) -> B:
280        self._annotate_args(expression)
281
282        left, right = expression.left, expression.right
283        left_type, right_type = left.type.this, right.type.this  # type: ignore
284
285        if isinstance(expression, exp.Connector):
286            if left_type == exp.DataType.Type.NULL and right_type == exp.DataType.Type.NULL:
287                self._set_type(expression, exp.DataType.Type.NULL)
288            elif exp.DataType.Type.NULL in (left_type, right_type):
289                self._set_type(
290                    expression,
291                    exp.DataType.build("NULLABLE", expressions=exp.DataType.build("BOOLEAN")),
292                )
293            else:
294                self._set_type(expression, exp.DataType.Type.BOOLEAN)
295        elif isinstance(expression, exp.Predicate):
296            self._set_type(expression, exp.DataType.Type.BOOLEAN)
297        elif (left_type, right_type) in self.binary_coercions:
298            self._set_type(expression, self.binary_coercions[(left_type, right_type)](left, right))
299        else:
300            self._set_type(expression, self._maybe_coerce(left_type, right_type))
301
302        return expression
303
304    def _annotate_unary(self, expression: E) -> E:
305        self._annotate_args(expression)
306
307        if isinstance(expression, exp.Condition) and not isinstance(expression, exp.Paren):
308            self._set_type(expression, exp.DataType.Type.BOOLEAN)
309        else:
310            self._set_type(expression, expression.this.type)
311
312        return expression
313
314    def _annotate_literal(self, expression: exp.Literal) -> exp.Literal:
315        if expression.is_string:
316            self._set_type(expression, exp.DataType.Type.VARCHAR)
317        elif expression.is_int:
318            self._set_type(expression, exp.DataType.Type.INT)
319        else:
320            self._set_type(expression, exp.DataType.Type.DOUBLE)
321
322        return expression
323
324    def _annotate_with_type(
325        self, expression: E, target_type: exp.DataType | exp.DataType.Type
326    ) -> E:
327        self._set_type(expression, target_type)
328        return self._annotate_args(expression)
329
330    @t.no_type_check
331    def _annotate_by_args(
332        self,
333        expression: E,
334        *args: str,
335        promote: bool = False,
336        array: bool = False,
337    ) -> E:
338        self._annotate_args(expression)
339
340        expressions: t.List[exp.Expression] = []
341        for arg in args:
342            arg_expr = expression.args.get(arg)
343            expressions.extend(expr for expr in ensure_list(arg_expr) if expr)
344
345        last_datatype = None
346        for expr in expressions:
347            expr_type = expr.type
348
349            # Stop at the first nested data type found - we don't want to _maybe_coerce nested types
350            if expr_type.args.get("nested"):
351                last_datatype = expr_type
352                break
353
354            if not expr_type.is_type(exp.DataType.Type.NULL, exp.DataType.Type.UNKNOWN):
355                last_datatype = self._maybe_coerce(last_datatype or expr_type, expr_type)
356
357        self._set_type(expression, last_datatype or exp.DataType.Type.UNKNOWN)
358
359        if promote:
360            if expression.type.this in exp.DataType.INTEGER_TYPES:
361                self._set_type(expression, exp.DataType.Type.BIGINT)
362            elif expression.type.this in exp.DataType.FLOAT_TYPES:
363                self._set_type(expression, exp.DataType.Type.DOUBLE)
364
365        if array:
366            self._set_type(
367                expression,
368                exp.DataType(
369                    this=exp.DataType.Type.ARRAY, expressions=[expression.type], nested=True
370                ),
371            )
372
373        return expression
374
375    def _annotate_timeunit(
376        self, expression: exp.TimeUnit | exp.DateTrunc
377    ) -> exp.TimeUnit | exp.DateTrunc:
378        self._annotate_args(expression)
379
380        if expression.this.type.this in exp.DataType.TEXT_TYPES:
381            datatype = _coerce_date_literal(expression.this, expression.unit)
382        elif expression.this.type.this in exp.DataType.TEMPORAL_TYPES:
383            datatype = _coerce_date(expression.this, expression.unit)
384        else:
385            datatype = exp.DataType.Type.UNKNOWN
386
387        self._set_type(expression, datatype)
388        return expression
389
390    def _annotate_bracket(self, expression: exp.Bracket) -> exp.Bracket:
391        self._annotate_args(expression)
392
393        bracket_arg = expression.expressions[0]
394        this = expression.this
395
396        if isinstance(bracket_arg, exp.Slice):
397            self._set_type(expression, this.type)
398        elif this.type.is_type(exp.DataType.Type.ARRAY):
399            self._set_type(expression, seq_get(this.type.expressions, 0))
400        elif isinstance(this, (exp.Map, exp.VarMap)) and bracket_arg in this.keys:
401            index = this.keys.index(bracket_arg)
402            value = seq_get(this.values, index)
403            self._set_type(expression, value.type if value else None)
404        else:
405            self._set_type(expression, exp.DataType.Type.UNKNOWN)
406
407        return expression
408
409    def _annotate_div(self, expression: exp.Div) -> exp.Div:
410        self._annotate_args(expression)
411
412        left_type, right_type = expression.left.type.this, expression.right.type.this  # type: ignore
413
414        if (
415            expression.args.get("typed")
416            and left_type in exp.DataType.INTEGER_TYPES
417            and right_type in exp.DataType.INTEGER_TYPES
418        ):
419            self._set_type(expression, exp.DataType.Type.BIGINT)
420        else:
421            self._set_type(expression, self._maybe_coerce(left_type, right_type))
422            if expression.type and expression.type.this not in exp.DataType.REAL_TYPES:
423                self._set_type(
424                    expression, self._maybe_coerce(expression.type, exp.DataType.Type.DOUBLE)
425                )
426
427        return expression
428
429    def _annotate_dot(self, expression: exp.Dot) -> exp.Dot:
430        self._annotate_args(expression)
431        self._set_type(expression, None)
432        this_type = expression.this.type
433
434        if this_type and this_type.is_type(exp.DataType.Type.STRUCT):
435            for e in this_type.expressions:
436                if e.name == expression.expression.name:
437                    self._set_type(expression, e.kind)
438                    break
439
440        return expression
441
442    def _annotate_explode(self, expression: exp.Explode) -> exp.Explode:
443        self._annotate_args(expression)
444        self._set_type(expression, seq_get(expression.this.type.expressions, 0))
445        return expression
446
447    def _annotate_unnest(self, expression: exp.Unnest) -> exp.Unnest:
448        self._annotate_args(expression)
449        child = seq_get(expression.expressions, 0)
450
451        if child and child.is_type(exp.DataType.Type.ARRAY):
452            expr_type = seq_get(child.type.expressions, 0)
453        else:
454            expr_type = None
455
456        self._set_type(expression, expr_type)
457        return expression
458
459    def _annotate_struct_value(
460        self, expression: exp.Expression
461    ) -> t.Optional[exp.DataType] | exp.ColumnDef:
462        alias = expression.args.get("alias")
463        if alias:
464            return exp.ColumnDef(this=alias.copy(), kind=expression.type)
465
466        # Case: key = value or key := value
467        if expression.expression:
468            return exp.ColumnDef(this=expression.this.copy(), kind=expression.expression.type)
469
470        return expression.type
471
472    def _annotate_struct(self, expression: exp.Struct) -> exp.Struct:
473        self._annotate_args(expression)
474        self._set_type(
475            expression,
476            exp.DataType(
477                this=exp.DataType.Type.STRUCT,
478                expressions=[self._annotate_struct_value(expr) for expr in expression.expressions],
479                nested=True,
480            ),
481        )
482        return expression
483
484    @t.overload
485    def _annotate_map(self, expression: exp.Map) -> exp.Map: ...
486
487    @t.overload
488    def _annotate_map(self, expression: exp.VarMap) -> exp.VarMap: ...
489
490    def _annotate_map(self, expression):
491        self._annotate_args(expression)
492
493        keys = expression.args.get("keys")
494        values = expression.args.get("values")
495
496        map_type = exp.DataType(this=exp.DataType.Type.MAP)
497        if isinstance(keys, exp.Array) and isinstance(values, exp.Array):
498            key_type = seq_get(keys.type.expressions, 0) or exp.DataType.Type.UNKNOWN
499            value_type = seq_get(values.type.expressions, 0) or exp.DataType.Type.UNKNOWN
500
501            if key_type != exp.DataType.Type.UNKNOWN and value_type != exp.DataType.Type.UNKNOWN:
502                map_type.set("expressions", [key_type, value_type])
503                map_type.set("nested", True)
504
505        self._set_type(expression, map_type)
506        return expression
507
508    def _annotate_to_map(self, expression: exp.ToMap) -> exp.ToMap:
509        self._annotate_args(expression)
510
511        map_type = exp.DataType(this=exp.DataType.Type.MAP)
512        arg = expression.this
513        if arg.is_type(exp.DataType.Type.STRUCT):
514            for coldef in arg.type.expressions:
515                kind = coldef.kind
516                if kind != exp.DataType.Type.UNKNOWN:
517                    map_type.set("expressions", [exp.DataType.build("varchar"), kind])
518                    map_type.set("nested", True)
519                    break
520
521        self._set_type(expression, map_type)
522        return expression
523
524    def _annotate_extract(self, expression: exp.Extract) -> exp.Extract:
525        self._annotate_args(expression)
526        part = expression.name
527        if part == "TIME":
528            self._set_type(expression, exp.DataType.Type.TIME)
529        elif part == "DATE":
530            self._set_type(expression, exp.DataType.Type.DATE)
531        else:
532            self._set_type(expression, exp.DataType.Type.INT)
533        return expression
def annotate_types( expression: ~E, schema: Union[Dict, sqlglot.schema.Schema, NoneType] = None, annotators: Optional[Dict[Type[~E], Callable[[TypeAnnotator, ~E], ~E]]] = None, coerces_to: Optional[Dict[sqlglot.expressions.DataType.Type, Set[sqlglot.expressions.DataType.Type]]] = None, dialect: Union[str, sqlglot.dialects.dialect.Dialect, Type[sqlglot.dialects.dialect.Dialect], NoneType] = None) -> ~E:
31def annotate_types(
32    expression: E,
33    schema: t.Optional[t.Dict | Schema] = None,
34    annotators: t.Optional[AnnotatorsType] = None,
35    coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None,
36    dialect: t.Optional[DialectType] = None,
37) -> E:
38    """
39    Infers the types of an expression, annotating its AST accordingly.
40
41    Example:
42        >>> import sqlglot
43        >>> schema = {"y": {"cola": "SMALLINT"}}
44        >>> sql = "SELECT x.cola + 2.5 AS cola FROM (SELECT y.cola AS cola FROM y AS y) AS x"
45        >>> annotated_expr = annotate_types(sqlglot.parse_one(sql), schema=schema)
46        >>> annotated_expr.expressions[0].type.this  # Get the type of "x.cola + 2.5 AS cola"
47        <Type.DOUBLE: 'DOUBLE'>
48
49    Args:
50        expression: Expression to annotate.
51        schema: Database schema.
52        annotators: Maps expression type to corresponding annotation function.
53        coerces_to: Maps expression type to set of types that it can be coerced into.
54
55    Returns:
56        The expression annotated with types.
57    """
58
59    schema = ensure_schema(schema)
60
61    return TypeAnnotator(schema, annotators, coerces_to, dialect=dialect).annotate(expression)

Infers the types of an expression, annotating its AST accordingly.

Example:
>>> import sqlglot
>>> schema = {"y": {"cola": "SMALLINT"}}
>>> sql = "SELECT x.cola + 2.5 AS cola FROM (SELECT y.cola AS cola FROM y AS y) AS x"
>>> annotated_expr = annotate_types(sqlglot.parse_one(sql), schema=schema)
>>> annotated_expr.expressions[0].type.this  # Get the type of "x.cola + 2.5 AS cola"
<Type.DOUBLE: 'DOUBLE'>
Arguments:
  • expression: Expression to annotate.
  • schema: Database schema.
  • annotators: Maps expression type to corresponding annotation function.
  • coerces_to: Maps expression type to set of types that it can be coerced into.
Returns:

The expression annotated with types.

84def swap_args(func: BinaryCoercionFunc) -> BinaryCoercionFunc:
85    @functools.wraps(func)
86    def _swapped(l: exp.Expression, r: exp.Expression) -> exp.DataType.Type:
87        return func(r, l)
88
89    return _swapped
92def swap_all(coercions: BinaryCoercions) -> BinaryCoercions:
93    return {**coercions, **{(b, a): swap_args(func) for (a, b), func in coercions.items()}}
class TypeAnnotator:
135class TypeAnnotator(metaclass=_TypeAnnotator):
136    NESTED_TYPES = {
137        exp.DataType.Type.ARRAY,
138    }
139
140    # Specifies what types a given type can be coerced into (autofilled)
141    COERCES_TO: t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]] = {}
142
143    # Coercion functions for binary operations.
144    # Map of type pairs to a callable that takes both sides of the binary operation and returns the resulting type.
145    BINARY_COERCIONS: BinaryCoercions = {
146        **swap_all(
147            {
148                (t, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date_literal(
149                    l, r.args.get("unit")
150                )
151                for t in exp.DataType.TEXT_TYPES
152            }
153        ),
154        **swap_all(
155            {
156                # text + numeric will yield the numeric type to match most dialects' semantics
157                (text, numeric): lambda l, r: t.cast(
158                    exp.DataType.Type, l.type if l.type in exp.DataType.NUMERIC_TYPES else r.type
159                )
160                for text in exp.DataType.TEXT_TYPES
161                for numeric in exp.DataType.NUMERIC_TYPES
162            }
163        ),
164        **swap_all(
165            {
166                (exp.DataType.Type.DATE, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date(
167                    l, r.args.get("unit")
168                ),
169            }
170        ),
171    }
172
173    def __init__(
174        self,
175        schema: Schema,
176        annotators: t.Optional[AnnotatorsType] = None,
177        coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None,
178        binary_coercions: t.Optional[BinaryCoercions] = None,
179        dialect: t.Optional[DialectType] = None,
180    ) -> None:
181        self.schema = schema
182        self.annotators = annotators or Dialect.get_or_raise(dialect).ANNOTATORS
183        self.coerces_to = coerces_to or self.COERCES_TO
184        self.binary_coercions = binary_coercions or self.BINARY_COERCIONS
185
186        # Caches the ids of annotated sub-Expressions, to ensure we only visit them once
187        self._visited: t.Set[int] = set()
188
189    def _set_type(
190        self, expression: exp.Expression, target_type: t.Optional[exp.DataType | exp.DataType.Type]
191    ) -> None:
192        expression.type = target_type or exp.DataType.Type.UNKNOWN  # type: ignore
193        self._visited.add(id(expression))
194
195    def annotate(self, expression: E) -> E:
196        for scope in traverse_scope(expression):
197            self.annotate_scope(scope)
198        return self._maybe_annotate(expression)  # This takes care of non-traversable expressions
199
200    def annotate_scope(self, scope: Scope) -> None:
201        selects = {}
202        for name, source in scope.sources.items():
203            if not isinstance(source, Scope):
204                continue
205            if isinstance(source.expression, exp.UDTF):
206                values = []
207
208                if isinstance(source.expression, exp.Lateral):
209                    if isinstance(source.expression.this, exp.Explode):
210                        values = [source.expression.this.this]
211                elif isinstance(source.expression, exp.Unnest):
212                    values = [source.expression]
213                else:
214                    values = source.expression.expressions[0].expressions
215
216                if not values:
217                    continue
218
219                selects[name] = {
220                    alias: column
221                    for alias, column in zip(
222                        source.expression.alias_column_names,
223                        values,
224                    )
225                }
226            else:
227                selects[name] = {
228                    select.alias_or_name: select for select in source.expression.selects
229                }
230
231        # First annotate the current scope's column references
232        for col in scope.columns:
233            if not col.table:
234                continue
235
236            source = scope.sources.get(col.table)
237            if isinstance(source, exp.Table):
238                self._set_type(col, self.schema.get_column_type(source, col))
239            elif source:
240                if col.table in selects and col.name in selects[col.table]:
241                    self._set_type(col, selects[col.table][col.name].type)
242                elif isinstance(source.expression, exp.Unnest):
243                    self._set_type(col, source.expression.type)
244
245        # Then (possibly) annotate the remaining expressions in the scope
246        self._maybe_annotate(scope.expression)
247
248    def _maybe_annotate(self, expression: E) -> E:
249        if id(expression) in self._visited:
250            return expression  # We've already inferred the expression's type
251
252        annotator = self.annotators.get(expression.__class__)
253
254        return (
255            annotator(self, expression)
256            if annotator
257            else self._annotate_with_type(expression, exp.DataType.Type.UNKNOWN)
258        )
259
260    def _annotate_args(self, expression: E) -> E:
261        for value in expression.iter_expressions():
262            self._maybe_annotate(value)
263
264        return expression
265
266    def _maybe_coerce(
267        self, type1: exp.DataType | exp.DataType.Type, type2: exp.DataType | exp.DataType.Type
268    ) -> exp.DataType | exp.DataType.Type:
269        type1_value = type1.this if isinstance(type1, exp.DataType) else type1
270        type2_value = type2.this if isinstance(type2, exp.DataType) else type2
271
272        # We propagate the NULL / UNKNOWN types upwards if found
273        if exp.DataType.Type.NULL in (type1_value, type2_value):
274            return exp.DataType.Type.NULL
275        if exp.DataType.Type.UNKNOWN in (type1_value, type2_value):
276            return exp.DataType.Type.UNKNOWN
277
278        return type2_value if type2_value in self.coerces_to.get(type1_value, {}) else type1_value
279
280    def _annotate_binary(self, expression: B) -> B:
281        self._annotate_args(expression)
282
283        left, right = expression.left, expression.right
284        left_type, right_type = left.type.this, right.type.this  # type: ignore
285
286        if isinstance(expression, exp.Connector):
287            if left_type == exp.DataType.Type.NULL and right_type == exp.DataType.Type.NULL:
288                self._set_type(expression, exp.DataType.Type.NULL)
289            elif exp.DataType.Type.NULL in (left_type, right_type):
290                self._set_type(
291                    expression,
292                    exp.DataType.build("NULLABLE", expressions=exp.DataType.build("BOOLEAN")),
293                )
294            else:
295                self._set_type(expression, exp.DataType.Type.BOOLEAN)
296        elif isinstance(expression, exp.Predicate):
297            self._set_type(expression, exp.DataType.Type.BOOLEAN)
298        elif (left_type, right_type) in self.binary_coercions:
299            self._set_type(expression, self.binary_coercions[(left_type, right_type)](left, right))
300        else:
301            self._set_type(expression, self._maybe_coerce(left_type, right_type))
302
303        return expression
304
305    def _annotate_unary(self, expression: E) -> E:
306        self._annotate_args(expression)
307
308        if isinstance(expression, exp.Condition) and not isinstance(expression, exp.Paren):
309            self._set_type(expression, exp.DataType.Type.BOOLEAN)
310        else:
311            self._set_type(expression, expression.this.type)
312
313        return expression
314
315    def _annotate_literal(self, expression: exp.Literal) -> exp.Literal:
316        if expression.is_string:
317            self._set_type(expression, exp.DataType.Type.VARCHAR)
318        elif expression.is_int:
319            self._set_type(expression, exp.DataType.Type.INT)
320        else:
321            self._set_type(expression, exp.DataType.Type.DOUBLE)
322
323        return expression
324
325    def _annotate_with_type(
326        self, expression: E, target_type: exp.DataType | exp.DataType.Type
327    ) -> E:
328        self._set_type(expression, target_type)
329        return self._annotate_args(expression)
330
331    @t.no_type_check
332    def _annotate_by_args(
333        self,
334        expression: E,
335        *args: str,
336        promote: bool = False,
337        array: bool = False,
338    ) -> E:
339        self._annotate_args(expression)
340
341        expressions: t.List[exp.Expression] = []
342        for arg in args:
343            arg_expr = expression.args.get(arg)
344            expressions.extend(expr for expr in ensure_list(arg_expr) if expr)
345
346        last_datatype = None
347        for expr in expressions:
348            expr_type = expr.type
349
350            # Stop at the first nested data type found - we don't want to _maybe_coerce nested types
351            if expr_type.args.get("nested"):
352                last_datatype = expr_type
353                break
354
355            if not expr_type.is_type(exp.DataType.Type.NULL, exp.DataType.Type.UNKNOWN):
356                last_datatype = self._maybe_coerce(last_datatype or expr_type, expr_type)
357
358        self._set_type(expression, last_datatype or exp.DataType.Type.UNKNOWN)
359
360        if promote:
361            if expression.type.this in exp.DataType.INTEGER_TYPES:
362                self._set_type(expression, exp.DataType.Type.BIGINT)
363            elif expression.type.this in exp.DataType.FLOAT_TYPES:
364                self._set_type(expression, exp.DataType.Type.DOUBLE)
365
366        if array:
367            self._set_type(
368                expression,
369                exp.DataType(
370                    this=exp.DataType.Type.ARRAY, expressions=[expression.type], nested=True
371                ),
372            )
373
374        return expression
375
376    def _annotate_timeunit(
377        self, expression: exp.TimeUnit | exp.DateTrunc
378    ) -> exp.TimeUnit | exp.DateTrunc:
379        self._annotate_args(expression)
380
381        if expression.this.type.this in exp.DataType.TEXT_TYPES:
382            datatype = _coerce_date_literal(expression.this, expression.unit)
383        elif expression.this.type.this in exp.DataType.TEMPORAL_TYPES:
384            datatype = _coerce_date(expression.this, expression.unit)
385        else:
386            datatype = exp.DataType.Type.UNKNOWN
387
388        self._set_type(expression, datatype)
389        return expression
390
391    def _annotate_bracket(self, expression: exp.Bracket) -> exp.Bracket:
392        self._annotate_args(expression)
393
394        bracket_arg = expression.expressions[0]
395        this = expression.this
396
397        if isinstance(bracket_arg, exp.Slice):
398            self._set_type(expression, this.type)
399        elif this.type.is_type(exp.DataType.Type.ARRAY):
400            self._set_type(expression, seq_get(this.type.expressions, 0))
401        elif isinstance(this, (exp.Map, exp.VarMap)) and bracket_arg in this.keys:
402            index = this.keys.index(bracket_arg)
403            value = seq_get(this.values, index)
404            self._set_type(expression, value.type if value else None)
405        else:
406            self._set_type(expression, exp.DataType.Type.UNKNOWN)
407
408        return expression
409
410    def _annotate_div(self, expression: exp.Div) -> exp.Div:
411        self._annotate_args(expression)
412
413        left_type, right_type = expression.left.type.this, expression.right.type.this  # type: ignore
414
415        if (
416            expression.args.get("typed")
417            and left_type in exp.DataType.INTEGER_TYPES
418            and right_type in exp.DataType.INTEGER_TYPES
419        ):
420            self._set_type(expression, exp.DataType.Type.BIGINT)
421        else:
422            self._set_type(expression, self._maybe_coerce(left_type, right_type))
423            if expression.type and expression.type.this not in exp.DataType.REAL_TYPES:
424                self._set_type(
425                    expression, self._maybe_coerce(expression.type, exp.DataType.Type.DOUBLE)
426                )
427
428        return expression
429
430    def _annotate_dot(self, expression: exp.Dot) -> exp.Dot:
431        self._annotate_args(expression)
432        self._set_type(expression, None)
433        this_type = expression.this.type
434
435        if this_type and this_type.is_type(exp.DataType.Type.STRUCT):
436            for e in this_type.expressions:
437                if e.name == expression.expression.name:
438                    self._set_type(expression, e.kind)
439                    break
440
441        return expression
442
443    def _annotate_explode(self, expression: exp.Explode) -> exp.Explode:
444        self._annotate_args(expression)
445        self._set_type(expression, seq_get(expression.this.type.expressions, 0))
446        return expression
447
448    def _annotate_unnest(self, expression: exp.Unnest) -> exp.Unnest:
449        self._annotate_args(expression)
450        child = seq_get(expression.expressions, 0)
451
452        if child and child.is_type(exp.DataType.Type.ARRAY):
453            expr_type = seq_get(child.type.expressions, 0)
454        else:
455            expr_type = None
456
457        self._set_type(expression, expr_type)
458        return expression
459
460    def _annotate_struct_value(
461        self, expression: exp.Expression
462    ) -> t.Optional[exp.DataType] | exp.ColumnDef:
463        alias = expression.args.get("alias")
464        if alias:
465            return exp.ColumnDef(this=alias.copy(), kind=expression.type)
466
467        # Case: key = value or key := value
468        if expression.expression:
469            return exp.ColumnDef(this=expression.this.copy(), kind=expression.expression.type)
470
471        return expression.type
472
473    def _annotate_struct(self, expression: exp.Struct) -> exp.Struct:
474        self._annotate_args(expression)
475        self._set_type(
476            expression,
477            exp.DataType(
478                this=exp.DataType.Type.STRUCT,
479                expressions=[self._annotate_struct_value(expr) for expr in expression.expressions],
480                nested=True,
481            ),
482        )
483        return expression
484
485    @t.overload
486    def _annotate_map(self, expression: exp.Map) -> exp.Map: ...
487
488    @t.overload
489    def _annotate_map(self, expression: exp.VarMap) -> exp.VarMap: ...
490
491    def _annotate_map(self, expression):
492        self._annotate_args(expression)
493
494        keys = expression.args.get("keys")
495        values = expression.args.get("values")
496
497        map_type = exp.DataType(this=exp.DataType.Type.MAP)
498        if isinstance(keys, exp.Array) and isinstance(values, exp.Array):
499            key_type = seq_get(keys.type.expressions, 0) or exp.DataType.Type.UNKNOWN
500            value_type = seq_get(values.type.expressions, 0) or exp.DataType.Type.UNKNOWN
501
502            if key_type != exp.DataType.Type.UNKNOWN and value_type != exp.DataType.Type.UNKNOWN:
503                map_type.set("expressions", [key_type, value_type])
504                map_type.set("nested", True)
505
506        self._set_type(expression, map_type)
507        return expression
508
509    def _annotate_to_map(self, expression: exp.ToMap) -> exp.ToMap:
510        self._annotate_args(expression)
511
512        map_type = exp.DataType(this=exp.DataType.Type.MAP)
513        arg = expression.this
514        if arg.is_type(exp.DataType.Type.STRUCT):
515            for coldef in arg.type.expressions:
516                kind = coldef.kind
517                if kind != exp.DataType.Type.UNKNOWN:
518                    map_type.set("expressions", [exp.DataType.build("varchar"), kind])
519                    map_type.set("nested", True)
520                    break
521
522        self._set_type(expression, map_type)
523        return expression
524
525    def _annotate_extract(self, expression: exp.Extract) -> exp.Extract:
526        self._annotate_args(expression)
527        part = expression.name
528        if part == "TIME":
529            self._set_type(expression, exp.DataType.Type.TIME)
530        elif part == "DATE":
531            self._set_type(expression, exp.DataType.Type.DATE)
532        else:
533            self._set_type(expression, exp.DataType.Type.INT)
534        return expression
TypeAnnotator( schema: sqlglot.schema.Schema, annotators: Optional[Dict[Type[~E], Callable[[TypeAnnotator, ~E], ~E]]] = None, coerces_to: Optional[Dict[sqlglot.expressions.DataType.Type, Set[sqlglot.expressions.DataType.Type]]] = None, binary_coercions: Optional[Dict[Tuple[sqlglot.expressions.DataType.Type, sqlglot.expressions.DataType.Type], Callable[[sqlglot.expressions.Expression, sqlglot.expressions.Expression], sqlglot.expressions.DataType.Type]]] = None, dialect: Union[str, sqlglot.dialects.dialect.Dialect, Type[sqlglot.dialects.dialect.Dialect], NoneType] = None)
173    def __init__(
174        self,
175        schema: Schema,
176        annotators: t.Optional[AnnotatorsType] = None,
177        coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None,
178        binary_coercions: t.Optional[BinaryCoercions] = None,
179        dialect: t.Optional[DialectType] = None,
180    ) -> None:
181        self.schema = schema
182        self.annotators = annotators or Dialect.get_or_raise(dialect).ANNOTATORS
183        self.coerces_to = coerces_to or self.COERCES_TO
184        self.binary_coercions = binary_coercions or self.BINARY_COERCIONS
185
186        # Caches the ids of annotated sub-Expressions, to ensure we only visit them once
187        self._visited: t.Set[int] = set()
NESTED_TYPES = {<Type.ARRAY: 'ARRAY'>}
COERCES_TO: Dict[sqlglot.expressions.DataType.Type, Set[sqlglot.expressions.DataType.Type]] = {<Type.TEXT: 'TEXT'>: set(), <Type.NVARCHAR: 'NVARCHAR'>: {<Type.TEXT: 'TEXT'>}, <Type.VARCHAR: 'VARCHAR'>: {<Type.TEXT: 'TEXT'>, <Type.NVARCHAR: 'NVARCHAR'>}, <Type.NCHAR: 'NCHAR'>: {<Type.TEXT: 'TEXT'>, <Type.NVARCHAR: 'NVARCHAR'>, <Type.VARCHAR: 'VARCHAR'>}, <Type.CHAR: 'CHAR'>: {<Type.TEXT: 'TEXT'>, <Type.NVARCHAR: 'NVARCHAR'>, <Type.VARCHAR: 'VARCHAR'>, <Type.NCHAR: 'NCHAR'>}, <Type.DOUBLE: 'DOUBLE'>: set(), <Type.FLOAT: 'FLOAT'>: {<Type.DOUBLE: 'DOUBLE'>}, <Type.DECIMAL: 'DECIMAL'>: {<Type.DOUBLE: 'DOUBLE'>, <Type.FLOAT: 'FLOAT'>}, <Type.BIGINT: 'BIGINT'>: {<Type.DOUBLE: 'DOUBLE'>, <Type.FLOAT: 'FLOAT'>, <Type.DECIMAL: 'DECIMAL'>}, <Type.INT: 'INT'>: {<Type.DOUBLE: 'DOUBLE'>, <Type.BIGINT: 'BIGINT'>, <Type.FLOAT: 'FLOAT'>, <Type.DECIMAL: 'DECIMAL'>}, <Type.SMALLINT: 'SMALLINT'>: {<Type.DOUBLE: 'DOUBLE'>, <Type.DECIMAL: 'DECIMAL'>, <Type.INT: 'INT'>, <Type.FLOAT: 'FLOAT'>, <Type.BIGINT: 'BIGINT'>}, <Type.TINYINT: 'TINYINT'>: {<Type.DOUBLE: 'DOUBLE'>, <Type.SMALLINT: 'SMALLINT'>, <Type.DECIMAL: 'DECIMAL'>, <Type.INT: 'INT'>, <Type.FLOAT: 'FLOAT'>, <Type.BIGINT: 'BIGINT'>}, <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>: set(), <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>: {<Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>}, <Type.TIMESTAMP: 'TIMESTAMP'>: {<Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>}, <Type.DATETIME: 'DATETIME'>: {<Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.TIMESTAMP: 'TIMESTAMP'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>}, <Type.DATE: 'DATE'>: {<Type.DATETIME: 'DATETIME'>, <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.TIMESTAMP: 'TIMESTAMP'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>}}
BINARY_COERCIONS: Dict[Tuple[sqlglot.expressions.DataType.Type, sqlglot.expressions.DataType.Type], Callable[[sqlglot.expressions.Expression, sqlglot.expressions.Expression], sqlglot.expressions.DataType.Type]] = {(<Type.NVARCHAR: 'NVARCHAR'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DATE: 'DATE'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.DATE: 'DATE'>): <function TypeAnnotator.<lambda>>}
schema
annotators
coerces_to
binary_coercions
def annotate(self, expression: ~E) -> ~E:
195    def annotate(self, expression: E) -> E:
196        for scope in traverse_scope(expression):
197            self.annotate_scope(scope)
198        return self._maybe_annotate(expression)  # This takes care of non-traversable expressions
def annotate_scope(self, scope: sqlglot.optimizer.scope.Scope) -> None:
200    def annotate_scope(self, scope: Scope) -> None:
201        selects = {}
202        for name, source in scope.sources.items():
203            if not isinstance(source, Scope):
204                continue
205            if isinstance(source.expression, exp.UDTF):
206                values = []
207
208                if isinstance(source.expression, exp.Lateral):
209                    if isinstance(source.expression.this, exp.Explode):
210                        values = [source.expression.this.this]
211                elif isinstance(source.expression, exp.Unnest):
212                    values = [source.expression]
213                else:
214                    values = source.expression.expressions[0].expressions
215
216                if not values:
217                    continue
218
219                selects[name] = {
220                    alias: column
221                    for alias, column in zip(
222                        source.expression.alias_column_names,
223                        values,
224                    )
225                }
226            else:
227                selects[name] = {
228                    select.alias_or_name: select for select in source.expression.selects
229                }
230
231        # First annotate the current scope's column references
232        for col in scope.columns:
233            if not col.table:
234                continue
235
236            source = scope.sources.get(col.table)
237            if isinstance(source, exp.Table):
238                self._set_type(col, self.schema.get_column_type(source, col))
239            elif source:
240                if col.table in selects and col.name in selects[col.table]:
241                    self._set_type(col, selects[col.table][col.name].type)
242                elif isinstance(source.expression, exp.Unnest):
243                    self._set_type(col, source.expression.type)
244
245        # Then (possibly) annotate the remaining expressions in the scope
246        self._maybe_annotate(scope.expression)