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 return expression 252 253 def annotate(self, expression: E, annotate_scope: bool = True) -> E: 254 # This flag is used to avoid costly scope traversals when we only care about annotating 255 # non-column expressions (partial type inference), e.g., when simplifying in the optimizer 256 if annotate_scope: 257 for scope in traverse_scope(expression): 258 self.annotate_scope(scope) 259 260 # This takes care of non-traversable expressions 261 self._annotate_expression(expression) 262 263 # Replace NULL type with the default type of the targeted dialect, since the former is not an actual type; 264 # it is mostly used to aid type coercion, e.g. in query set operations. 265 for expr in self._null_expressions.values(): 266 expr.type = self.dialect.DEFAULT_NULL_TYPE 267 268 return expression 269 270 def _get_scope_selects(self, scope: Scope) -> t.Dict[str, t.Dict[str, t.Any]]: 271 if scope not in self._scope_selects: 272 selects = {} 273 for name, source in scope.sources.items(): 274 if not isinstance(source, Scope): 275 continue 276 277 expression = source.expression 278 if isinstance(expression, exp.UDTF): 279 values = [] 280 281 if isinstance(expression, exp.Lateral): 282 if isinstance(expression.this, exp.Explode): 283 values = [expression.this.this] 284 elif isinstance(expression, exp.Unnest): 285 values = [expression] 286 elif not isinstance(expression, exp.TableFromRows): 287 values = expression.expressions[0].expressions 288 289 if not values: 290 continue 291 292 alias_column_names = expression.alias_column_names 293 294 if ( 295 isinstance(expression, exp.Unnest) 296 and expression.type 297 and expression.type.is_type(exp.DataType.Type.STRUCT) 298 ): 299 selects[name] = { 300 col_def.name: t.cast( 301 t.Union[exp.DataType, exp.DataType.Type], col_def.kind 302 ) 303 for col_def in expression.type.expressions 304 if isinstance(col_def, exp.ColumnDef) and col_def.kind 305 } 306 else: 307 selects[name] = { 308 alias: column.type for alias, column in zip(alias_column_names, values) 309 } 310 elif isinstance(expression, exp.SetOperation) and len( 311 expression.left.selects 312 ) == len(expression.right.selects): 313 selects[name] = self._get_setop_column_types(expression) 314 else: 315 selects[name] = {s.alias_or_name: s.type for s in expression.selects} 316 317 self._scope_selects[scope] = selects 318 319 return self._scope_selects[scope] 320 321 def annotate_scope(self, scope: Scope) -> None: 322 if isinstance(self.schema, MappingSchema): 323 for table_column in scope.table_columns: 324 source = scope.sources.get(table_column.name) 325 326 if isinstance(source, exp.Table): 327 schema = self.schema.find( 328 source, raise_on_missing=False, ensure_data_types=True 329 ) 330 if not isinstance(schema, dict): 331 continue 332 333 struct_type = exp.DataType( 334 this=exp.DataType.Type.STRUCT, 335 expressions=[ 336 exp.ColumnDef(this=exp.to_identifier(c), kind=kind) 337 for c, kind in schema.items() 338 ], 339 nested=True, 340 ) 341 self._set_type(table_column, struct_type) 342 elif ( 343 isinstance(source, Scope) 344 and isinstance(source.expression, exp.Query) 345 and ( 346 source.expression.meta.get("query_type") or exp.DataType.build("UNKNOWN") 347 ).is_type(exp.DataType.Type.STRUCT) 348 ): 349 self._set_type(table_column, source.expression.meta["query_type"]) 350 351 # Iterate through all the expressions of the current scope in post-order, and annotate 352 self._annotate_expression(scope.expression, scope) 353 354 if self.dialect.QUERY_RESULTS_ARE_STRUCTS and isinstance(scope.expression, exp.Query): 355 struct_type = exp.DataType( 356 this=exp.DataType.Type.STRUCT, 357 expressions=[ 358 exp.ColumnDef( 359 this=exp.to_identifier(select.output_name), 360 kind=select.type.copy() if select.type else None, 361 ) 362 for select in scope.expression.selects 363 ], 364 nested=True, 365 ) 366 367 if not any( 368 cd.kind.is_type(exp.DataType.Type.UNKNOWN) 369 for cd in struct_type.expressions 370 if cd.kind 371 ): 372 # We don't use `_set_type` on purpose here. If we annotated the query directly, then 373 # using it in other contexts (e.g., ARRAY(<query>)) could result in incorrect type 374 # annotations, i.e., it shouldn't be interpreted as a STRUCT value. 375 scope.expression.meta["query_type"] = struct_type 376 377 def _annotate_expression( 378 self, 379 expression: exp.Expression, 380 scope: t.Optional[Scope] = None, 381 ) -> None: 382 stack = [(expression, False)] 383 384 while stack: 385 expr, children_annotated = stack.pop() 386 387 if id(expr) in self._visited or ( 388 not self._overwrite_types 389 and expr.type 390 and not expr.is_type(exp.DataType.Type.UNKNOWN) 391 ): 392 continue # We've already inferred the expression's type 393 394 if not children_annotated: 395 stack.append((expr, True)) 396 for child_expr in expr.iter_expressions(): 397 stack.append((child_expr, False)) 398 continue 399 400 if scope and isinstance(expr, exp.Column) and expr.table: 401 source = None 402 source_scope = scope 403 while source_scope and not source: 404 source = source_scope.sources.get(expr.table) 405 if not source: 406 source_scope = source_scope.parent 407 408 if isinstance(source, exp.Table): 409 self._set_type(expr, self.schema.get_column_type(source, expr)) 410 elif source: 411 col_type = ( 412 self._get_scope_selects(source_scope).get(expr.table, {}).get(expr.name) 413 ) 414 if col_type: 415 self._set_type(expr, col_type) 416 elif isinstance(source.expression, exp.Unnest): 417 self._set_type(expr, source.expression.type) 418 else: 419 self._set_type(expr, exp.DataType.Type.UNKNOWN) 420 else: 421 self._set_type(expr, exp.DataType.Type.UNKNOWN) 422 423 if expr.is_type(exp.DataType.Type.JSON) and ( 424 dot_parts := expr.meta.get("dot_parts") 425 ): 426 # JSON dot access is case sensitive across all dialects, so we need to undo the normalization. 427 i = iter(dot_parts) 428 parent = expr.parent 429 while isinstance(parent, exp.Dot): 430 parent.expression.replace(exp.to_identifier(next(i), quoted=True)) 431 parent = parent.parent 432 433 expr.meta.pop("dot_parts", None) 434 435 if expr.type and expr.type.args.get("nullable") is False: 436 expr.meta["nonnull"] = True 437 continue 438 439 spec = self.expression_metadata.get(expr.__class__) 440 441 if spec and (annotator := spec.get("annotator")): 442 annotator(self, expr) 443 elif spec and (returns := spec.get("returns")): 444 self._set_type(expr, t.cast(exp.DataType.Type, returns)) 445 else: 446 self._set_type(expr, exp.DataType.Type.UNKNOWN) 447 448 def _maybe_coerce( 449 self, 450 type1: exp.DataType | exp.DataType.Type, 451 type2: exp.DataType | exp.DataType.Type, 452 ) -> exp.DataType | exp.DataType.Type: 453 """ 454 Returns type2 if type1 can be coerced into it, otherwise type1. 455 456 If either type is parameterized (e.g. DECIMAL(18, 2) contains two parameters), 457 we assume type1 does not coerce into type2, so we also return it in this case. 458 """ 459 if isinstance(type1, exp.DataType): 460 if type1.expressions: 461 return type1 462 type1_value = type1.this 463 else: 464 type1_value = type1 465 466 if isinstance(type2, exp.DataType): 467 if type2.expressions: 468 return type2 469 type2_value = type2.this 470 else: 471 type2_value = type2 472 473 # We propagate the UNKNOWN type upwards if found 474 if exp.DataType.Type.UNKNOWN in (type1_value, type2_value): 475 return exp.DataType.Type.UNKNOWN 476 477 if type1_value == exp.DataType.Type.NULL: 478 return type2_value 479 if type2_value == exp.DataType.Type.NULL: 480 return type1_value 481 482 return type2_value if type2_value in self.coerces_to.get(type1_value, {}) else type1_value 483 484 def _get_setop_column_types( 485 self, setop: exp.SetOperation 486 ) -> t.Dict[str, exp.DataType | exp.DataType.Type]: 487 """ 488 Computes and returns the coerced column types for a SetOperation. 489 490 This handles UNION, INTERSECT, EXCEPT, etc., coercing types across 491 left and right operands for all projections/columns. 492 493 Args: 494 setop: The SetOperation expression to analyze 495 496 Returns: 497 Dictionary mapping column names to their coerced types 498 """ 499 setop_id = id(setop) 500 if setop_id in self._setop_column_types: 501 return self._setop_column_types[setop_id] 502 503 col_types: t.Dict[str, exp.DataType | exp.DataType.Type] = {} 504 505 # Validate that left and right have same number of projections 506 if not ( 507 isinstance(setop, exp.SetOperation) 508 and setop.left.selects 509 and setop.right.selects 510 and len(setop.left.selects) == len(setop.right.selects) 511 ): 512 return col_types 513 514 # Process a chain / sub-tree of set operations 515 for set_op in setop.walk( 516 prune=lambda n: not isinstance(n, (exp.SetOperation, exp.Subquery)) 517 ): 518 if not isinstance(set_op, exp.SetOperation): 519 continue 520 521 if set_op.args.get("by_name"): 522 r_type_by_select = {s.alias_or_name: s.type for s in set_op.right.selects} 523 setop_cols = { 524 s.alias_or_name: self._maybe_coerce( 525 t.cast(exp.DataType, s.type), 526 r_type_by_select.get(s.alias_or_name) or exp.DataType.Type.UNKNOWN, 527 ) 528 for s in set_op.left.selects 529 } 530 else: 531 setop_cols = { 532 ls.alias_or_name: self._maybe_coerce( 533 t.cast(exp.DataType, ls.type), t.cast(exp.DataType, rs.type) 534 ) 535 for ls, rs in zip(set_op.left.selects, set_op.right.selects) 536 } 537 538 # Coerce intermediate results with the previously registered types, if they exist 539 for col_name, col_type in setop_cols.items(): 540 col_types[col_name] = self._maybe_coerce( 541 col_type, col_types.get(col_name, exp.DataType.Type.NULL) 542 ) 543 544 self._setop_column_types[setop_id] = col_types 545 return col_types 546 547 def _annotate_binary(self, expression: B) -> B: 548 left, right = expression.left, expression.right 549 if not left or not right: 550 expression_sql = expression.sql(self.dialect) 551 logger.warning(f"Failed to annotate badly formed binary expression: {expression_sql}") 552 self._set_type(expression, None) 553 return expression 554 555 left_type, right_type = left.type.this, right.type.this # type: ignore 556 557 if isinstance(expression, (exp.Connector, exp.Predicate)): 558 self._set_type(expression, exp.DataType.Type.BOOLEAN) 559 elif (left_type, right_type) in self.binary_coercions: 560 self._set_type(expression, self.binary_coercions[(left_type, right_type)](left, right)) 561 else: 562 self._annotate_by_args(expression, left, right) 563 564 if isinstance(expression, exp.Is) or ( 565 left.meta.get("nonnull") is True and right.meta.get("nonnull") is True 566 ): 567 expression.meta["nonnull"] = True 568 569 return expression 570 571 def _annotate_unary(self, expression: E) -> E: 572 if isinstance(expression, exp.Not): 573 self._set_type(expression, exp.DataType.Type.BOOLEAN) 574 else: 575 self._set_type(expression, expression.this.type) 576 577 if expression.this.meta.get("nonnull") is True: 578 expression.meta["nonnull"] = True 579 580 return expression 581 582 def _annotate_literal(self, expression: exp.Literal) -> exp.Literal: 583 if expression.is_string: 584 self._set_type(expression, exp.DataType.Type.VARCHAR) 585 elif expression.is_int: 586 self._set_type(expression, exp.DataType.Type.INT) 587 else: 588 self._set_type(expression, exp.DataType.Type.DOUBLE) 589 590 expression.meta["nonnull"] = True 591 592 return expression 593 594 @t.no_type_check 595 def _annotate_by_args( 596 self, 597 expression: E, 598 *args: str | exp.Expression, 599 promote: bool = False, 600 array: bool = False, 601 ) -> E: 602 literal_type = None 603 non_literal_type = None 604 nested_type = None 605 606 for arg in args: 607 if isinstance(arg, str): 608 expressions = expression.args.get(arg) 609 else: 610 expressions = arg 611 612 for expr in ensure_list(expressions): 613 expr_type = expr.type 614 615 # Stop at the first nested data type found - we don't want to _maybe_coerce nested types 616 if expr_type.args.get("nested"): 617 nested_type = expr_type 618 break 619 620 if isinstance(expr, exp.Literal): 621 literal_type = self._maybe_coerce(literal_type or expr_type, expr_type) 622 else: 623 non_literal_type = self._maybe_coerce(non_literal_type or expr_type, expr_type) 624 625 if nested_type: 626 break 627 628 result_type = None 629 630 if nested_type: 631 result_type = nested_type 632 elif literal_type and non_literal_type: 633 if self.dialect.PRIORITIZE_NON_LITERAL_TYPES: 634 literal_this_type = ( 635 literal_type.this if isinstance(literal_type, exp.DataType) else literal_type 636 ) 637 non_literal_this_type = ( 638 non_literal_type.this 639 if isinstance(non_literal_type, exp.DataType) 640 else non_literal_type 641 ) 642 if ( 643 literal_this_type in exp.DataType.INTEGER_TYPES 644 and non_literal_this_type in exp.DataType.INTEGER_TYPES 645 ) or ( 646 literal_this_type in exp.DataType.REAL_TYPES 647 and non_literal_this_type in exp.DataType.REAL_TYPES 648 ): 649 result_type = non_literal_type 650 else: 651 result_type = literal_type or non_literal_type or exp.DataType.Type.UNKNOWN 652 653 self._set_type( 654 expression, result_type or self._maybe_coerce(non_literal_type, literal_type) 655 ) 656 657 if promote: 658 if expression.type.this in exp.DataType.INTEGER_TYPES: 659 self._set_type(expression, exp.DataType.Type.BIGINT) 660 elif expression.type.this in exp.DataType.FLOAT_TYPES: 661 self._set_type(expression, exp.DataType.Type.DOUBLE) 662 663 if array: 664 self._set_type( 665 expression, 666 exp.DataType( 667 this=exp.DataType.Type.ARRAY, expressions=[expression.type], nested=True 668 ), 669 ) 670 671 return expression 672 673 def _annotate_timeunit( 674 self, expression: exp.TimeUnit | exp.DateTrunc 675 ) -> exp.TimeUnit | exp.DateTrunc: 676 if expression.this.type.this in exp.DataType.TEXT_TYPES: 677 datatype = _coerce_date_literal(expression.this, expression.unit) 678 elif expression.this.type.this in exp.DataType.TEMPORAL_TYPES: 679 datatype = _coerce_date(expression.this, expression.unit) 680 else: 681 datatype = exp.DataType.Type.UNKNOWN 682 683 self._set_type(expression, datatype) 684 return expression 685 686 def _annotate_bracket(self, expression: exp.Bracket) -> exp.Bracket: 687 bracket_arg = expression.expressions[0] 688 this = expression.this 689 690 if isinstance(bracket_arg, exp.Slice): 691 self._set_type(expression, this.type) 692 elif this.type.is_type(exp.DataType.Type.ARRAY): 693 self._set_type(expression, seq_get(this.type.expressions, 0)) 694 elif isinstance(this, (exp.Map, exp.VarMap)) and bracket_arg in this.keys: 695 index = this.keys.index(bracket_arg) 696 value = seq_get(this.values, index) 697 self._set_type(expression, value.type if value else None) 698 else: 699 self._set_type(expression, exp.DataType.Type.UNKNOWN) 700 701 return expression 702 703 def _annotate_div(self, expression: exp.Div) -> exp.Div: 704 left_type, right_type = expression.left.type.this, expression.right.type.this # type: ignore 705 706 if ( 707 expression.args.get("typed") 708 and left_type in exp.DataType.INTEGER_TYPES 709 and right_type in exp.DataType.INTEGER_TYPES 710 ): 711 self._set_type(expression, exp.DataType.Type.BIGINT) 712 else: 713 self._set_type(expression, self._maybe_coerce(left_type, right_type)) 714 if expression.type and expression.type.this not in exp.DataType.REAL_TYPES: 715 self._set_type( 716 expression, self._maybe_coerce(expression.type, exp.DataType.Type.DOUBLE) 717 ) 718 719 return expression 720 721 def _annotate_dot(self, expression: exp.Dot) -> exp.Dot: 722 self._set_type(expression, None) 723 724 # Propagate type from qualified UDF calls (e.g., db.my_udf(...)) 725 if isinstance(expression.expression, exp.Anonymous): 726 self._set_type(expression, expression.expression.type) 727 return expression 728 729 this_type = expression.this.type 730 731 if this_type and this_type.is_type(exp.DataType.Type.STRUCT): 732 for e in this_type.expressions: 733 if e.name == expression.expression.name: 734 self._set_type(expression, e.kind) 735 break 736 737 return expression 738 739 def _annotate_explode(self, expression: exp.Explode) -> exp.Explode: 740 self._set_type(expression, seq_get(expression.this.type.expressions, 0)) 741 return expression 742 743 def _annotate_unnest(self, expression: exp.Unnest) -> exp.Unnest: 744 child = seq_get(expression.expressions, 0) 745 746 if child and child.is_type(exp.DataType.Type.ARRAY): 747 expr_type = seq_get(child.type.expressions, 0) 748 else: 749 expr_type = None 750 751 self._set_type(expression, expr_type) 752 return expression 753 754 def _annotate_subquery(self, expression: exp.Subquery) -> exp.Subquery: 755 # For scalar subqueries (subqueries with a single projection), infer the type 756 # from that single projection. This allows type propagation in cases like: 757 # SELECT (SELECT 1 AS c) AS c 758 query = expression.unnest() 759 760 if isinstance(query, exp.Query): 761 selects = query.selects 762 if len(selects) == 1: 763 self._set_type(expression, selects[0].type) 764 return expression 765 766 self._set_type(expression, exp.DataType.Type.UNKNOWN) 767 return expression 768 769 def _annotate_struct_value( 770 self, expression: exp.Expression 771 ) -> t.Optional[exp.DataType] | exp.ColumnDef: 772 # Case: STRUCT(key AS value) 773 this: t.Optional[exp.Expression] = None 774 kind = expression.type 775 776 if alias := expression.args.get("alias"): 777 this = alias.copy() 778 elif expression.expression: 779 # Case: STRUCT(key = value) or STRUCT(key := value) 780 this = expression.this.copy() 781 kind = expression.expression.type 782 elif isinstance(expression, exp.Column): 783 # Case: STRUCT(c) 784 this = expression.this.copy() 785 786 if kind and kind.is_type(exp.DataType.Type.UNKNOWN): 787 return None 788 789 if this: 790 return exp.ColumnDef(this=this, kind=kind) 791 792 return kind 793 794 def _annotate_struct(self, expression: exp.Struct) -> exp.Struct: 795 expressions = [] 796 for expr in expression.expressions: 797 struct_field_type = self._annotate_struct_value(expr) 798 if struct_field_type is None: 799 self._set_type(expression, None) 800 return expression 801 802 expressions.append(struct_field_type) 803 804 self._set_type( 805 expression, 806 exp.DataType(this=exp.DataType.Type.STRUCT, expressions=expressions, nested=True), 807 ) 808 return expression 809 810 @t.overload 811 def _annotate_map(self, expression: exp.Map) -> exp.Map: ... 812 813 @t.overload 814 def _annotate_map(self, expression: exp.VarMap) -> exp.VarMap: ... 815 816 def _annotate_map(self, expression): 817 keys = expression.args.get("keys") 818 values = expression.args.get("values") 819 820 map_type = exp.DataType(this=exp.DataType.Type.MAP) 821 if isinstance(keys, exp.Array) and isinstance(values, exp.Array): 822 key_type = seq_get(keys.type.expressions, 0) or exp.DataType.Type.UNKNOWN 823 value_type = seq_get(values.type.expressions, 0) or exp.DataType.Type.UNKNOWN 824 825 if key_type != exp.DataType.Type.UNKNOWN and value_type != exp.DataType.Type.UNKNOWN: 826 map_type.set("expressions", [key_type, value_type]) 827 map_type.set("nested", True) 828 829 self._set_type(expression, map_type) 830 return expression 831 832 def _annotate_to_map(self, expression: exp.ToMap) -> exp.ToMap: 833 map_type = exp.DataType(this=exp.DataType.Type.MAP) 834 arg = expression.this 835 if arg.is_type(exp.DataType.Type.STRUCT): 836 for coldef in arg.type.expressions: 837 kind = coldef.kind 838 if kind != exp.DataType.Type.UNKNOWN: 839 map_type.set("expressions", [exp.DataType.build("varchar"), kind]) 840 map_type.set("nested", True) 841 break 842 843 self._set_type(expression, map_type) 844 return expression 845 846 def _annotate_extract(self, expression: exp.Extract) -> exp.Extract: 847 part = expression.name 848 if part == "TIME": 849 self._set_type(expression, exp.DataType.Type.TIME) 850 elif part == "DATE": 851 self._set_type(expression, exp.DataType.Type.DATE) 852 elif part in BIGINT_EXTRACT_DATE_PARTS: 853 self._set_type(expression, exp.DataType.Type.BIGINT) 854 else: 855 self._set_type(expression, exp.DataType.Type.INT) 856 return expression 857 858 def _annotate_by_array_element(self, expression: exp.Expression) -> exp.Expression: 859 array_arg = expression.this 860 if array_arg.type.is_type(exp.DataType.Type.ARRAY): 861 element_type = seq_get(array_arg.type.expressions, 0) or exp.DataType.Type.UNKNOWN 862 self._set_type(expression, element_type) 863 else: 864 self._set_type(expression, exp.DataType.Type.UNKNOWN) 865 866 return expression
logger =
<Logger sqlglot (WARNING)>
BIGINT_EXTRACT_DATE_PARTS =
{'EPOCH_MICROSECOND', 'NANOSECOND', 'EPOCH_MILLISECOND', 'EPOCH_SECOND', 'EPOCH_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 return expression 253 254 def annotate(self, expression: E, annotate_scope: bool = True) -> E: 255 # This flag is used to avoid costly scope traversals when we only care about annotating 256 # non-column expressions (partial type inference), e.g., when simplifying in the optimizer 257 if annotate_scope: 258 for scope in traverse_scope(expression): 259 self.annotate_scope(scope) 260 261 # This takes care of non-traversable expressions 262 self._annotate_expression(expression) 263 264 # Replace NULL type with the default type of the targeted dialect, since the former is not an actual type; 265 # it is mostly used to aid type coercion, e.g. in query set operations. 266 for expr in self._null_expressions.values(): 267 expr.type = self.dialect.DEFAULT_NULL_TYPE 268 269 return expression 270 271 def _get_scope_selects(self, scope: Scope) -> t.Dict[str, t.Dict[str, t.Any]]: 272 if scope not in self._scope_selects: 273 selects = {} 274 for name, source in scope.sources.items(): 275 if not isinstance(source, Scope): 276 continue 277 278 expression = source.expression 279 if isinstance(expression, exp.UDTF): 280 values = [] 281 282 if isinstance(expression, exp.Lateral): 283 if isinstance(expression.this, exp.Explode): 284 values = [expression.this.this] 285 elif isinstance(expression, exp.Unnest): 286 values = [expression] 287 elif not isinstance(expression, exp.TableFromRows): 288 values = expression.expressions[0].expressions 289 290 if not values: 291 continue 292 293 alias_column_names = expression.alias_column_names 294 295 if ( 296 isinstance(expression, exp.Unnest) 297 and expression.type 298 and expression.type.is_type(exp.DataType.Type.STRUCT) 299 ): 300 selects[name] = { 301 col_def.name: t.cast( 302 t.Union[exp.DataType, exp.DataType.Type], col_def.kind 303 ) 304 for col_def in expression.type.expressions 305 if isinstance(col_def, exp.ColumnDef) and col_def.kind 306 } 307 else: 308 selects[name] = { 309 alias: column.type for alias, column in zip(alias_column_names, values) 310 } 311 elif isinstance(expression, exp.SetOperation) and len( 312 expression.left.selects 313 ) == len(expression.right.selects): 314 selects[name] = self._get_setop_column_types(expression) 315 else: 316 selects[name] = {s.alias_or_name: s.type for s in expression.selects} 317 318 self._scope_selects[scope] = selects 319 320 return self._scope_selects[scope] 321 322 def annotate_scope(self, scope: Scope) -> None: 323 if isinstance(self.schema, MappingSchema): 324 for table_column in scope.table_columns: 325 source = scope.sources.get(table_column.name) 326 327 if isinstance(source, exp.Table): 328 schema = self.schema.find( 329 source, raise_on_missing=False, ensure_data_types=True 330 ) 331 if not isinstance(schema, dict): 332 continue 333 334 struct_type = exp.DataType( 335 this=exp.DataType.Type.STRUCT, 336 expressions=[ 337 exp.ColumnDef(this=exp.to_identifier(c), kind=kind) 338 for c, kind in schema.items() 339 ], 340 nested=True, 341 ) 342 self._set_type(table_column, struct_type) 343 elif ( 344 isinstance(source, Scope) 345 and isinstance(source.expression, exp.Query) 346 and ( 347 source.expression.meta.get("query_type") or exp.DataType.build("UNKNOWN") 348 ).is_type(exp.DataType.Type.STRUCT) 349 ): 350 self._set_type(table_column, source.expression.meta["query_type"]) 351 352 # Iterate through all the expressions of the current scope in post-order, and annotate 353 self._annotate_expression(scope.expression, scope) 354 355 if self.dialect.QUERY_RESULTS_ARE_STRUCTS and isinstance(scope.expression, exp.Query): 356 struct_type = exp.DataType( 357 this=exp.DataType.Type.STRUCT, 358 expressions=[ 359 exp.ColumnDef( 360 this=exp.to_identifier(select.output_name), 361 kind=select.type.copy() if select.type else None, 362 ) 363 for select in scope.expression.selects 364 ], 365 nested=True, 366 ) 367 368 if not any( 369 cd.kind.is_type(exp.DataType.Type.UNKNOWN) 370 for cd in struct_type.expressions 371 if cd.kind 372 ): 373 # We don't use `_set_type` on purpose here. If we annotated the query directly, then 374 # using it in other contexts (e.g., ARRAY(<query>)) could result in incorrect type 375 # annotations, i.e., it shouldn't be interpreted as a STRUCT value. 376 scope.expression.meta["query_type"] = struct_type 377 378 def _annotate_expression( 379 self, 380 expression: exp.Expression, 381 scope: t.Optional[Scope] = None, 382 ) -> None: 383 stack = [(expression, False)] 384 385 while stack: 386 expr, children_annotated = stack.pop() 387 388 if id(expr) in self._visited or ( 389 not self._overwrite_types 390 and expr.type 391 and not expr.is_type(exp.DataType.Type.UNKNOWN) 392 ): 393 continue # We've already inferred the expression's type 394 395 if not children_annotated: 396 stack.append((expr, True)) 397 for child_expr in expr.iter_expressions(): 398 stack.append((child_expr, False)) 399 continue 400 401 if scope and isinstance(expr, exp.Column) and expr.table: 402 source = None 403 source_scope = scope 404 while source_scope and not source: 405 source = source_scope.sources.get(expr.table) 406 if not source: 407 source_scope = source_scope.parent 408 409 if isinstance(source, exp.Table): 410 self._set_type(expr, self.schema.get_column_type(source, expr)) 411 elif source: 412 col_type = ( 413 self._get_scope_selects(source_scope).get(expr.table, {}).get(expr.name) 414 ) 415 if col_type: 416 self._set_type(expr, col_type) 417 elif isinstance(source.expression, exp.Unnest): 418 self._set_type(expr, source.expression.type) 419 else: 420 self._set_type(expr, exp.DataType.Type.UNKNOWN) 421 else: 422 self._set_type(expr, exp.DataType.Type.UNKNOWN) 423 424 if expr.is_type(exp.DataType.Type.JSON) and ( 425 dot_parts := expr.meta.get("dot_parts") 426 ): 427 # JSON dot access is case sensitive across all dialects, so we need to undo the normalization. 428 i = iter(dot_parts) 429 parent = expr.parent 430 while isinstance(parent, exp.Dot): 431 parent.expression.replace(exp.to_identifier(next(i), quoted=True)) 432 parent = parent.parent 433 434 expr.meta.pop("dot_parts", None) 435 436 if expr.type and expr.type.args.get("nullable") is False: 437 expr.meta["nonnull"] = True 438 continue 439 440 spec = self.expression_metadata.get(expr.__class__) 441 442 if spec and (annotator := spec.get("annotator")): 443 annotator(self, expr) 444 elif spec and (returns := spec.get("returns")): 445 self._set_type(expr, t.cast(exp.DataType.Type, returns)) 446 else: 447 self._set_type(expr, exp.DataType.Type.UNKNOWN) 448 449 def _maybe_coerce( 450 self, 451 type1: exp.DataType | exp.DataType.Type, 452 type2: exp.DataType | exp.DataType.Type, 453 ) -> exp.DataType | exp.DataType.Type: 454 """ 455 Returns type2 if type1 can be coerced into it, otherwise type1. 456 457 If either type is parameterized (e.g. DECIMAL(18, 2) contains two parameters), 458 we assume type1 does not coerce into type2, so we also return it in this case. 459 """ 460 if isinstance(type1, exp.DataType): 461 if type1.expressions: 462 return type1 463 type1_value = type1.this 464 else: 465 type1_value = type1 466 467 if isinstance(type2, exp.DataType): 468 if type2.expressions: 469 return type2 470 type2_value = type2.this 471 else: 472 type2_value = type2 473 474 # We propagate the UNKNOWN type upwards if found 475 if exp.DataType.Type.UNKNOWN in (type1_value, type2_value): 476 return exp.DataType.Type.UNKNOWN 477 478 if type1_value == exp.DataType.Type.NULL: 479 return type2_value 480 if type2_value == exp.DataType.Type.NULL: 481 return type1_value 482 483 return type2_value if type2_value in self.coerces_to.get(type1_value, {}) else type1_value 484 485 def _get_setop_column_types( 486 self, setop: exp.SetOperation 487 ) -> t.Dict[str, exp.DataType | exp.DataType.Type]: 488 """ 489 Computes and returns the coerced column types for a SetOperation. 490 491 This handles UNION, INTERSECT, EXCEPT, etc., coercing types across 492 left and right operands for all projections/columns. 493 494 Args: 495 setop: The SetOperation expression to analyze 496 497 Returns: 498 Dictionary mapping column names to their coerced types 499 """ 500 setop_id = id(setop) 501 if setop_id in self._setop_column_types: 502 return self._setop_column_types[setop_id] 503 504 col_types: t.Dict[str, exp.DataType | exp.DataType.Type] = {} 505 506 # Validate that left and right have same number of projections 507 if not ( 508 isinstance(setop, exp.SetOperation) 509 and setop.left.selects 510 and setop.right.selects 511 and len(setop.left.selects) == len(setop.right.selects) 512 ): 513 return col_types 514 515 # Process a chain / sub-tree of set operations 516 for set_op in setop.walk( 517 prune=lambda n: not isinstance(n, (exp.SetOperation, exp.Subquery)) 518 ): 519 if not isinstance(set_op, exp.SetOperation): 520 continue 521 522 if set_op.args.get("by_name"): 523 r_type_by_select = {s.alias_or_name: s.type for s in set_op.right.selects} 524 setop_cols = { 525 s.alias_or_name: self._maybe_coerce( 526 t.cast(exp.DataType, s.type), 527 r_type_by_select.get(s.alias_or_name) or exp.DataType.Type.UNKNOWN, 528 ) 529 for s in set_op.left.selects 530 } 531 else: 532 setop_cols = { 533 ls.alias_or_name: self._maybe_coerce( 534 t.cast(exp.DataType, ls.type), t.cast(exp.DataType, rs.type) 535 ) 536 for ls, rs in zip(set_op.left.selects, set_op.right.selects) 537 } 538 539 # Coerce intermediate results with the previously registered types, if they exist 540 for col_name, col_type in setop_cols.items(): 541 col_types[col_name] = self._maybe_coerce( 542 col_type, col_types.get(col_name, exp.DataType.Type.NULL) 543 ) 544 545 self._setop_column_types[setop_id] = col_types 546 return col_types 547 548 def _annotate_binary(self, expression: B) -> B: 549 left, right = expression.left, expression.right 550 if not left or not right: 551 expression_sql = expression.sql(self.dialect) 552 logger.warning(f"Failed to annotate badly formed binary expression: {expression_sql}") 553 self._set_type(expression, None) 554 return expression 555 556 left_type, right_type = left.type.this, right.type.this # type: ignore 557 558 if isinstance(expression, (exp.Connector, exp.Predicate)): 559 self._set_type(expression, exp.DataType.Type.BOOLEAN) 560 elif (left_type, right_type) in self.binary_coercions: 561 self._set_type(expression, self.binary_coercions[(left_type, right_type)](left, right)) 562 else: 563 self._annotate_by_args(expression, left, right) 564 565 if isinstance(expression, exp.Is) or ( 566 left.meta.get("nonnull") is True and right.meta.get("nonnull") is True 567 ): 568 expression.meta["nonnull"] = True 569 570 return expression 571 572 def _annotate_unary(self, expression: E) -> E: 573 if isinstance(expression, exp.Not): 574 self._set_type(expression, exp.DataType.Type.BOOLEAN) 575 else: 576 self._set_type(expression, expression.this.type) 577 578 if expression.this.meta.get("nonnull") is True: 579 expression.meta["nonnull"] = True 580 581 return expression 582 583 def _annotate_literal(self, expression: exp.Literal) -> exp.Literal: 584 if expression.is_string: 585 self._set_type(expression, exp.DataType.Type.VARCHAR) 586 elif expression.is_int: 587 self._set_type(expression, exp.DataType.Type.INT) 588 else: 589 self._set_type(expression, exp.DataType.Type.DOUBLE) 590 591 expression.meta["nonnull"] = True 592 593 return expression 594 595 @t.no_type_check 596 def _annotate_by_args( 597 self, 598 expression: E, 599 *args: str | exp.Expression, 600 promote: bool = False, 601 array: bool = False, 602 ) -> E: 603 literal_type = None 604 non_literal_type = None 605 nested_type = None 606 607 for arg in args: 608 if isinstance(arg, str): 609 expressions = expression.args.get(arg) 610 else: 611 expressions = arg 612 613 for expr in ensure_list(expressions): 614 expr_type = expr.type 615 616 # Stop at the first nested data type found - we don't want to _maybe_coerce nested types 617 if expr_type.args.get("nested"): 618 nested_type = expr_type 619 break 620 621 if isinstance(expr, exp.Literal): 622 literal_type = self._maybe_coerce(literal_type or expr_type, expr_type) 623 else: 624 non_literal_type = self._maybe_coerce(non_literal_type or expr_type, expr_type) 625 626 if nested_type: 627 break 628 629 result_type = None 630 631 if nested_type: 632 result_type = nested_type 633 elif literal_type and non_literal_type: 634 if self.dialect.PRIORITIZE_NON_LITERAL_TYPES: 635 literal_this_type = ( 636 literal_type.this if isinstance(literal_type, exp.DataType) else literal_type 637 ) 638 non_literal_this_type = ( 639 non_literal_type.this 640 if isinstance(non_literal_type, exp.DataType) 641 else non_literal_type 642 ) 643 if ( 644 literal_this_type in exp.DataType.INTEGER_TYPES 645 and non_literal_this_type in exp.DataType.INTEGER_TYPES 646 ) or ( 647 literal_this_type in exp.DataType.REAL_TYPES 648 and non_literal_this_type in exp.DataType.REAL_TYPES 649 ): 650 result_type = non_literal_type 651 else: 652 result_type = literal_type or non_literal_type or exp.DataType.Type.UNKNOWN 653 654 self._set_type( 655 expression, result_type or self._maybe_coerce(non_literal_type, literal_type) 656 ) 657 658 if promote: 659 if expression.type.this in exp.DataType.INTEGER_TYPES: 660 self._set_type(expression, exp.DataType.Type.BIGINT) 661 elif expression.type.this in exp.DataType.FLOAT_TYPES: 662 self._set_type(expression, exp.DataType.Type.DOUBLE) 663 664 if array: 665 self._set_type( 666 expression, 667 exp.DataType( 668 this=exp.DataType.Type.ARRAY, expressions=[expression.type], nested=True 669 ), 670 ) 671 672 return expression 673 674 def _annotate_timeunit( 675 self, expression: exp.TimeUnit | exp.DateTrunc 676 ) -> exp.TimeUnit | exp.DateTrunc: 677 if expression.this.type.this in exp.DataType.TEXT_TYPES: 678 datatype = _coerce_date_literal(expression.this, expression.unit) 679 elif expression.this.type.this in exp.DataType.TEMPORAL_TYPES: 680 datatype = _coerce_date(expression.this, expression.unit) 681 else: 682 datatype = exp.DataType.Type.UNKNOWN 683 684 self._set_type(expression, datatype) 685 return expression 686 687 def _annotate_bracket(self, expression: exp.Bracket) -> exp.Bracket: 688 bracket_arg = expression.expressions[0] 689 this = expression.this 690 691 if isinstance(bracket_arg, exp.Slice): 692 self._set_type(expression, this.type) 693 elif this.type.is_type(exp.DataType.Type.ARRAY): 694 self._set_type(expression, seq_get(this.type.expressions, 0)) 695 elif isinstance(this, (exp.Map, exp.VarMap)) and bracket_arg in this.keys: 696 index = this.keys.index(bracket_arg) 697 value = seq_get(this.values, index) 698 self._set_type(expression, value.type if value else None) 699 else: 700 self._set_type(expression, exp.DataType.Type.UNKNOWN) 701 702 return expression 703 704 def _annotate_div(self, expression: exp.Div) -> exp.Div: 705 left_type, right_type = expression.left.type.this, expression.right.type.this # type: ignore 706 707 if ( 708 expression.args.get("typed") 709 and left_type in exp.DataType.INTEGER_TYPES 710 and right_type in exp.DataType.INTEGER_TYPES 711 ): 712 self._set_type(expression, exp.DataType.Type.BIGINT) 713 else: 714 self._set_type(expression, self._maybe_coerce(left_type, right_type)) 715 if expression.type and expression.type.this not in exp.DataType.REAL_TYPES: 716 self._set_type( 717 expression, self._maybe_coerce(expression.type, exp.DataType.Type.DOUBLE) 718 ) 719 720 return expression 721 722 def _annotate_dot(self, expression: exp.Dot) -> exp.Dot: 723 self._set_type(expression, None) 724 725 # Propagate type from qualified UDF calls (e.g., db.my_udf(...)) 726 if isinstance(expression.expression, exp.Anonymous): 727 self._set_type(expression, expression.expression.type) 728 return expression 729 730 this_type = expression.this.type 731 732 if this_type and this_type.is_type(exp.DataType.Type.STRUCT): 733 for e in this_type.expressions: 734 if e.name == expression.expression.name: 735 self._set_type(expression, e.kind) 736 break 737 738 return expression 739 740 def _annotate_explode(self, expression: exp.Explode) -> exp.Explode: 741 self._set_type(expression, seq_get(expression.this.type.expressions, 0)) 742 return expression 743 744 def _annotate_unnest(self, expression: exp.Unnest) -> exp.Unnest: 745 child = seq_get(expression.expressions, 0) 746 747 if child and child.is_type(exp.DataType.Type.ARRAY): 748 expr_type = seq_get(child.type.expressions, 0) 749 else: 750 expr_type = None 751 752 self._set_type(expression, expr_type) 753 return expression 754 755 def _annotate_subquery(self, expression: exp.Subquery) -> exp.Subquery: 756 # For scalar subqueries (subqueries with a single projection), infer the type 757 # from that single projection. This allows type propagation in cases like: 758 # SELECT (SELECT 1 AS c) AS c 759 query = expression.unnest() 760 761 if isinstance(query, exp.Query): 762 selects = query.selects 763 if len(selects) == 1: 764 self._set_type(expression, selects[0].type) 765 return expression 766 767 self._set_type(expression, exp.DataType.Type.UNKNOWN) 768 return expression 769 770 def _annotate_struct_value( 771 self, expression: exp.Expression 772 ) -> t.Optional[exp.DataType] | exp.ColumnDef: 773 # Case: STRUCT(key AS value) 774 this: t.Optional[exp.Expression] = None 775 kind = expression.type 776 777 if alias := expression.args.get("alias"): 778 this = alias.copy() 779 elif expression.expression: 780 # Case: STRUCT(key = value) or STRUCT(key := value) 781 this = expression.this.copy() 782 kind = expression.expression.type 783 elif isinstance(expression, exp.Column): 784 # Case: STRUCT(c) 785 this = expression.this.copy() 786 787 if kind and kind.is_type(exp.DataType.Type.UNKNOWN): 788 return None 789 790 if this: 791 return exp.ColumnDef(this=this, kind=kind) 792 793 return kind 794 795 def _annotate_struct(self, expression: exp.Struct) -> exp.Struct: 796 expressions = [] 797 for expr in expression.expressions: 798 struct_field_type = self._annotate_struct_value(expr) 799 if struct_field_type is None: 800 self._set_type(expression, None) 801 return expression 802 803 expressions.append(struct_field_type) 804 805 self._set_type( 806 expression, 807 exp.DataType(this=exp.DataType.Type.STRUCT, expressions=expressions, nested=True), 808 ) 809 return expression 810 811 @t.overload 812 def _annotate_map(self, expression: exp.Map) -> exp.Map: ... 813 814 @t.overload 815 def _annotate_map(self, expression: exp.VarMap) -> exp.VarMap: ... 816 817 def _annotate_map(self, expression): 818 keys = expression.args.get("keys") 819 values = expression.args.get("values") 820 821 map_type = exp.DataType(this=exp.DataType.Type.MAP) 822 if isinstance(keys, exp.Array) and isinstance(values, exp.Array): 823 key_type = seq_get(keys.type.expressions, 0) or exp.DataType.Type.UNKNOWN 824 value_type = seq_get(values.type.expressions, 0) or exp.DataType.Type.UNKNOWN 825 826 if key_type != exp.DataType.Type.UNKNOWN and value_type != exp.DataType.Type.UNKNOWN: 827 map_type.set("expressions", [key_type, value_type]) 828 map_type.set("nested", True) 829 830 self._set_type(expression, map_type) 831 return expression 832 833 def _annotate_to_map(self, expression: exp.ToMap) -> exp.ToMap: 834 map_type = exp.DataType(this=exp.DataType.Type.MAP) 835 arg = expression.this 836 if arg.is_type(exp.DataType.Type.STRUCT): 837 for coldef in arg.type.expressions: 838 kind = coldef.kind 839 if kind != exp.DataType.Type.UNKNOWN: 840 map_type.set("expressions", [exp.DataType.build("varchar"), kind]) 841 map_type.set("nested", True) 842 break 843 844 self._set_type(expression, map_type) 845 return expression 846 847 def _annotate_extract(self, expression: exp.Extract) -> exp.Extract: 848 part = expression.name 849 if part == "TIME": 850 self._set_type(expression, exp.DataType.Type.TIME) 851 elif part == "DATE": 852 self._set_type(expression, exp.DataType.Type.DATE) 853 elif part in BIGINT_EXTRACT_DATE_PARTS: 854 self._set_type(expression, exp.DataType.Type.BIGINT) 855 else: 856 self._set_type(expression, exp.DataType.Type.INT) 857 return expression 858 859 def _annotate_by_array_element(self, expression: exp.Expression) -> exp.Expression: 860 array_arg = expression.this 861 if array_arg.type.is_type(exp.DataType.Type.ARRAY): 862 element_type = seq_get(array_arg.type.expressions, 0) or exp.DataType.Type.UNKNOWN 863 self._set_type(expression, element_type) 864 else: 865 self._set_type(expression, exp.DataType.Type.UNKNOWN) 866 867 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.NVARCHAR: 'NVARCHAR'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <Type.TIME: 'TIME'>, <Type.TIMESTAMP: 'TIMESTAMP'>, <Type.TEXT: 'TEXT'>, <Type.DATE: 'DATE'>, <Type.DATETIME: 'DATETIME'>}, <Type.NCHAR: 'NCHAR'>: {<Type.NVARCHAR: 'NVARCHAR'>, <Type.VARCHAR: 'VARCHAR'>, <Type.TEXT: 'TEXT'>}, <Type.CHAR: 'CHAR'>: {<Type.NVARCHAR: 'NVARCHAR'>, <Type.VARCHAR: 'VARCHAR'>, <Type.TEXT: 'TEXT'>, <Type.NCHAR: 'NCHAR'>}, <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.FLOAT: 'FLOAT'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.DOUBLE: 'DOUBLE'>, <Type.DECFLOAT: 'DECFLOAT'>}, <Type.BIGINT: 'BIGINT'>: {<Type.FLOAT: 'FLOAT'>, <Type.DECIMAL: 'DECIMAL'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.DOUBLE: 'DOUBLE'>, <Type.DECFLOAT: 'DECFLOAT'>}, <Type.INT: 'INT'>: {<Type.FLOAT: 'FLOAT'>, <Type.DECIMAL: 'DECIMAL'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.BIGINT: 'BIGINT'>, <Type.DOUBLE: 'DOUBLE'>, <Type.DECFLOAT: 'DECFLOAT'>}, <Type.SMALLINT: 'SMALLINT'>: {<Type.FLOAT: 'FLOAT'>, <Type.DECIMAL: 'DECIMAL'>, <Type.INT: 'INT'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.BIGINT: 'BIGINT'>, <Type.DOUBLE: 'DOUBLE'>, <Type.DECFLOAT: 'DECFLOAT'>}, <Type.TINYINT: 'TINYINT'>: {<Type.INT: 'INT'>, <Type.SMALLINT: 'SMALLINT'>, <Type.DECIMAL: 'DECIMAL'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.BIGINT: 'BIGINT'>, <Type.DECFLOAT: 'DECFLOAT'>, <Type.FLOAT: 'FLOAT'>, <Type.DOUBLE: 'DOUBLE'>}, <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>: set(), <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>: {<Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>}, <Type.TIMESTAMP: 'TIMESTAMP'>: {<Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>}, <Type.DATETIME: 'DATETIME'>: {<Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <Type.TIMESTAMP: 'TIMESTAMP'>}, <Type.DATE: 'DATE'>: {<Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>, <Type.DATETIME: 'DATETIME'>, <Type.TIMESTAMP: 'TIMESTAMP'>}}
BINARY_COERCIONS: Dict[Tuple[sqlglot.expressions.DataType.Type, sqlglot.expressions.DataType.Type], Callable[[sqlglot.expressions.Expression, sqlglot.expressions.Expression], sqlglot.expressions.DataType.Type]] =
{(<Type.NVARCHAR: 'NVARCHAR'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.CHAR: 'CHAR'>): <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.INTERVAL: 'INTERVAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECFLOAT: 'DECFLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECFLOAT: 'DECFLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECFLOAT: 'DECFLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECFLOAT: 'DECFLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECFLOAT: 'DECFLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL128: 'DECIMAL128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UDOUBLE: 'UDOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL256: 'DECIMAL256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECFLOAT: 'DECFLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL64: 'DECIMAL64'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL32: 'DECIMAL32'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECFLOAT: 'DECFLOAT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECFLOAT: 'DECFLOAT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECFLOAT: 'DECFLOAT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECFLOAT: 'DECFLOAT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECFLOAT: 'DECFLOAT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL128: 'DECIMAL128'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDOUBLE: 'UDOUBLE'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL256: 'DECIMAL256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECFLOAT: 'DECFLOAT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL64: 'DECIMAL64'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL32: 'DECIMAL32'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DATE: 'DATE'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.DATE: 'DATE'>): <function TypeAnnotator.<lambda>>}
def
annotate(self, expression: ~E, annotate_scope: bool = True) -> ~E:
254 def annotate(self, expression: E, annotate_scope: bool = True) -> E: 255 # This flag is used to avoid costly scope traversals when we only care about annotating 256 # non-column expressions (partial type inference), e.g., when simplifying in the optimizer 257 if annotate_scope: 258 for scope in traverse_scope(expression): 259 self.annotate_scope(scope) 260 261 # This takes care of non-traversable expressions 262 self._annotate_expression(expression) 263 264 # Replace NULL type with the default type of the targeted dialect, since the former is not an actual type; 265 # it is mostly used to aid type coercion, e.g. in query set operations. 266 for expr in self._null_expressions.values(): 267 expr.type = self.dialect.DEFAULT_NULL_TYPE 268 269 return expression
322 def annotate_scope(self, scope: Scope) -> None: 323 if isinstance(self.schema, MappingSchema): 324 for table_column in scope.table_columns: 325 source = scope.sources.get(table_column.name) 326 327 if isinstance(source, exp.Table): 328 schema = self.schema.find( 329 source, raise_on_missing=False, ensure_data_types=True 330 ) 331 if not isinstance(schema, dict): 332 continue 333 334 struct_type = exp.DataType( 335 this=exp.DataType.Type.STRUCT, 336 expressions=[ 337 exp.ColumnDef(this=exp.to_identifier(c), kind=kind) 338 for c, kind in schema.items() 339 ], 340 nested=True, 341 ) 342 self._set_type(table_column, struct_type) 343 elif ( 344 isinstance(source, Scope) 345 and isinstance(source.expression, exp.Query) 346 and ( 347 source.expression.meta.get("query_type") or exp.DataType.build("UNKNOWN") 348 ).is_type(exp.DataType.Type.STRUCT) 349 ): 350 self._set_type(table_column, source.expression.meta["query_type"]) 351 352 # Iterate through all the expressions of the current scope in post-order, and annotate 353 self._annotate_expression(scope.expression, scope) 354 355 if self.dialect.QUERY_RESULTS_ARE_STRUCTS and isinstance(scope.expression, exp.Query): 356 struct_type = exp.DataType( 357 this=exp.DataType.Type.STRUCT, 358 expressions=[ 359 exp.ColumnDef( 360 this=exp.to_identifier(select.output_name), 361 kind=select.type.copy() if select.type else None, 362 ) 363 for select in scope.expression.selects 364 ], 365 nested=True, 366 ) 367 368 if not any( 369 cd.kind.is_type(exp.DataType.Type.UNKNOWN) 370 for cd in struct_type.expressions 371 if cd.kind 372 ): 373 # We don't use `_set_type` on purpose here. If we annotated the query directly, then 374 # using it in other contexts (e.g., ARRAY(<query>)) could result in incorrect type 375 # annotations, i.e., it shouldn't be interpreted as a STRUCT value. 376 scope.expression.meta["query_type"] = struct_type