Edit on GitHub

# sqlglot.optimizer.annotate_types

View Source

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

def annotate_types( expression: ~E, schema: Union[Dict, sqlglot.schema.Schema, NoneType] = None, annotators: Optional[Dict[Type[~E], Callable[[TypeAnnotator, ~E], ~E]]] = None, coerces_to: Optional[Dict[sqlglot.expressions.DataType.Type, Set[sqlglot.expressions.DataType.Type]]] = None, dialect: Union[str, sqlglot.dialects.Dialect, Type[sqlglot.dialects.Dialect], NoneType] = None) -> ~E: View Source

    31def annotate_types(
    32    expression: E,
    33    schema: t.Optional[t.Dict | Schema] = None,
    34    annotators: t.Optional[AnnotatorsType] = None,
    35    coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None,
    36    dialect: DialectType = None,
    37) -> E:
    38    """
    39    Infers the types of an expression, annotating its AST accordingly.
    40
    41    Example:
    42        >>> import sqlglot
    43        >>> schema = {"y": {"cola": "SMALLINT"}}
    44        >>> sql = "SELECT x.cola + 2.5 AS cola FROM (SELECT y.cola AS cola FROM y AS y) AS x"
    45        >>> annotated_expr = annotate_types(sqlglot.parse_one(sql), schema=schema)
    46        >>> annotated_expr.expressions[0].type.this  # Get the type of "x.cola + 2.5 AS cola"
    47        <Type.DOUBLE: 'DOUBLE'>
    48
    49    Args:
    50        expression: Expression to annotate.
    51        schema: Database schema.
    52        annotators: Maps expression type to corresponding annotation function.
    53        coerces_to: Maps expression type to set of types that it can be coerced into.
    54
    55    Returns:
    56        The expression annotated with types.
    57    """
    58
    59    schema = ensure_schema(schema, dialect=dialect)
    60
    61    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.

def swap_args( func: Callable[[sqlglot.expressions.Expression, sqlglot.expressions.Expression], sqlglot.expressions.DataType.Type]) -> Callable[[sqlglot.expressions.Expression, sqlglot.expressions.Expression], sqlglot.expressions.DataType.Type]: View Source

    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

def swap_all( coercions: Dict[Tuple[sqlglot.expressions.DataType.Type, sqlglot.expressions.DataType.Type], Callable[[sqlglot.expressions.Expression, sqlglot.expressions.Expression], sqlglot.expressions.DataType.Type]]) -> Dict[Tuple[sqlglot.expressions.DataType.Type, sqlglot.expressions.DataType.Type], Callable[[sqlglot.expressions.Expression, sqlglot.expressions.Expression], sqlglot.expressions.DataType.Type]]: View Source

    92def swap_all(coercions: BinaryCoercions) -> BinaryCoercions:
    93    return {**coercions, **{(b, a): swap_args(func) for (a, b), func in coercions.items()}}

class TypeAnnotator: View Source

    142class TypeAnnotator(metaclass=_TypeAnnotator):
    143    NESTED_TYPES = {
    144        exp.DataType.Type.ARRAY,
    145    }
    146
    147    # Specifies what types a given type can be coerced into (autofilled)
    148    COERCES_TO: t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]] = {}
    149
    150    # Coercion functions for binary operations.
    151    # Map of type pairs to a callable that takes both sides of the binary operation and returns the resulting type.
    152    BINARY_COERCIONS: BinaryCoercions = {
    153        **swap_all(
    154            {
    155                (t, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date_literal(
    156                    l, r.args.get("unit")
    157                )
    158                for t in exp.DataType.TEXT_TYPES
    159            }
    160        ),
    161        **swap_all(
    162            {
    163                # text + numeric will yield the numeric type to match most dialects' semantics
    164                (text, numeric): lambda l, r: t.cast(
    165                    exp.DataType.Type, l.type if l.type in exp.DataType.NUMERIC_TYPES else r.type
    166                )
    167                for text in exp.DataType.TEXT_TYPES
    168                for numeric in exp.DataType.NUMERIC_TYPES
    169            }
    170        ),
    171        **swap_all(
    172            {
    173                (exp.DataType.Type.DATE, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date(
    174                    l, r.args.get("unit")
    175                ),
    176            }
    177        ),
    178    }
    179
    180    def __init__(
    181        self,
    182        schema: Schema,
    183        annotators: t.Optional[AnnotatorsType] = None,
    184        coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None,
    185        binary_coercions: t.Optional[BinaryCoercions] = None,
    186    ) -> None:
    187        self.schema = schema
    188        self.annotators = annotators or Dialect.get_or_raise(schema.dialect).ANNOTATORS
    189        self.coerces_to = (
    190            coerces_to or Dialect.get_or_raise(schema.dialect).COERCES_TO or self.COERCES_TO
    191        )
    192        self.binary_coercions = binary_coercions or self.BINARY_COERCIONS
    193
    194        # Caches the ids of annotated sub-Expressions, to ensure we only visit them once
    195        self._visited: t.Set[int] = set()
    196
    197        # Maps an exp.SetOperation's id (e.g. UNION) to its projection types. This is computed if the
    198        # exp.SetOperation is the expression of a scope source, as selecting from it multiple times
    199        # would reprocess the entire subtree to coerce the types of its operands' projections
    200        self._setop_column_types: t.Dict[int, t.Dict[str, exp.DataType | exp.DataType.Type]] = {}
    201
    202    def _set_type(
    203        self, expression: exp.Expression, target_type: t.Optional[exp.DataType | exp.DataType.Type]
    204    ) -> None:
    205        expression.type = target_type or exp.DataType.Type.UNKNOWN  # type: ignore
    206        self._visited.add(id(expression))
    207
    208    def annotate(self, expression: E) -> E:
    209        for scope in traverse_scope(expression):
    210            self.annotate_scope(scope)
    211        return self._maybe_annotate(expression)  # This takes care of non-traversable expressions
    212
    213    def annotate_scope(self, scope: Scope) -> None:
    214        selects = {}
    215        for name, source in scope.sources.items():
    216            if not isinstance(source, Scope):
    217                continue
    218
    219            expression = source.expression
    220            if isinstance(expression, exp.UDTF):
    221                values = []
    222
    223                if isinstance(expression, exp.Lateral):
    224                    if isinstance(expression.this, exp.Explode):
    225                        values = [expression.this.this]
    226                elif isinstance(expression, exp.Unnest):
    227                    values = [expression]
    228                elif not isinstance(expression, exp.TableFromRows):
    229                    values = expression.expressions[0].expressions
    230
    231                if not values:
    232                    continue
    233
    234                selects[name] = {
    235                    alias: column.type
    236                    for alias, column in zip(expression.alias_column_names, values)
    237                }
    238            elif isinstance(expression, exp.SetOperation) and len(expression.left.selects) == len(
    239                expression.right.selects
    240            ):
    241                selects[name] = col_types = self._setop_column_types.setdefault(id(expression), {})
    242
    243                if not col_types:
    244                    # Process a chain / sub-tree of set operations
    245                    for set_op in expression.walk(
    246                        prune=lambda n: not isinstance(n, (exp.SetOperation, exp.Subquery))
    247                    ):
    248                        if not isinstance(set_op, exp.SetOperation):
    249                            continue
    250
    251                        if set_op.args.get("by_name"):
    252                            r_type_by_select = {
    253                                s.alias_or_name: s.type for s in set_op.right.selects
    254                            }
    255                            setop_cols = {
    256                                s.alias_or_name: self._maybe_coerce(
    257                                    t.cast(exp.DataType, s.type),
    258                                    r_type_by_select.get(s.alias_or_name)
    259                                    or exp.DataType.Type.UNKNOWN,
    260                                )
    261                                for s in set_op.left.selects
    262                            }
    263                        else:
    264                            setop_cols = {
    265                                ls.alias_or_name: self._maybe_coerce(
    266                                    t.cast(exp.DataType, ls.type), t.cast(exp.DataType, rs.type)
    267                                )
    268                                for ls, rs in zip(set_op.left.selects, set_op.right.selects)
    269                            }
    270
    271                        # Coerce intermediate results with the previously registered types, if they exist
    272                        for col_name, col_type in setop_cols.items():
    273                            col_types[col_name] = self._maybe_coerce(
    274                                col_type, col_types.get(col_name, exp.DataType.Type.NULL)
    275                            )
    276
    277            else:
    278                selects[name] = {s.alias_or_name: s.type for s in expression.selects}
    279
    280        # First annotate the current scope's column references
    281        for col in scope.columns:
    282            if not col.table:
    283                continue
    284
    285            source = scope.sources.get(col.table)
    286            if isinstance(source, exp.Table):
    287                self._set_type(col, self.schema.get_column_type(source, col))
    288            elif source:
    289                if col.table in selects and col.name in selects[col.table]:
    290                    self._set_type(col, selects[col.table][col.name])
    291                elif isinstance(source.expression, exp.Unnest):
    292                    self._set_type(col, source.expression.type)
    293
    294        if isinstance(self.schema, MappingSchema):
    295            for table_column in scope.table_columns:
    296                source = scope.sources.get(table_column.name)
    297
    298                if isinstance(source, exp.Table):
    299                    schema = self.schema.find(
    300                        source, raise_on_missing=False, ensure_data_types=True
    301                    )
    302                    if not isinstance(schema, dict):
    303                        continue
    304
    305                    struct_type = exp.DataType(
    306                        this=exp.DataType.Type.STRUCT,
    307                        expressions=[
    308                            exp.ColumnDef(this=exp.to_identifier(c), kind=kind)
    309                            for c, kind in schema.items()
    310                        ],
    311                        nested=True,
    312                    )
    313                    self._set_type(table_column, struct_type)
    314                elif (
    315                    isinstance(source, Scope)
    316                    and isinstance(source.expression, exp.Query)
    317                    and source.expression.is_type(exp.DataType.Type.STRUCT)
    318                ):
    319                    self._set_type(table_column, source.expression.type)
    320
    321        # Then (possibly) annotate the remaining expressions in the scope
    322        self._maybe_annotate(scope.expression)
    323
    324        if self.schema.dialect == "bigquery" and isinstance(scope.expression, exp.Query):
    325            struct_type = exp.DataType(
    326                this=exp.DataType.Type.STRUCT,
    327                expressions=[
    328                    exp.ColumnDef(this=exp.to_identifier(select.output_name), kind=select.type)
    329                    for select in scope.expression.selects
    330                ],
    331                nested=True,
    332            )
    333
    334            if not any(
    335                cd.kind.is_type(exp.DataType.Type.UNKNOWN)
    336                for cd in struct_type.expressions
    337                if cd.kind
    338            ):
    339                self._set_type(scope.expression, struct_type)
    340
    341    def _maybe_annotate(self, expression: E) -> E:
    342        if id(expression) in self._visited:
    343            return expression  # We've already inferred the expression's type
    344
    345        annotator = self.annotators.get(expression.__class__)
    346
    347        return (
    348            annotator(self, expression)
    349            if annotator
    350            else self._annotate_with_type(expression, exp.DataType.Type.UNKNOWN)
    351        )
    352
    353    def _annotate_args(self, expression: E) -> E:
    354        for value in expression.iter_expressions():
    355            self._maybe_annotate(value)
    356
    357        return expression
    358
    359    def _maybe_coerce(
    360        self,
    361        type1: exp.DataType | exp.DataType.Type,
    362        type2: exp.DataType | exp.DataType.Type,
    363    ) -> exp.DataType | exp.DataType.Type:
    364        """
    365        Returns type2 if type1 can be coerced into it, otherwise type1.
    366
    367        If either type is parameterized (e.g. DECIMAL(18, 2) contains two parameters),
    368        we assume type1 does not coerce into type2, so we also return it in this case.
    369        """
    370        if isinstance(type1, exp.DataType):
    371            if type1.expressions:
    372                return type1
    373            type1_value = type1.this
    374        else:
    375            type1_value = type1
    376
    377        if isinstance(type2, exp.DataType):
    378            if type2.expressions:
    379                return type2
    380            type2_value = type2.this
    381        else:
    382            type2_value = type2
    383
    384        # We propagate the UNKNOWN type upwards if found
    385        if exp.DataType.Type.UNKNOWN in (type1_value, type2_value):
    386            return exp.DataType.Type.UNKNOWN
    387
    388        return type2_value if type2_value in self.coerces_to.get(type1_value, {}) else type1_value
    389
    390    def _annotate_binary(self, expression: B) -> B:
    391        self._annotate_args(expression)
    392
    393        left, right = expression.left, expression.right
    394        left_type, right_type = left.type.this, right.type.this  # type: ignore
    395
    396        if isinstance(expression, (exp.Connector, exp.Predicate)):
    397            self._set_type(expression, exp.DataType.Type.BOOLEAN)
    398        elif (left_type, right_type) in self.binary_coercions:
    399            self._set_type(expression, self.binary_coercions[(left_type, right_type)](left, right))
    400        else:
    401            self._set_type(expression, self._maybe_coerce(left_type, right_type))
    402
    403        return expression
    404
    405    def _annotate_unary(self, expression: E) -> E:
    406        self._annotate_args(expression)
    407
    408        if isinstance(expression, exp.Not):
    409            self._set_type(expression, exp.DataType.Type.BOOLEAN)
    410        else:
    411            self._set_type(expression, expression.this.type)
    412
    413        return expression
    414
    415    def _annotate_literal(self, expression: exp.Literal) -> exp.Literal:
    416        if expression.is_string:
    417            self._set_type(expression, exp.DataType.Type.VARCHAR)
    418        elif expression.is_int:
    419            self._set_type(expression, exp.DataType.Type.INT)
    420        else:
    421            self._set_type(expression, exp.DataType.Type.DOUBLE)
    422
    423        return expression
    424
    425    def _annotate_with_type(
    426        self, expression: E, target_type: exp.DataType | exp.DataType.Type
    427    ) -> E:
    428        self._set_type(expression, target_type)
    429        return self._annotate_args(expression)
    430
    431    @t.no_type_check
    432    def _annotate_by_args(
    433        self,
    434        expression: E,
    435        *args: str,
    436        promote: bool = False,
    437        array: bool = False,
    438    ) -> E:
    439        self._annotate_args(expression)
    440
    441        expressions: t.List[exp.Expression] = []
    442        for arg in args:
    443            arg_expr = expression.args.get(arg)
    444            expressions.extend(expr for expr in ensure_list(arg_expr) if expr)
    445
    446        last_datatype = None
    447        for expr in expressions:
    448            expr_type = expr.type
    449
    450            # Stop at the first nested data type found - we don't want to _maybe_coerce nested types
    451            if expr_type.args.get("nested"):
    452                last_datatype = expr_type
    453                break
    454
    455            if not expr_type.is_type(exp.DataType.Type.UNKNOWN):
    456                last_datatype = self._maybe_coerce(last_datatype or expr_type, expr_type)
    457
    458        self._set_type(expression, last_datatype or exp.DataType.Type.UNKNOWN)
    459
    460        if promote:
    461            if expression.type.this in exp.DataType.INTEGER_TYPES:
    462                self._set_type(expression, exp.DataType.Type.BIGINT)
    463            elif expression.type.this in exp.DataType.FLOAT_TYPES:
    464                self._set_type(expression, exp.DataType.Type.DOUBLE)
    465
    466        if array:
    467            self._set_type(
    468                expression,
    469                exp.DataType(
    470                    this=exp.DataType.Type.ARRAY, expressions=[expression.type], nested=True
    471                ),
    472            )
    473
    474        return expression
    475
    476    def _annotate_timeunit(
    477        self, expression: exp.TimeUnit | exp.DateTrunc
    478    ) -> exp.TimeUnit | exp.DateTrunc:
    479        self._annotate_args(expression)
    480
    481        if expression.this.type.this in exp.DataType.TEXT_TYPES:
    482            datatype = _coerce_date_literal(expression.this, expression.unit)
    483        elif expression.this.type.this in exp.DataType.TEMPORAL_TYPES:
    484            datatype = _coerce_date(expression.this, expression.unit)
    485        else:
    486            datatype = exp.DataType.Type.UNKNOWN
    487
    488        self._set_type(expression, datatype)
    489        return expression
    490
    491    def _annotate_bracket(self, expression: exp.Bracket) -> exp.Bracket:
    492        self._annotate_args(expression)
    493
    494        bracket_arg = expression.expressions[0]
    495        this = expression.this
    496
    497        if isinstance(bracket_arg, exp.Slice):
    498            self._set_type(expression, this.type)
    499        elif this.type.is_type(exp.DataType.Type.ARRAY):
    500            self._set_type(expression, seq_get(this.type.expressions, 0))
    501        elif isinstance(this, (exp.Map, exp.VarMap)) and bracket_arg in this.keys:
    502            index = this.keys.index(bracket_arg)
    503            value = seq_get(this.values, index)
    504            self._set_type(expression, value.type if value else None)
    505        else:
    506            self._set_type(expression, exp.DataType.Type.UNKNOWN)
    507
    508        return expression
    509
    510    def _annotate_div(self, expression: exp.Div) -> exp.Div:
    511        self._annotate_args(expression)
    512
    513        left_type, right_type = expression.left.type.this, expression.right.type.this  # type: ignore
    514
    515        if (
    516            expression.args.get("typed")
    517            and left_type in exp.DataType.INTEGER_TYPES
    518            and right_type in exp.DataType.INTEGER_TYPES
    519        ):
    520            self._set_type(expression, exp.DataType.Type.BIGINT)
    521        else:
    522            self._set_type(expression, self._maybe_coerce(left_type, right_type))
    523            if expression.type and expression.type.this not in exp.DataType.REAL_TYPES:
    524                self._set_type(
    525                    expression, self._maybe_coerce(expression.type, exp.DataType.Type.DOUBLE)
    526                )
    527
    528        return expression
    529
    530    def _annotate_dot(self, expression: exp.Dot) -> exp.Dot:
    531        self._annotate_args(expression)
    532        self._set_type(expression, None)
    533        this_type = expression.this.type
    534
    535        if this_type and this_type.is_type(exp.DataType.Type.STRUCT):
    536            for e in this_type.expressions:
    537                if e.name == expression.expression.name:
    538                    self._set_type(expression, e.kind)
    539                    break
    540
    541        return expression
    542
    543    def _annotate_explode(self, expression: exp.Explode) -> exp.Explode:
    544        self._annotate_args(expression)
    545        self._set_type(expression, seq_get(expression.this.type.expressions, 0))
    546        return expression
    547
    548    def _annotate_unnest(self, expression: exp.Unnest) -> exp.Unnest:
    549        self._annotate_args(expression)
    550        child = seq_get(expression.expressions, 0)
    551
    552        if child and child.is_type(exp.DataType.Type.ARRAY):
    553            expr_type = seq_get(child.type.expressions, 0)
    554        else:
    555            expr_type = None
    556
    557        self._set_type(expression, expr_type)
    558        return expression
    559
    560    def _annotate_struct_value(
    561        self, expression: exp.Expression
    562    ) -> t.Optional[exp.DataType] | exp.ColumnDef:
    563        alias = expression.args.get("alias")
    564        if alias:
    565            return exp.ColumnDef(this=alias.copy(), kind=expression.type)
    566
    567        # Case: key = value or key := value
    568        if expression.expression:
    569            return exp.ColumnDef(this=expression.this.copy(), kind=expression.expression.type)
    570
    571        return expression.type
    572
    573    def _annotate_struct(self, expression: exp.Struct) -> exp.Struct:
    574        self._annotate_args(expression)
    575        self._set_type(
    576            expression,
    577            exp.DataType(
    578                this=exp.DataType.Type.STRUCT,
    579                expressions=[self._annotate_struct_value(expr) for expr in expression.expressions],
    580                nested=True,
    581            ),
    582        )
    583        return expression
    584
    585    @t.overload
    586    def _annotate_map(self, expression: exp.Map) -> exp.Map: ...
    587
    588    @t.overload
    589    def _annotate_map(self, expression: exp.VarMap) -> exp.VarMap: ...
    590
    591    def _annotate_map(self, expression):
    592        self._annotate_args(expression)
    593
    594        keys = expression.args.get("keys")
    595        values = expression.args.get("values")
    596
    597        map_type = exp.DataType(this=exp.DataType.Type.MAP)
    598        if isinstance(keys, exp.Array) and isinstance(values, exp.Array):
    599            key_type = seq_get(keys.type.expressions, 0) or exp.DataType.Type.UNKNOWN
    600            value_type = seq_get(values.type.expressions, 0) or exp.DataType.Type.UNKNOWN
    601
    602            if key_type != exp.DataType.Type.UNKNOWN and value_type != exp.DataType.Type.UNKNOWN:
    603                map_type.set("expressions", [key_type, value_type])
    604                map_type.set("nested", True)
    605
    606        self._set_type(expression, map_type)
    607        return expression
    608
    609    def _annotate_to_map(self, expression: exp.ToMap) -> exp.ToMap:
    610        self._annotate_args(expression)
    611
    612        map_type = exp.DataType(this=exp.DataType.Type.MAP)
    613        arg = expression.this
    614        if arg.is_type(exp.DataType.Type.STRUCT):
    615            for coldef in arg.type.expressions:
    616                kind = coldef.kind
    617                if kind != exp.DataType.Type.UNKNOWN:
    618                    map_type.set("expressions", [exp.DataType.build("varchar"), kind])
    619                    map_type.set("nested", True)
    620                    break
    621
    622        self._set_type(expression, map_type)
    623        return expression
    624
    625    def _annotate_extract(self, expression: exp.Extract) -> exp.Extract:
    626        self._annotate_args(expression)
    627        part = expression.name
    628        if part == "TIME":
    629            self._set_type(expression, exp.DataType.Type.TIME)
    630        elif part == "DATE":
    631            self._set_type(expression, exp.DataType.Type.DATE)
    632        else:
    633            self._set_type(expression, exp.DataType.Type.INT)
    634        return expression
    635
    636    def _annotate_by_array_element(self, expression: exp.Expression) -> exp.Expression:
    637        self._annotate_args(expression)
    638
    639        array_arg = expression.this
    640        if array_arg.type.is_type(exp.DataType.Type.ARRAY):
    641            element_type = seq_get(array_arg.type.expressions, 0) or exp.DataType.Type.UNKNOWN
    642            self._set_type(expression, element_type)
    643        else:
    644            self._set_type(expression, exp.DataType.Type.UNKNOWN)
    645
    646        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) View Source

    180    def __init__(
    181        self,
    182        schema: Schema,
    183        annotators: t.Optional[AnnotatorsType] = None,
    184        coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None,
    185        binary_coercions: t.Optional[BinaryCoercions] = None,
    186    ) -> None:
    187        self.schema = schema
    188        self.annotators = annotators or Dialect.get_or_raise(schema.dialect).ANNOTATORS
    189        self.coerces_to = (
    190            coerces_to or Dialect.get_or_raise(schema.dialect).COERCES_TO or self.COERCES_TO
    191        )
    192        self.binary_coercions = binary_coercions or self.BINARY_COERCIONS
    193
    194        # Caches the ids of annotated sub-Expressions, to ensure we only visit them once
    195        self._visited: t.Set[int] = set()
    196
    197        # Maps an exp.SetOperation's id (e.g. UNION) to its projection types. This is computed if the
    198        # exp.SetOperation is the expression of a scope source, as selecting from it multiple times
    199        # would reprocess the entire subtree to coerce the types of its operands' projections
    200        self._setop_column_types: t.Dict[int, t.Dict[str, exp.DataType | exp.DataType.Type]] = {}

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.TEXT: 'TEXT'>, <Type.VARCHAR: 'VARCHAR'>}, <Type.CHAR: 'CHAR'>: {<Type.NVARCHAR: 'NVARCHAR'>, <Type.TEXT: 'TEXT'>, <Type.VARCHAR: 'VARCHAR'>, <Type.NCHAR: 'NCHAR'>}, <Type.DOUBLE: 'DOUBLE'>: set(), <Type.FLOAT: 'FLOAT'>: {<Type.DOUBLE: 'DOUBLE'>}, <Type.DECIMAL: 'DECIMAL'>: {<Type.DOUBLE: 'DOUBLE'>, <Type.FLOAT: 'FLOAT'>}, <Type.BIGINT: 'BIGINT'>: {<Type.DOUBLE: 'DOUBLE'>, <Type.FLOAT: 'FLOAT'>, <Type.DECIMAL: 'DECIMAL'>}, <Type.INT: 'INT'>: {<Type.DOUBLE: 'DOUBLE'>, <Type.FLOAT: 'FLOAT'>, <Type.DECIMAL: 'DECIMAL'>, <Type.BIGINT: 'BIGINT'>}, <Type.SMALLINT: 'SMALLINT'>: {<Type.FLOAT: 'FLOAT'>, <Type.DECIMAL: 'DECIMAL'>, <Type.DOUBLE: 'DOUBLE'>, <Type.INT: 'INT'>, <Type.BIGINT: 'BIGINT'>}, <Type.TINYINT: 'TINYINT'>: {<Type.FLOAT: 'FLOAT'>, <Type.SMALLINT: 'SMALLINT'>, <Type.DECIMAL: 'DECIMAL'>, <Type.DOUBLE: 'DOUBLE'>, <Type.INT: 'INT'>, <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.TIMESTAMP: 'TIMESTAMP'>, <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>}, <Type.DATE: 'DATE'>: {<Type.TIMESTAMP: 'TIMESTAMP'>, <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <Type.DATETIME: 'DATETIME'>}, <Type.NULL: 'NULL'>: {<Type.NVARCHAR: 'NVARCHAR'>, <Type.DOUBLE: 'DOUBLE'>, <Type.CHAR: 'CHAR'>, <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <Type.VARCHAR: 'VARCHAR'>, <Type.BIGINT: 'BIGINT'>, <Type.DATETIME: 'DATETIME'>, <Type.FLOAT: 'FLOAT'>, <Type.SMALLINT: 'SMALLINT'>, <Type.DECIMAL: 'DECIMAL'>, <Type.TIMESTAMP: 'TIMESTAMP'>, <Type.NCHAR: 'NCHAR'>, <Type.INT: 'INT'>, <Type.TEXT: 'TEXT'>, <Type.TINYINT: 'TINYINT'>, <Type.DATE: 'DATE'>}}
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.NAME: 'NAME'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <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.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.CHAR: 'CHAR'>): <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.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT128: 'INT128'>): <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.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT128: 'INT128'>): <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.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT128: 'INT128'>): <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.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT128: 'INT128'>): <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.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT128: 'INT128'>): <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.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT128: 'INT128'>): <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.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <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.FLOAT: 'FLOAT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <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.FLOAT: 'FLOAT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <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.FLOAT: 'FLOAT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <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.FLOAT: 'FLOAT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <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.FLOAT: 'FLOAT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <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.FLOAT: 'FLOAT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <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: View Source

    208    def annotate(self, expression: E) -> E:
    209        for scope in traverse_scope(expression):
    210            self.annotate_scope(scope)
    211        return self._maybe_annotate(expression)  # This takes care of non-traversable expressions

def annotate_scope(self, scope: sqlglot.optimizer.scope.Scope) -> None: View Source

    213    def annotate_scope(self, scope: Scope) -> None:
    214        selects = {}
    215        for name, source in scope.sources.items():
    216            if not isinstance(source, Scope):
    217                continue
    218
    219            expression = source.expression
    220            if isinstance(expression, exp.UDTF):
    221                values = []
    222
    223                if isinstance(expression, exp.Lateral):
    224                    if isinstance(expression.this, exp.Explode):
    225                        values = [expression.this.this]
    226                elif isinstance(expression, exp.Unnest):
    227                    values = [expression]
    228                elif not isinstance(expression, exp.TableFromRows):
    229                    values = expression.expressions[0].expressions
    230
    231                if not values:
    232                    continue
    233
    234                selects[name] = {
    235                    alias: column.type
    236                    for alias, column in zip(expression.alias_column_names, values)
    237                }
    238            elif isinstance(expression, exp.SetOperation) and len(expression.left.selects) == len(
    239                expression.right.selects
    240            ):
    241                selects[name] = col_types = self._setop_column_types.setdefault(id(expression), {})
    242
    243                if not col_types:
    244                    # Process a chain / sub-tree of set operations
    245                    for set_op in expression.walk(
    246                        prune=lambda n: not isinstance(n, (exp.SetOperation, exp.Subquery))
    247                    ):
    248                        if not isinstance(set_op, exp.SetOperation):
    249                            continue
    250
    251                        if set_op.args.get("by_name"):
    252                            r_type_by_select = {
    253                                s.alias_or_name: s.type for s in set_op.right.selects
    254                            }
    255                            setop_cols = {
    256                                s.alias_or_name: self._maybe_coerce(
    257                                    t.cast(exp.DataType, s.type),
    258                                    r_type_by_select.get(s.alias_or_name)
    259                                    or exp.DataType.Type.UNKNOWN,
    260                                )
    261                                for s in set_op.left.selects
    262                            }
    263                        else:
    264                            setop_cols = {
    265                                ls.alias_or_name: self._maybe_coerce(
    266                                    t.cast(exp.DataType, ls.type), t.cast(exp.DataType, rs.type)
    267                                )
    268                                for ls, rs in zip(set_op.left.selects, set_op.right.selects)
    269                            }
    270
    271                        # Coerce intermediate results with the previously registered types, if they exist
    272                        for col_name, col_type in setop_cols.items():
    273                            col_types[col_name] = self._maybe_coerce(
    274                                col_type, col_types.get(col_name, exp.DataType.Type.NULL)
    275                            )
    276
    277            else:
    278                selects[name] = {s.alias_or_name: s.type for s in expression.selects}
    279
    280        # First annotate the current scope's column references
    281        for col in scope.columns:
    282            if not col.table:
    283                continue
    284
    285            source = scope.sources.get(col.table)
    286            if isinstance(source, exp.Table):
    287                self._set_type(col, self.schema.get_column_type(source, col))
    288            elif source:
    289                if col.table in selects and col.name in selects[col.table]:
    290                    self._set_type(col, selects[col.table][col.name])
    291                elif isinstance(source.expression, exp.Unnest):
    292                    self._set_type(col, source.expression.type)
    293
    294        if isinstance(self.schema, MappingSchema):
    295            for table_column in scope.table_columns:
    296                source = scope.sources.get(table_column.name)
    297
    298                if isinstance(source, exp.Table):
    299                    schema = self.schema.find(
    300                        source, raise_on_missing=False, ensure_data_types=True
    301                    )
    302                    if not isinstance(schema, dict):
    303                        continue
    304
    305                    struct_type = exp.DataType(
    306                        this=exp.DataType.Type.STRUCT,
    307                        expressions=[
    308                            exp.ColumnDef(this=exp.to_identifier(c), kind=kind)
    309                            for c, kind in schema.items()
    310                        ],
    311                        nested=True,
    312                    )
    313                    self._set_type(table_column, struct_type)
    314                elif (
    315                    isinstance(source, Scope)
    316                    and isinstance(source.expression, exp.Query)
    317                    and source.expression.is_type(exp.DataType.Type.STRUCT)
    318                ):
    319                    self._set_type(table_column, source.expression.type)
    320
    321        # Then (possibly) annotate the remaining expressions in the scope
    322        self._maybe_annotate(scope.expression)
    323
    324        if self.schema.dialect == "bigquery" and isinstance(scope.expression, exp.Query):
    325            struct_type = exp.DataType(
    326                this=exp.DataType.Type.STRUCT,
    327                expressions=[
    328                    exp.ColumnDef(this=exp.to_identifier(select.output_name), kind=select.type)
    329                    for select in scope.expression.selects
    330                ],
    331                nested=True,
    332            )
    333
    334            if not any(
    335                cd.kind.is_type(exp.DataType.Type.UNKNOWN)
    336                for cd in struct_type.expressions
    337                if cd.kind
    338            ):
    339                self._set_type(scope.expression, struct_type)