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    subclasses,
 14)
 15from sqlglot.optimizer.scope import Scope, traverse_scope
 16from sqlglot.schema import Schema, ensure_schema
 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
 28def annotate_types(
 29    expression: E,
 30    schema: t.Optional[t.Dict | Schema] = None,
 31    annotators: t.Optional[t.Dict[t.Type[E], t.Callable[[TypeAnnotator, E], E]]] = None,
 32    coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None,
 33) -> E:
 34    """
 35    Infers the types of an expression, annotating its AST accordingly.
 36
 37    Example:
 38        >>> import sqlglot
 39        >>> schema = {"y": {"cola": "SMALLINT"}}
 40        >>> sql = "SELECT x.cola + 2.5 AS cola FROM (SELECT y.cola AS cola FROM y AS y) AS x"
 41        >>> annotated_expr = annotate_types(sqlglot.parse_one(sql), schema=schema)
 42        >>> annotated_expr.expressions[0].type.this  # Get the type of "x.cola + 2.5 AS cola"
 43        <Type.DOUBLE: 'DOUBLE'>
 44
 45    Args:
 46        expression: Expression to annotate.
 47        schema: Database schema.
 48        annotators: Maps expression type to corresponding annotation function.
 49        coerces_to: Maps expression type to set of types that it can be coerced into.
 50
 51    Returns:
 52        The expression annotated with types.
 53    """
 54
 55    schema = ensure_schema(schema)
 56
 57    return TypeAnnotator(schema, annotators, coerces_to).annotate(expression)
 58
 59
 60def _annotate_with_type_lambda(data_type: exp.DataType.Type) -> t.Callable[[TypeAnnotator, E], E]:
 61    return lambda self, e: self._annotate_with_type(e, data_type)
 62
 63
 64def _coerce_date_literal(l: exp.Expression, unit: t.Optional[exp.Expression]) -> exp.DataType.Type:
 65    date_text = l.name
 66    is_iso_date_ = is_iso_date(date_text)
 67
 68    if is_iso_date_ and is_date_unit(unit):
 69        return exp.DataType.Type.DATE
 70
 71    # An ISO date is also an ISO datetime, but not vice versa
 72    if is_iso_date_ or is_iso_datetime(date_text):
 73        return exp.DataType.Type.DATETIME
 74
 75    return exp.DataType.Type.UNKNOWN
 76
 77
 78def _coerce_date(l: exp.Expression, unit: t.Optional[exp.Expression]) -> exp.DataType.Type:
 79    if not is_date_unit(unit):
 80        return exp.DataType.Type.DATETIME
 81    return l.type.this if l.type else exp.DataType.Type.UNKNOWN
 82
 83
 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
 90
 91
 92def swap_all(coercions: BinaryCoercions) -> BinaryCoercions:
 93    return {**coercions, **{(b, a): swap_args(func) for (a, b), func in coercions.items()}}
 94
 95
 96class _TypeAnnotator(type):
 97    def __new__(cls, clsname, bases, attrs):
 98        klass = super().__new__(cls, clsname, bases, attrs)
 99
100        # Highest-to-lowest type precedence, as specified in Spark's docs (ANSI):
101        # https://spark.apache.org/docs/3.2.0/sql-ref-ansi-compliance.html
102        text_precedence = (
103            exp.DataType.Type.TEXT,
104            exp.DataType.Type.NVARCHAR,
105            exp.DataType.Type.VARCHAR,
106            exp.DataType.Type.NCHAR,
107            exp.DataType.Type.CHAR,
108        )
109        numeric_precedence = (
110            exp.DataType.Type.DOUBLE,
111            exp.DataType.Type.FLOAT,
112            exp.DataType.Type.DECIMAL,
113            exp.DataType.Type.BIGINT,
114            exp.DataType.Type.INT,
115            exp.DataType.Type.SMALLINT,
116            exp.DataType.Type.TINYINT,
117        )
118        timelike_precedence = (
119            exp.DataType.Type.TIMESTAMPLTZ,
120            exp.DataType.Type.TIMESTAMPTZ,
121            exp.DataType.Type.TIMESTAMP,
122            exp.DataType.Type.DATETIME,
123            exp.DataType.Type.DATE,
124        )
125
126        for type_precedence in (text_precedence, numeric_precedence, timelike_precedence):
127            coerces_to = set()
128            for data_type in type_precedence:
129                klass.COERCES_TO[data_type] = coerces_to.copy()
130                coerces_to |= {data_type}
131
132        return klass
133
134
135class TypeAnnotator(metaclass=_TypeAnnotator):
136    TYPE_TO_EXPRESSIONS: t.Dict[exp.DataType.Type, t.Set[t.Type[exp.Expression]]] = {
137        exp.DataType.Type.BIGINT: {
138            exp.ApproxDistinct,
139            exp.ArraySize,
140            exp.Count,
141            exp.Length,
142        },
143        exp.DataType.Type.BOOLEAN: {
144            exp.Between,
145            exp.Boolean,
146            exp.In,
147            exp.RegexpLike,
148        },
149        exp.DataType.Type.DATE: {
150            exp.CurrentDate,
151            exp.Date,
152            exp.DateFromParts,
153            exp.DateStrToDate,
154            exp.DiToDate,
155            exp.StrToDate,
156            exp.TimeStrToDate,
157            exp.TsOrDsToDate,
158        },
159        exp.DataType.Type.DATETIME: {
160            exp.CurrentDatetime,
161            exp.DatetimeAdd,
162            exp.DatetimeSub,
163        },
164        exp.DataType.Type.DOUBLE: {
165            exp.ApproxQuantile,
166            exp.Avg,
167            exp.Div,
168            exp.Exp,
169            exp.Ln,
170            exp.Log,
171            exp.Pow,
172            exp.Quantile,
173            exp.Round,
174            exp.SafeDivide,
175            exp.Sqrt,
176            exp.Stddev,
177            exp.StddevPop,
178            exp.StddevSamp,
179            exp.Variance,
180            exp.VariancePop,
181        },
182        exp.DataType.Type.INT: {
183            exp.Ceil,
184            exp.DatetimeDiff,
185            exp.DateDiff,
186            exp.Extract,
187            exp.TimestampDiff,
188            exp.TimeDiff,
189            exp.DateToDi,
190            exp.Floor,
191            exp.Levenshtein,
192            exp.Sign,
193            exp.StrPosition,
194            exp.TsOrDiToDi,
195        },
196        exp.DataType.Type.JSON: {
197            exp.ParseJSON,
198        },
199        exp.DataType.Type.TIMESTAMP: {
200            exp.CurrentTime,
201            exp.CurrentTimestamp,
202            exp.StrToTime,
203            exp.TimeAdd,
204            exp.TimeStrToTime,
205            exp.TimeSub,
206            exp.TimestampAdd,
207            exp.TimestampSub,
208            exp.UnixToTime,
209        },
210        exp.DataType.Type.TINYINT: {
211            exp.Day,
212            exp.Month,
213            exp.Week,
214            exp.Year,
215        },
216        exp.DataType.Type.VARCHAR: {
217            exp.ArrayConcat,
218            exp.Concat,
219            exp.ConcatWs,
220            exp.DateToDateStr,
221            exp.GroupConcat,
222            exp.Initcap,
223            exp.Lower,
224            exp.Substring,
225            exp.TimeToStr,
226            exp.TimeToTimeStr,
227            exp.Trim,
228            exp.TsOrDsToDateStr,
229            exp.UnixToStr,
230            exp.UnixToTimeStr,
231            exp.Upper,
232        },
233    }
234
235    ANNOTATORS: t.Dict = {
236        **{
237            expr_type: lambda self, e: self._annotate_unary(e)
238            for expr_type in subclasses(exp.__name__, (exp.Unary, exp.Alias))
239        },
240        **{
241            expr_type: lambda self, e: self._annotate_binary(e)
242            for expr_type in subclasses(exp.__name__, exp.Binary)
243        },
244        **{
245            expr_type: _annotate_with_type_lambda(data_type)
246            for data_type, expressions in TYPE_TO_EXPRESSIONS.items()
247            for expr_type in expressions
248        },
249        exp.Abs: lambda self, e: self._annotate_by_args(e, "this"),
250        exp.Anonymous: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.UNKNOWN),
251        exp.Array: lambda self, e: self._annotate_by_args(e, "expressions", array=True),
252        exp.ArrayAgg: lambda self, e: self._annotate_by_args(e, "this", array=True),
253        exp.ArrayConcat: lambda self, e: self._annotate_by_args(e, "this", "expressions"),
254        exp.Bracket: lambda self, e: self._annotate_bracket(e),
255        exp.Cast: lambda self, e: self._annotate_with_type(e, e.args["to"]),
256        exp.Case: lambda self, e: self._annotate_by_args(e, "default", "ifs"),
257        exp.Coalesce: lambda self, e: self._annotate_by_args(e, "this", "expressions"),
258        exp.DataType: lambda self, e: self._annotate_with_type(e, e.copy()),
259        exp.DateAdd: lambda self, e: self._annotate_timeunit(e),
260        exp.DateSub: lambda self, e: self._annotate_timeunit(e),
261        exp.DateTrunc: lambda self, e: self._annotate_timeunit(e),
262        exp.Distinct: lambda self, e: self._annotate_by_args(e, "expressions"),
263        exp.Div: lambda self, e: self._annotate_div(e),
264        exp.Dot: lambda self, e: self._annotate_dot(e),
265        exp.Explode: lambda self, e: self._annotate_explode(e),
266        exp.Filter: lambda self, e: self._annotate_by_args(e, "this"),
267        exp.GenerateDateArray: lambda self, e: self._annotate_with_type(
268            e, exp.DataType.build("ARRAY<DATE>")
269        ),
270        exp.If: lambda self, e: self._annotate_by_args(e, "true", "false"),
271        exp.Interval: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.INTERVAL),
272        exp.Least: lambda self, e: self._annotate_by_args(e, "expressions"),
273        exp.Literal: lambda self, e: self._annotate_literal(e),
274        exp.Map: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.MAP),
275        exp.Max: lambda self, e: self._annotate_by_args(e, "this", "expressions"),
276        exp.Min: lambda self, e: self._annotate_by_args(e, "this", "expressions"),
277        exp.Null: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.NULL),
278        exp.Nullif: lambda self, e: self._annotate_by_args(e, "this", "expression"),
279        exp.PropertyEQ: lambda self, e: self._annotate_by_args(e, "expression"),
280        exp.Slice: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.UNKNOWN),
281        exp.Struct: lambda self, e: self._annotate_by_args(e, "expressions", struct=True),
282        exp.Sum: lambda self, e: self._annotate_by_args(e, "this", "expressions", promote=True),
283        exp.Timestamp: lambda self, e: self._annotate_with_type(
284            e,
285            exp.DataType.Type.TIMESTAMPTZ if e.args.get("with_tz") else exp.DataType.Type.TIMESTAMP,
286        ),
287        exp.TryCast: lambda self, e: self._annotate_with_type(e, e.args["to"]),
288        exp.Unnest: lambda self, e: self._annotate_unnest(e),
289        exp.VarMap: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.MAP),
290    }
291
292    NESTED_TYPES = {
293        exp.DataType.Type.ARRAY,
294    }
295
296    # Specifies what types a given type can be coerced into (autofilled)
297    COERCES_TO: t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]] = {}
298
299    # Coercion functions for binary operations.
300    # Map of type pairs to a callable that takes both sides of the binary operation and returns the resulting type.
301    BINARY_COERCIONS: BinaryCoercions = {
302        **swap_all(
303            {
304                (t, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date_literal(
305                    l, r.args.get("unit")
306                )
307                for t in exp.DataType.TEXT_TYPES
308            }
309        ),
310        **swap_all(
311            {
312                # text + numeric will yield the numeric type to match most dialects' semantics
313                (text, numeric): lambda l, r: t.cast(
314                    exp.DataType.Type, l.type if l.type in exp.DataType.NUMERIC_TYPES else r.type
315                )
316                for text in exp.DataType.TEXT_TYPES
317                for numeric in exp.DataType.NUMERIC_TYPES
318            }
319        ),
320        **swap_all(
321            {
322                (exp.DataType.Type.DATE, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date(
323                    l, r.args.get("unit")
324                ),
325            }
326        ),
327    }
328
329    def __init__(
330        self,
331        schema: Schema,
332        annotators: t.Optional[t.Dict[t.Type[E], t.Callable[[TypeAnnotator, E], E]]] = None,
333        coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None,
334        binary_coercions: t.Optional[BinaryCoercions] = None,
335    ) -> None:
336        self.schema = schema
337        self.annotators = annotators or self.ANNOTATORS
338        self.coerces_to = coerces_to or self.COERCES_TO
339        self.binary_coercions = binary_coercions or self.BINARY_COERCIONS
340
341        # Caches the ids of annotated sub-Expressions, to ensure we only visit them once
342        self._visited: t.Set[int] = set()
343
344    def _set_type(
345        self, expression: exp.Expression, target_type: t.Optional[exp.DataType | exp.DataType.Type]
346    ) -> None:
347        expression.type = target_type or exp.DataType.Type.UNKNOWN  # type: ignore
348        self._visited.add(id(expression))
349
350    def annotate(self, expression: E) -> E:
351        for scope in traverse_scope(expression):
352            selects = {}
353            for name, source in scope.sources.items():
354                if not isinstance(source, Scope):
355                    continue
356                if isinstance(source.expression, exp.UDTF):
357                    values = []
358
359                    if isinstance(source.expression, exp.Lateral):
360                        if isinstance(source.expression.this, exp.Explode):
361                            values = [source.expression.this.this]
362                    elif isinstance(source.expression, exp.Unnest):
363                        values = [source.expression]
364                    else:
365                        values = source.expression.expressions[0].expressions
366
367                    if not values:
368                        continue
369
370                    selects[name] = {
371                        alias: column
372                        for alias, column in zip(
373                            source.expression.alias_column_names,
374                            values,
375                        )
376                    }
377                else:
378                    selects[name] = {
379                        select.alias_or_name: select for select in source.expression.selects
380                    }
381
382            # First annotate the current scope's column references
383            for col in scope.columns:
384                if not col.table:
385                    continue
386
387                source = scope.sources.get(col.table)
388                if isinstance(source, exp.Table):
389                    self._set_type(col, self.schema.get_column_type(source, col))
390                elif source:
391                    if col.table in selects and col.name in selects[col.table]:
392                        self._set_type(col, selects[col.table][col.name].type)
393                    elif isinstance(source.expression, exp.Unnest):
394                        self._set_type(col, source.expression.type)
395
396            # Then (possibly) annotate the remaining expressions in the scope
397            self._maybe_annotate(scope.expression)
398
399        return self._maybe_annotate(expression)  # This takes care of non-traversable expressions
400
401    def _maybe_annotate(self, expression: E) -> E:
402        if id(expression) in self._visited:
403            return expression  # We've already inferred the expression's type
404
405        annotator = self.annotators.get(expression.__class__)
406
407        return (
408            annotator(self, expression)
409            if annotator
410            else self._annotate_with_type(expression, exp.DataType.Type.UNKNOWN)
411        )
412
413    def _annotate_args(self, expression: E) -> E:
414        for value in expression.iter_expressions():
415            self._maybe_annotate(value)
416
417        return expression
418
419    def _maybe_coerce(
420        self, type1: exp.DataType | exp.DataType.Type, type2: exp.DataType | exp.DataType.Type
421    ) -> exp.DataType | exp.DataType.Type:
422        type1_value = type1.this if isinstance(type1, exp.DataType) else type1
423        type2_value = type2.this if isinstance(type2, exp.DataType) else type2
424
425        # We propagate the NULL / UNKNOWN types upwards if found
426        if exp.DataType.Type.NULL in (type1_value, type2_value):
427            return exp.DataType.Type.NULL
428        if exp.DataType.Type.UNKNOWN in (type1_value, type2_value):
429            return exp.DataType.Type.UNKNOWN
430
431        if type1_value in self.NESTED_TYPES:
432            return type1
433        if type2_value in self.NESTED_TYPES:
434            return type2
435
436        return type2_value if type2_value in self.coerces_to.get(type1_value, {}) else type1_value  # type: ignore
437
438    # Note: the following "no_type_check" decorators were added because mypy was yelling due
439    # to assigning Type values to expression.type (since its getter returns Optional[DataType]).
440    # This is a known mypy issue: https://github.com/python/mypy/issues/3004
441
442    @t.no_type_check
443    def _annotate_binary(self, expression: B) -> B:
444        self._annotate_args(expression)
445
446        left, right = expression.left, expression.right
447        left_type, right_type = left.type.this, right.type.this
448
449        if isinstance(expression, exp.Connector):
450            if left_type == exp.DataType.Type.NULL and right_type == exp.DataType.Type.NULL:
451                self._set_type(expression, exp.DataType.Type.NULL)
452            elif exp.DataType.Type.NULL in (left_type, right_type):
453                self._set_type(
454                    expression,
455                    exp.DataType.build("NULLABLE", expressions=exp.DataType.build("BOOLEAN")),
456                )
457            else:
458                self._set_type(expression, exp.DataType.Type.BOOLEAN)
459        elif isinstance(expression, exp.Predicate):
460            self._set_type(expression, exp.DataType.Type.BOOLEAN)
461        elif (left_type, right_type) in self.binary_coercions:
462            self._set_type(expression, self.binary_coercions[(left_type, right_type)](left, right))
463        else:
464            self._set_type(expression, self._maybe_coerce(left_type, right_type))
465
466        return expression
467
468    @t.no_type_check
469    def _annotate_unary(self, expression: E) -> E:
470        self._annotate_args(expression)
471
472        if isinstance(expression, exp.Condition) and not isinstance(expression, exp.Paren):
473            self._set_type(expression, exp.DataType.Type.BOOLEAN)
474        else:
475            self._set_type(expression, expression.this.type)
476
477        return expression
478
479    @t.no_type_check
480    def _annotate_literal(self, expression: exp.Literal) -> exp.Literal:
481        if expression.is_string:
482            self._set_type(expression, exp.DataType.Type.VARCHAR)
483        elif expression.is_int:
484            self._set_type(expression, exp.DataType.Type.INT)
485        else:
486            self._set_type(expression, exp.DataType.Type.DOUBLE)
487
488        return expression
489
490    @t.no_type_check
491    def _annotate_with_type(self, expression: E, target_type: exp.DataType.Type) -> E:
492        self._set_type(expression, target_type)
493        return self._annotate_args(expression)
494
495    @t.no_type_check
496    def _annotate_struct_value(
497        self, expression: exp.Expression
498    ) -> t.Optional[exp.DataType] | exp.ColumnDef:
499        alias = expression.args.get("alias")
500        if alias:
501            return exp.ColumnDef(this=alias.copy(), kind=expression.type)
502
503        # Case: key = value or key := value
504        if expression.expression:
505            return exp.ColumnDef(this=expression.this.copy(), kind=expression.expression.type)
506
507        return expression.type
508
509    @t.no_type_check
510    def _annotate_by_args(
511        self,
512        expression: E,
513        *args: str,
514        promote: bool = False,
515        array: bool = False,
516        struct: bool = False,
517    ) -> E:
518        self._annotate_args(expression)
519
520        expressions: t.List[exp.Expression] = []
521        for arg in args:
522            arg_expr = expression.args.get(arg)
523            expressions.extend(expr for expr in ensure_list(arg_expr) if expr)
524
525        last_datatype = None
526        for expr in expressions:
527            expr_type = expr.type
528
529            # Stop at the first nested data type found - we don't want to _maybe_coerce nested types
530            if expr_type.args.get("nested"):
531                last_datatype = expr_type
532                break
533
534            last_datatype = self._maybe_coerce(last_datatype or expr_type, expr_type)
535
536        self._set_type(expression, last_datatype or exp.DataType.Type.UNKNOWN)
537
538        if promote:
539            if expression.type.this in exp.DataType.INTEGER_TYPES:
540                self._set_type(expression, exp.DataType.Type.BIGINT)
541            elif expression.type.this in exp.DataType.FLOAT_TYPES:
542                self._set_type(expression, exp.DataType.Type.DOUBLE)
543
544        if array:
545            self._set_type(
546                expression,
547                exp.DataType(
548                    this=exp.DataType.Type.ARRAY, expressions=[expression.type], nested=True
549                ),
550            )
551
552        if struct:
553            self._set_type(
554                expression,
555                exp.DataType(
556                    this=exp.DataType.Type.STRUCT,
557                    expressions=[self._annotate_struct_value(expr) for expr in expressions],
558                    nested=True,
559                ),
560            )
561
562        return expression
563
564    def _annotate_timeunit(
565        self, expression: exp.TimeUnit | exp.DateTrunc
566    ) -> exp.TimeUnit | exp.DateTrunc:
567        self._annotate_args(expression)
568
569        if expression.this.type.this in exp.DataType.TEXT_TYPES:
570            datatype = _coerce_date_literal(expression.this, expression.unit)
571        elif expression.this.type.this in exp.DataType.TEMPORAL_TYPES:
572            datatype = _coerce_date(expression.this, expression.unit)
573        else:
574            datatype = exp.DataType.Type.UNKNOWN
575
576        self._set_type(expression, datatype)
577        return expression
578
579    def _annotate_bracket(self, expression: exp.Bracket) -> exp.Bracket:
580        self._annotate_args(expression)
581
582        bracket_arg = expression.expressions[0]
583        this = expression.this
584
585        if isinstance(bracket_arg, exp.Slice):
586            self._set_type(expression, this.type)
587        elif this.type.is_type(exp.DataType.Type.ARRAY):
588            self._set_type(expression, seq_get(this.type.expressions, 0))
589        elif isinstance(this, (exp.Map, exp.VarMap)) and bracket_arg in this.keys:
590            index = this.keys.index(bracket_arg)
591            value = seq_get(this.values, index)
592            self._set_type(expression, value.type if value else None)
593        else:
594            self._set_type(expression, exp.DataType.Type.UNKNOWN)
595
596        return expression
597
598    def _annotate_div(self, expression: exp.Div) -> exp.Div:
599        self._annotate_args(expression)
600
601        left_type, right_type = expression.left.type.this, expression.right.type.this  # type: ignore
602
603        if (
604            expression.args.get("typed")
605            and left_type in exp.DataType.INTEGER_TYPES
606            and right_type in exp.DataType.INTEGER_TYPES
607        ):
608            self._set_type(expression, exp.DataType.Type.BIGINT)
609        else:
610            self._set_type(expression, self._maybe_coerce(left_type, right_type))
611            if expression.type and expression.type.this not in exp.DataType.REAL_TYPES:
612                self._set_type(
613                    expression, self._maybe_coerce(expression.type, exp.DataType.Type.DOUBLE)
614                )
615
616        return expression
617
618    def _annotate_dot(self, expression: exp.Dot) -> exp.Dot:
619        self._annotate_args(expression)
620        self._set_type(expression, None)
621        this_type = expression.this.type
622
623        if this_type and this_type.is_type(exp.DataType.Type.STRUCT):
624            for e in this_type.expressions:
625                if e.name == expression.expression.name:
626                    self._set_type(expression, e.kind)
627                    break
628
629        return expression
630
631    def _annotate_explode(self, expression: exp.Explode) -> exp.Explode:
632        self._annotate_args(expression)
633        self._set_type(expression, seq_get(expression.this.type.expressions, 0))
634        return expression
635
636    def _annotate_unnest(self, expression: exp.Unnest) -> exp.Unnest:
637        self._annotate_args(expression)
638        child = seq_get(expression.expressions, 0)
639        self._set_type(expression, child and seq_get(child.type.expressions, 0))
640        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) -> ~E:
29def annotate_types(
30    expression: E,
31    schema: t.Optional[t.Dict | Schema] = None,
32    annotators: t.Optional[t.Dict[t.Type[E], t.Callable[[TypeAnnotator, E], E]]] = None,
33    coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None,
34) -> E:
35    """
36    Infers the types of an expression, annotating its AST accordingly.
37
38    Example:
39        >>> import sqlglot
40        >>> schema = {"y": {"cola": "SMALLINT"}}
41        >>> sql = "SELECT x.cola + 2.5 AS cola FROM (SELECT y.cola AS cola FROM y AS y) AS x"
42        >>> annotated_expr = annotate_types(sqlglot.parse_one(sql), schema=schema)
43        >>> annotated_expr.expressions[0].type.this  # Get the type of "x.cola + 2.5 AS cola"
44        <Type.DOUBLE: 'DOUBLE'>
45
46    Args:
47        expression: Expression to annotate.
48        schema: Database schema.
49        annotators: Maps expression type to corresponding annotation function.
50        coerces_to: Maps expression type to set of types that it can be coerced into.
51
52    Returns:
53        The expression annotated with types.
54    """
55
56    schema = ensure_schema(schema)
57
58    return TypeAnnotator(schema, annotators, coerces_to).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.

85def swap_args(func: BinaryCoercionFunc) -> BinaryCoercionFunc:
86    @functools.wraps(func)
87    def _swapped(l: exp.Expression, r: exp.Expression) -> exp.DataType.Type:
88        return func(r, l)
89
90    return _swapped
93def swap_all(coercions: BinaryCoercions) -> BinaryCoercions:
94    return {**coercions, **{(b, a): swap_args(func) for (a, b), func in coercions.items()}}
class TypeAnnotator:
136class TypeAnnotator(metaclass=_TypeAnnotator):
137    TYPE_TO_EXPRESSIONS: t.Dict[exp.DataType.Type, t.Set[t.Type[exp.Expression]]] = {
138        exp.DataType.Type.BIGINT: {
139            exp.ApproxDistinct,
140            exp.ArraySize,
141            exp.Count,
142            exp.Length,
143        },
144        exp.DataType.Type.BOOLEAN: {
145            exp.Between,
146            exp.Boolean,
147            exp.In,
148            exp.RegexpLike,
149        },
150        exp.DataType.Type.DATE: {
151            exp.CurrentDate,
152            exp.Date,
153            exp.DateFromParts,
154            exp.DateStrToDate,
155            exp.DiToDate,
156            exp.StrToDate,
157            exp.TimeStrToDate,
158            exp.TsOrDsToDate,
159        },
160        exp.DataType.Type.DATETIME: {
161            exp.CurrentDatetime,
162            exp.DatetimeAdd,
163            exp.DatetimeSub,
164        },
165        exp.DataType.Type.DOUBLE: {
166            exp.ApproxQuantile,
167            exp.Avg,
168            exp.Div,
169            exp.Exp,
170            exp.Ln,
171            exp.Log,
172            exp.Pow,
173            exp.Quantile,
174            exp.Round,
175            exp.SafeDivide,
176            exp.Sqrt,
177            exp.Stddev,
178            exp.StddevPop,
179            exp.StddevSamp,
180            exp.Variance,
181            exp.VariancePop,
182        },
183        exp.DataType.Type.INT: {
184            exp.Ceil,
185            exp.DatetimeDiff,
186            exp.DateDiff,
187            exp.Extract,
188            exp.TimestampDiff,
189            exp.TimeDiff,
190            exp.DateToDi,
191            exp.Floor,
192            exp.Levenshtein,
193            exp.Sign,
194            exp.StrPosition,
195            exp.TsOrDiToDi,
196        },
197        exp.DataType.Type.JSON: {
198            exp.ParseJSON,
199        },
200        exp.DataType.Type.TIMESTAMP: {
201            exp.CurrentTime,
202            exp.CurrentTimestamp,
203            exp.StrToTime,
204            exp.TimeAdd,
205            exp.TimeStrToTime,
206            exp.TimeSub,
207            exp.TimestampAdd,
208            exp.TimestampSub,
209            exp.UnixToTime,
210        },
211        exp.DataType.Type.TINYINT: {
212            exp.Day,
213            exp.Month,
214            exp.Week,
215            exp.Year,
216        },
217        exp.DataType.Type.VARCHAR: {
218            exp.ArrayConcat,
219            exp.Concat,
220            exp.ConcatWs,
221            exp.DateToDateStr,
222            exp.GroupConcat,
223            exp.Initcap,
224            exp.Lower,
225            exp.Substring,
226            exp.TimeToStr,
227            exp.TimeToTimeStr,
228            exp.Trim,
229            exp.TsOrDsToDateStr,
230            exp.UnixToStr,
231            exp.UnixToTimeStr,
232            exp.Upper,
233        },
234    }
235
236    ANNOTATORS: t.Dict = {
237        **{
238            expr_type: lambda self, e: self._annotate_unary(e)
239            for expr_type in subclasses(exp.__name__, (exp.Unary, exp.Alias))
240        },
241        **{
242            expr_type: lambda self, e: self._annotate_binary(e)
243            for expr_type in subclasses(exp.__name__, exp.Binary)
244        },
245        **{
246            expr_type: _annotate_with_type_lambda(data_type)
247            for data_type, expressions in TYPE_TO_EXPRESSIONS.items()
248            for expr_type in expressions
249        },
250        exp.Abs: lambda self, e: self._annotate_by_args(e, "this"),
251        exp.Anonymous: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.UNKNOWN),
252        exp.Array: lambda self, e: self._annotate_by_args(e, "expressions", array=True),
253        exp.ArrayAgg: lambda self, e: self._annotate_by_args(e, "this", array=True),
254        exp.ArrayConcat: lambda self, e: self._annotate_by_args(e, "this", "expressions"),
255        exp.Bracket: lambda self, e: self._annotate_bracket(e),
256        exp.Cast: lambda self, e: self._annotate_with_type(e, e.args["to"]),
257        exp.Case: lambda self, e: self._annotate_by_args(e, "default", "ifs"),
258        exp.Coalesce: lambda self, e: self._annotate_by_args(e, "this", "expressions"),
259        exp.DataType: lambda self, e: self._annotate_with_type(e, e.copy()),
260        exp.DateAdd: lambda self, e: self._annotate_timeunit(e),
261        exp.DateSub: lambda self, e: self._annotate_timeunit(e),
262        exp.DateTrunc: lambda self, e: self._annotate_timeunit(e),
263        exp.Distinct: lambda self, e: self._annotate_by_args(e, "expressions"),
264        exp.Div: lambda self, e: self._annotate_div(e),
265        exp.Dot: lambda self, e: self._annotate_dot(e),
266        exp.Explode: lambda self, e: self._annotate_explode(e),
267        exp.Filter: lambda self, e: self._annotate_by_args(e, "this"),
268        exp.GenerateDateArray: lambda self, e: self._annotate_with_type(
269            e, exp.DataType.build("ARRAY<DATE>")
270        ),
271        exp.If: lambda self, e: self._annotate_by_args(e, "true", "false"),
272        exp.Interval: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.INTERVAL),
273        exp.Least: lambda self, e: self._annotate_by_args(e, "expressions"),
274        exp.Literal: lambda self, e: self._annotate_literal(e),
275        exp.Map: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.MAP),
276        exp.Max: lambda self, e: self._annotate_by_args(e, "this", "expressions"),
277        exp.Min: lambda self, e: self._annotate_by_args(e, "this", "expressions"),
278        exp.Null: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.NULL),
279        exp.Nullif: lambda self, e: self._annotate_by_args(e, "this", "expression"),
280        exp.PropertyEQ: lambda self, e: self._annotate_by_args(e, "expression"),
281        exp.Slice: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.UNKNOWN),
282        exp.Struct: lambda self, e: self._annotate_by_args(e, "expressions", struct=True),
283        exp.Sum: lambda self, e: self._annotate_by_args(e, "this", "expressions", promote=True),
284        exp.Timestamp: lambda self, e: self._annotate_with_type(
285            e,
286            exp.DataType.Type.TIMESTAMPTZ if e.args.get("with_tz") else exp.DataType.Type.TIMESTAMP,
287        ),
288        exp.TryCast: lambda self, e: self._annotate_with_type(e, e.args["to"]),
289        exp.Unnest: lambda self, e: self._annotate_unnest(e),
290        exp.VarMap: lambda self, e: self._annotate_with_type(e, exp.DataType.Type.MAP),
291    }
292
293    NESTED_TYPES = {
294        exp.DataType.Type.ARRAY,
295    }
296
297    # Specifies what types a given type can be coerced into (autofilled)
298    COERCES_TO: t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]] = {}
299
300    # Coercion functions for binary operations.
301    # Map of type pairs to a callable that takes both sides of the binary operation and returns the resulting type.
302    BINARY_COERCIONS: BinaryCoercions = {
303        **swap_all(
304            {
305                (t, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date_literal(
306                    l, r.args.get("unit")
307                )
308                for t in exp.DataType.TEXT_TYPES
309            }
310        ),
311        **swap_all(
312            {
313                # text + numeric will yield the numeric type to match most dialects' semantics
314                (text, numeric): lambda l, r: t.cast(
315                    exp.DataType.Type, l.type if l.type in exp.DataType.NUMERIC_TYPES else r.type
316                )
317                for text in exp.DataType.TEXT_TYPES
318                for numeric in exp.DataType.NUMERIC_TYPES
319            }
320        ),
321        **swap_all(
322            {
323                (exp.DataType.Type.DATE, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date(
324                    l, r.args.get("unit")
325                ),
326            }
327        ),
328    }
329
330    def __init__(
331        self,
332        schema: Schema,
333        annotators: t.Optional[t.Dict[t.Type[E], t.Callable[[TypeAnnotator, E], E]]] = None,
334        coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None,
335        binary_coercions: t.Optional[BinaryCoercions] = None,
336    ) -> None:
337        self.schema = schema
338        self.annotators = annotators or self.ANNOTATORS
339        self.coerces_to = coerces_to or self.COERCES_TO
340        self.binary_coercions = binary_coercions or self.BINARY_COERCIONS
341
342        # Caches the ids of annotated sub-Expressions, to ensure we only visit them once
343        self._visited: t.Set[int] = set()
344
345    def _set_type(
346        self, expression: exp.Expression, target_type: t.Optional[exp.DataType | exp.DataType.Type]
347    ) -> None:
348        expression.type = target_type or exp.DataType.Type.UNKNOWN  # type: ignore
349        self._visited.add(id(expression))
350
351    def annotate(self, expression: E) -> E:
352        for scope in traverse_scope(expression):
353            selects = {}
354            for name, source in scope.sources.items():
355                if not isinstance(source, Scope):
356                    continue
357                if isinstance(source.expression, exp.UDTF):
358                    values = []
359
360                    if isinstance(source.expression, exp.Lateral):
361                        if isinstance(source.expression.this, exp.Explode):
362                            values = [source.expression.this.this]
363                    elif isinstance(source.expression, exp.Unnest):
364                        values = [source.expression]
365                    else:
366                        values = source.expression.expressions[0].expressions
367
368                    if not values:
369                        continue
370
371                    selects[name] = {
372                        alias: column
373                        for alias, column in zip(
374                            source.expression.alias_column_names,
375                            values,
376                        )
377                    }
378                else:
379                    selects[name] = {
380                        select.alias_or_name: select for select in source.expression.selects
381                    }
382
383            # First annotate the current scope's column references
384            for col in scope.columns:
385                if not col.table:
386                    continue
387
388                source = scope.sources.get(col.table)
389                if isinstance(source, exp.Table):
390                    self._set_type(col, self.schema.get_column_type(source, col))
391                elif source:
392                    if col.table in selects and col.name in selects[col.table]:
393                        self._set_type(col, selects[col.table][col.name].type)
394                    elif isinstance(source.expression, exp.Unnest):
395                        self._set_type(col, source.expression.type)
396
397            # Then (possibly) annotate the remaining expressions in the scope
398            self._maybe_annotate(scope.expression)
399
400        return self._maybe_annotate(expression)  # This takes care of non-traversable expressions
401
402    def _maybe_annotate(self, expression: E) -> E:
403        if id(expression) in self._visited:
404            return expression  # We've already inferred the expression's type
405
406        annotator = self.annotators.get(expression.__class__)
407
408        return (
409            annotator(self, expression)
410            if annotator
411            else self._annotate_with_type(expression, exp.DataType.Type.UNKNOWN)
412        )
413
414    def _annotate_args(self, expression: E) -> E:
415        for value in expression.iter_expressions():
416            self._maybe_annotate(value)
417
418        return expression
419
420    def _maybe_coerce(
421        self, type1: exp.DataType | exp.DataType.Type, type2: exp.DataType | exp.DataType.Type
422    ) -> exp.DataType | exp.DataType.Type:
423        type1_value = type1.this if isinstance(type1, exp.DataType) else type1
424        type2_value = type2.this if isinstance(type2, exp.DataType) else type2
425
426        # We propagate the NULL / UNKNOWN types upwards if found
427        if exp.DataType.Type.NULL in (type1_value, type2_value):
428            return exp.DataType.Type.NULL
429        if exp.DataType.Type.UNKNOWN in (type1_value, type2_value):
430            return exp.DataType.Type.UNKNOWN
431
432        if type1_value in self.NESTED_TYPES:
433            return type1
434        if type2_value in self.NESTED_TYPES:
435            return type2
436
437        return type2_value if type2_value in self.coerces_to.get(type1_value, {}) else type1_value  # type: ignore
438
439    # Note: the following "no_type_check" decorators were added because mypy was yelling due
440    # to assigning Type values to expression.type (since its getter returns Optional[DataType]).
441    # This is a known mypy issue: https://github.com/python/mypy/issues/3004
442
443    @t.no_type_check
444    def _annotate_binary(self, expression: B) -> B:
445        self._annotate_args(expression)
446
447        left, right = expression.left, expression.right
448        left_type, right_type = left.type.this, right.type.this
449
450        if isinstance(expression, exp.Connector):
451            if left_type == exp.DataType.Type.NULL and right_type == exp.DataType.Type.NULL:
452                self._set_type(expression, exp.DataType.Type.NULL)
453            elif exp.DataType.Type.NULL in (left_type, right_type):
454                self._set_type(
455                    expression,
456                    exp.DataType.build("NULLABLE", expressions=exp.DataType.build("BOOLEAN")),
457                )
458            else:
459                self._set_type(expression, exp.DataType.Type.BOOLEAN)
460        elif isinstance(expression, exp.Predicate):
461            self._set_type(expression, exp.DataType.Type.BOOLEAN)
462        elif (left_type, right_type) in self.binary_coercions:
463            self._set_type(expression, self.binary_coercions[(left_type, right_type)](left, right))
464        else:
465            self._set_type(expression, self._maybe_coerce(left_type, right_type))
466
467        return expression
468
469    @t.no_type_check
470    def _annotate_unary(self, expression: E) -> E:
471        self._annotate_args(expression)
472
473        if isinstance(expression, exp.Condition) and not isinstance(expression, exp.Paren):
474            self._set_type(expression, exp.DataType.Type.BOOLEAN)
475        else:
476            self._set_type(expression, expression.this.type)
477
478        return expression
479
480    @t.no_type_check
481    def _annotate_literal(self, expression: exp.Literal) -> exp.Literal:
482        if expression.is_string:
483            self._set_type(expression, exp.DataType.Type.VARCHAR)
484        elif expression.is_int:
485            self._set_type(expression, exp.DataType.Type.INT)
486        else:
487            self._set_type(expression, exp.DataType.Type.DOUBLE)
488
489        return expression
490
491    @t.no_type_check
492    def _annotate_with_type(self, expression: E, target_type: exp.DataType.Type) -> E:
493        self._set_type(expression, target_type)
494        return self._annotate_args(expression)
495
496    @t.no_type_check
497    def _annotate_struct_value(
498        self, expression: exp.Expression
499    ) -> t.Optional[exp.DataType] | exp.ColumnDef:
500        alias = expression.args.get("alias")
501        if alias:
502            return exp.ColumnDef(this=alias.copy(), kind=expression.type)
503
504        # Case: key = value or key := value
505        if expression.expression:
506            return exp.ColumnDef(this=expression.this.copy(), kind=expression.expression.type)
507
508        return expression.type
509
510    @t.no_type_check
511    def _annotate_by_args(
512        self,
513        expression: E,
514        *args: str,
515        promote: bool = False,
516        array: bool = False,
517        struct: bool = False,
518    ) -> E:
519        self._annotate_args(expression)
520
521        expressions: t.List[exp.Expression] = []
522        for arg in args:
523            arg_expr = expression.args.get(arg)
524            expressions.extend(expr for expr in ensure_list(arg_expr) if expr)
525
526        last_datatype = None
527        for expr in expressions:
528            expr_type = expr.type
529
530            # Stop at the first nested data type found - we don't want to _maybe_coerce nested types
531            if expr_type.args.get("nested"):
532                last_datatype = expr_type
533                break
534
535            last_datatype = self._maybe_coerce(last_datatype or expr_type, expr_type)
536
537        self._set_type(expression, last_datatype or exp.DataType.Type.UNKNOWN)
538
539        if promote:
540            if expression.type.this in exp.DataType.INTEGER_TYPES:
541                self._set_type(expression, exp.DataType.Type.BIGINT)
542            elif expression.type.this in exp.DataType.FLOAT_TYPES:
543                self._set_type(expression, exp.DataType.Type.DOUBLE)
544
545        if array:
546            self._set_type(
547                expression,
548                exp.DataType(
549                    this=exp.DataType.Type.ARRAY, expressions=[expression.type], nested=True
550                ),
551            )
552
553        if struct:
554            self._set_type(
555                expression,
556                exp.DataType(
557                    this=exp.DataType.Type.STRUCT,
558                    expressions=[self._annotate_struct_value(expr) for expr in expressions],
559                    nested=True,
560                ),
561            )
562
563        return expression
564
565    def _annotate_timeunit(
566        self, expression: exp.TimeUnit | exp.DateTrunc
567    ) -> exp.TimeUnit | exp.DateTrunc:
568        self._annotate_args(expression)
569
570        if expression.this.type.this in exp.DataType.TEXT_TYPES:
571            datatype = _coerce_date_literal(expression.this, expression.unit)
572        elif expression.this.type.this in exp.DataType.TEMPORAL_TYPES:
573            datatype = _coerce_date(expression.this, expression.unit)
574        else:
575            datatype = exp.DataType.Type.UNKNOWN
576
577        self._set_type(expression, datatype)
578        return expression
579
580    def _annotate_bracket(self, expression: exp.Bracket) -> exp.Bracket:
581        self._annotate_args(expression)
582
583        bracket_arg = expression.expressions[0]
584        this = expression.this
585
586        if isinstance(bracket_arg, exp.Slice):
587            self._set_type(expression, this.type)
588        elif this.type.is_type(exp.DataType.Type.ARRAY):
589            self._set_type(expression, seq_get(this.type.expressions, 0))
590        elif isinstance(this, (exp.Map, exp.VarMap)) and bracket_arg in this.keys:
591            index = this.keys.index(bracket_arg)
592            value = seq_get(this.values, index)
593            self._set_type(expression, value.type if value else None)
594        else:
595            self._set_type(expression, exp.DataType.Type.UNKNOWN)
596
597        return expression
598
599    def _annotate_div(self, expression: exp.Div) -> exp.Div:
600        self._annotate_args(expression)
601
602        left_type, right_type = expression.left.type.this, expression.right.type.this  # type: ignore
603
604        if (
605            expression.args.get("typed")
606            and left_type in exp.DataType.INTEGER_TYPES
607            and right_type in exp.DataType.INTEGER_TYPES
608        ):
609            self._set_type(expression, exp.DataType.Type.BIGINT)
610        else:
611            self._set_type(expression, self._maybe_coerce(left_type, right_type))
612            if expression.type and expression.type.this not in exp.DataType.REAL_TYPES:
613                self._set_type(
614                    expression, self._maybe_coerce(expression.type, exp.DataType.Type.DOUBLE)
615                )
616
617        return expression
618
619    def _annotate_dot(self, expression: exp.Dot) -> exp.Dot:
620        self._annotate_args(expression)
621        self._set_type(expression, None)
622        this_type = expression.this.type
623
624        if this_type and this_type.is_type(exp.DataType.Type.STRUCT):
625            for e in this_type.expressions:
626                if e.name == expression.expression.name:
627                    self._set_type(expression, e.kind)
628                    break
629
630        return expression
631
632    def _annotate_explode(self, expression: exp.Explode) -> exp.Explode:
633        self._annotate_args(expression)
634        self._set_type(expression, seq_get(expression.this.type.expressions, 0))
635        return expression
636
637    def _annotate_unnest(self, expression: exp.Unnest) -> exp.Unnest:
638        self._annotate_args(expression)
639        child = seq_get(expression.expressions, 0)
640        self._set_type(expression, child and seq_get(child.type.expressions, 0))
641        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)
330    def __init__(
331        self,
332        schema: Schema,
333        annotators: t.Optional[t.Dict[t.Type[E], t.Callable[[TypeAnnotator, E], E]]] = None,
334        coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None,
335        binary_coercions: t.Optional[BinaryCoercions] = None,
336    ) -> None:
337        self.schema = schema
338        self.annotators = annotators or self.ANNOTATORS
339        self.coerces_to = coerces_to or self.COERCES_TO
340        self.binary_coercions = binary_coercions or self.BINARY_COERCIONS
341
342        # Caches the ids of annotated sub-Expressions, to ensure we only visit them once
343        self._visited: t.Set[int] = set()
TYPE_TO_EXPRESSIONS: Dict[sqlglot.expressions.DataType.Type, Set[Type[sqlglot.expressions.Expression]]] = {<Type.BIGINT: 'BIGINT'>: {<class 'sqlglot.expressions.Count'>, <class 'sqlglot.expressions.Length'>, <class 'sqlglot.expressions.ArraySize'>, <class 'sqlglot.expressions.ApproxDistinct'>}, <Type.BOOLEAN: 'BOOLEAN'>: {<class 'sqlglot.expressions.Between'>, <class 'sqlglot.expressions.RegexpLike'>, <class 'sqlglot.expressions.Boolean'>, <class 'sqlglot.expressions.In'>}, <Type.DATE: 'DATE'>: {<class 'sqlglot.expressions.CurrentDate'>, <class 'sqlglot.expressions.TimeStrToDate'>, <class 'sqlglot.expressions.TsOrDsToDate'>, <class 'sqlglot.expressions.Date'>, <class 'sqlglot.expressions.StrToDate'>, <class 'sqlglot.expressions.DateStrToDate'>, <class 'sqlglot.expressions.DiToDate'>, <class 'sqlglot.expressions.DateFromParts'>}, <Type.DATETIME: 'DATETIME'>: {<class 'sqlglot.expressions.CurrentDatetime'>, <class 'sqlglot.expressions.DatetimeAdd'>, <class 'sqlglot.expressions.DatetimeSub'>}, <Type.DOUBLE: 'DOUBLE'>: {<class 'sqlglot.expressions.Div'>, <class 'sqlglot.expressions.Ln'>, <class 'sqlglot.expressions.StddevSamp'>, <class 'sqlglot.expressions.ApproxQuantile'>, <class 'sqlglot.expressions.StddevPop'>, <class 'sqlglot.expressions.Variance'>, <class 'sqlglot.expressions.Quantile'>, <class 'sqlglot.expressions.Stddev'>, <class 'sqlglot.expressions.SafeDivide'>, <class 'sqlglot.expressions.Exp'>, <class 'sqlglot.expressions.Avg'>, <class 'sqlglot.expressions.Sqrt'>, <class 'sqlglot.expressions.VariancePop'>, <class 'sqlglot.expressions.Round'>, <class 'sqlglot.expressions.Pow'>, <class 'sqlglot.expressions.Log'>}, <Type.INT: 'INT'>: {<class 'sqlglot.expressions.Floor'>, <class 'sqlglot.expressions.Extract'>, <class 'sqlglot.expressions.TimeDiff'>, <class 'sqlglot.expressions.Levenshtein'>, <class 'sqlglot.expressions.Ceil'>, <class 'sqlglot.expressions.DateDiff'>, <class 'sqlglot.expressions.Sign'>, <class 'sqlglot.expressions.DateToDi'>, <class 'sqlglot.expressions.StrPosition'>, <class 'sqlglot.expressions.TimestampDiff'>, <class 'sqlglot.expressions.TsOrDiToDi'>, <class 'sqlglot.expressions.DatetimeDiff'>}, <Type.JSON: 'JSON'>: {<class 'sqlglot.expressions.ParseJSON'>}, <Type.TIMESTAMP: 'TIMESTAMP'>: {<class 'sqlglot.expressions.UnixToTime'>, <class 'sqlglot.expressions.StrToTime'>, <class 'sqlglot.expressions.TimeSub'>, <class 'sqlglot.expressions.TimestampSub'>, <class 'sqlglot.expressions.TimeAdd'>, <class 'sqlglot.expressions.TimeStrToTime'>, <class 'sqlglot.expressions.CurrentTimestamp'>, <class 'sqlglot.expressions.TimestampAdd'>, <class 'sqlglot.expressions.CurrentTime'>}, <Type.TINYINT: 'TINYINT'>: {<class 'sqlglot.expressions.Week'>, <class 'sqlglot.expressions.Year'>, <class 'sqlglot.expressions.Month'>, <class 'sqlglot.expressions.Day'>}, <Type.VARCHAR: 'VARCHAR'>: {<class 'sqlglot.expressions.TimeToTimeStr'>, <class 'sqlglot.expressions.TsOrDsToDateStr'>, <class 'sqlglot.expressions.TimeToStr'>, <class 'sqlglot.expressions.UnixToTimeStr'>, <class 'sqlglot.expressions.UnixToStr'>, <class 'sqlglot.expressions.GroupConcat'>, <class 'sqlglot.expressions.Trim'>, <class 'sqlglot.expressions.Upper'>, <class 'sqlglot.expressions.DateToDateStr'>, <class 'sqlglot.expressions.Lower'>, <class 'sqlglot.expressions.ConcatWs'>, <class 'sqlglot.expressions.Substring'>, <class 'sqlglot.expressions.Concat'>, <class 'sqlglot.expressions.ArrayConcat'>, <class 'sqlglot.expressions.Initcap'>}}
ANNOTATORS: Dict = {<class 'sqlglot.expressions.Alias'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.BitwiseNot'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Neg'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Not'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Paren'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.PivotAlias'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Unary'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Add'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.And'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.ArrayContained'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.ArrayContains'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.ArrayOverlaps'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Binary'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.BitwiseAnd'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.BitwiseLeftShift'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.BitwiseOr'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.BitwiseRightShift'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.BitwiseXor'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Collate'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Connector'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.DPipe'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Distance'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Div'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Dot'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.EQ'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Escape'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.GT'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.GTE'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Glob'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.ILike'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.ILikeAny'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.IntDiv'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Is'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.JSONArrayContains'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.JSONBContains'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.JSONBExtract'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.JSONBExtractScalar'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.JSONExtract'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.JSONExtractScalar'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Kwarg'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.LT'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.LTE'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Like'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.LikeAny'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Mod'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Mul'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.NEQ'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.NullSafeEQ'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.NullSafeNEQ'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Operator'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Or'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Overlaps'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Pow'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.PropertyEQ'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.RegexpILike'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.RegexpLike'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.SimilarTo'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Slice'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Sub'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Xor'>: <function TypeAnnotator.<dictcomp>.<lambda>>, <class 'sqlglot.expressions.Count'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Length'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.ArraySize'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.ApproxDistinct'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Between'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Boolean'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.In'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.CurrentDate'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.TimeStrToDate'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.TsOrDsToDate'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Date'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.StrToDate'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.DateStrToDate'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.DiToDate'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.DateFromParts'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.CurrentDatetime'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.DatetimeAdd'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.DatetimeSub'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Ln'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.StddevSamp'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.ApproxQuantile'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.StddevPop'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Variance'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Quantile'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Stddev'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.SafeDivide'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Exp'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Avg'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Sqrt'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.VariancePop'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Round'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Log'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Floor'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Extract'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.TimeDiff'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Levenshtein'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Ceil'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.DateDiff'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Sign'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.DateToDi'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.StrPosition'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.TimestampDiff'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.TsOrDiToDi'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.DatetimeDiff'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.ParseJSON'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.UnixToTime'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.StrToTime'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.TimeSub'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.TimestampSub'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.TimeAdd'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.TimeStrToTime'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.CurrentTimestamp'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.TimestampAdd'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.CurrentTime'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Week'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Year'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Month'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Day'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.TimeToTimeStr'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.TsOrDsToDateStr'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.TimeToStr'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.UnixToTimeStr'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.UnixToStr'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.GroupConcat'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Trim'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Upper'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.DateToDateStr'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Lower'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.ConcatWs'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Substring'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Concat'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.ArrayConcat'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Initcap'>: <function _annotate_with_type_lambda.<locals>.<lambda>>, <class 'sqlglot.expressions.Abs'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Anonymous'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Array'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.ArrayAgg'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Bracket'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Cast'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Case'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Coalesce'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.DataType'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.DateAdd'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.DateSub'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.DateTrunc'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Distinct'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Explode'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Filter'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.GenerateDateArray'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.If'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Interval'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Least'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Literal'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Map'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Max'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Min'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Null'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Nullif'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Struct'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Sum'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Timestamp'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.TryCast'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.Unnest'>: <function TypeAnnotator.<lambda>>, <class 'sqlglot.expressions.VarMap'>: <function TypeAnnotator.<lambda>>}
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.NVARCHAR: 'NVARCHAR'>, <Type.TEXT: 'TEXT'>}, <Type.NCHAR: 'NCHAR'>: {<Type.NVARCHAR: 'NVARCHAR'>, <Type.VARCHAR: 'VARCHAR'>, <Type.TEXT: 'TEXT'>}, <Type.CHAR: 'CHAR'>: {<Type.NVARCHAR: 'NVARCHAR'>, <Type.VARCHAR: 'VARCHAR'>, <Type.NCHAR: 'NCHAR'>, <Type.TEXT: 'TEXT'>}, <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.DECIMAL: 'DECIMAL'>, <Type.FLOAT: 'FLOAT'>}, <Type.INT: 'INT'>: {<Type.DOUBLE: 'DOUBLE'>, <Type.DECIMAL: 'DECIMAL'>, <Type.FLOAT: 'FLOAT'>, <Type.BIGINT: 'BIGINT'>}, <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.DECIMAL: 'DECIMAL'>, <Type.INT: 'INT'>, <Type.SMALLINT: 'SMALLINT'>, <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.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <Type.TIMESTAMP: 'TIMESTAMP'>}, <Type.DATE: 'DATE'>: {<Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <Type.TIMESTAMP: 'TIMESTAMP'>, <Type.DATETIME: 'DATETIME'>}}
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.VARCHAR: 'VARCHAR'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <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.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT128: 'UINT128'>): <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.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <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.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT128: 'UINT128'>): <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.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <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.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT128: 'UINT128'>): <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.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <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.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT128: 'UINT128'>): <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.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <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.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT128: 'UINT128'>): <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.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <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.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT128: 'UINT128'>): <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.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <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.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <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.BIT: 'BIT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <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.UBIGINT: 'UBIGINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <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.BIT: 'BIT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <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.UBIGINT: 'UBIGINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <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.BIT: 'BIT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <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.UBIGINT: 'UBIGINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <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.BIT: 'BIT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <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.UBIGINT: 'UBIGINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <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.BIT: 'BIT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <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.UBIGINT: 'UBIGINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <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.BIT: 'BIT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <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.UBIGINT: 'UBIGINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.TEXT: 'TEXT'>): <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:
351    def annotate(self, expression: E) -> E:
352        for scope in traverse_scope(expression):
353            selects = {}
354            for name, source in scope.sources.items():
355                if not isinstance(source, Scope):
356                    continue
357                if isinstance(source.expression, exp.UDTF):
358                    values = []
359
360                    if isinstance(source.expression, exp.Lateral):
361                        if isinstance(source.expression.this, exp.Explode):
362                            values = [source.expression.this.this]
363                    elif isinstance(source.expression, exp.Unnest):
364                        values = [source.expression]
365                    else:
366                        values = source.expression.expressions[0].expressions
367
368                    if not values:
369                        continue
370
371                    selects[name] = {
372                        alias: column
373                        for alias, column in zip(
374                            source.expression.alias_column_names,
375                            values,
376                        )
377                    }
378                else:
379                    selects[name] = {
380                        select.alias_or_name: select for select in source.expression.selects
381                    }
382
383            # First annotate the current scope's column references
384            for col in scope.columns:
385                if not col.table:
386                    continue
387
388                source = scope.sources.get(col.table)
389                if isinstance(source, exp.Table):
390                    self._set_type(col, self.schema.get_column_type(source, col))
391                elif source:
392                    if col.table in selects and col.name in selects[col.table]:
393                        self._set_type(col, selects[col.table][col.name].type)
394                    elif isinstance(source.expression, exp.Unnest):
395                        self._set_type(col, source.expression.type)
396
397            # Then (possibly) annotate the remaining expressions in the scope
398            self._maybe_annotate(scope.expression)
399
400        return self._maybe_annotate(expression)  # This takes care of non-traversable expressions