def scalar_type_to_python_type( stype: s_types.Type, schema: s_schema.Schema, ) -> type: for basetype_name, pytype in typemap.items(): basetype = schema.get(basetype_name, type=s_obj.InheritingObject) if stype.issubclass(schema, basetype): return pytype if stype.is_enum(schema): return str raise UnsupportedExpressionError( f'{stype.get_displayname(schema)} is not representable in Python')
def compile_cast( ir_expr: Union[irast.Set, irast.Expr], new_stype: s_types.Type, *, srcctx: Optional[parsing.ParserContext], ctx: context.ContextLevel, cardinality_mod: Optional[qlast.CardinalityModifier] = None ) -> irast.Set: if isinstance(ir_expr, irast.EmptySet): # For the common case of casting an empty set, we simply # generate a new EmptySet node of the requested type. return setgen.new_empty_set( stype=new_stype, alias=ir_expr.path_id.target_name_hint.name, ctx=ctx, srcctx=ir_expr.context) elif irutils.is_untyped_empty_array_expr(ir_expr): # Ditto for empty arrays. new_typeref = typegen.type_to_typeref(new_stype, ctx.env) return setgen.ensure_set(irast.Array(elements=[], typeref=new_typeref), ctx=ctx) ir_set = setgen.ensure_set(ir_expr, ctx=ctx) orig_stype = setgen.get_set_type(ir_set, ctx=ctx) if (orig_stype == new_stype and cardinality_mod is not qlast.CardinalityModifier.Required): return ir_set elif orig_stype.is_object_type() and new_stype.is_object_type(): # Object types cannot be cast between themselves, # as cast is a _constructor_ operation, and the only # valid way to construct an object is to INSERT it. raise errors.QueryError( f'cannot cast object type ' f'{orig_stype.get_displayname(ctx.env.schema)!r} ' f'to {new_stype.get_displayname(ctx.env.schema)!r}, use ' f'`...[IS {new_stype.get_displayname(ctx.env.schema)}]` instead', context=srcctx) if isinstance(ir_set.expr, irast.Array): return _cast_array_literal(ir_set, orig_stype, new_stype, srcctx=srcctx, ctx=ctx) elif orig_stype.is_tuple(ctx.env.schema): return _cast_tuple(ir_set, orig_stype, new_stype, srcctx=srcctx, ctx=ctx) elif orig_stype.issubclass(ctx.env.schema, new_stype): # The new type is a supertype of the old type, # and is always a wider domain, so we simply reassign # the stype. return _inheritance_cast_to_ir(ir_set, orig_stype, new_stype, cardinality_mod=cardinality_mod, ctx=ctx) elif new_stype.issubclass(ctx.env.schema, orig_stype): # The new type is a subtype, so may potentially have # a more restrictive domain, generate a cast call. return _inheritance_cast_to_ir(ir_set, orig_stype, new_stype, cardinality_mod=cardinality_mod, ctx=ctx) elif orig_stype.is_array(): return _cast_array(ir_set, orig_stype, new_stype, srcctx=srcctx, ctx=ctx) else: json_t = ctx.env.get_track_schema_type('std::json') if (new_stype.issubclass(ctx.env.schema, json_t) and ir_set.path_id.is_objtype_path()): # JSON casts of objects are special: we want the full shape # and not just an identity. with ctx.new() as subctx: subctx.implicit_id_in_shapes = False subctx.implicit_tid_in_shapes = False viewgen.compile_view_shapes(ir_set, ctx=subctx) elif (orig_stype.issubclass(ctx.env.schema, json_t) and new_stype.is_enum(ctx.env.schema)): # Casts from json to enums need some special handling # here, where we have access to the enum type. Just turn # it into json->str and str->enum. str_typ = ctx.env.get_track_schema_type('std::str') str_ir = compile_cast(ir_expr, str_typ, srcctx=srcctx, ctx=ctx) return compile_cast(str_ir, new_stype, cardinality_mod=cardinality_mod, srcctx=srcctx, ctx=ctx) elif (orig_stype.issubclass(ctx.env.schema, json_t) and isinstance(new_stype, s_types.Array) and not new_stype.get_subtypes(ctx.env.schema)[0].issubclass( ctx.env.schema, json_t)): # Turn casts from json->array<T> into json->array<json> # and array<json>->array<T>. ctx.env.schema, json_array_typ = s_types.Array.from_subtypes( ctx.env.schema, [json_t]) json_array_ir = compile_cast(ir_expr, json_array_typ, srcctx=srcctx, ctx=ctx) return compile_cast(json_array_ir, new_stype, cardinality_mod=cardinality_mod, srcctx=srcctx, ctx=ctx) elif (orig_stype.issubclass(ctx.env.schema, json_t) and isinstance(new_stype, s_types.Tuple)): return _cast_json_to_tuple(ir_set, orig_stype, new_stype, srcctx=srcctx, ctx=ctx) return _compile_cast(ir_expr, orig_stype, new_stype, cardinality_mod=cardinality_mod, srcctx=srcctx, ctx=ctx)