Пример #1
0
def make_array(
        elements: typing.List[irast.Base], *,
        ctx: context.ContextLevel) -> irast.Array:

    arr = irast.Array(elements=elements)
    arr.stype = inference.infer_type(arr, env=ctx.env)
    return arr
Пример #2
0
def ql_typeref_to_ir_typeref(
        ql_t: qlast.TypeExpr, *,
        ctx: context.ContextLevel) -> typing.Union[irast.Array, irast.TypeRef]:

    types = _ql_typeexpr_to_ir_typeref(ql_t, ctx=ctx)
    if len(types) > 1:
        return irast.Array(elements=types)
    else:
        return types[0]
Пример #3
0
def compile_Array(expr: qlast.Base, *,
                  ctx: context.ContextLevel) -> irast.Base:
    elements = [dispatch.compile(e, ctx=ctx) for e in expr.elements]
    # check that none of the elements are themselves arrays
    for el, expr_el in zip(elements, expr.elements):
        if isinstance(irutils.infer_type(el, ctx.schema), s_types.Array):
            raise errors.EdgeQLError(f'nested arrays are not supported',
                                     context=expr_el.context)
    return setgen.generated_set(irast.Array(elements=elements), ctx=ctx)
Пример #4
0
def compile_TypeCast(expr: qlast.Base, *,
                     ctx: context.ContextLevel) -> irast.Base:
    target_typeref = typegen.ql_typeref_to_ir_typeref(expr.type, ctx=ctx)

    if (isinstance(expr.expr, qlast.Array) and not expr.expr.elements
            and target_typeref.maintype == 'array'):
        ir_expr = irast.Array()

    elif isinstance(expr.expr, qlast.Parameter):
        pt = typegen.ql_typeref_to_type(expr.type, ctx=ctx)
        param_name = expr.expr.name
        if param_name not in ctx.env.query_parameters:
            if ctx.env.query_parameters:
                first_key: str = next(iter(ctx.env.query_parameters))
                if first_key.isdecimal():
                    if not param_name.isdecimal():
                        raise errors.QueryError(
                            f'expected a positional argument',
                            context=expr.expr.context)
                else:
                    if param_name.isdecimal():
                        raise errors.QueryError(f'expected a named argument',
                                                context=expr.expr.context)
            ctx.env.query_parameters[param_name] = pt
        else:
            param_first_type = ctx.env.query_parameters[param_name]
            if not param_first_type.explicitly_castable_to(pt, ctx.env.schema):
                raise errors.QueryError(
                    f'cannot cast '
                    f'{param_first_type.get_displayname(ctx.env.schema)} to '
                    f'{pt.get_displayname(ctx.env.schema)}',
                    context=expr.expr.context)

        param = irast.Parameter(stype=pt,
                                name=param_name,
                                context=expr.expr.context)
        return setgen.ensure_set(param, ctx=ctx)

    else:
        with ctx.new() as subctx:
            # We use "exposed" mode in case this is a type of a cast
            # that wants view shapes, e.g. a std::json cast.  We do
            # this wholesale to support tuple and array casts without
            # having to analyze the target type (which is cumbersome
            # in QL AST).
            subctx.expr_exposed = True
            ir_expr = dispatch.compile(expr.expr, ctx=subctx)

    new_stype = typegen.ql_typeref_to_type(expr.type, ctx=ctx)
    return cast.compile_cast(ir_expr,
                             new_stype,
                             ctx=ctx,
                             srcctx=expr.expr.context)
Пример #5
0
def compile_TypeCast(expr: qlast.Base, *,
                     ctx: context.ContextLevel) -> irast.Base:
    maintype = expr.type.maintype

    if (isinstance(expr.expr, qlast.EmptyCollection)
            and maintype.name == 'array'):
        ir_expr = irast.Array()
    else:
        ir_expr = dispatch.compile(expr.expr, ctx=ctx)

    return setgen.ensure_set(_cast_expr(expr.type,
                                        ir_expr,
                                        ctx=ctx,
                                        source_context=expr.expr.context),
                             ctx=ctx)
Пример #6
0
def process_type_ref_expr(
        expr: irast.Base) -> typing.Union[irast.Array, irast.TypeRef]:
    if isinstance(expr.expr, irast.Tuple):
        elems = []

        for elem in expr.expr.elements:
            ref_elem = process_type_ref_elem(elem.val, elem.context)

            elems.append(ref_elem)

        expr = irast.Array(elements=elems)

    else:
        expr = process_type_ref_elem(expr, expr.context)

    return expr
Пример #7
0
def _cast_array_literal(ir_set: irast.Set, orig_stype: s_types.Type,
                        new_stype: s_types.Type, *,
                        srcctx: parsing.ParserContext,
                        ctx: context.ContextLevel) -> irast.Base:

    orig_typeref = irutils.type_to_typeref(ctx.env.schema, orig_stype)
    new_typeref = irutils.type_to_typeref(ctx.env.schema, new_stype)

    direct_cast = _find_cast(orig_stype, new_stype, srcctx=srcctx, ctx=ctx)

    if direct_cast is None:
        if not new_stype.is_array():
            raise errors.QueryError(
                f'cannot cast {orig_stype.get_displayname(ctx.env.schema)!r} '
                f'to {new_stype.get_displayname(ctx.env.schema)!r}',
                context=srcctx) from None
        el_type = new_stype.get_subtypes()[0]
    else:
        el_type = new_stype

    casted_els = []
    for el in ir_set.expr.elements:
        el = compile_cast(el, el_type, ctx=ctx, srcctx=srcctx)
        casted_els.append(el)

    new_array = setgen.generated_set(irast.Array(elements=casted_els,
                                                 stype=orig_stype),
                                     ctx=ctx)

    if direct_cast is not None:
        return _cast_to_ir(new_array,
                           direct_cast,
                           orig_stype,
                           new_stype,
                           ctx=ctx)

    else:
        cast_ir = irast.TypeCast(
            expr=new_array,
            from_type=orig_typeref,
            to_type=new_typeref,
            sql_cast=True,
        )

    return setgen.ensure_set(cast_ir, ctx=ctx)
Пример #8
0
def compile_cast(ir_expr: irast.Base, new_stype: s_types.Type, *,
                 srcctx: parsing.ParserContext,
                 ctx: context.ContextLevel) -> irast.OperatorCall:

    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 irutils.new_empty_set(ctx.env.schema,
                                     stype=new_stype,
                                     alias=ir_expr.path_id.target_name.name)

    elif irutils.is_untyped_empty_array_expr(ir_expr):
        # Ditto for empty arrays.
        return setgen.generated_set(irast.Array(elements=[], stype=new_stype),
                                    ctx=ctx)

    ir_set = setgen.ensure_set(ir_expr, ctx=ctx)
    orig_stype = ir_set.stype

    if orig_stype == new_stype:
        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():
        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, 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, 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.schema.get('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.
            viewgen.compile_view_shapes(ir_set, ctx=ctx)

        return _compile_cast(ir_expr,
                             orig_stype,
                             new_stype,
                             srcctx=srcctx,
                             ctx=ctx)
Пример #9
0
def compile_Array(
        expr: qlast.Base, *, ctx: context.ContextLevel) -> irast.Base:
    elements = [dispatch.compile(e, ctx=ctx) for e in expr.elements]
    return setgen.generated_set(irast.Array(elements=elements), ctx=ctx)