Beispiel #1
0
def compile_Tuple(expr: irast.Base, *,
                  ctx: context.CompilerContextLevel) -> pgast.Base:
    ttype = _infer_type(expr, ctx=ctx)
    ttypes = ttype.element_types
    telems = list(ttypes)

    path_id = irast.PathId(ttype)

    elements = []

    for i, e in enumerate(expr.elements):
        telem = telems[i]
        ttype = ttypes[telem]
        el_path_id = irutils.tuple_indirection_path_id(path_id, telem, ttype)
        val = dispatch.compile(e.val, ctx=ctx)
        elements.append(pgast.TupleElement(path_id=el_path_id, val=val))

    result = pgast.TupleVar(elements=elements)

    return output.output_as_value(result, env=ctx.env)
Beispiel #2
0
def tuple_element_for_shape_el(shape_el, value):
    if shape_el.path_id.is_type_indirection_path():
        rptr = shape_el.rptr.source.rptr
    else:
        rptr = shape_el.rptr
    ptrcls = rptr.ptrcls
    ptrdir = rptr.direction or s_pointers.PointerDirection.Outbound
    ptrname = ptrcls.shortname

    attr_name = s_pointers.PointerVector(
        name=ptrname.name,
        module=ptrname.module,
        direction=ptrdir,
        target=ptrcls.get_far_endpoint(ptrdir),
        is_linkprop=ptrcls.is_link_property())

    return pgast.TupleElement(
        path_id=shape_el.path_id,
        name=attr_name,
        val=value,
    )
Beispiel #3
0
def get_rvar_fieldref(
        rvar: typing.Optional[pgast.BaseRangeVar],
        colname: typing.Union[str, pgast.TupleVar],
        *, optional: bool=False, nullable: bool=None) \
        -> typing.Union[pgast.ColumnRef, pgast.TupleVar]:

    if isinstance(colname, pgast.TupleVar):
        elements = []

        for el in colname.elements:
            val = get_rvar_fieldref(rvar, el.name)
            elements.append(
                pgast.TupleElement(path_id=el.path_id, name=el.name, val=val))

        fieldref = pgast.TupleVar(elements, named=colname.named)
    else:
        fieldref = get_column(rvar,
                              colname,
                              optional=optional,
                              nullable=nullable)

    return fieldref
Beispiel #4
0
def _compile_shape(ir_set: irast.Set, shape: typing.List[irast.Set], *,
                   ctx: context.CompilerContextLevel) -> pgast.TupleVar:
    elements = []

    with ctx.newscope() as shapectx:
        shapectx.disable_semi_join.add(ir_set.path_id)
        shapectx.unique_paths.add(ir_set.path_id)

        for el in shape:
            rptr = el.rptr
            ptrcls = rptr.ptrcls
            ptrdir = rptr.direction or s_pointers.PointerDirection.Outbound
            is_singleton = ptrcls.singular(ptrdir)

            if (irutils.is_subquery_set(el)
                    or isinstance(el.scls, s_objtypes.ObjectType)
                    or not is_singleton or not ptrcls.required):
                wrapper = relgen.set_as_subquery(el,
                                                 as_value=True,
                                                 ctx=shapectx)
                if not is_singleton:
                    value = relgen.set_to_array(ir_set=el,
                                                query=wrapper,
                                                ctx=shapectx)
                else:
                    value = wrapper
            else:
                value = dispatch.compile(el, ctx=shapectx)

            elements.append(astutils.tuple_element_for_shape_el(el, value))

    result = pgast.TupleVar(elements=elements, named=True)
    pathctx.put_path_value_var(ctx.rel,
                               ir_set.path_id,
                               result,
                               force=True,
                               env=ctx.env)

    for element in elements:
        # The ref might have already been added by the nested shape
        # processing, so add it conditionally.
        pathctx.put_path_value_var_if_not_exists(ctx.rel,
                                                 element.path_id,
                                                 element.val,
                                                 env=ctx.env)

    if output.in_serialization_ctx(ctx):
        ser_elements = []
        for el in elements:
            ser_val = pathctx.get_path_serialized_or_value_var(ctx.rel,
                                                               el.path_id,
                                                               env=ctx.env)
            ser_elements.append(
                pgast.TupleElement(path_id=el.path_id,
                                   name=el.name,
                                   val=ser_val))

        ser_result = pgast.TupleVar(elements=ser_elements, named=True)
        sval = output.serialize_expr(ser_result, env=ctx.env)
        pathctx.put_path_serialized_var(ctx.rel,
                                        ir_set.path_id,
                                        sval,
                                        force=True,
                                        env=ctx.env)

    return result
Beispiel #5
0
def get_path_output(rel: pgast.BaseRelation,
                    path_id: irast.PathId,
                    *,
                    aspect: str,
                    ptr_info: typing.Optional[
                        pg_types.PointerStorageInfo] = None,
                    env: context.Environment) -> pgast.OutputVar:

    view_path_id_map = getattr(rel, 'view_path_id_map', None)
    if view_path_id_map:
        path_id = map_path_id(path_id, view_path_id_map)

    result = rel.path_outputs.get((path_id, aspect))
    if result is not None:
        return result

    if isinstance(rel, pgast.Relation):
        return _get_rel_path_output(rel,
                                    path_id,
                                    aspect=aspect,
                                    ptr_info=ptr_info,
                                    env=env)
    else:
        ref = get_path_var(rel, path_id, aspect=aspect, env=env)

    other_output = find_path_output(rel, path_id, ref, env=env)
    if other_output is not None:
        rel.path_outputs[path_id, aspect] = other_output
        return other_output

    if isinstance(ref, pgast.TupleVar):
        elements = []
        for el in ref.elements:
            el_path_id = reverse_map_path_id(el.path_id, rel.view_path_id_map)
            element = get_path_output(rel, el_path_id, aspect=aspect, env=env)
            elements.append(
                pgast.TupleElement(path_id=el_path_id, name=element))
        result = pgast.TupleVar(elements=elements, named=ref.named)

    else:
        if astutils.is_set_op_query(rel):
            assert isinstance(ref, pgast.ColumnRef)
            result = dbobj.get_column(None, ref)
        else:
            alias = get_path_output_alias(path_id, aspect, env=env)

            restarget = pgast.ResTarget(name=alias, val=ref)
            if hasattr(rel, 'returning_list'):
                rel.returning_list.append(restarget)
            else:
                rel.target_list.append(restarget)

            if isinstance(ref, pgast.ColumnRef):
                nullable = ref.nullable
                optional = ref.optional
            else:
                nullable = rel.nullable
                optional = None

            result = pgast.ColumnRef(name=[alias],
                                     nullable=nullable,
                                     optional=optional)

    rel.path_outputs[path_id, aspect] = result
    return result