示例#1
0
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')
示例#2
0
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)