sqlglot.optimizer.annotate_types
1from __future__ import annotations 2 3import functools 4import logging 5import typing as t 6 7from sqlglot import exp 8from sqlglot.dialects.dialect import Dialect 9from sqlglot.helper import ( 10 ensure_list, 11 is_date_unit, 12 is_iso_date, 13 is_iso_datetime, 14 seq_get, 15) 16from sqlglot.optimizer.scope import Scope, traverse_scope 17from sqlglot.schema import MappingSchema, Schema, ensure_schema 18 19if t.TYPE_CHECKING: 20 from sqlglot._typing import B, E 21 22 BinaryCoercionFunc = t.Callable[[exp.Expression, exp.Expression], exp.DataType.Type] 23 BinaryCoercions = t.Dict[ 24 t.Tuple[exp.DataType.Type, exp.DataType.Type], 25 BinaryCoercionFunc, 26 ] 27 28 from sqlglot.dialects.dialect import DialectType 29 from sqlglot.typing import ExpressionMetadataType 30 31logger = logging.getLogger("sqlglot") 32 33# EXTRACT/DATE_PART specifiers that return BIGINT instead of INT 34BIGINT_EXTRACT_DATE_PARTS = { 35 "EPOCH_SECOND", 36 "EPOCH_MILLISECOND", 37 "EPOCH_MICROSECOND", 38 "EPOCH_NANOSECOND", 39 "NANOSECOND", 40} 41 42 43def annotate_types( 44 expression: E, 45 schema: t.Optional[t.Dict | Schema] = None, 46 expression_metadata: t.Optional[ExpressionMetadataType] = None, 47 coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None, 48 dialect: DialectType = None, 49 overwrite_types: bool = True, 50) -> E: 51 """ 52 Infers the types of an expression, annotating its AST accordingly. 53 54 Example: 55 >>> import sqlglot 56 >>> schema = {"y": {"cola": "SMALLINT"}} 57 >>> sql = "SELECT x.cola + 2.5 AS cola FROM (SELECT y.cola AS cola FROM y AS y) AS x" 58 >>> annotated_expr = annotate_types(sqlglot.parse_one(sql), schema=schema) 59 >>> annotated_expr.expressions[0].type.this # Get the type of "x.cola + 2.5 AS cola" 60 <Type.DOUBLE: 'DOUBLE'> 61 62 Args: 63 expression: Expression to annotate. 64 schema: Database schema. 65 expression_metadata: Maps expression type to corresponding annotation function. 66 coerces_to: Maps expression type to set of types that it can be coerced into. 67 overwrite_types: Re-annotate the existing AST types. 68 69 Returns: 70 The expression annotated with types. 71 """ 72 73 schema = ensure_schema(schema, dialect=dialect) 74 75 return TypeAnnotator( 76 schema=schema, 77 expression_metadata=expression_metadata, 78 coerces_to=coerces_to, 79 overwrite_types=overwrite_types, 80 ).annotate(expression) 81 82 83def _coerce_date_literal(l: exp.Expression, unit: t.Optional[exp.Expression]) -> exp.DataType.Type: 84 date_text = l.name 85 is_iso_date_ = is_iso_date(date_text) 86 87 if is_iso_date_ and is_date_unit(unit): 88 return exp.DataType.Type.DATE 89 90 # An ISO date is also an ISO datetime, but not vice versa 91 if is_iso_date_ or is_iso_datetime(date_text): 92 return exp.DataType.Type.DATETIME 93 94 return exp.DataType.Type.UNKNOWN 95 96 97def _coerce_date(l: exp.Expression, unit: t.Optional[exp.Expression]) -> exp.DataType.Type: 98 if not is_date_unit(unit): 99 return exp.DataType.Type.DATETIME 100 return l.type.this if l.type else exp.DataType.Type.UNKNOWN 101 102 103def swap_args(func: BinaryCoercionFunc) -> BinaryCoercionFunc: 104 @functools.wraps(func) 105 def _swapped(l: exp.Expression, r: exp.Expression) -> exp.DataType.Type: 106 return func(r, l) 107 108 return _swapped 109 110 111def swap_all(coercions: BinaryCoercions) -> BinaryCoercions: 112 return {**coercions, **{(b, a): swap_args(func) for (a, b), func in coercions.items()}} 113 114 115class _TypeAnnotator(type): 116 def __new__(cls, clsname, bases, attrs): 117 klass = super().__new__(cls, clsname, bases, attrs) 118 119 # Highest-to-lowest type precedence, as specified in Spark's docs (ANSI): 120 # https://spark.apache.org/docs/3.2.0/sql-ref-ansi-compliance.html 121 text_precedence = ( 122 exp.DataType.Type.TEXT, 123 exp.DataType.Type.NVARCHAR, 124 exp.DataType.Type.VARCHAR, 125 exp.DataType.Type.NCHAR, 126 exp.DataType.Type.CHAR, 127 ) 128 numeric_precedence = ( 129 exp.DataType.Type.DECFLOAT, 130 exp.DataType.Type.DOUBLE, 131 exp.DataType.Type.FLOAT, 132 exp.DataType.Type.BIGDECIMAL, 133 exp.DataType.Type.DECIMAL, 134 exp.DataType.Type.BIGINT, 135 exp.DataType.Type.INT, 136 exp.DataType.Type.SMALLINT, 137 exp.DataType.Type.TINYINT, 138 ) 139 timelike_precedence = ( 140 exp.DataType.Type.TIMESTAMPLTZ, 141 exp.DataType.Type.TIMESTAMPTZ, 142 exp.DataType.Type.TIMESTAMP, 143 exp.DataType.Type.DATETIME, 144 exp.DataType.Type.DATE, 145 ) 146 147 for type_precedence in (text_precedence, numeric_precedence, timelike_precedence): 148 coerces_to = set() 149 for data_type in type_precedence: 150 klass.COERCES_TO[data_type] = coerces_to.copy() 151 coerces_to |= {data_type} 152 return klass 153 154 155class TypeAnnotator(metaclass=_TypeAnnotator): 156 NESTED_TYPES = { 157 exp.DataType.Type.ARRAY, 158 } 159 160 # Specifies what types a given type can be coerced into (autofilled) 161 COERCES_TO: t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]] = {} 162 163 # Coercion functions for binary operations. 164 # Map of type pairs to a callable that takes both sides of the binary operation and returns the resulting type. 165 BINARY_COERCIONS: BinaryCoercions = { 166 **swap_all( 167 { 168 (t, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date_literal( 169 l, r.args.get("unit") 170 ) 171 for t in exp.DataType.TEXT_TYPES 172 } 173 ), 174 **swap_all( 175 { 176 # text + numeric will yield the numeric type to match most dialects' semantics 177 (text, numeric): lambda l, r: t.cast( 178 exp.DataType.Type, l.type if l.type in exp.DataType.NUMERIC_TYPES else r.type 179 ) 180 for text in exp.DataType.TEXT_TYPES 181 for numeric in exp.DataType.NUMERIC_TYPES 182 } 183 ), 184 **swap_all( 185 { 186 (exp.DataType.Type.DATE, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date( 187 l, r.args.get("unit") 188 ), 189 } 190 ), 191 } 192 193 def __init__( 194 self, 195 schema: Schema, 196 expression_metadata: t.Optional[ExpressionMetadataType] = None, 197 coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None, 198 binary_coercions: t.Optional[BinaryCoercions] = None, 199 overwrite_types: bool = True, 200 ) -> None: 201 self.schema = schema 202 dialect = schema.dialect or Dialect() 203 self.dialect = dialect 204 self.expression_metadata = expression_metadata or dialect.EXPRESSION_METADATA 205 self.coerces_to = coerces_to or dialect.COERCES_TO or self.COERCES_TO 206 self.binary_coercions = binary_coercions or self.BINARY_COERCIONS 207 208 # Caches the ids of annotated sub-Expressions, to ensure we only visit them once 209 self._visited: t.Set[int] = set() 210 211 # Caches NULL-annotated expressions to set them to UNKNOWN after type inference is completed 212 self._null_expressions: t.Dict[int, exp.Expression] = {} 213 214 # Databricks and Spark ≥v3 actually support NULL (i.e., VOID) as a type 215 self._supports_null_type = dialect.SUPPORTS_NULL_TYPE 216 217 # Maps an exp.SetOperation's id (e.g. UNION) to its projection types. This is computed if the 218 # exp.SetOperation is the expression of a scope source, as selecting from it multiple times 219 # would reprocess the entire subtree to coerce the types of its operands' projections 220 self._setop_column_types: t.Dict[int, t.Dict[str, exp.DataType | exp.DataType.Type]] = {} 221 222 # When set to False, this enables partial annotation by skipping already-annotated nodes 223 self._overwrite_types = overwrite_types 224 225 # Maps Scope to its corresponding selected sources 226 self._scope_selects: t.Dict[Scope, t.Dict[str, t.Dict[str, t.Any]]] = {} 227 228 def clear(self) -> None: 229 self._visited.clear() 230 self._null_expressions.clear() 231 self._setop_column_types.clear() 232 self._scope_selects.clear() 233 234 def _set_type( 235 self, expression: E, target_type: t.Optional[exp.DataType | exp.DataType.Type] 236 ) -> E: 237 prev_type = expression.type 238 expression_id = id(expression) 239 240 expression.type = target_type or exp.DataType.Type.UNKNOWN # type: ignore 241 self._visited.add(expression_id) 242 243 if ( 244 not self._supports_null_type 245 and t.cast(exp.DataType, expression.type).this == exp.DataType.Type.NULL 246 ): 247 self._null_expressions[expression_id] = expression 248 elif prev_type and t.cast(exp.DataType, prev_type).this == exp.DataType.Type.NULL: 249 self._null_expressions.pop(expression_id, None) 250 251 if ( 252 isinstance(expression, exp.Column) 253 and expression.is_type(exp.DataType.Type.JSON) 254 and (dot_parts := expression.meta.get("dot_parts")) 255 ): 256 # JSON dot access is case sensitive across all dialects, so we need to undo the normalization. 257 i = iter(dot_parts) 258 parent = expression.parent 259 while isinstance(parent, exp.Dot): 260 parent.expression.replace(exp.to_identifier(next(i), quoted=True)) 261 parent = parent.parent 262 263 expression.meta.pop("dot_parts", None) 264 265 return expression 266 267 def annotate(self, expression: E, annotate_scope: bool = True) -> E: 268 # This flag is used to avoid costly scope traversals when we only care about annotating 269 # non-column expressions (partial type inference), e.g., when simplifying in the optimizer 270 if annotate_scope: 271 for scope in traverse_scope(expression): 272 self.annotate_scope(scope) 273 274 # This takes care of non-traversable expressions 275 self._annotate_expression(expression) 276 277 # Replace NULL type with the default type of the targeted dialect, since the former is not an actual type; 278 # it is mostly used to aid type coercion, e.g. in query set operations. 279 for expr in self._null_expressions.values(): 280 expr.type = self.dialect.DEFAULT_NULL_TYPE 281 282 return expression 283 284 def _get_scope_selects(self, scope: Scope) -> t.Dict[str, t.Dict[str, t.Any]]: 285 if scope not in self._scope_selects: 286 selects = {} 287 for name, source in scope.sources.items(): 288 if not isinstance(source, Scope): 289 continue 290 291 expression = source.expression 292 if isinstance(expression, exp.UDTF): 293 values = [] 294 295 if isinstance(expression, exp.Lateral): 296 if isinstance(expression.this, exp.Explode): 297 values = [expression.this.this] 298 elif isinstance(expression, exp.Unnest): 299 values = [expression] 300 elif not isinstance(expression, exp.TableFromRows): 301 values = expression.expressions[0].expressions 302 303 if not values: 304 continue 305 306 alias_column_names = expression.alias_column_names 307 308 if ( 309 isinstance(expression, exp.Unnest) 310 and expression.type 311 and expression.type.is_type(exp.DataType.Type.STRUCT) 312 ): 313 selects[name] = { 314 col_def.name: t.cast( 315 t.Union[exp.DataType, exp.DataType.Type], col_def.kind 316 ) 317 for col_def in expression.type.expressions 318 if isinstance(col_def, exp.ColumnDef) and col_def.kind 319 } 320 else: 321 selects[name] = { 322 alias: column.type for alias, column in zip(alias_column_names, values) 323 } 324 elif isinstance(expression, exp.SetOperation) and len( 325 expression.left.selects 326 ) == len(expression.right.selects): 327 selects[name] = self._get_setop_column_types(expression) 328 else: 329 selects[name] = {s.alias_or_name: s.type for s in expression.selects} 330 331 self._scope_selects[scope] = selects 332 333 return self._scope_selects[scope] 334 335 def annotate_scope(self, scope: Scope) -> None: 336 if isinstance(self.schema, MappingSchema): 337 for table_column in scope.table_columns: 338 source = scope.sources.get(table_column.name) 339 340 if isinstance(source, exp.Table): 341 schema = self.schema.find( 342 source, raise_on_missing=False, ensure_data_types=True 343 ) 344 if not isinstance(schema, dict): 345 continue 346 347 struct_type = exp.DataType( 348 this=exp.DataType.Type.STRUCT, 349 expressions=[ 350 exp.ColumnDef(this=exp.to_identifier(c), kind=kind) 351 for c, kind in schema.items() 352 ], 353 nested=True, 354 ) 355 self._set_type(table_column, struct_type) 356 elif ( 357 isinstance(source, Scope) 358 and isinstance(source.expression, exp.Query) 359 and ( 360 source.expression.meta.get("query_type") or exp.DataType.build("UNKNOWN") 361 ).is_type(exp.DataType.Type.STRUCT) 362 ): 363 self._set_type(table_column, source.expression.meta["query_type"]) 364 365 # Iterate through all the expressions of the current scope in post-order, and annotate 366 self._annotate_expression(scope.expression, scope) 367 368 if self.dialect.QUERY_RESULTS_ARE_STRUCTS and isinstance(scope.expression, exp.Query): 369 struct_type = exp.DataType( 370 this=exp.DataType.Type.STRUCT, 371 expressions=[ 372 exp.ColumnDef( 373 this=exp.to_identifier(select.output_name), 374 kind=select.type.copy() if select.type else None, 375 ) 376 for select in scope.expression.selects 377 ], 378 nested=True, 379 ) 380 381 if not any( 382 cd.kind.is_type(exp.DataType.Type.UNKNOWN) 383 for cd in struct_type.expressions 384 if cd.kind 385 ): 386 # We don't use `_set_type` on purpose here. If we annotated the query directly, then 387 # using it in other contexts (e.g., ARRAY(<query>)) could result in incorrect type 388 # annotations, i.e., it shouldn't be interpreted as a STRUCT value. 389 scope.expression.meta["query_type"] = struct_type 390 391 def _annotate_expression( 392 self, 393 expression: exp.Expression, 394 scope: t.Optional[Scope] = None, 395 ) -> None: 396 stack = [(expression, False)] 397 398 while stack: 399 expr, children_annotated = stack.pop() 400 401 if id(expr) in self._visited or ( 402 not self._overwrite_types 403 and expr.type 404 and not expr.is_type(exp.DataType.Type.UNKNOWN) 405 ): 406 continue # We've already inferred the expression's type 407 408 if not children_annotated: 409 stack.append((expr, True)) 410 for child_expr in expr.iter_expressions(): 411 stack.append((child_expr, False)) 412 continue 413 414 if scope and isinstance(expr, exp.Column) and expr.table: 415 source = None 416 source_scope = scope 417 while source_scope and not source: 418 source = source_scope.sources.get(expr.table) 419 if not source: 420 source_scope = source_scope.parent 421 422 if isinstance(source, exp.Table): 423 self._set_type(expr, self.schema.get_column_type(source, expr)) 424 elif source: 425 col_type = ( 426 self._get_scope_selects(source_scope).get(expr.table, {}).get(expr.name) 427 ) 428 if col_type: 429 self._set_type(expr, col_type) 430 elif isinstance(source.expression, exp.Unnest): 431 self._set_type(expr, source.expression.type) 432 else: 433 self._set_type(expr, exp.DataType.Type.UNKNOWN) 434 else: 435 self._set_type(expr, exp.DataType.Type.UNKNOWN) 436 437 if expr.type and expr.type.args.get("nullable") is False: 438 expr.meta["nonnull"] = True 439 continue 440 441 spec = self.expression_metadata.get(expr.__class__) 442 443 if spec and (annotator := spec.get("annotator")): 444 annotator(self, expr) 445 elif spec and (returns := spec.get("returns")): 446 self._set_type(expr, t.cast(exp.DataType.Type, returns)) 447 else: 448 self._set_type(expr, exp.DataType.Type.UNKNOWN) 449 450 def _maybe_coerce( 451 self, 452 type1: exp.DataType | exp.DataType.Type, 453 type2: exp.DataType | exp.DataType.Type, 454 ) -> exp.DataType | exp.DataType.Type: 455 """ 456 Returns type2 if type1 can be coerced into it, otherwise type1. 457 458 If either type is parameterized (e.g. DECIMAL(18, 2) contains two parameters), 459 we assume type1 does not coerce into type2, so we also return it in this case. 460 """ 461 if isinstance(type1, exp.DataType): 462 if type1.expressions: 463 return type1 464 type1_value = type1.this 465 else: 466 type1_value = type1 467 468 if isinstance(type2, exp.DataType): 469 if type2.expressions: 470 return type2 471 type2_value = type2.this 472 else: 473 type2_value = type2 474 475 # We propagate the UNKNOWN type upwards if found 476 if exp.DataType.Type.UNKNOWN in (type1_value, type2_value): 477 return exp.DataType.Type.UNKNOWN 478 479 if type1_value == exp.DataType.Type.NULL: 480 return type2_value 481 if type2_value == exp.DataType.Type.NULL: 482 return type1_value 483 484 return type2_value if type2_value in self.coerces_to.get(type1_value, {}) else type1_value 485 486 def _get_setop_column_types( 487 self, setop: exp.SetOperation 488 ) -> t.Dict[str, exp.DataType | exp.DataType.Type]: 489 """ 490 Computes and returns the coerced column types for a SetOperation. 491 492 This handles UNION, INTERSECT, EXCEPT, etc., coercing types across 493 left and right operands for all projections/columns. 494 495 Args: 496 setop: The SetOperation expression to analyze 497 498 Returns: 499 Dictionary mapping column names to their coerced types 500 """ 501 setop_id = id(setop) 502 if setop_id in self._setop_column_types: 503 return self._setop_column_types[setop_id] 504 505 col_types: t.Dict[str, exp.DataType | exp.DataType.Type] = {} 506 507 # Validate that left and right have same number of projections 508 if not ( 509 isinstance(setop, exp.SetOperation) 510 and setop.left.selects 511 and setop.right.selects 512 and len(setop.left.selects) == len(setop.right.selects) 513 ): 514 return col_types 515 516 # Process a chain / sub-tree of set operations 517 for set_op in setop.walk( 518 prune=lambda n: not isinstance(n, (exp.SetOperation, exp.Subquery)) 519 ): 520 if not isinstance(set_op, exp.SetOperation): 521 continue 522 523 if set_op.args.get("by_name"): 524 r_type_by_select = {s.alias_or_name: s.type for s in set_op.right.selects} 525 setop_cols = { 526 s.alias_or_name: self._maybe_coerce( 527 t.cast(exp.DataType, s.type), 528 r_type_by_select.get(s.alias_or_name) or exp.DataType.Type.UNKNOWN, 529 ) 530 for s in set_op.left.selects 531 } 532 else: 533 setop_cols = { 534 ls.alias_or_name: self._maybe_coerce( 535 t.cast(exp.DataType, ls.type), t.cast(exp.DataType, rs.type) 536 ) 537 for ls, rs in zip(set_op.left.selects, set_op.right.selects) 538 } 539 540 # Coerce intermediate results with the previously registered types, if they exist 541 for col_name, col_type in setop_cols.items(): 542 col_types[col_name] = self._maybe_coerce( 543 col_type, col_types.get(col_name, exp.DataType.Type.NULL) 544 ) 545 546 self._setop_column_types[setop_id] = col_types 547 return col_types 548 549 def _annotate_binary(self, expression: B) -> B: 550 left, right = expression.left, expression.right 551 if not left or not right: 552 expression_sql = expression.sql(self.dialect) 553 logger.warning(f"Failed to annotate badly formed binary expression: {expression_sql}") 554 self._set_type(expression, None) 555 return expression 556 557 left_type, right_type = left.type.this, right.type.this # type: ignore 558 559 if isinstance(expression, (exp.Connector, exp.Predicate)): 560 self._set_type(expression, exp.DataType.Type.BOOLEAN) 561 elif (left_type, right_type) in self.binary_coercions: 562 self._set_type(expression, self.binary_coercions[(left_type, right_type)](left, right)) 563 else: 564 self._annotate_by_args(expression, left, right) 565 566 if isinstance(expression, exp.Is) or ( 567 left.meta.get("nonnull") is True and right.meta.get("nonnull") is True 568 ): 569 expression.meta["nonnull"] = True 570 571 return expression 572 573 def _annotate_unary(self, expression: E) -> E: 574 if isinstance(expression, exp.Not): 575 self._set_type(expression, exp.DataType.Type.BOOLEAN) 576 else: 577 self._set_type(expression, expression.this.type) 578 579 if expression.this.meta.get("nonnull") is True: 580 expression.meta["nonnull"] = True 581 582 return expression 583 584 def _annotate_literal(self, expression: exp.Literal) -> exp.Literal: 585 if expression.is_string: 586 self._set_type(expression, exp.DataType.Type.VARCHAR) 587 elif expression.is_int: 588 self._set_type(expression, exp.DataType.Type.INT) 589 else: 590 self._set_type(expression, exp.DataType.Type.DOUBLE) 591 592 expression.meta["nonnull"] = True 593 594 return expression 595 596 @t.no_type_check 597 def _annotate_by_args( 598 self, 599 expression: E, 600 *args: str | exp.Expression, 601 promote: bool = False, 602 array: bool = False, 603 ) -> E: 604 literal_type = None 605 non_literal_type = None 606 nested_type = None 607 608 for arg in args: 609 if isinstance(arg, str): 610 expressions = expression.args.get(arg) 611 else: 612 expressions = arg 613 614 for expr in ensure_list(expressions): 615 expr_type = expr.type 616 617 # Stop at the first nested data type found - we don't want to _maybe_coerce nested types 618 if expr_type.args.get("nested"): 619 nested_type = expr_type 620 break 621 622 if isinstance(expr, exp.Literal): 623 literal_type = self._maybe_coerce(literal_type or expr_type, expr_type) 624 else: 625 non_literal_type = self._maybe_coerce(non_literal_type or expr_type, expr_type) 626 627 if nested_type: 628 break 629 630 result_type = None 631 632 if nested_type: 633 result_type = nested_type 634 elif literal_type and non_literal_type: 635 if self.dialect.PRIORITIZE_NON_LITERAL_TYPES: 636 literal_this_type = ( 637 literal_type.this if isinstance(literal_type, exp.DataType) else literal_type 638 ) 639 non_literal_this_type = ( 640 non_literal_type.this 641 if isinstance(non_literal_type, exp.DataType) 642 else non_literal_type 643 ) 644 if ( 645 literal_this_type in exp.DataType.INTEGER_TYPES 646 and non_literal_this_type in exp.DataType.INTEGER_TYPES 647 ) or ( 648 literal_this_type in exp.DataType.REAL_TYPES 649 and non_literal_this_type in exp.DataType.REAL_TYPES 650 ): 651 result_type = non_literal_type 652 else: 653 result_type = literal_type or non_literal_type or exp.DataType.Type.UNKNOWN 654 655 self._set_type( 656 expression, result_type or self._maybe_coerce(non_literal_type, literal_type) 657 ) 658 659 if promote: 660 if expression.type.this in exp.DataType.INTEGER_TYPES: 661 self._set_type(expression, exp.DataType.Type.BIGINT) 662 elif expression.type.this in exp.DataType.FLOAT_TYPES: 663 self._set_type(expression, exp.DataType.Type.DOUBLE) 664 665 if array: 666 self._set_type( 667 expression, 668 exp.DataType( 669 this=exp.DataType.Type.ARRAY, expressions=[expression.type], nested=True 670 ), 671 ) 672 673 return expression 674 675 def _annotate_timeunit( 676 self, expression: exp.TimeUnit | exp.DateTrunc 677 ) -> exp.TimeUnit | exp.DateTrunc: 678 if expression.this.type.this in exp.DataType.TEXT_TYPES: 679 datatype = _coerce_date_literal(expression.this, expression.unit) 680 elif expression.this.type.this in exp.DataType.TEMPORAL_TYPES: 681 datatype = _coerce_date(expression.this, expression.unit) 682 else: 683 datatype = exp.DataType.Type.UNKNOWN 684 685 self._set_type(expression, datatype) 686 return expression 687 688 def _annotate_bracket(self, expression: exp.Bracket) -> exp.Bracket: 689 bracket_arg = expression.expressions[0] 690 this = expression.this 691 692 if isinstance(bracket_arg, exp.Slice): 693 self._set_type(expression, this.type) 694 elif this.type.is_type(exp.DataType.Type.ARRAY): 695 self._set_type(expression, seq_get(this.type.expressions, 0)) 696 elif isinstance(this, (exp.Map, exp.VarMap)) and bracket_arg in this.keys: 697 index = this.keys.index(bracket_arg) 698 value = seq_get(this.values, index) 699 self._set_type(expression, value.type if value else None) 700 else: 701 self._set_type(expression, exp.DataType.Type.UNKNOWN) 702 703 return expression 704 705 def _annotate_div(self, expression: exp.Div) -> exp.Div: 706 left_type, right_type = expression.left.type.this, expression.right.type.this # type: ignore 707 708 if ( 709 expression.args.get("typed") 710 and left_type in exp.DataType.INTEGER_TYPES 711 and right_type in exp.DataType.INTEGER_TYPES 712 ): 713 self._set_type(expression, exp.DataType.Type.BIGINT) 714 else: 715 self._set_type(expression, self._maybe_coerce(left_type, right_type)) 716 if expression.type and expression.type.this not in exp.DataType.REAL_TYPES: 717 self._set_type( 718 expression, self._maybe_coerce(expression.type, exp.DataType.Type.DOUBLE) 719 ) 720 721 return expression 722 723 def _annotate_dot(self, expression: exp.Dot) -> exp.Dot: 724 self._set_type(expression, None) 725 726 # Propagate type from qualified UDF calls (e.g., db.my_udf(...)) 727 if isinstance(expression.expression, exp.Anonymous): 728 self._set_type(expression, expression.expression.type) 729 return expression 730 731 this_type = expression.this.type 732 733 if this_type and this_type.is_type(exp.DataType.Type.STRUCT): 734 for e in this_type.expressions: 735 if e.name == expression.expression.name: 736 self._set_type(expression, e.kind) 737 break 738 739 return expression 740 741 def _annotate_explode(self, expression: exp.Explode) -> exp.Explode: 742 self._set_type(expression, seq_get(expression.this.type.expressions, 0)) 743 return expression 744 745 def _annotate_unnest(self, expression: exp.Unnest) -> exp.Unnest: 746 child = seq_get(expression.expressions, 0) 747 748 if child and child.is_type(exp.DataType.Type.ARRAY): 749 expr_type = seq_get(child.type.expressions, 0) 750 else: 751 expr_type = None 752 753 self._set_type(expression, expr_type) 754 return expression 755 756 def _annotate_subquery(self, expression: exp.Subquery) -> exp.Subquery: 757 # For scalar subqueries (subqueries with a single projection), infer the type 758 # from that single projection. This allows type propagation in cases like: 759 # SELECT (SELECT 1 AS c) AS c 760 query = expression.unnest() 761 762 if isinstance(query, exp.Query): 763 selects = query.selects 764 if len(selects) == 1: 765 self._set_type(expression, selects[0].type) 766 return expression 767 768 self._set_type(expression, exp.DataType.Type.UNKNOWN) 769 return expression 770 771 def _annotate_struct_value( 772 self, expression: exp.Expression 773 ) -> t.Optional[exp.DataType] | exp.ColumnDef: 774 # Case: STRUCT(key AS value) 775 this: t.Optional[exp.Expression] = None 776 kind = expression.type 777 778 if alias := expression.args.get("alias"): 779 this = alias.copy() 780 elif expression.expression: 781 # Case: STRUCT(key = value) or STRUCT(key := value) 782 this = expression.this.copy() 783 kind = expression.expression.type 784 elif isinstance(expression, exp.Column): 785 # Case: STRUCT(c) 786 this = expression.this.copy() 787 788 if kind and kind.is_type(exp.DataType.Type.UNKNOWN): 789 return None 790 791 if this: 792 return exp.ColumnDef(this=this, kind=kind) 793 794 return kind 795 796 def _annotate_struct(self, expression: exp.Struct) -> exp.Struct: 797 expressions = [] 798 for expr in expression.expressions: 799 struct_field_type = self._annotate_struct_value(expr) 800 if struct_field_type is None: 801 self._set_type(expression, None) 802 return expression 803 804 expressions.append(struct_field_type) 805 806 self._set_type( 807 expression, 808 exp.DataType(this=exp.DataType.Type.STRUCT, expressions=expressions, nested=True), 809 ) 810 return expression 811 812 @t.overload 813 def _annotate_map(self, expression: exp.Map) -> exp.Map: ... 814 815 @t.overload 816 def _annotate_map(self, expression: exp.VarMap) -> exp.VarMap: ... 817 818 def _annotate_map(self, expression): 819 keys = expression.args.get("keys") 820 values = expression.args.get("values") 821 822 map_type = exp.DataType(this=exp.DataType.Type.MAP) 823 if isinstance(keys, exp.Array) and isinstance(values, exp.Array): 824 key_type = seq_get(keys.type.expressions, 0) or exp.DataType.Type.UNKNOWN 825 value_type = seq_get(values.type.expressions, 0) or exp.DataType.Type.UNKNOWN 826 827 if key_type != exp.DataType.Type.UNKNOWN and value_type != exp.DataType.Type.UNKNOWN: 828 map_type.set("expressions", [key_type, value_type]) 829 map_type.set("nested", True) 830 831 self._set_type(expression, map_type) 832 return expression 833 834 def _annotate_to_map(self, expression: exp.ToMap) -> exp.ToMap: 835 map_type = exp.DataType(this=exp.DataType.Type.MAP) 836 arg = expression.this 837 if arg.is_type(exp.DataType.Type.STRUCT): 838 for coldef in arg.type.expressions: 839 kind = coldef.kind 840 if kind != exp.DataType.Type.UNKNOWN: 841 map_type.set("expressions", [exp.DataType.build("varchar"), kind]) 842 map_type.set("nested", True) 843 break 844 845 self._set_type(expression, map_type) 846 return expression 847 848 def _annotate_extract(self, expression: exp.Extract) -> exp.Extract: 849 part = expression.name 850 if part == "TIME": 851 self._set_type(expression, exp.DataType.Type.TIME) 852 elif part == "DATE": 853 self._set_type(expression, exp.DataType.Type.DATE) 854 elif part in BIGINT_EXTRACT_DATE_PARTS: 855 self._set_type(expression, exp.DataType.Type.BIGINT) 856 else: 857 self._set_type(expression, exp.DataType.Type.INT) 858 return expression 859 860 def _annotate_by_array_element(self, expression: exp.Expression) -> exp.Expression: 861 array_arg = expression.this 862 if array_arg.type.is_type(exp.DataType.Type.ARRAY): 863 element_type = seq_get(array_arg.type.expressions, 0) or exp.DataType.Type.UNKNOWN 864 self._set_type(expression, element_type) 865 else: 866 self._set_type(expression, exp.DataType.Type.UNKNOWN) 867 868 return expression
logger =
<Logger sqlglot (WARNING)>
BIGINT_EXTRACT_DATE_PARTS =
{'EPOCH_MICROSECOND', 'EPOCH_MILLISECOND', 'EPOCH_NANOSECOND', 'EPOCH_SECOND', 'NANOSECOND'}
def
annotate_types( expression: ~E, schema: Union[Dict, sqlglot.schema.Schema, NoneType] = None, expression_metadata: Optional[Dict[type[sqlglot.expressions.Expression], Dict[str, Any]]] = 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, overwrite_types: bool = True) -> ~E:
44def annotate_types( 45 expression: E, 46 schema: t.Optional[t.Dict | Schema] = None, 47 expression_metadata: t.Optional[ExpressionMetadataType] = None, 48 coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None, 49 dialect: DialectType = None, 50 overwrite_types: bool = True, 51) -> E: 52 """ 53 Infers the types of an expression, annotating its AST accordingly. 54 55 Example: 56 >>> import sqlglot 57 >>> schema = {"y": {"cola": "SMALLINT"}} 58 >>> sql = "SELECT x.cola + 2.5 AS cola FROM (SELECT y.cola AS cola FROM y AS y) AS x" 59 >>> annotated_expr = annotate_types(sqlglot.parse_one(sql), schema=schema) 60 >>> annotated_expr.expressions[0].type.this # Get the type of "x.cola + 2.5 AS cola" 61 <Type.DOUBLE: 'DOUBLE'> 62 63 Args: 64 expression: Expression to annotate. 65 schema: Database schema. 66 expression_metadata: Maps expression type to corresponding annotation function. 67 coerces_to: Maps expression type to set of types that it can be coerced into. 68 overwrite_types: Re-annotate the existing AST types. 69 70 Returns: 71 The expression annotated with types. 72 """ 73 74 schema = ensure_schema(schema, dialect=dialect) 75 76 return TypeAnnotator( 77 schema=schema, 78 expression_metadata=expression_metadata, 79 coerces_to=coerces_to, 80 overwrite_types=overwrite_types, 81 ).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.
- expression_metadata: Maps expression type to corresponding annotation function.
- coerces_to: Maps expression type to set of types that it can be coerced into.
- overwrite_types: Re-annotate the existing AST types.
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:
156class TypeAnnotator(metaclass=_TypeAnnotator): 157 NESTED_TYPES = { 158 exp.DataType.Type.ARRAY, 159 } 160 161 # Specifies what types a given type can be coerced into (autofilled) 162 COERCES_TO: t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]] = {} 163 164 # Coercion functions for binary operations. 165 # Map of type pairs to a callable that takes both sides of the binary operation and returns the resulting type. 166 BINARY_COERCIONS: BinaryCoercions = { 167 **swap_all( 168 { 169 (t, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date_literal( 170 l, r.args.get("unit") 171 ) 172 for t in exp.DataType.TEXT_TYPES 173 } 174 ), 175 **swap_all( 176 { 177 # text + numeric will yield the numeric type to match most dialects' semantics 178 (text, numeric): lambda l, r: t.cast( 179 exp.DataType.Type, l.type if l.type in exp.DataType.NUMERIC_TYPES else r.type 180 ) 181 for text in exp.DataType.TEXT_TYPES 182 for numeric in exp.DataType.NUMERIC_TYPES 183 } 184 ), 185 **swap_all( 186 { 187 (exp.DataType.Type.DATE, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date( 188 l, r.args.get("unit") 189 ), 190 } 191 ), 192 } 193 194 def __init__( 195 self, 196 schema: Schema, 197 expression_metadata: t.Optional[ExpressionMetadataType] = None, 198 coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None, 199 binary_coercions: t.Optional[BinaryCoercions] = None, 200 overwrite_types: bool = True, 201 ) -> None: 202 self.schema = schema 203 dialect = schema.dialect or Dialect() 204 self.dialect = dialect 205 self.expression_metadata = expression_metadata or dialect.EXPRESSION_METADATA 206 self.coerces_to = coerces_to or dialect.COERCES_TO or self.COERCES_TO 207 self.binary_coercions = binary_coercions or self.BINARY_COERCIONS 208 209 # Caches the ids of annotated sub-Expressions, to ensure we only visit them once 210 self._visited: t.Set[int] = set() 211 212 # Caches NULL-annotated expressions to set them to UNKNOWN after type inference is completed 213 self._null_expressions: t.Dict[int, exp.Expression] = {} 214 215 # Databricks and Spark ≥v3 actually support NULL (i.e., VOID) as a type 216 self._supports_null_type = dialect.SUPPORTS_NULL_TYPE 217 218 # Maps an exp.SetOperation's id (e.g. UNION) to its projection types. This is computed if the 219 # exp.SetOperation is the expression of a scope source, as selecting from it multiple times 220 # would reprocess the entire subtree to coerce the types of its operands' projections 221 self._setop_column_types: t.Dict[int, t.Dict[str, exp.DataType | exp.DataType.Type]] = {} 222 223 # When set to False, this enables partial annotation by skipping already-annotated nodes 224 self._overwrite_types = overwrite_types 225 226 # Maps Scope to its corresponding selected sources 227 self._scope_selects: t.Dict[Scope, t.Dict[str, t.Dict[str, t.Any]]] = {} 228 229 def clear(self) -> None: 230 self._visited.clear() 231 self._null_expressions.clear() 232 self._setop_column_types.clear() 233 self._scope_selects.clear() 234 235 def _set_type( 236 self, expression: E, target_type: t.Optional[exp.DataType | exp.DataType.Type] 237 ) -> E: 238 prev_type = expression.type 239 expression_id = id(expression) 240 241 expression.type = target_type or exp.DataType.Type.UNKNOWN # type: ignore 242 self._visited.add(expression_id) 243 244 if ( 245 not self._supports_null_type 246 and t.cast(exp.DataType, expression.type).this == exp.DataType.Type.NULL 247 ): 248 self._null_expressions[expression_id] = expression 249 elif prev_type and t.cast(exp.DataType, prev_type).this == exp.DataType.Type.NULL: 250 self._null_expressions.pop(expression_id, None) 251 252 if ( 253 isinstance(expression, exp.Column) 254 and expression.is_type(exp.DataType.Type.JSON) 255 and (dot_parts := expression.meta.get("dot_parts")) 256 ): 257 # JSON dot access is case sensitive across all dialects, so we need to undo the normalization. 258 i = iter(dot_parts) 259 parent = expression.parent 260 while isinstance(parent, exp.Dot): 261 parent.expression.replace(exp.to_identifier(next(i), quoted=True)) 262 parent = parent.parent 263 264 expression.meta.pop("dot_parts", None) 265 266 return expression 267 268 def annotate(self, expression: E, annotate_scope: bool = True) -> E: 269 # This flag is used to avoid costly scope traversals when we only care about annotating 270 # non-column expressions (partial type inference), e.g., when simplifying in the optimizer 271 if annotate_scope: 272 for scope in traverse_scope(expression): 273 self.annotate_scope(scope) 274 275 # This takes care of non-traversable expressions 276 self._annotate_expression(expression) 277 278 # Replace NULL type with the default type of the targeted dialect, since the former is not an actual type; 279 # it is mostly used to aid type coercion, e.g. in query set operations. 280 for expr in self._null_expressions.values(): 281 expr.type = self.dialect.DEFAULT_NULL_TYPE 282 283 return expression 284 285 def _get_scope_selects(self, scope: Scope) -> t.Dict[str, t.Dict[str, t.Any]]: 286 if scope not in self._scope_selects: 287 selects = {} 288 for name, source in scope.sources.items(): 289 if not isinstance(source, Scope): 290 continue 291 292 expression = source.expression 293 if isinstance(expression, exp.UDTF): 294 values = [] 295 296 if isinstance(expression, exp.Lateral): 297 if isinstance(expression.this, exp.Explode): 298 values = [expression.this.this] 299 elif isinstance(expression, exp.Unnest): 300 values = [expression] 301 elif not isinstance(expression, exp.TableFromRows): 302 values = expression.expressions[0].expressions 303 304 if not values: 305 continue 306 307 alias_column_names = expression.alias_column_names 308 309 if ( 310 isinstance(expression, exp.Unnest) 311 and expression.type 312 and expression.type.is_type(exp.DataType.Type.STRUCT) 313 ): 314 selects[name] = { 315 col_def.name: t.cast( 316 t.Union[exp.DataType, exp.DataType.Type], col_def.kind 317 ) 318 for col_def in expression.type.expressions 319 if isinstance(col_def, exp.ColumnDef) and col_def.kind 320 } 321 else: 322 selects[name] = { 323 alias: column.type for alias, column in zip(alias_column_names, values) 324 } 325 elif isinstance(expression, exp.SetOperation) and len( 326 expression.left.selects 327 ) == len(expression.right.selects): 328 selects[name] = self._get_setop_column_types(expression) 329 else: 330 selects[name] = {s.alias_or_name: s.type for s in expression.selects} 331 332 self._scope_selects[scope] = selects 333 334 return self._scope_selects[scope] 335 336 def annotate_scope(self, scope: Scope) -> None: 337 if isinstance(self.schema, MappingSchema): 338 for table_column in scope.table_columns: 339 source = scope.sources.get(table_column.name) 340 341 if isinstance(source, exp.Table): 342 schema = self.schema.find( 343 source, raise_on_missing=False, ensure_data_types=True 344 ) 345 if not isinstance(schema, dict): 346 continue 347 348 struct_type = exp.DataType( 349 this=exp.DataType.Type.STRUCT, 350 expressions=[ 351 exp.ColumnDef(this=exp.to_identifier(c), kind=kind) 352 for c, kind in schema.items() 353 ], 354 nested=True, 355 ) 356 self._set_type(table_column, struct_type) 357 elif ( 358 isinstance(source, Scope) 359 and isinstance(source.expression, exp.Query) 360 and ( 361 source.expression.meta.get("query_type") or exp.DataType.build("UNKNOWN") 362 ).is_type(exp.DataType.Type.STRUCT) 363 ): 364 self._set_type(table_column, source.expression.meta["query_type"]) 365 366 # Iterate through all the expressions of the current scope in post-order, and annotate 367 self._annotate_expression(scope.expression, scope) 368 369 if self.dialect.QUERY_RESULTS_ARE_STRUCTS and isinstance(scope.expression, exp.Query): 370 struct_type = exp.DataType( 371 this=exp.DataType.Type.STRUCT, 372 expressions=[ 373 exp.ColumnDef( 374 this=exp.to_identifier(select.output_name), 375 kind=select.type.copy() if select.type else None, 376 ) 377 for select in scope.expression.selects 378 ], 379 nested=True, 380 ) 381 382 if not any( 383 cd.kind.is_type(exp.DataType.Type.UNKNOWN) 384 for cd in struct_type.expressions 385 if cd.kind 386 ): 387 # We don't use `_set_type` on purpose here. If we annotated the query directly, then 388 # using it in other contexts (e.g., ARRAY(<query>)) could result in incorrect type 389 # annotations, i.e., it shouldn't be interpreted as a STRUCT value. 390 scope.expression.meta["query_type"] = struct_type 391 392 def _annotate_expression( 393 self, 394 expression: exp.Expression, 395 scope: t.Optional[Scope] = None, 396 ) -> None: 397 stack = [(expression, False)] 398 399 while stack: 400 expr, children_annotated = stack.pop() 401 402 if id(expr) in self._visited or ( 403 not self._overwrite_types 404 and expr.type 405 and not expr.is_type(exp.DataType.Type.UNKNOWN) 406 ): 407 continue # We've already inferred the expression's type 408 409 if not children_annotated: 410 stack.append((expr, True)) 411 for child_expr in expr.iter_expressions(): 412 stack.append((child_expr, False)) 413 continue 414 415 if scope and isinstance(expr, exp.Column) and expr.table: 416 source = None 417 source_scope = scope 418 while source_scope and not source: 419 source = source_scope.sources.get(expr.table) 420 if not source: 421 source_scope = source_scope.parent 422 423 if isinstance(source, exp.Table): 424 self._set_type(expr, self.schema.get_column_type(source, expr)) 425 elif source: 426 col_type = ( 427 self._get_scope_selects(source_scope).get(expr.table, {}).get(expr.name) 428 ) 429 if col_type: 430 self._set_type(expr, col_type) 431 elif isinstance(source.expression, exp.Unnest): 432 self._set_type(expr, source.expression.type) 433 else: 434 self._set_type(expr, exp.DataType.Type.UNKNOWN) 435 else: 436 self._set_type(expr, exp.DataType.Type.UNKNOWN) 437 438 if expr.type and expr.type.args.get("nullable") is False: 439 expr.meta["nonnull"] = True 440 continue 441 442 spec = self.expression_metadata.get(expr.__class__) 443 444 if spec and (annotator := spec.get("annotator")): 445 annotator(self, expr) 446 elif spec and (returns := spec.get("returns")): 447 self._set_type(expr, t.cast(exp.DataType.Type, returns)) 448 else: 449 self._set_type(expr, exp.DataType.Type.UNKNOWN) 450 451 def _maybe_coerce( 452 self, 453 type1: exp.DataType | exp.DataType.Type, 454 type2: exp.DataType | exp.DataType.Type, 455 ) -> exp.DataType | exp.DataType.Type: 456 """ 457 Returns type2 if type1 can be coerced into it, otherwise type1. 458 459 If either type is parameterized (e.g. DECIMAL(18, 2) contains two parameters), 460 we assume type1 does not coerce into type2, so we also return it in this case. 461 """ 462 if isinstance(type1, exp.DataType): 463 if type1.expressions: 464 return type1 465 type1_value = type1.this 466 else: 467 type1_value = type1 468 469 if isinstance(type2, exp.DataType): 470 if type2.expressions: 471 return type2 472 type2_value = type2.this 473 else: 474 type2_value = type2 475 476 # We propagate the UNKNOWN type upwards if found 477 if exp.DataType.Type.UNKNOWN in (type1_value, type2_value): 478 return exp.DataType.Type.UNKNOWN 479 480 if type1_value == exp.DataType.Type.NULL: 481 return type2_value 482 if type2_value == exp.DataType.Type.NULL: 483 return type1_value 484 485 return type2_value if type2_value in self.coerces_to.get(type1_value, {}) else type1_value 486 487 def _get_setop_column_types( 488 self, setop: exp.SetOperation 489 ) -> t.Dict[str, exp.DataType | exp.DataType.Type]: 490 """ 491 Computes and returns the coerced column types for a SetOperation. 492 493 This handles UNION, INTERSECT, EXCEPT, etc., coercing types across 494 left and right operands for all projections/columns. 495 496 Args: 497 setop: The SetOperation expression to analyze 498 499 Returns: 500 Dictionary mapping column names to their coerced types 501 """ 502 setop_id = id(setop) 503 if setop_id in self._setop_column_types: 504 return self._setop_column_types[setop_id] 505 506 col_types: t.Dict[str, exp.DataType | exp.DataType.Type] = {} 507 508 # Validate that left and right have same number of projections 509 if not ( 510 isinstance(setop, exp.SetOperation) 511 and setop.left.selects 512 and setop.right.selects 513 and len(setop.left.selects) == len(setop.right.selects) 514 ): 515 return col_types 516 517 # Process a chain / sub-tree of set operations 518 for set_op in setop.walk( 519 prune=lambda n: not isinstance(n, (exp.SetOperation, exp.Subquery)) 520 ): 521 if not isinstance(set_op, exp.SetOperation): 522 continue 523 524 if set_op.args.get("by_name"): 525 r_type_by_select = {s.alias_or_name: s.type for s in set_op.right.selects} 526 setop_cols = { 527 s.alias_or_name: self._maybe_coerce( 528 t.cast(exp.DataType, s.type), 529 r_type_by_select.get(s.alias_or_name) or exp.DataType.Type.UNKNOWN, 530 ) 531 for s in set_op.left.selects 532 } 533 else: 534 setop_cols = { 535 ls.alias_or_name: self._maybe_coerce( 536 t.cast(exp.DataType, ls.type), t.cast(exp.DataType, rs.type) 537 ) 538 for ls, rs in zip(set_op.left.selects, set_op.right.selects) 539 } 540 541 # Coerce intermediate results with the previously registered types, if they exist 542 for col_name, col_type in setop_cols.items(): 543 col_types[col_name] = self._maybe_coerce( 544 col_type, col_types.get(col_name, exp.DataType.Type.NULL) 545 ) 546 547 self._setop_column_types[setop_id] = col_types 548 return col_types 549 550 def _annotate_binary(self, expression: B) -> B: 551 left, right = expression.left, expression.right 552 if not left or not right: 553 expression_sql = expression.sql(self.dialect) 554 logger.warning(f"Failed to annotate badly formed binary expression: {expression_sql}") 555 self._set_type(expression, None) 556 return expression 557 558 left_type, right_type = left.type.this, right.type.this # type: ignore 559 560 if isinstance(expression, (exp.Connector, exp.Predicate)): 561 self._set_type(expression, exp.DataType.Type.BOOLEAN) 562 elif (left_type, right_type) in self.binary_coercions: 563 self._set_type(expression, self.binary_coercions[(left_type, right_type)](left, right)) 564 else: 565 self._annotate_by_args(expression, left, right) 566 567 if isinstance(expression, exp.Is) or ( 568 left.meta.get("nonnull") is True and right.meta.get("nonnull") is True 569 ): 570 expression.meta["nonnull"] = True 571 572 return expression 573 574 def _annotate_unary(self, expression: E) -> E: 575 if isinstance(expression, exp.Not): 576 self._set_type(expression, exp.DataType.Type.BOOLEAN) 577 else: 578 self._set_type(expression, expression.this.type) 579 580 if expression.this.meta.get("nonnull") is True: 581 expression.meta["nonnull"] = True 582 583 return expression 584 585 def _annotate_literal(self, expression: exp.Literal) -> exp.Literal: 586 if expression.is_string: 587 self._set_type(expression, exp.DataType.Type.VARCHAR) 588 elif expression.is_int: 589 self._set_type(expression, exp.DataType.Type.INT) 590 else: 591 self._set_type(expression, exp.DataType.Type.DOUBLE) 592 593 expression.meta["nonnull"] = True 594 595 return expression 596 597 @t.no_type_check 598 def _annotate_by_args( 599 self, 600 expression: E, 601 *args: str | exp.Expression, 602 promote: bool = False, 603 array: bool = False, 604 ) -> E: 605 literal_type = None 606 non_literal_type = None 607 nested_type = None 608 609 for arg in args: 610 if isinstance(arg, str): 611 expressions = expression.args.get(arg) 612 else: 613 expressions = arg 614 615 for expr in ensure_list(expressions): 616 expr_type = expr.type 617 618 # Stop at the first nested data type found - we don't want to _maybe_coerce nested types 619 if expr_type.args.get("nested"): 620 nested_type = expr_type 621 break 622 623 if isinstance(expr, exp.Literal): 624 literal_type = self._maybe_coerce(literal_type or expr_type, expr_type) 625 else: 626 non_literal_type = self._maybe_coerce(non_literal_type or expr_type, expr_type) 627 628 if nested_type: 629 break 630 631 result_type = None 632 633 if nested_type: 634 result_type = nested_type 635 elif literal_type and non_literal_type: 636 if self.dialect.PRIORITIZE_NON_LITERAL_TYPES: 637 literal_this_type = ( 638 literal_type.this if isinstance(literal_type, exp.DataType) else literal_type 639 ) 640 non_literal_this_type = ( 641 non_literal_type.this 642 if isinstance(non_literal_type, exp.DataType) 643 else non_literal_type 644 ) 645 if ( 646 literal_this_type in exp.DataType.INTEGER_TYPES 647 and non_literal_this_type in exp.DataType.INTEGER_TYPES 648 ) or ( 649 literal_this_type in exp.DataType.REAL_TYPES 650 and non_literal_this_type in exp.DataType.REAL_TYPES 651 ): 652 result_type = non_literal_type 653 else: 654 result_type = literal_type or non_literal_type or exp.DataType.Type.UNKNOWN 655 656 self._set_type( 657 expression, result_type or self._maybe_coerce(non_literal_type, literal_type) 658 ) 659 660 if promote: 661 if expression.type.this in exp.DataType.INTEGER_TYPES: 662 self._set_type(expression, exp.DataType.Type.BIGINT) 663 elif expression.type.this in exp.DataType.FLOAT_TYPES: 664 self._set_type(expression, exp.DataType.Type.DOUBLE) 665 666 if array: 667 self._set_type( 668 expression, 669 exp.DataType( 670 this=exp.DataType.Type.ARRAY, expressions=[expression.type], nested=True 671 ), 672 ) 673 674 return expression 675 676 def _annotate_timeunit( 677 self, expression: exp.TimeUnit | exp.DateTrunc 678 ) -> exp.TimeUnit | exp.DateTrunc: 679 if expression.this.type.this in exp.DataType.TEXT_TYPES: 680 datatype = _coerce_date_literal(expression.this, expression.unit) 681 elif expression.this.type.this in exp.DataType.TEMPORAL_TYPES: 682 datatype = _coerce_date(expression.this, expression.unit) 683 else: 684 datatype = exp.DataType.Type.UNKNOWN 685 686 self._set_type(expression, datatype) 687 return expression 688 689 def _annotate_bracket(self, expression: exp.Bracket) -> exp.Bracket: 690 bracket_arg = expression.expressions[0] 691 this = expression.this 692 693 if isinstance(bracket_arg, exp.Slice): 694 self._set_type(expression, this.type) 695 elif this.type.is_type(exp.DataType.Type.ARRAY): 696 self._set_type(expression, seq_get(this.type.expressions, 0)) 697 elif isinstance(this, (exp.Map, exp.VarMap)) and bracket_arg in this.keys: 698 index = this.keys.index(bracket_arg) 699 value = seq_get(this.values, index) 700 self._set_type(expression, value.type if value else None) 701 else: 702 self._set_type(expression, exp.DataType.Type.UNKNOWN) 703 704 return expression 705 706 def _annotate_div(self, expression: exp.Div) -> exp.Div: 707 left_type, right_type = expression.left.type.this, expression.right.type.this # type: ignore 708 709 if ( 710 expression.args.get("typed") 711 and left_type in exp.DataType.INTEGER_TYPES 712 and right_type in exp.DataType.INTEGER_TYPES 713 ): 714 self._set_type(expression, exp.DataType.Type.BIGINT) 715 else: 716 self._set_type(expression, self._maybe_coerce(left_type, right_type)) 717 if expression.type and expression.type.this not in exp.DataType.REAL_TYPES: 718 self._set_type( 719 expression, self._maybe_coerce(expression.type, exp.DataType.Type.DOUBLE) 720 ) 721 722 return expression 723 724 def _annotate_dot(self, expression: exp.Dot) -> exp.Dot: 725 self._set_type(expression, None) 726 727 # Propagate type from qualified UDF calls (e.g., db.my_udf(...)) 728 if isinstance(expression.expression, exp.Anonymous): 729 self._set_type(expression, expression.expression.type) 730 return expression 731 732 this_type = expression.this.type 733 734 if this_type and this_type.is_type(exp.DataType.Type.STRUCT): 735 for e in this_type.expressions: 736 if e.name == expression.expression.name: 737 self._set_type(expression, e.kind) 738 break 739 740 return expression 741 742 def _annotate_explode(self, expression: exp.Explode) -> exp.Explode: 743 self._set_type(expression, seq_get(expression.this.type.expressions, 0)) 744 return expression 745 746 def _annotate_unnest(self, expression: exp.Unnest) -> exp.Unnest: 747 child = seq_get(expression.expressions, 0) 748 749 if child and child.is_type(exp.DataType.Type.ARRAY): 750 expr_type = seq_get(child.type.expressions, 0) 751 else: 752 expr_type = None 753 754 self._set_type(expression, expr_type) 755 return expression 756 757 def _annotate_subquery(self, expression: exp.Subquery) -> exp.Subquery: 758 # For scalar subqueries (subqueries with a single projection), infer the type 759 # from that single projection. This allows type propagation in cases like: 760 # SELECT (SELECT 1 AS c) AS c 761 query = expression.unnest() 762 763 if isinstance(query, exp.Query): 764 selects = query.selects 765 if len(selects) == 1: 766 self._set_type(expression, selects[0].type) 767 return expression 768 769 self._set_type(expression, exp.DataType.Type.UNKNOWN) 770 return expression 771 772 def _annotate_struct_value( 773 self, expression: exp.Expression 774 ) -> t.Optional[exp.DataType] | exp.ColumnDef: 775 # Case: STRUCT(key AS value) 776 this: t.Optional[exp.Expression] = None 777 kind = expression.type 778 779 if alias := expression.args.get("alias"): 780 this = alias.copy() 781 elif expression.expression: 782 # Case: STRUCT(key = value) or STRUCT(key := value) 783 this = expression.this.copy() 784 kind = expression.expression.type 785 elif isinstance(expression, exp.Column): 786 # Case: STRUCT(c) 787 this = expression.this.copy() 788 789 if kind and kind.is_type(exp.DataType.Type.UNKNOWN): 790 return None 791 792 if this: 793 return exp.ColumnDef(this=this, kind=kind) 794 795 return kind 796 797 def _annotate_struct(self, expression: exp.Struct) -> exp.Struct: 798 expressions = [] 799 for expr in expression.expressions: 800 struct_field_type = self._annotate_struct_value(expr) 801 if struct_field_type is None: 802 self._set_type(expression, None) 803 return expression 804 805 expressions.append(struct_field_type) 806 807 self._set_type( 808 expression, 809 exp.DataType(this=exp.DataType.Type.STRUCT, expressions=expressions, nested=True), 810 ) 811 return expression 812 813 @t.overload 814 def _annotate_map(self, expression: exp.Map) -> exp.Map: ... 815 816 @t.overload 817 def _annotate_map(self, expression: exp.VarMap) -> exp.VarMap: ... 818 819 def _annotate_map(self, expression): 820 keys = expression.args.get("keys") 821 values = expression.args.get("values") 822 823 map_type = exp.DataType(this=exp.DataType.Type.MAP) 824 if isinstance(keys, exp.Array) and isinstance(values, exp.Array): 825 key_type = seq_get(keys.type.expressions, 0) or exp.DataType.Type.UNKNOWN 826 value_type = seq_get(values.type.expressions, 0) or exp.DataType.Type.UNKNOWN 827 828 if key_type != exp.DataType.Type.UNKNOWN and value_type != exp.DataType.Type.UNKNOWN: 829 map_type.set("expressions", [key_type, value_type]) 830 map_type.set("nested", True) 831 832 self._set_type(expression, map_type) 833 return expression 834 835 def _annotate_to_map(self, expression: exp.ToMap) -> exp.ToMap: 836 map_type = exp.DataType(this=exp.DataType.Type.MAP) 837 arg = expression.this 838 if arg.is_type(exp.DataType.Type.STRUCT): 839 for coldef in arg.type.expressions: 840 kind = coldef.kind 841 if kind != exp.DataType.Type.UNKNOWN: 842 map_type.set("expressions", [exp.DataType.build("varchar"), kind]) 843 map_type.set("nested", True) 844 break 845 846 self._set_type(expression, map_type) 847 return expression 848 849 def _annotate_extract(self, expression: exp.Extract) -> exp.Extract: 850 part = expression.name 851 if part == "TIME": 852 self._set_type(expression, exp.DataType.Type.TIME) 853 elif part == "DATE": 854 self._set_type(expression, exp.DataType.Type.DATE) 855 elif part in BIGINT_EXTRACT_DATE_PARTS: 856 self._set_type(expression, exp.DataType.Type.BIGINT) 857 else: 858 self._set_type(expression, exp.DataType.Type.INT) 859 return expression 860 861 def _annotate_by_array_element(self, expression: exp.Expression) -> exp.Expression: 862 array_arg = expression.this 863 if array_arg.type.is_type(exp.DataType.Type.ARRAY): 864 element_type = seq_get(array_arg.type.expressions, 0) or exp.DataType.Type.UNKNOWN 865 self._set_type(expression, element_type) 866 else: 867 self._set_type(expression, exp.DataType.Type.UNKNOWN) 868 869 return expression
TypeAnnotator( schema: sqlglot.schema.Schema, expression_metadata: Optional[Dict[type[sqlglot.expressions.Expression], Dict[str, Any]]] = 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, overwrite_types: bool = True)
194 def __init__( 195 self, 196 schema: Schema, 197 expression_metadata: t.Optional[ExpressionMetadataType] = None, 198 coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None, 199 binary_coercions: t.Optional[BinaryCoercions] = None, 200 overwrite_types: bool = True, 201 ) -> None: 202 self.schema = schema 203 dialect = schema.dialect or Dialect() 204 self.dialect = dialect 205 self.expression_metadata = expression_metadata or dialect.EXPRESSION_METADATA 206 self.coerces_to = coerces_to or dialect.COERCES_TO or self.COERCES_TO 207 self.binary_coercions = binary_coercions or self.BINARY_COERCIONS 208 209 # Caches the ids of annotated sub-Expressions, to ensure we only visit them once 210 self._visited: t.Set[int] = set() 211 212 # Caches NULL-annotated expressions to set them to UNKNOWN after type inference is completed 213 self._null_expressions: t.Dict[int, exp.Expression] = {} 214 215 # Databricks and Spark ≥v3 actually support NULL (i.e., VOID) as a type 216 self._supports_null_type = dialect.SUPPORTS_NULL_TYPE 217 218 # Maps an exp.SetOperation's id (e.g. UNION) to its projection types. This is computed if the 219 # exp.SetOperation is the expression of a scope source, as selecting from it multiple times 220 # would reprocess the entire subtree to coerce the types of its operands' projections 221 self._setop_column_types: t.Dict[int, t.Dict[str, exp.DataType | exp.DataType.Type]] = {} 222 223 # When set to False, this enables partial annotation by skipping already-annotated nodes 224 self._overwrite_types = overwrite_types 225 226 # Maps Scope to its corresponding selected sources 227 self._scope_selects: t.Dict[Scope, t.Dict[str, t.Dict[str, t.Any]]] = {}
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.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <Type.TIME: 'TIME'>, <Type.DATE: 'DATE'>, <Type.DATETIME: 'DATETIME'>, <Type.TIMESTAMP: 'TIMESTAMP'>, <Type.NVARCHAR: 'NVARCHAR'>}, <Type.NCHAR: 'NCHAR'>: {<Type.TEXT: 'TEXT'>, <Type.VARCHAR: 'VARCHAR'>, <Type.NVARCHAR: 'NVARCHAR'>}, <Type.CHAR: 'CHAR'>: {<Type.NCHAR: 'NCHAR'>, <Type.TEXT: 'TEXT'>, <Type.VARCHAR: 'VARCHAR'>, <Type.NVARCHAR: 'NVARCHAR'>}, <Type.DECFLOAT: 'DECFLOAT'>: set(), <Type.DOUBLE: 'DOUBLE'>: {<Type.DECFLOAT: 'DECFLOAT'>}, <Type.FLOAT: 'FLOAT'>: {<Type.DOUBLE: 'DOUBLE'>, <Type.DECFLOAT: 'DECFLOAT'>}, <Type.BIGDECIMAL: 'BIGDECIMAL'>: {<Type.FLOAT: 'FLOAT'>, <Type.DOUBLE: 'DOUBLE'>, <Type.DECFLOAT: 'DECFLOAT'>}, <Type.DECIMAL: 'DECIMAL'>: {<Type.DOUBLE: 'DOUBLE'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.FLOAT: 'FLOAT'>, <Type.DECFLOAT: 'DECFLOAT'>}, <Type.BIGINT: 'BIGINT'>: {<Type.DECIMAL: 'DECIMAL'>, <Type.DOUBLE: 'DOUBLE'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.FLOAT: 'FLOAT'>, <Type.DECFLOAT: 'DECFLOAT'>}, <Type.INT: 'INT'>: {<Type.DECIMAL: 'DECIMAL'>, <Type.DOUBLE: 'DOUBLE'>, <Type.BIGINT: 'BIGINT'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.FLOAT: 'FLOAT'>, <Type.DECFLOAT: 'DECFLOAT'>}, <Type.SMALLINT: 'SMALLINT'>: {<Type.DECIMAL: 'DECIMAL'>, <Type.DOUBLE: 'DOUBLE'>, <Type.BIGINT: 'BIGINT'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.FLOAT: 'FLOAT'>, <Type.DECFLOAT: 'DECFLOAT'>, <Type.INT: 'INT'>}, <Type.TINYINT: 'TINYINT'>: {<Type.DECIMAL: 'DECIMAL'>, <Type.BIGINT: 'BIGINT'>, <Type.FLOAT: 'FLOAT'>, <Type.DECFLOAT: 'DECFLOAT'>, <Type.INT: 'INT'>, <Type.DOUBLE: 'DOUBLE'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>, <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.TIMESTAMP: 'TIMESTAMP'>, <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>}, <Type.DATE: 'DATE'>: {<Type.DATETIME: 'DATETIME'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <Type.TIMESTAMP: 'TIMESTAMP'>, <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>}}
BINARY_COERCIONS: Dict[Tuple[sqlglot.expressions.DataType.Type, sqlglot.expressions.DataType.Type], Callable[[sqlglot.expressions.Expression, sqlglot.expressions.Expression], sqlglot.expressions.DataType.Type]] =
{(<Type.CHAR: 'CHAR'>, <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.NVARCHAR: 'NVARCHAR'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.CHAR: 'CHAR'>): <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.INTERVAL: 'INTERVAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UDOUBLE: 'UDOUBLE'>): <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.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECFLOAT: 'DECFLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UDOUBLE: 'UDOUBLE'>): <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.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECFLOAT: 'DECFLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UDOUBLE: 'UDOUBLE'>): <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.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECFLOAT: 'DECFLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UDOUBLE: 'UDOUBLE'>): <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.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECFLOAT: 'DECFLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UDOUBLE: 'UDOUBLE'>): <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.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECFLOAT: 'DECFLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UDOUBLE: 'UDOUBLE'>): <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.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECFLOAT: 'DECFLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <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.BIGINT: 'BIGINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECFLOAT: 'DECFLOAT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <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.BIGINT: 'BIGINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECFLOAT: 'DECFLOAT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <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.BIGINT: 'BIGINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECFLOAT: 'DECFLOAT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <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.BIGINT: 'BIGINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECFLOAT: 'DECFLOAT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <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.BIGINT: 'BIGINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECFLOAT: 'DECFLOAT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <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.BIGINT: 'BIGINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECFLOAT: 'DECFLOAT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DATE: 'DATE'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.DATE: 'DATE'>): <function TypeAnnotator.<lambda>>}
def
annotate(self, expression: ~E, annotate_scope: bool = True) -> ~E:
268 def annotate(self, expression: E, annotate_scope: bool = True) -> E: 269 # This flag is used to avoid costly scope traversals when we only care about annotating 270 # non-column expressions (partial type inference), e.g., when simplifying in the optimizer 271 if annotate_scope: 272 for scope in traverse_scope(expression): 273 self.annotate_scope(scope) 274 275 # This takes care of non-traversable expressions 276 self._annotate_expression(expression) 277 278 # Replace NULL type with the default type of the targeted dialect, since the former is not an actual type; 279 # it is mostly used to aid type coercion, e.g. in query set operations. 280 for expr in self._null_expressions.values(): 281 expr.type = self.dialect.DEFAULT_NULL_TYPE 282 283 return expression
336 def annotate_scope(self, scope: Scope) -> None: 337 if isinstance(self.schema, MappingSchema): 338 for table_column in scope.table_columns: 339 source = scope.sources.get(table_column.name) 340 341 if isinstance(source, exp.Table): 342 schema = self.schema.find( 343 source, raise_on_missing=False, ensure_data_types=True 344 ) 345 if not isinstance(schema, dict): 346 continue 347 348 struct_type = exp.DataType( 349 this=exp.DataType.Type.STRUCT, 350 expressions=[ 351 exp.ColumnDef(this=exp.to_identifier(c), kind=kind) 352 for c, kind in schema.items() 353 ], 354 nested=True, 355 ) 356 self._set_type(table_column, struct_type) 357 elif ( 358 isinstance(source, Scope) 359 and isinstance(source.expression, exp.Query) 360 and ( 361 source.expression.meta.get("query_type") or exp.DataType.build("UNKNOWN") 362 ).is_type(exp.DataType.Type.STRUCT) 363 ): 364 self._set_type(table_column, source.expression.meta["query_type"]) 365 366 # Iterate through all the expressions of the current scope in post-order, and annotate 367 self._annotate_expression(scope.expression, scope) 368 369 if self.dialect.QUERY_RESULTS_ARE_STRUCTS and isinstance(scope.expression, exp.Query): 370 struct_type = exp.DataType( 371 this=exp.DataType.Type.STRUCT, 372 expressions=[ 373 exp.ColumnDef( 374 this=exp.to_identifier(select.output_name), 375 kind=select.type.copy() if select.type else None, 376 ) 377 for select in scope.expression.selects 378 ], 379 nested=True, 380 ) 381 382 if not any( 383 cd.kind.is_type(exp.DataType.Type.UNKNOWN) 384 for cd in struct_type.expressions 385 if cd.kind 386 ): 387 # We don't use `_set_type` on purpose here. If we annotated the query directly, then 388 # using it in other contexts (e.g., ARRAY(<query>)) could result in incorrect type 389 # annotations, i.e., it shouldn't be interpreted as a STRUCT value. 390 scope.expression.meta["query_type"] = struct_type