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 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: t.Optional[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) 59 60 return TypeAnnotator(schema, annotators, coerces_to, dialect=dialect).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 return klass 132 133 134class TypeAnnotator(metaclass=_TypeAnnotator): 135 NESTED_TYPES = { 136 exp.DataType.Type.ARRAY, 137 } 138 139 # Specifies what types a given type can be coerced into (autofilled) 140 COERCES_TO: t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]] = {} 141 142 # Coercion functions for binary operations. 143 # Map of type pairs to a callable that takes both sides of the binary operation and returns the resulting type. 144 BINARY_COERCIONS: BinaryCoercions = { 145 **swap_all( 146 { 147 (t, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date_literal( 148 l, r.args.get("unit") 149 ) 150 for t in exp.DataType.TEXT_TYPES 151 } 152 ), 153 **swap_all( 154 { 155 # text + numeric will yield the numeric type to match most dialects' semantics 156 (text, numeric): lambda l, r: t.cast( 157 exp.DataType.Type, l.type if l.type in exp.DataType.NUMERIC_TYPES else r.type 158 ) 159 for text in exp.DataType.TEXT_TYPES 160 for numeric in exp.DataType.NUMERIC_TYPES 161 } 162 ), 163 **swap_all( 164 { 165 (exp.DataType.Type.DATE, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date( 166 l, r.args.get("unit") 167 ), 168 } 169 ), 170 } 171 172 def __init__( 173 self, 174 schema: Schema, 175 annotators: t.Optional[AnnotatorsType] = None, 176 coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None, 177 binary_coercions: t.Optional[BinaryCoercions] = None, 178 dialect: t.Optional[DialectType] = None, 179 ) -> None: 180 self.schema = schema 181 self.annotators = annotators or Dialect.get_or_raise(dialect).ANNOTATORS 182 self.coerces_to = coerces_to or self.COERCES_TO 183 self.binary_coercions = binary_coercions or self.BINARY_COERCIONS 184 185 # Caches the ids of annotated sub-Expressions, to ensure we only visit them once 186 self._visited: t.Set[int] = set() 187 188 def _set_type( 189 self, expression: exp.Expression, target_type: t.Optional[exp.DataType | exp.DataType.Type] 190 ) -> None: 191 expression.type = target_type or exp.DataType.Type.UNKNOWN # type: ignore 192 self._visited.add(id(expression)) 193 194 def annotate(self, expression: E) -> E: 195 for scope in traverse_scope(expression): 196 self.annotate_scope(scope) 197 return self._maybe_annotate(expression) # This takes care of non-traversable expressions 198 199 def annotate_scope(self, scope: Scope) -> None: 200 selects = {} 201 for name, source in scope.sources.items(): 202 if not isinstance(source, Scope): 203 continue 204 if isinstance(source.expression, exp.UDTF): 205 values = [] 206 207 if isinstance(source.expression, exp.Lateral): 208 if isinstance(source.expression.this, exp.Explode): 209 values = [source.expression.this.this] 210 elif isinstance(source.expression, exp.Unnest): 211 values = [source.expression] 212 else: 213 values = source.expression.expressions[0].expressions 214 215 if not values: 216 continue 217 218 selects[name] = { 219 alias: column 220 for alias, column in zip( 221 source.expression.alias_column_names, 222 values, 223 ) 224 } 225 else: 226 selects[name] = { 227 select.alias_or_name: select for select in source.expression.selects 228 } 229 230 # First annotate the current scope's column references 231 for col in scope.columns: 232 if not col.table: 233 continue 234 235 source = scope.sources.get(col.table) 236 if isinstance(source, exp.Table): 237 self._set_type(col, self.schema.get_column_type(source, col)) 238 elif source: 239 if col.table in selects and col.name in selects[col.table]: 240 self._set_type(col, selects[col.table][col.name].type) 241 elif isinstance(source.expression, exp.Unnest): 242 self._set_type(col, source.expression.type) 243 244 # Then (possibly) annotate the remaining expressions in the scope 245 self._maybe_annotate(scope.expression) 246 247 def _maybe_annotate(self, expression: E) -> E: 248 if id(expression) in self._visited: 249 return expression # We've already inferred the expression's type 250 251 annotator = self.annotators.get(expression.__class__) 252 253 return ( 254 annotator(self, expression) 255 if annotator 256 else self._annotate_with_type(expression, exp.DataType.Type.UNKNOWN) 257 ) 258 259 def _annotate_args(self, expression: E) -> E: 260 for value in expression.iter_expressions(): 261 self._maybe_annotate(value) 262 263 return expression 264 265 def _maybe_coerce( 266 self, type1: exp.DataType | exp.DataType.Type, type2: exp.DataType | exp.DataType.Type 267 ) -> exp.DataType | exp.DataType.Type: 268 type1_value = type1.this if isinstance(type1, exp.DataType) else type1 269 type2_value = type2.this if isinstance(type2, exp.DataType) else type2 270 271 # We propagate the NULL / UNKNOWN types upwards if found 272 if exp.DataType.Type.NULL in (type1_value, type2_value): 273 return exp.DataType.Type.NULL 274 if exp.DataType.Type.UNKNOWN in (type1_value, type2_value): 275 return exp.DataType.Type.UNKNOWN 276 277 return type2_value if type2_value in self.coerces_to.get(type1_value, {}) else type1_value 278 279 def _annotate_binary(self, expression: B) -> B: 280 self._annotate_args(expression) 281 282 left, right = expression.left, expression.right 283 left_type, right_type = left.type.this, right.type.this # type: ignore 284 285 if isinstance(expression, exp.Connector): 286 if left_type == exp.DataType.Type.NULL and right_type == exp.DataType.Type.NULL: 287 self._set_type(expression, exp.DataType.Type.NULL) 288 elif exp.DataType.Type.NULL in (left_type, right_type): 289 self._set_type( 290 expression, 291 exp.DataType.build("NULLABLE", expressions=exp.DataType.build("BOOLEAN")), 292 ) 293 else: 294 self._set_type(expression, exp.DataType.Type.BOOLEAN) 295 elif isinstance(expression, exp.Predicate): 296 self._set_type(expression, exp.DataType.Type.BOOLEAN) 297 elif (left_type, right_type) in self.binary_coercions: 298 self._set_type(expression, self.binary_coercions[(left_type, right_type)](left, right)) 299 else: 300 self._set_type(expression, self._maybe_coerce(left_type, right_type)) 301 302 return expression 303 304 def _annotate_unary(self, expression: E) -> E: 305 self._annotate_args(expression) 306 307 if isinstance(expression, exp.Condition) and not isinstance(expression, exp.Paren): 308 self._set_type(expression, exp.DataType.Type.BOOLEAN) 309 else: 310 self._set_type(expression, expression.this.type) 311 312 return expression 313 314 def _annotate_literal(self, expression: exp.Literal) -> exp.Literal: 315 if expression.is_string: 316 self._set_type(expression, exp.DataType.Type.VARCHAR) 317 elif expression.is_int: 318 self._set_type(expression, exp.DataType.Type.INT) 319 else: 320 self._set_type(expression, exp.DataType.Type.DOUBLE) 321 322 return expression 323 324 def _annotate_with_type( 325 self, expression: E, target_type: exp.DataType | exp.DataType.Type 326 ) -> E: 327 self._set_type(expression, target_type) 328 return self._annotate_args(expression) 329 330 @t.no_type_check 331 def _annotate_by_args( 332 self, 333 expression: E, 334 *args: str, 335 promote: bool = False, 336 array: bool = False, 337 ) -> E: 338 self._annotate_args(expression) 339 340 expressions: t.List[exp.Expression] = [] 341 for arg in args: 342 arg_expr = expression.args.get(arg) 343 expressions.extend(expr for expr in ensure_list(arg_expr) if expr) 344 345 last_datatype = None 346 for expr in expressions: 347 expr_type = expr.type 348 349 # Stop at the first nested data type found - we don't want to _maybe_coerce nested types 350 if expr_type.args.get("nested"): 351 last_datatype = expr_type 352 break 353 354 if not expr_type.is_type(exp.DataType.Type.NULL, exp.DataType.Type.UNKNOWN): 355 last_datatype = self._maybe_coerce(last_datatype or expr_type, expr_type) 356 357 self._set_type(expression, last_datatype or exp.DataType.Type.UNKNOWN) 358 359 if promote: 360 if expression.type.this in exp.DataType.INTEGER_TYPES: 361 self._set_type(expression, exp.DataType.Type.BIGINT) 362 elif expression.type.this in exp.DataType.FLOAT_TYPES: 363 self._set_type(expression, exp.DataType.Type.DOUBLE) 364 365 if array: 366 self._set_type( 367 expression, 368 exp.DataType( 369 this=exp.DataType.Type.ARRAY, expressions=[expression.type], nested=True 370 ), 371 ) 372 373 return expression 374 375 def _annotate_timeunit( 376 self, expression: exp.TimeUnit | exp.DateTrunc 377 ) -> exp.TimeUnit | exp.DateTrunc: 378 self._annotate_args(expression) 379 380 if expression.this.type.this in exp.DataType.TEXT_TYPES: 381 datatype = _coerce_date_literal(expression.this, expression.unit) 382 elif expression.this.type.this in exp.DataType.TEMPORAL_TYPES: 383 datatype = _coerce_date(expression.this, expression.unit) 384 else: 385 datatype = exp.DataType.Type.UNKNOWN 386 387 self._set_type(expression, datatype) 388 return expression 389 390 def _annotate_bracket(self, expression: exp.Bracket) -> exp.Bracket: 391 self._annotate_args(expression) 392 393 bracket_arg = expression.expressions[0] 394 this = expression.this 395 396 if isinstance(bracket_arg, exp.Slice): 397 self._set_type(expression, this.type) 398 elif this.type.is_type(exp.DataType.Type.ARRAY): 399 self._set_type(expression, seq_get(this.type.expressions, 0)) 400 elif isinstance(this, (exp.Map, exp.VarMap)) and bracket_arg in this.keys: 401 index = this.keys.index(bracket_arg) 402 value = seq_get(this.values, index) 403 self._set_type(expression, value.type if value else None) 404 else: 405 self._set_type(expression, exp.DataType.Type.UNKNOWN) 406 407 return expression 408 409 def _annotate_div(self, expression: exp.Div) -> exp.Div: 410 self._annotate_args(expression) 411 412 left_type, right_type = expression.left.type.this, expression.right.type.this # type: ignore 413 414 if ( 415 expression.args.get("typed") 416 and left_type in exp.DataType.INTEGER_TYPES 417 and right_type in exp.DataType.INTEGER_TYPES 418 ): 419 self._set_type(expression, exp.DataType.Type.BIGINT) 420 else: 421 self._set_type(expression, self._maybe_coerce(left_type, right_type)) 422 if expression.type and expression.type.this not in exp.DataType.REAL_TYPES: 423 self._set_type( 424 expression, self._maybe_coerce(expression.type, exp.DataType.Type.DOUBLE) 425 ) 426 427 return expression 428 429 def _annotate_dot(self, expression: exp.Dot) -> exp.Dot: 430 self._annotate_args(expression) 431 self._set_type(expression, None) 432 this_type = expression.this.type 433 434 if this_type and this_type.is_type(exp.DataType.Type.STRUCT): 435 for e in this_type.expressions: 436 if e.name == expression.expression.name: 437 self._set_type(expression, e.kind) 438 break 439 440 return expression 441 442 def _annotate_explode(self, expression: exp.Explode) -> exp.Explode: 443 self._annotate_args(expression) 444 self._set_type(expression, seq_get(expression.this.type.expressions, 0)) 445 return expression 446 447 def _annotate_unnest(self, expression: exp.Unnest) -> exp.Unnest: 448 self._annotate_args(expression) 449 child = seq_get(expression.expressions, 0) 450 451 if child and child.is_type(exp.DataType.Type.ARRAY): 452 expr_type = seq_get(child.type.expressions, 0) 453 else: 454 expr_type = None 455 456 self._set_type(expression, expr_type) 457 return expression 458 459 def _annotate_struct_value( 460 self, expression: exp.Expression 461 ) -> t.Optional[exp.DataType] | exp.ColumnDef: 462 alias = expression.args.get("alias") 463 if alias: 464 return exp.ColumnDef(this=alias.copy(), kind=expression.type) 465 466 # Case: key = value or key := value 467 if expression.expression: 468 return exp.ColumnDef(this=expression.this.copy(), kind=expression.expression.type) 469 470 return expression.type 471 472 def _annotate_struct(self, expression: exp.Struct) -> exp.Struct: 473 self._annotate_args(expression) 474 self._set_type( 475 expression, 476 exp.DataType( 477 this=exp.DataType.Type.STRUCT, 478 expressions=[self._annotate_struct_value(expr) for expr in expression.expressions], 479 nested=True, 480 ), 481 ) 482 return expression 483 484 @t.overload 485 def _annotate_map(self, expression: exp.Map) -> exp.Map: ... 486 487 @t.overload 488 def _annotate_map(self, expression: exp.VarMap) -> exp.VarMap: ... 489 490 def _annotate_map(self, expression): 491 self._annotate_args(expression) 492 493 keys = expression.args.get("keys") 494 values = expression.args.get("values") 495 496 map_type = exp.DataType(this=exp.DataType.Type.MAP) 497 if isinstance(keys, exp.Array) and isinstance(values, exp.Array): 498 key_type = seq_get(keys.type.expressions, 0) or exp.DataType.Type.UNKNOWN 499 value_type = seq_get(values.type.expressions, 0) or exp.DataType.Type.UNKNOWN 500 501 if key_type != exp.DataType.Type.UNKNOWN and value_type != exp.DataType.Type.UNKNOWN: 502 map_type.set("expressions", [key_type, value_type]) 503 map_type.set("nested", True) 504 505 self._set_type(expression, map_type) 506 return expression 507 508 def _annotate_to_map(self, expression: exp.ToMap) -> exp.ToMap: 509 self._annotate_args(expression) 510 511 map_type = exp.DataType(this=exp.DataType.Type.MAP) 512 arg = expression.this 513 if arg.is_type(exp.DataType.Type.STRUCT): 514 for coldef in arg.type.expressions: 515 kind = coldef.kind 516 if kind != exp.DataType.Type.UNKNOWN: 517 map_type.set("expressions", [exp.DataType.build("varchar"), kind]) 518 map_type.set("nested", True) 519 break 520 521 self._set_type(expression, map_type) 522 return expression 523 524 def _annotate_extract(self, expression: exp.Extract) -> exp.Extract: 525 self._annotate_args(expression) 526 part = expression.name 527 if part == "TIME": 528 self._set_type(expression, exp.DataType.Type.TIME) 529 elif part == "DATE": 530 self._set_type(expression, exp.DataType.Type.DATE) 531 else: 532 self._set_type(expression, exp.DataType.Type.INT) 533 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.Dialect, Type[sqlglot.dialects.dialect.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: t.Optional[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) 60 61 return TypeAnnotator(schema, annotators, coerces_to, dialect=dialect).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:
135class TypeAnnotator(metaclass=_TypeAnnotator): 136 NESTED_TYPES = { 137 exp.DataType.Type.ARRAY, 138 } 139 140 # Specifies what types a given type can be coerced into (autofilled) 141 COERCES_TO: t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]] = {} 142 143 # Coercion functions for binary operations. 144 # Map of type pairs to a callable that takes both sides of the binary operation and returns the resulting type. 145 BINARY_COERCIONS: BinaryCoercions = { 146 **swap_all( 147 { 148 (t, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date_literal( 149 l, r.args.get("unit") 150 ) 151 for t in exp.DataType.TEXT_TYPES 152 } 153 ), 154 **swap_all( 155 { 156 # text + numeric will yield the numeric type to match most dialects' semantics 157 (text, numeric): lambda l, r: t.cast( 158 exp.DataType.Type, l.type if l.type in exp.DataType.NUMERIC_TYPES else r.type 159 ) 160 for text in exp.DataType.TEXT_TYPES 161 for numeric in exp.DataType.NUMERIC_TYPES 162 } 163 ), 164 **swap_all( 165 { 166 (exp.DataType.Type.DATE, exp.DataType.Type.INTERVAL): lambda l, r: _coerce_date( 167 l, r.args.get("unit") 168 ), 169 } 170 ), 171 } 172 173 def __init__( 174 self, 175 schema: Schema, 176 annotators: t.Optional[AnnotatorsType] = None, 177 coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None, 178 binary_coercions: t.Optional[BinaryCoercions] = None, 179 dialect: t.Optional[DialectType] = None, 180 ) -> None: 181 self.schema = schema 182 self.annotators = annotators or Dialect.get_or_raise(dialect).ANNOTATORS 183 self.coerces_to = coerces_to or self.COERCES_TO 184 self.binary_coercions = binary_coercions or self.BINARY_COERCIONS 185 186 # Caches the ids of annotated sub-Expressions, to ensure we only visit them once 187 self._visited: t.Set[int] = set() 188 189 def _set_type( 190 self, expression: exp.Expression, target_type: t.Optional[exp.DataType | exp.DataType.Type] 191 ) -> None: 192 expression.type = target_type or exp.DataType.Type.UNKNOWN # type: ignore 193 self._visited.add(id(expression)) 194 195 def annotate(self, expression: E) -> E: 196 for scope in traverse_scope(expression): 197 self.annotate_scope(scope) 198 return self._maybe_annotate(expression) # This takes care of non-traversable expressions 199 200 def annotate_scope(self, scope: Scope) -> None: 201 selects = {} 202 for name, source in scope.sources.items(): 203 if not isinstance(source, Scope): 204 continue 205 if isinstance(source.expression, exp.UDTF): 206 values = [] 207 208 if isinstance(source.expression, exp.Lateral): 209 if isinstance(source.expression.this, exp.Explode): 210 values = [source.expression.this.this] 211 elif isinstance(source.expression, exp.Unnest): 212 values = [source.expression] 213 else: 214 values = source.expression.expressions[0].expressions 215 216 if not values: 217 continue 218 219 selects[name] = { 220 alias: column 221 for alias, column in zip( 222 source.expression.alias_column_names, 223 values, 224 ) 225 } 226 else: 227 selects[name] = { 228 select.alias_or_name: select for select in source.expression.selects 229 } 230 231 # First annotate the current scope's column references 232 for col in scope.columns: 233 if not col.table: 234 continue 235 236 source = scope.sources.get(col.table) 237 if isinstance(source, exp.Table): 238 self._set_type(col, self.schema.get_column_type(source, col)) 239 elif source: 240 if col.table in selects and col.name in selects[col.table]: 241 self._set_type(col, selects[col.table][col.name].type) 242 elif isinstance(source.expression, exp.Unnest): 243 self._set_type(col, source.expression.type) 244 245 # Then (possibly) annotate the remaining expressions in the scope 246 self._maybe_annotate(scope.expression) 247 248 def _maybe_annotate(self, expression: E) -> E: 249 if id(expression) in self._visited: 250 return expression # We've already inferred the expression's type 251 252 annotator = self.annotators.get(expression.__class__) 253 254 return ( 255 annotator(self, expression) 256 if annotator 257 else self._annotate_with_type(expression, exp.DataType.Type.UNKNOWN) 258 ) 259 260 def _annotate_args(self, expression: E) -> E: 261 for value in expression.iter_expressions(): 262 self._maybe_annotate(value) 263 264 return expression 265 266 def _maybe_coerce( 267 self, type1: exp.DataType | exp.DataType.Type, type2: exp.DataType | exp.DataType.Type 268 ) -> exp.DataType | exp.DataType.Type: 269 type1_value = type1.this if isinstance(type1, exp.DataType) else type1 270 type2_value = type2.this if isinstance(type2, exp.DataType) else type2 271 272 # We propagate the NULL / UNKNOWN types upwards if found 273 if exp.DataType.Type.NULL in (type1_value, type2_value): 274 return exp.DataType.Type.NULL 275 if exp.DataType.Type.UNKNOWN in (type1_value, type2_value): 276 return exp.DataType.Type.UNKNOWN 277 278 return type2_value if type2_value in self.coerces_to.get(type1_value, {}) else type1_value 279 280 def _annotate_binary(self, expression: B) -> B: 281 self._annotate_args(expression) 282 283 left, right = expression.left, expression.right 284 left_type, right_type = left.type.this, right.type.this # type: ignore 285 286 if isinstance(expression, exp.Connector): 287 if left_type == exp.DataType.Type.NULL and right_type == exp.DataType.Type.NULL: 288 self._set_type(expression, exp.DataType.Type.NULL) 289 elif exp.DataType.Type.NULL in (left_type, right_type): 290 self._set_type( 291 expression, 292 exp.DataType.build("NULLABLE", expressions=exp.DataType.build("BOOLEAN")), 293 ) 294 else: 295 self._set_type(expression, exp.DataType.Type.BOOLEAN) 296 elif isinstance(expression, exp.Predicate): 297 self._set_type(expression, exp.DataType.Type.BOOLEAN) 298 elif (left_type, right_type) in self.binary_coercions: 299 self._set_type(expression, self.binary_coercions[(left_type, right_type)](left, right)) 300 else: 301 self._set_type(expression, self._maybe_coerce(left_type, right_type)) 302 303 return expression 304 305 def _annotate_unary(self, expression: E) -> E: 306 self._annotate_args(expression) 307 308 if isinstance(expression, exp.Condition) and not isinstance(expression, exp.Paren): 309 self._set_type(expression, exp.DataType.Type.BOOLEAN) 310 else: 311 self._set_type(expression, expression.this.type) 312 313 return expression 314 315 def _annotate_literal(self, expression: exp.Literal) -> exp.Literal: 316 if expression.is_string: 317 self._set_type(expression, exp.DataType.Type.VARCHAR) 318 elif expression.is_int: 319 self._set_type(expression, exp.DataType.Type.INT) 320 else: 321 self._set_type(expression, exp.DataType.Type.DOUBLE) 322 323 return expression 324 325 def _annotate_with_type( 326 self, expression: E, target_type: exp.DataType | exp.DataType.Type 327 ) -> E: 328 self._set_type(expression, target_type) 329 return self._annotate_args(expression) 330 331 @t.no_type_check 332 def _annotate_by_args( 333 self, 334 expression: E, 335 *args: str, 336 promote: bool = False, 337 array: bool = False, 338 ) -> E: 339 self._annotate_args(expression) 340 341 expressions: t.List[exp.Expression] = [] 342 for arg in args: 343 arg_expr = expression.args.get(arg) 344 expressions.extend(expr for expr in ensure_list(arg_expr) if expr) 345 346 last_datatype = None 347 for expr in expressions: 348 expr_type = expr.type 349 350 # Stop at the first nested data type found - we don't want to _maybe_coerce nested types 351 if expr_type.args.get("nested"): 352 last_datatype = expr_type 353 break 354 355 if not expr_type.is_type(exp.DataType.Type.NULL, exp.DataType.Type.UNKNOWN): 356 last_datatype = self._maybe_coerce(last_datatype or expr_type, expr_type) 357 358 self._set_type(expression, last_datatype or exp.DataType.Type.UNKNOWN) 359 360 if promote: 361 if expression.type.this in exp.DataType.INTEGER_TYPES: 362 self._set_type(expression, exp.DataType.Type.BIGINT) 363 elif expression.type.this in exp.DataType.FLOAT_TYPES: 364 self._set_type(expression, exp.DataType.Type.DOUBLE) 365 366 if array: 367 self._set_type( 368 expression, 369 exp.DataType( 370 this=exp.DataType.Type.ARRAY, expressions=[expression.type], nested=True 371 ), 372 ) 373 374 return expression 375 376 def _annotate_timeunit( 377 self, expression: exp.TimeUnit | exp.DateTrunc 378 ) -> exp.TimeUnit | exp.DateTrunc: 379 self._annotate_args(expression) 380 381 if expression.this.type.this in exp.DataType.TEXT_TYPES: 382 datatype = _coerce_date_literal(expression.this, expression.unit) 383 elif expression.this.type.this in exp.DataType.TEMPORAL_TYPES: 384 datatype = _coerce_date(expression.this, expression.unit) 385 else: 386 datatype = exp.DataType.Type.UNKNOWN 387 388 self._set_type(expression, datatype) 389 return expression 390 391 def _annotate_bracket(self, expression: exp.Bracket) -> exp.Bracket: 392 self._annotate_args(expression) 393 394 bracket_arg = expression.expressions[0] 395 this = expression.this 396 397 if isinstance(bracket_arg, exp.Slice): 398 self._set_type(expression, this.type) 399 elif this.type.is_type(exp.DataType.Type.ARRAY): 400 self._set_type(expression, seq_get(this.type.expressions, 0)) 401 elif isinstance(this, (exp.Map, exp.VarMap)) and bracket_arg in this.keys: 402 index = this.keys.index(bracket_arg) 403 value = seq_get(this.values, index) 404 self._set_type(expression, value.type if value else None) 405 else: 406 self._set_type(expression, exp.DataType.Type.UNKNOWN) 407 408 return expression 409 410 def _annotate_div(self, expression: exp.Div) -> exp.Div: 411 self._annotate_args(expression) 412 413 left_type, right_type = expression.left.type.this, expression.right.type.this # type: ignore 414 415 if ( 416 expression.args.get("typed") 417 and left_type in exp.DataType.INTEGER_TYPES 418 and right_type in exp.DataType.INTEGER_TYPES 419 ): 420 self._set_type(expression, exp.DataType.Type.BIGINT) 421 else: 422 self._set_type(expression, self._maybe_coerce(left_type, right_type)) 423 if expression.type and expression.type.this not in exp.DataType.REAL_TYPES: 424 self._set_type( 425 expression, self._maybe_coerce(expression.type, exp.DataType.Type.DOUBLE) 426 ) 427 428 return expression 429 430 def _annotate_dot(self, expression: exp.Dot) -> exp.Dot: 431 self._annotate_args(expression) 432 self._set_type(expression, None) 433 this_type = expression.this.type 434 435 if this_type and this_type.is_type(exp.DataType.Type.STRUCT): 436 for e in this_type.expressions: 437 if e.name == expression.expression.name: 438 self._set_type(expression, e.kind) 439 break 440 441 return expression 442 443 def _annotate_explode(self, expression: exp.Explode) -> exp.Explode: 444 self._annotate_args(expression) 445 self._set_type(expression, seq_get(expression.this.type.expressions, 0)) 446 return expression 447 448 def _annotate_unnest(self, expression: exp.Unnest) -> exp.Unnest: 449 self._annotate_args(expression) 450 child = seq_get(expression.expressions, 0) 451 452 if child and child.is_type(exp.DataType.Type.ARRAY): 453 expr_type = seq_get(child.type.expressions, 0) 454 else: 455 expr_type = None 456 457 self._set_type(expression, expr_type) 458 return expression 459 460 def _annotate_struct_value( 461 self, expression: exp.Expression 462 ) -> t.Optional[exp.DataType] | exp.ColumnDef: 463 alias = expression.args.get("alias") 464 if alias: 465 return exp.ColumnDef(this=alias.copy(), kind=expression.type) 466 467 # Case: key = value or key := value 468 if expression.expression: 469 return exp.ColumnDef(this=expression.this.copy(), kind=expression.expression.type) 470 471 return expression.type 472 473 def _annotate_struct(self, expression: exp.Struct) -> exp.Struct: 474 self._annotate_args(expression) 475 self._set_type( 476 expression, 477 exp.DataType( 478 this=exp.DataType.Type.STRUCT, 479 expressions=[self._annotate_struct_value(expr) for expr in expression.expressions], 480 nested=True, 481 ), 482 ) 483 return expression 484 485 @t.overload 486 def _annotate_map(self, expression: exp.Map) -> exp.Map: ... 487 488 @t.overload 489 def _annotate_map(self, expression: exp.VarMap) -> exp.VarMap: ... 490 491 def _annotate_map(self, expression): 492 self._annotate_args(expression) 493 494 keys = expression.args.get("keys") 495 values = expression.args.get("values") 496 497 map_type = exp.DataType(this=exp.DataType.Type.MAP) 498 if isinstance(keys, exp.Array) and isinstance(values, exp.Array): 499 key_type = seq_get(keys.type.expressions, 0) or exp.DataType.Type.UNKNOWN 500 value_type = seq_get(values.type.expressions, 0) or exp.DataType.Type.UNKNOWN 501 502 if key_type != exp.DataType.Type.UNKNOWN and value_type != exp.DataType.Type.UNKNOWN: 503 map_type.set("expressions", [key_type, value_type]) 504 map_type.set("nested", True) 505 506 self._set_type(expression, map_type) 507 return expression 508 509 def _annotate_to_map(self, expression: exp.ToMap) -> exp.ToMap: 510 self._annotate_args(expression) 511 512 map_type = exp.DataType(this=exp.DataType.Type.MAP) 513 arg = expression.this 514 if arg.is_type(exp.DataType.Type.STRUCT): 515 for coldef in arg.type.expressions: 516 kind = coldef.kind 517 if kind != exp.DataType.Type.UNKNOWN: 518 map_type.set("expressions", [exp.DataType.build("varchar"), kind]) 519 map_type.set("nested", True) 520 break 521 522 self._set_type(expression, map_type) 523 return expression 524 525 def _annotate_extract(self, expression: exp.Extract) -> exp.Extract: 526 self._annotate_args(expression) 527 part = expression.name 528 if part == "TIME": 529 self._set_type(expression, exp.DataType.Type.TIME) 530 elif part == "DATE": 531 self._set_type(expression, exp.DataType.Type.DATE) 532 else: 533 self._set_type(expression, exp.DataType.Type.INT) 534 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, dialect: Union[str, sqlglot.dialects.dialect.Dialect, Type[sqlglot.dialects.dialect.Dialect], NoneType] = None)
173 def __init__( 174 self, 175 schema: Schema, 176 annotators: t.Optional[AnnotatorsType] = None, 177 coerces_to: t.Optional[t.Dict[exp.DataType.Type, t.Set[exp.DataType.Type]]] = None, 178 binary_coercions: t.Optional[BinaryCoercions] = None, 179 dialect: t.Optional[DialectType] = None, 180 ) -> None: 181 self.schema = schema 182 self.annotators = annotators or Dialect.get_or_raise(dialect).ANNOTATORS 183 self.coerces_to = coerces_to or self.COERCES_TO 184 self.binary_coercions = binary_coercions or self.BINARY_COERCIONS 185 186 # Caches the ids of annotated sub-Expressions, to ensure we only visit them once 187 self._visited: t.Set[int] = set()
COERCES_TO: Dict[sqlglot.expressions.DataType.Type, Set[sqlglot.expressions.DataType.Type]] =
{<Type.TEXT: 'TEXT'>: set(), <Type.NVARCHAR: 'NVARCHAR'>: {<Type.TEXT: 'TEXT'>}, <Type.VARCHAR: 'VARCHAR'>: {<Type.TEXT: 'TEXT'>, <Type.NVARCHAR: 'NVARCHAR'>}, <Type.NCHAR: 'NCHAR'>: {<Type.TEXT: 'TEXT'>, <Type.NVARCHAR: 'NVARCHAR'>, <Type.VARCHAR: 'VARCHAR'>}, <Type.CHAR: 'CHAR'>: {<Type.TEXT: 'TEXT'>, <Type.NVARCHAR: 'NVARCHAR'>, <Type.VARCHAR: 'VARCHAR'>, <Type.NCHAR: 'NCHAR'>}, <Type.DOUBLE: 'DOUBLE'>: set(), <Type.FLOAT: 'FLOAT'>: {<Type.DOUBLE: 'DOUBLE'>}, <Type.DECIMAL: 'DECIMAL'>: {<Type.DOUBLE: 'DOUBLE'>, <Type.FLOAT: 'FLOAT'>}, <Type.BIGINT: 'BIGINT'>: {<Type.DOUBLE: 'DOUBLE'>, <Type.FLOAT: 'FLOAT'>, <Type.DECIMAL: 'DECIMAL'>}, <Type.INT: 'INT'>: {<Type.DOUBLE: 'DOUBLE'>, <Type.BIGINT: 'BIGINT'>, <Type.FLOAT: 'FLOAT'>, <Type.DECIMAL: 'DECIMAL'>}, <Type.SMALLINT: 'SMALLINT'>: {<Type.DOUBLE: 'DOUBLE'>, <Type.DECIMAL: 'DECIMAL'>, <Type.INT: 'INT'>, <Type.FLOAT: 'FLOAT'>, <Type.BIGINT: 'BIGINT'>}, <Type.TINYINT: 'TINYINT'>: {<Type.DOUBLE: 'DOUBLE'>, <Type.SMALLINT: 'SMALLINT'>, <Type.DECIMAL: 'DECIMAL'>, <Type.INT: 'INT'>, <Type.FLOAT: 'FLOAT'>, <Type.BIGINT: 'BIGINT'>}, <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>: set(), <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>: {<Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>}, <Type.TIMESTAMP: 'TIMESTAMP'>: {<Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>}, <Type.DATETIME: 'DATETIME'>: {<Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.TIMESTAMP: 'TIMESTAMP'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>}, <Type.DATE: 'DATE'>: {<Type.DATETIME: 'DATETIME'>, <Type.TIMESTAMPLTZ: 'TIMESTAMPLTZ'>, <Type.TIMESTAMP: 'TIMESTAMP'>, <Type.TIMESTAMPTZ: 'TIMESTAMPTZ'>}}
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.NAME: 'NAME'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.CHAR: 'CHAR'>): <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.INTERVAL: 'INTERVAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NVARCHAR: 'NVARCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.CHAR: 'CHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NAME: 'NAME'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TEXT: 'TEXT'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.VARCHAR: 'VARCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.SMALLINT: 'SMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.MEDIUMINT: 'MEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.USMALLINT: 'USMALLINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT: 'UINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.SMALLMONEY: 'SMALLMONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIGINT: 'BIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT: 'INT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UMEDIUMINT: 'UMEDIUMINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UTINYINT: 'UTINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT256: 'INT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIT: 'BIT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.FLOAT: 'FLOAT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.INT128: 'INT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DECIMAL: 'DECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.DOUBLE: 'DOUBLE'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.TINYINT: 'TINYINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UBIGINT: 'UBIGINT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.MONEY: 'MONEY'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UDECIMAL: 'UDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT256: 'UINT256'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.BIGDECIMAL: 'BIGDECIMAL'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.NCHAR: 'NCHAR'>, <Type.UINT128: 'UINT128'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NVARCHAR: 'NVARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.CHAR: 'CHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NAME: 'NAME'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.TEXT: 'TEXT'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.VARCHAR: 'VARCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLINT: 'SMALLINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MEDIUMINT: 'MEDIUMINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.USMALLINT: 'USMALLINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT: 'UINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.SMALLMONEY: 'SMALLMONEY'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGINT: 'BIGINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT: 'INT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UMEDIUMINT: 'UMEDIUMINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UTINYINT: 'UTINYINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT256: 'INT256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIT: 'BIT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.FLOAT: 'FLOAT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.INT128: 'INT128'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DECIMAL: 'DECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DOUBLE: 'DOUBLE'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.TINYINT: 'TINYINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UBIGINT: 'UBIGINT'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.MONEY: 'MONEY'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UDECIMAL: 'UDECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT256: 'UINT256'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.BIGDECIMAL: 'BIGDECIMAL'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.UINT128: 'UINT128'>, <Type.NCHAR: 'NCHAR'>): <function TypeAnnotator.<dictcomp>.<lambda>>, (<Type.DATE: 'DATE'>, <Type.INTERVAL: 'INTERVAL'>): <function TypeAnnotator.<lambda>>, (<Type.INTERVAL: 'INTERVAL'>, <Type.DATE: 'DATE'>): <function TypeAnnotator.<lambda>>}
200 def annotate_scope(self, scope: Scope) -> None: 201 selects = {} 202 for name, source in scope.sources.items(): 203 if not isinstance(source, Scope): 204 continue 205 if isinstance(source.expression, exp.UDTF): 206 values = [] 207 208 if isinstance(source.expression, exp.Lateral): 209 if isinstance(source.expression.this, exp.Explode): 210 values = [source.expression.this.this] 211 elif isinstance(source.expression, exp.Unnest): 212 values = [source.expression] 213 else: 214 values = source.expression.expressions[0].expressions 215 216 if not values: 217 continue 218 219 selects[name] = { 220 alias: column 221 for alias, column in zip( 222 source.expression.alias_column_names, 223 values, 224 ) 225 } 226 else: 227 selects[name] = { 228 select.alias_or_name: select for select in source.expression.selects 229 } 230 231 # First annotate the current scope's column references 232 for col in scope.columns: 233 if not col.table: 234 continue 235 236 source = scope.sources.get(col.table) 237 if isinstance(source, exp.Table): 238 self._set_type(col, self.schema.get_column_type(source, col)) 239 elif source: 240 if col.table in selects and col.name in selects[col.table]: 241 self._set_type(col, selects[col.table][col.name].type) 242 elif isinstance(source.expression, exp.Unnest): 243 self._set_type(col, source.expression.type) 244 245 # Then (possibly) annotate the remaining expressions in the scope 246 self._maybe_annotate(scope.expression)