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