sqlglot.optimizer.annotate_types
1from __future__ import annotations 2 3import functools 4import typing as t 5 6from sqlglot import exp 7from sqlglot.helper import ( 8 ensure_list, 9 is_date_unit, 10 is_iso_date, 11 is_iso_datetime, 12 seq_get, 13) 14from sqlglot.optimizer.scope import Scope, traverse_scope 15from sqlglot.schema import 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 ( 317 source.expression.meta.get("query_type") or exp.DataType.build("UNKNOWN") 318 ).is_type(exp.DataType.Type.STRUCT) 319 ): 320 self._set_type(table_column, source.expression.meta["query_type"]) 321 322 # Then (possibly) annotate the remaining expressions in the scope 323 self._maybe_annotate(scope.expression) 324 325 if self.schema.dialect == "bigquery" and isinstance(scope.expression, exp.Query): 326 struct_type = exp.DataType( 327 this=exp.DataType.Type.STRUCT, 328 expressions=[ 329 exp.ColumnDef(this=exp.to_identifier(select.output_name), kind=select.type) 330 for select in scope.expression.selects 331 ], 332 nested=True, 333 ) 334 335 if not any( 336 cd.kind.is_type(exp.DataType.Type.UNKNOWN) 337 for cd in struct_type.expressions 338 if cd.kind 339 ): 340 # We don't use `_set_type` on purpose here. If we annotated the query directly, then 341 # using it in other contexts (e.g., ARRAY(<query>)) could result in incorrect type 342 # annotations, i.e., it shouldn't be interpreted as a STRUCT value. 343 scope.expression.meta["query_type"] = struct_type 344 345 def _maybe_annotate(self, expression: E) -> E: 346 if id(expression) in self._visited: 347 return expression # We've already inferred the expression's type 348 349 annotator = self.annotators.get(expression.__class__) 350 351 return ( 352 annotator(self, expression) 353 if annotator 354 else self._annotate_with_type(expression, exp.DataType.Type.UNKNOWN) 355 ) 356 357 def _annotate_args(self, expression: E) -> E: 358 for value in expression.iter_expressions(): 359 self._maybe_annotate(value) 360 361 return expression 362 363 def _maybe_coerce( 364 self, 365 type1: exp.DataType | exp.DataType.Type, 366 type2: exp.DataType | exp.DataType.Type, 367 ) -> exp.DataType | exp.DataType.Type: 368 """ 369 Returns type2 if type1 can be coerced into it, otherwise type1. 370 371 If either type is parameterized (e.g. DECIMAL(18, 2) contains two parameters), 372 we assume type1 does not coerce into type2, so we also return it in this case. 373 """ 374 if isinstance(type1, exp.DataType): 375 if type1.expressions: 376 return type1 377 type1_value = type1.this 378 else: 379 type1_value = type1 380 381 if isinstance(type2, exp.DataType): 382 if type2.expressions: 383 return type2 384 type2_value = type2.this 385 else: 386 type2_value = type2 387 388 # We propagate the UNKNOWN type upwards if found 389 if exp.DataType.Type.UNKNOWN in (type1_value, type2_value): 390 return exp.DataType.Type.UNKNOWN 391 392 return type2_value if type2_value in self.coerces_to.get(type1_value, {}) else type1_value 393 394 def _annotate_binary(self, expression: B) -> B: 395 self._annotate_args(expression) 396 397 left, right = expression.left, expression.right 398 left_type, right_type = left.type.this, right.type.this # type: ignore 399 400 if isinstance(expression, (exp.Connector, exp.Predicate)): 401 self._set_type(expression, exp.DataType.Type.BOOLEAN) 402 elif (left_type, right_type) in self.binary_coercions: 403 self._set_type(expression, self.binary_coercions[(left_type, right_type)](left, right)) 404 else: 405 self._set_type(expression, self._maybe_coerce(left_type, right_type)) 406 407 return expression 408 409 def _annotate_unary(self, expression: E) -> E: 410 self._annotate_args(expression) 411 412 if isinstance(expression, exp.Not): 413 self._set_type(expression, exp.DataType.Type.BOOLEAN) 414 else: 415 self._set_type(expression, expression.this.type) 416 417 return expression 418 419 def _annotate_literal(self, expression: exp.Literal) -> exp.Literal: 420 if expression.is_string: 421 self._set_type(expression, exp.DataType.Type.VARCHAR) 422 elif expression.is_int: 423 self._set_type(expression, exp.DataType.Type.INT) 424 else: 425 self._set_type(expression, exp.DataType.Type.DOUBLE) 426 427 return expression 428 429 def _annotate_with_type( 430 self, expression: E, target_type: exp.DataType | exp.DataType.Type 431 ) -> E: 432 self._set_type(expression, target_type) 433 return self._annotate_args(expression) 434 435 @t.no_type_check 436 def _annotate_by_args( 437 self, 438 expression: E, 439 *args: str, 440 promote: bool = False, 441 array: bool = False, 442 ) -> E: 443 self._annotate_args(expression) 444 445 expressions: t.List[exp.Expression] = [] 446 for arg in args: 447 arg_expr = expression.args.get(arg) 448 expressions.extend(expr for expr in ensure_list(arg_expr) if expr) 449 450 last_datatype = None 451 for expr in expressions: 452 expr_type = expr.type 453 454 # Stop at the first nested data type found - we don't want to _maybe_coerce nested types 455 if expr_type.args.get("nested"): 456 last_datatype = expr_type 457 break 458 459 if not expr_type.is_type(exp.DataType.Type.UNKNOWN): 460 last_datatype = self._maybe_coerce(last_datatype or expr_type, expr_type) 461 462 self._set_type(expression, last_datatype or exp.DataType.Type.UNKNOWN) 463 464 if promote: 465 if expression.type.this in exp.DataType.INTEGER_TYPES: 466 self._set_type(expression, exp.DataType.Type.BIGINT) 467 elif expression.type.this in exp.DataType.FLOAT_TYPES: 468 self._set_type(expression, exp.DataType.Type.DOUBLE) 469 470 if array: 471 self._set_type( 472 expression, 473 exp.DataType( 474 this=exp.DataType.Type.ARRAY, expressions=[expression.type], nested=True 475 ), 476 ) 477 478 return expression 479 480 def _annotate_timeunit( 481 self, expression: exp.TimeUnit | exp.DateTrunc 482 ) -> exp.TimeUnit | exp.DateTrunc: 483 self._annotate_args(expression) 484 485 if expression.this.type.this in exp.DataType.TEXT_TYPES: 486 datatype = _coerce_date_literal(expression.this, expression.unit) 487 elif expression.this.type.this in exp.DataType.TEMPORAL_TYPES: 488 datatype = _coerce_date(expression.this, expression.unit) 489 else: 490 datatype = exp.DataType.Type.UNKNOWN 491 492 self._set_type(expression, datatype) 493 return expression 494 495 def _annotate_bracket(self, expression: exp.Bracket) -> exp.Bracket: 496 self._annotate_args(expression) 497 498 bracket_arg = expression.expressions[0] 499 this = expression.this 500 501 if isinstance(bracket_arg, exp.Slice): 502 self._set_type(expression, this.type) 503 elif this.type.is_type(exp.DataType.Type.ARRAY): 504 self._set_type(expression, seq_get(this.type.expressions, 0)) 505 elif isinstance(this, (exp.Map, exp.VarMap)) and bracket_arg in this.keys: 506 index = this.keys.index(bracket_arg) 507 value = seq_get(this.values, index) 508 self._set_type(expression, value.type if value else None) 509 else: 510 self._set_type(expression, exp.DataType.Type.UNKNOWN) 511 512 return expression 513 514 def _annotate_div(self, expression: exp.Div) -> exp.Div: 515 self._annotate_args(expression) 516 517 left_type, right_type = expression.left.type.this, expression.right.type.this # type: ignore 518 519 if ( 520 expression.args.get("typed") 521 and left_type in exp.DataType.INTEGER_TYPES 522 and right_type in exp.DataType.INTEGER_TYPES 523 ): 524 self._set_type(expression, exp.DataType.Type.BIGINT) 525 else: 526 self._set_type(expression, self._maybe_coerce(left_type, right_type)) 527 if expression.type and expression.type.this not in exp.DataType.REAL_TYPES: 528 self._set_type( 529 expression, self._maybe_coerce(expression.type, exp.DataType.Type.DOUBLE) 530 ) 531 532 return expression 533 534 def _annotate_dot(self, expression: exp.Dot) -> exp.Dot: 535 self._annotate_args(expression) 536 self._set_type(expression, None) 537 this_type = expression.this.type 538 539 if this_type and this_type.is_type(exp.DataType.Type.STRUCT): 540 for e in this_type.expressions: 541 if e.name == expression.expression.name: 542 self._set_type(expression, e.kind) 543 break 544 545 return expression 546 547 def _annotate_explode(self, expression: exp.Explode) -> exp.Explode: 548 self._annotate_args(expression) 549 self._set_type(expression, seq_get(expression.this.type.expressions, 0)) 550 return expression 551 552 def _annotate_unnest(self, expression: exp.Unnest) -> exp.Unnest: 553 self._annotate_args(expression) 554 child = seq_get(expression.expressions, 0) 555 556 if child and child.is_type(exp.DataType.Type.ARRAY): 557 expr_type = seq_get(child.type.expressions, 0) 558 else: 559 expr_type = None 560 561 self._set_type(expression, expr_type) 562 return expression 563 564 def _annotate_struct_value( 565 self, expression: exp.Expression 566 ) -> t.Optional[exp.DataType] | exp.ColumnDef: 567 alias = expression.args.get("alias") 568 if alias: 569 return exp.ColumnDef(this=alias.copy(), kind=expression.type) 570 571 # Case: key = value or key := value 572 if expression.expression: 573 return exp.ColumnDef(this=expression.this.copy(), kind=expression.expression.type) 574 575 return expression.type 576 577 def _annotate_struct(self, expression: exp.Struct) -> exp.Struct: 578 self._annotate_args(expression) 579 self._set_type( 580 expression, 581 exp.DataType( 582 this=exp.DataType.Type.STRUCT, 583 expressions=[self._annotate_struct_value(expr) for expr in expression.expressions], 584 nested=True, 585 ), 586 ) 587 return expression 588 589 @t.overload 590 def _annotate_map(self, expression: exp.Map) -> exp.Map: ... 591 592 @t.overload 593 def _annotate_map(self, expression: exp.VarMap) -> exp.VarMap: ... 594 595 def _annotate_map(self, expression): 596 self._annotate_args(expression) 597 598 keys = expression.args.get("keys") 599 values = expression.args.get("values") 600 601 map_type = exp.DataType(this=exp.DataType.Type.MAP) 602 if isinstance(keys, exp.Array) and isinstance(values, exp.Array): 603 key_type = seq_get(keys.type.expressions, 0) or exp.DataType.Type.UNKNOWN 604 value_type = seq_get(values.type.expressions, 0) or exp.DataType.Type.UNKNOWN 605 606 if key_type != exp.DataType.Type.UNKNOWN and value_type != exp.DataType.Type.UNKNOWN: 607 map_type.set("expressions", [key_type, value_type]) 608 map_type.set("nested", True) 609 610 self._set_type(expression, map_type) 611 return expression 612 613 def _annotate_to_map(self, expression: exp.ToMap) -> exp.ToMap: 614 self._annotate_args(expression) 615 616 map_type = exp.DataType(this=exp.DataType.Type.MAP) 617 arg = expression.this 618 if arg.is_type(exp.DataType.Type.STRUCT): 619 for coldef in arg.type.expressions: 620 kind = coldef.kind 621 if kind != exp.DataType.Type.UNKNOWN: 622 map_type.set("expressions", [exp.DataType.build("varchar"), kind]) 623 map_type.set("nested", True) 624 break 625 626 self._set_type(expression, map_type) 627 return expression 628 629 def _annotate_extract(self, expression: exp.Extract) -> exp.Extract: 630 self._annotate_args(expression) 631 part = expression.name 632 if part == "TIME": 633 self._set_type(expression, exp.DataType.Type.TIME) 634 elif part == "DATE": 635 self._set_type(expression, exp.DataType.Type.DATE) 636 else: 637 self._set_type(expression, exp.DataType.Type.INT) 638 return expression 639 640 def _annotate_by_array_element(self, expression: exp.Expression) -> exp.Expression: 641 self._annotate_args(expression) 642 643 array_arg = expression.this 644 if array_arg.type.is_type(exp.DataType.Type.ARRAY): 645 element_type = seq_get(array_arg.type.expressions, 0) or exp.DataType.Type.UNKNOWN 646 self._set_type(expression, element_type) 647 else: 648 self._set_type(expression, exp.DataType.Type.UNKNOWN) 649 650 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:
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]:
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]]:
class
TypeAnnotator:
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 ( 318 source.expression.meta.get("query_type") or exp.DataType.build("UNKNOWN") 319 ).is_type(exp.DataType.Type.STRUCT) 320 ): 321 self._set_type(table_column, source.expression.meta["query_type"]) 322 323 # Then (possibly) annotate the remaining expressions in the scope 324 self._maybe_annotate(scope.expression) 325 326 if self.schema.dialect == "bigquery" and isinstance(scope.expression, exp.Query): 327 struct_type = exp.DataType( 328 this=exp.DataType.Type.STRUCT, 329 expressions=[ 330 exp.ColumnDef(this=exp.to_identifier(select.output_name), kind=select.type) 331 for select in scope.expression.selects 332 ], 333 nested=True, 334 ) 335 336 if not any( 337 cd.kind.is_type(exp.DataType.Type.UNKNOWN) 338 for cd in struct_type.expressions 339 if cd.kind 340 ): 341 # We don't use `_set_type` on purpose here. If we annotated the query directly, then 342 # using it in other contexts (e.g., ARRAY(<query>)) could result in incorrect type 343 # annotations, i.e., it shouldn't be interpreted as a STRUCT value. 344 scope.expression.meta["query_type"] = struct_type 345 346 def _maybe_annotate(self, expression: E) -> E: 347 if id(expression) in self._visited: 348 return expression # We've already inferred the expression's type 349 350 annotator = self.annotators.get(expression.__class__) 351 352 return ( 353 annotator(self, expression) 354 if annotator 355 else self._annotate_with_type(expression, exp.DataType.Type.UNKNOWN) 356 ) 357 358 def _annotate_args(self, expression: E) -> E: 359 for value in expression.iter_expressions(): 360 self._maybe_annotate(value) 361 362 return expression 363 364 def _maybe_coerce( 365 self, 366 type1: exp.DataType | exp.DataType.Type, 367 type2: exp.DataType | exp.DataType.Type, 368 ) -> exp.DataType | exp.DataType.Type: 369 """ 370 Returns type2 if type1 can be coerced into it, otherwise type1. 371 372 If either type is parameterized (e.g. DECIMAL(18, 2) contains two parameters), 373 we assume type1 does not coerce into type2, so we also return it in this case. 374 """ 375 if isinstance(type1, exp.DataType): 376 if type1.expressions: 377 return type1 378 type1_value = type1.this 379 else: 380 type1_value = type1 381 382 if isinstance(type2, exp.DataType): 383 if type2.expressions: 384 return type2 385 type2_value = type2.this 386 else: 387 type2_value = type2 388 389 # We propagate the UNKNOWN type upwards if found 390 if exp.DataType.Type.UNKNOWN in (type1_value, type2_value): 391 return exp.DataType.Type.UNKNOWN 392 393 return type2_value if type2_value in self.coerces_to.get(type1_value, {}) else type1_value 394 395 def _annotate_binary(self, expression: B) -> B: 396 self._annotate_args(expression) 397 398 left, right = expression.left, expression.right 399 left_type, right_type = left.type.this, right.type.this # type: ignore 400 401 if isinstance(expression, (exp.Connector, exp.Predicate)): 402 self._set_type(expression, exp.DataType.Type.BOOLEAN) 403 elif (left_type, right_type) in self.binary_coercions: 404 self._set_type(expression, self.binary_coercions[(left_type, right_type)](left, right)) 405 else: 406 self._set_type(expression, self._maybe_coerce(left_type, right_type)) 407 408 return expression 409 410 def _annotate_unary(self, expression: E) -> E: 411 self._annotate_args(expression) 412 413 if isinstance(expression, exp.Not): 414 self._set_type(expression, exp.DataType.Type.BOOLEAN) 415 else: 416 self._set_type(expression, expression.this.type) 417 418 return expression 419 420 def _annotate_literal(self, expression: exp.Literal) -> exp.Literal: 421 if expression.is_string: 422 self._set_type(expression, exp.DataType.Type.VARCHAR) 423 elif expression.is_int: 424 self._set_type(expression, exp.DataType.Type.INT) 425 else: 426 self._set_type(expression, exp.DataType.Type.DOUBLE) 427 428 return expression 429 430 def _annotate_with_type( 431 self, expression: E, target_type: exp.DataType | exp.DataType.Type 432 ) -> E: 433 self._set_type(expression, target_type) 434 return self._annotate_args(expression) 435 436 @t.no_type_check 437 def _annotate_by_args( 438 self, 439 expression: E, 440 *args: str, 441 promote: bool = False, 442 array: bool = False, 443 ) -> E: 444 self._annotate_args(expression) 445 446 expressions: t.List[exp.Expression] = [] 447 for arg in args: 448 arg_expr = expression.args.get(arg) 449 expressions.extend(expr for expr in ensure_list(arg_expr) if expr) 450 451 last_datatype = None 452 for expr in expressions: 453 expr_type = expr.type 454 455 # Stop at the first nested data type found - we don't want to _maybe_coerce nested types 456 if expr_type.args.get("nested"): 457 last_datatype = expr_type 458 break 459 460 if not expr_type.is_type(exp.DataType.Type.UNKNOWN): 461 last_datatype = self._maybe_coerce(last_datatype or expr_type, expr_type) 462 463 self._set_type(expression, last_datatype or exp.DataType.Type.UNKNOWN) 464 465 if promote: 466 if expression.type.this in exp.DataType.INTEGER_TYPES: 467 self._set_type(expression, exp.DataType.Type.BIGINT) 468 elif expression.type.this in exp.DataType.FLOAT_TYPES: 469 self._set_type(expression, exp.DataType.Type.DOUBLE) 470 471 if array: 472 self._set_type( 473 expression, 474 exp.DataType( 475 this=exp.DataType.Type.ARRAY, expressions=[expression.type], nested=True 476 ), 477 ) 478 479 return expression 480 481 def _annotate_timeunit( 482 self, expression: exp.TimeUnit | exp.DateTrunc 483 ) -> exp.TimeUnit | exp.DateTrunc: 484 self._annotate_args(expression) 485 486 if expression.this.type.this in exp.DataType.TEXT_TYPES: 487 datatype = _coerce_date_literal(expression.this, expression.unit) 488 elif expression.this.type.this in exp.DataType.TEMPORAL_TYPES: 489 datatype = _coerce_date(expression.this, expression.unit) 490 else: 491 datatype = exp.DataType.Type.UNKNOWN 492 493 self._set_type(expression, datatype) 494 return expression 495 496 def _annotate_bracket(self, expression: exp.Bracket) -> exp.Bracket: 497 self._annotate_args(expression) 498 499 bracket_arg = expression.expressions[0] 500 this = expression.this 501 502 if isinstance(bracket_arg, exp.Slice): 503 self._set_type(expression, this.type) 504 elif this.type.is_type(exp.DataType.Type.ARRAY): 505 self._set_type(expression, seq_get(this.type.expressions, 0)) 506 elif isinstance(this, (exp.Map, exp.VarMap)) and bracket_arg in this.keys: 507 index = this.keys.index(bracket_arg) 508 value = seq_get(this.values, index) 509 self._set_type(expression, value.type if value else None) 510 else: 511 self._set_type(expression, exp.DataType.Type.UNKNOWN) 512 513 return expression 514 515 def _annotate_div(self, expression: exp.Div) -> exp.Div: 516 self._annotate_args(expression) 517 518 left_type, right_type = expression.left.type.this, expression.right.type.this # type: ignore 519 520 if ( 521 expression.args.get("typed") 522 and left_type in exp.DataType.INTEGER_TYPES 523 and right_type in exp.DataType.INTEGER_TYPES 524 ): 525 self._set_type(expression, exp.DataType.Type.BIGINT) 526 else: 527 self._set_type(expression, self._maybe_coerce(left_type, right_type)) 528 if expression.type and expression.type.this not in exp.DataType.REAL_TYPES: 529 self._set_type( 530 expression, self._maybe_coerce(expression.type, exp.DataType.Type.DOUBLE) 531 ) 532 533 return expression 534 535 def _annotate_dot(self, expression: exp.Dot) -> exp.Dot: 536 self._annotate_args(expression) 537 self._set_type(expression, None) 538 this_type = expression.this.type 539 540 if this_type and this_type.is_type(exp.DataType.Type.STRUCT): 541 for e in this_type.expressions: 542 if e.name == expression.expression.name: 543 self._set_type(expression, e.kind) 544 break 545 546 return expression 547 548 def _annotate_explode(self, expression: exp.Explode) -> exp.Explode: 549 self._annotate_args(expression) 550 self._set_type(expression, seq_get(expression.this.type.expressions, 0)) 551 return expression 552 553 def _annotate_unnest(self, expression: exp.Unnest) -> exp.Unnest: 554 self._annotate_args(expression) 555 child = seq_get(expression.expressions, 0) 556 557 if child and child.is_type(exp.DataType.Type.ARRAY): 558 expr_type = seq_get(child.type.expressions, 0) 559 else: 560 expr_type = None 561 562 self._set_type(expression, expr_type) 563 return expression 564 565 def _annotate_struct_value( 566 self, expression: exp.Expression 567 ) -> t.Optional[exp.DataType] | exp.ColumnDef: 568 alias = expression.args.get("alias") 569 if alias: 570 return exp.ColumnDef(this=alias.copy(), kind=expression.type) 571 572 # Case: key = value or key := value 573 if expression.expression: 574 return exp.ColumnDef(this=expression.this.copy(), kind=expression.expression.type) 575 576 return expression.type 577 578 def _annotate_struct(self, expression: exp.Struct) -> exp.Struct: 579 self._annotate_args(expression) 580 self._set_type( 581 expression, 582 exp.DataType( 583 this=exp.DataType.Type.STRUCT, 584 expressions=[self._annotate_struct_value(expr) for expr in expression.expressions], 585 nested=True, 586 ), 587 ) 588 return expression 589 590 @t.overload 591 def _annotate_map(self, expression: exp.Map) -> exp.Map: ... 592 593 @t.overload 594 def _annotate_map(self, expression: exp.VarMap) -> exp.VarMap: ... 595 596 def _annotate_map(self, expression): 597 self._annotate_args(expression) 598 599 keys = expression.args.get("keys") 600 values = expression.args.get("values") 601 602 map_type = exp.DataType(this=exp.DataType.Type.MAP) 603 if isinstance(keys, exp.Array) and isinstance(values, exp.Array): 604 key_type = seq_get(keys.type.expressions, 0) or exp.DataType.Type.UNKNOWN 605 value_type = seq_get(values.type.expressions, 0) or exp.DataType.Type.UNKNOWN 606 607 if key_type != exp.DataType.Type.UNKNOWN and value_type != exp.DataType.Type.UNKNOWN: 608 map_type.set("expressions", [key_type, value_type]) 609 map_type.set("nested", True) 610 611 self._set_type(expression, map_type) 612 return expression 613 614 def _annotate_to_map(self, expression: exp.ToMap) -> exp.ToMap: 615 self._annotate_args(expression) 616 617 map_type = exp.DataType(this=exp.DataType.Type.MAP) 618 arg = expression.this 619 if arg.is_type(exp.DataType.Type.STRUCT): 620 for coldef in arg.type.expressions: 621 kind = coldef.kind 622 if kind != exp.DataType.Type.UNKNOWN: 623 map_type.set("expressions", [exp.DataType.build("varchar"), kind]) 624 map_type.set("nested", True) 625 break 626 627 self._set_type(expression, map_type) 628 return expression 629 630 def _annotate_extract(self, expression: exp.Extract) -> exp.Extract: 631 self._annotate_args(expression) 632 part = expression.name 633 if part == "TIME": 634 self._set_type(expression, exp.DataType.Type.TIME) 635 elif part == "DATE": 636 self._set_type(expression, exp.DataType.Type.DATE) 637 else: 638 self._set_type(expression, exp.DataType.Type.INT) 639 return expression 640 641 def _annotate_by_array_element(self, expression: exp.Expression) -> exp.Expression: 642 self._annotate_args(expression) 643 644 array_arg = expression.this 645 if array_arg.type.is_type(exp.DataType.Type.ARRAY): 646 element_type = seq_get(array_arg.type.expressions, 0) or exp.DataType.Type.UNKNOWN 647 self._set_type(expression, element_type) 648 else: 649 self._set_type(expression, exp.DataType.Type.UNKNOWN) 650 651 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)
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]] = {}
COERCES_TO: Dict[sqlglot.expressions.DataType.Type, Set[sqlglot.expressions.DataType.Type]] =
{<Type.TEXT: 'TEXT'>: set(), <Type.NVARCHAR: 'NVARCHAR'>: {<Type.TEXT: 'TEXT'>}, <Type.VARCHAR: 'VARCHAR'>: {<Type.TEXT: 'TEXT'>, <Type.NVARCHAR: 'NVARCHAR'>}, <Type.NCHAR: 'NCHAR'>: {<Type.TEXT: 'TEXT'>, <Type.VARCHAR: 'VARCHAR'>, <Type.NVARCHAR: 'NVARCHAR'>}, <Type.CHAR: 'CHAR'>: {<Type.TEXT: 'TEXT'>, <Type.VARCHAR: 'VARCHAR'>, <Type.NVARCHAR: 'NVARCHAR'>, <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.DECIMAL: 'DECIMAL'>, <Type.DOUBLE: 'DOUBLE'>, <Type.FLOAT: 'FLOAT'>}, <Type.INT: 'INT'>: {<Type.DECIMAL: 'DECIMAL'>, <Type.DOUBLE: 'DOUBLE'>, <Type.FLOAT: 'FLOAT'>, <Type.BIGINT: 'BIGINT'>}, <Type.SMALLINT: 'SMALLINT'>: {<Type.INT: 'INT'>, <Type.BIGINT: 'BIGINT'>, <Type.DECIMAL: 'DECIMAL'>, <Type.DOUBLE: 'DOUBLE'>, <Type.FLOAT: 'FLOAT'>}, <Type.TINYINT: 'TINYINT'>: {<Type.INT: 'INT'>, <Type.BIGINT: 'BIGINT'>, <Type.DECIMAL: 'DECIMAL'>, <Type.DOUBLE: 'DOUBLE'>, <Type.FLOAT: 'FLOAT'>, <Type.SMALLINT: 'SMALLINT'>}, <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>: set(), <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>: {<Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>}, <Type.TIMESTAMP: 'TIMESTAMP'>: {<Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>}, <Type.DATETIME: 'DATETIME'>: {<Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.TIMESTAMP: 'TIMESTAMP'>}, <Type.DATE: 'DATE'>: {<Type.DATETIME: 'DATETIME'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.TIMESTAMP: 'TIMESTAMP'>}, <Type.NULL: 'NULL'>: {<Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <Type.TIMESTAMP: 'TIMESTAMP'>, <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL: 'DECIMAL'>, <Type.INT: 'INT'>, <Type.CHAR: 'CHAR'>, <Type.NCHAR: 'NCHAR'>, <Type.VARCHAR: 'VARCHAR'>, <Type.DOUBLE: 'DOUBLE'>, <Type.BIGINT: 'BIGINT'>, <Type.DATE: 'DATE'>, <Type.DATETIME: 'DATETIME'>, <Type.SMALLINT: 'SMALLINT'>, <Type.TINYINT: 'TINYINT'>, <Type.TEXT: 'TEXT'>, <Type.FLOAT: 'FLOAT'>}}
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.NCHAR: 'NCHAR'>, <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.TEXT: 'TEXT'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.NCHAR: 'NCHAR'>): <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.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DATE: 'DATE'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.DATE: 'DATE'>): <function TypeAnnotator.<lambda>>}
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 ( 318 source.expression.meta.get("query_type") or exp.DataType.build("UNKNOWN") 319 ).is_type(exp.DataType.Type.STRUCT) 320 ): 321 self._set_type(table_column, source.expression.meta["query_type"]) 322 323 # Then (possibly) annotate the remaining expressions in the scope 324 self._maybe_annotate(scope.expression) 325 326 if self.schema.dialect == "bigquery" and isinstance(scope.expression, exp.Query): 327 struct_type = exp.DataType( 328 this=exp.DataType.Type.STRUCT, 329 expressions=[ 330 exp.ColumnDef(this=exp.to_identifier(select.output_name), kind=select.type) 331 for select in scope.expression.selects 332 ], 333 nested=True, 334 ) 335 336 if not any( 337 cd.kind.is_type(exp.DataType.Type.UNKNOWN) 338 for cd in struct_type.expressions 339 if cd.kind 340 ): 341 # We don't use `_set_type` on purpose here. If we annotated the query directly, then 342 # using it in other contexts (e.g., ARRAY(<query>)) could result in incorrect type 343 # annotations, i.e., it shouldn't be interpreted as a STRUCT value. 344 scope.expression.meta["query_type"] = struct_type