Exemplo n.º 1
0
def put_path_var(
        rel: pgast.BaseRelation, path_id: irast.PathId, var: pgast.BaseExpr, *,
        aspect: str, force: bool=False, env: context.Environment) -> None:
    if (path_id, aspect) in rel.path_namespace and not force:
        raise KeyError(
            f'{aspect} of {path_id} is already present in {rel}')
    rel.path_namespace[path_id, aspect] = var
Exemplo n.º 2
0
def ensure_transient_identity_for_set(ir_set: irast.Set,
                                      stmt: pgast.BaseRelation,
                                      *,
                                      ctx: context.CompilerContextLevel,
                                      type: str = 'int') -> None:

    if type == 'uuid':
        id_expr = pgast.FuncCall(
            name=(
                'edgedbext',
                'uuid_generate_v1mc',
            ),
            args=[],
        )
    else:
        id_expr = pgast.FuncCall(name=('row_number', ),
                                 args=[],
                                 over=pgast.WindowDef())

    pathctx.put_path_identity_var(stmt,
                                  ir_set.path_id,
                                  id_expr,
                                  force=True,
                                  env=ctx.env)
    pathctx.put_path_bond(stmt, ir_set.path_id)

    if (ctx.volatility_ref is not None
            and ctx.volatility_ref is not context.NO_VOLATILITY
            and isinstance(stmt, pgast.SelectStmt)):
        # Apply the volatility reference.
        # See the comment in process_set_as_subquery().
        stmt.where_clause = astutils.extend_binop(
            stmt.where_clause,
            pgast.NullTest(
                arg=ctx.volatility_ref,
                negated=True,
            ))
Exemplo n.º 3
0
def _get_path_output(rel: pgast.BaseRelation,
                     path_id: irast.PathId,
                     *,
                     aspect: str,
                     allow_nullable: bool = True,
                     ptr_info: typing.Optional[
                         pg_types.PointerStorageInfo] = None,
                     env: context.Environment) -> pgast.OutputVar:

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

    ref: pgast.BaseExpr
    alias = None
    rptr = path_id.rptr()
    if rptr is not None and irtyputils.is_id_ptrref(rptr):
        # A value reference to Object.id is the same as a value
        # reference to the Object itself.
        src_path_id = path_id.src_path()
        id_output = rel.path_outputs.get((src_path_id, 'value'))
        if id_output is not None:
            _put_path_output_var(rel, path_id, aspect, id_output, env=env)
            return id_output

    if is_terminal_relation(rel):
        return _get_rel_path_output(rel,
                                    path_id,
                                    aspect=aspect,
                                    ptr_info=ptr_info,
                                    env=env)

    assert isinstance(rel, pgast.Query)
    if is_values_relation(rel):
        # The VALUES() construct seems to always expose its
        # value as "column1".
        alias = 'column1'
        ref = pgast.ColumnRef(name=[alias])
    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:
        _put_path_output_var(rel, path_id, aspect, other_output, env=env)
        return other_output

    if isinstance(ref, pgast.TupleVarBase):
        elements = []
        for el in ref.elements:
            el_path_id = reverse_map_path_id(el.path_id, rel.view_path_id_map)

            try:
                # Similarly to get_path_var(), check for outer path_id
                # first for tuple serialized var disambiguation.
                element = _get_path_output(rel,
                                           el_path_id,
                                           aspect=aspect,
                                           allow_nullable=False,
                                           env=env)
            except LookupError:
                element = get_path_output(rel,
                                          el_path_id,
                                          aspect=aspect,
                                          allow_nullable=False,
                                          env=env)

            elements.append(
                pgast.TupleElementBase(path_id=el_path_id, name=element))

        result = pgast.TupleVarBase(elements=elements, named=ref.named)

    else:
        if astutils.is_set_op_query(rel):
            assert isinstance(ref, pgast.OutputVar)
            result = astutils.strip_output_var(ref)
        else:
            assert isinstance(rel, pgast.ReturningQuery), \
                "expected ReturningQuery"

            if alias is None:
                alias = get_path_output_alias(path_id, aspect, env=env)

            restarget = pgast.ResTarget(name=alias,
                                        val=ref,
                                        ser_safe=getattr(
                                            ref, 'ser_safe', False))
            rel.target_list.append(restarget)

            nullable = is_nullable(ref, env=env)

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

            if nullable and not allow_nullable:
                var = get_path_var(rel, path_id, aspect=aspect, env=env)
                rel.where_clause = astutils.extend_binop(
                    rel.where_clause, pgast.NullTest(arg=var, negated=True))
                nullable = False

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

    _put_path_output_var(rel, path_id, aspect, result, env=env)
    if (path_id.is_objtype_path()
            and not isinstance(result, pgast.TupleVarBase)):
        equiv_aspect = None
        if aspect == 'identity':
            equiv_aspect = 'value'
        elif aspect == 'value':
            equiv_aspect = 'identity'

        if (equiv_aspect is not None
                and (path_id, equiv_aspect) not in rel.path_outputs):
            _put_path_output_var(rel, path_id, equiv_aspect, result, env=env)

    return result
Exemplo n.º 4
0
def _put_path_output_var(rel: pgast.BaseRelation, path_id: irast.PathId,
                         aspect: str, var: pgast.OutputVar, *,
                         env: context.Environment) -> None:

    rel.path_outputs[path_id, aspect] = var