示例#1
0
def _new_mapped_pointer_rvar(
        ir_ptr: irast.Pointer, *,
        ctx: context.CompilerContextLevel) -> pgast.PathRangeVar:
    ptrref = ir_ptr.ptrref
    dml_source = irutils.get_nearest_dml_stmt(ir_ptr.source)
    ptr_rvar = range_for_pointer(ir_ptr, dml_source=dml_source, ctx=ctx)
    src_col = 'source'

    source_ref = pgast.ColumnRef(name=[src_col], nullable=False)

    if (irtyputils.is_object(ptrref.out_target)
            and not irtyputils.is_computable_ptrref(ptrref)):
        tgt_ptr_info = pg_types.get_ptrref_storage_info(ptrref,
                                                        link_bias=True,
                                                        resolve_type=False)
        tgt_col = tgt_ptr_info.column_name
    else:
        tgt_col = 'target'

    target_ref = pgast.ColumnRef(name=[tgt_col], nullable=not ptrref.required)

    # Set up references according to the link direction.
    if ir_ptr.direction == s_pointers.PointerDirection.Inbound:
        near_ref = target_ref
        far_ref = source_ref
    else:
        near_ref = source_ref
        far_ref = target_ref

    src_pid = ir_ptr.source.path_id
    tgt_pid = ir_ptr.target.path_id
    ptr_pid = tgt_pid.ptr_path()

    ptr_rvar.query.path_id = ptr_pid
    pathctx.put_rvar_path_bond(ptr_rvar, src_pid)
    pathctx.put_rvar_path_output(ptr_rvar,
                                 src_pid,
                                 aspect='identity',
                                 var=near_ref,
                                 env=ctx.env)
    pathctx.put_rvar_path_output(ptr_rvar,
                                 src_pid,
                                 aspect='value',
                                 var=near_ref,
                                 env=ctx.env)
    pathctx.put_rvar_path_output(ptr_rvar,
                                 tgt_pid,
                                 aspect='value',
                                 var=far_ref,
                                 env=ctx.env)

    if tgt_pid.is_objtype_path():
        pathctx.put_rvar_path_bond(ptr_rvar, tgt_pid)
        pathctx.put_rvar_path_output(ptr_rvar,
                                     tgt_pid,
                                     aspect='identity',
                                     var=far_ref,
                                     env=ctx.env)

    return ptr_rvar
示例#2
0
def new_root_rvar(ir_set: irast.Set,
                  *,
                  typeref: Optional[irast.TypeRef] = None,
                  ctx: context.CompilerContextLevel) -> pgast.PathRangeVar:
    if not ir_set.path_id.is_objtype_path():
        raise ValueError('cannot create root rvar for non-object path')
    if typeref is None:
        typeref = ir_set.typeref

    if typeref.intersection:
        wrapper = pgast.SelectStmt()
        for component in typeref.intersection:
            component_rvar = new_root_rvar(ir_set, typeref=component, ctx=ctx)
            pathctx.put_rvar_path_bond(component_rvar, ir_set.path_id)
            include_rvar(wrapper, component_rvar, ir_set.path_id, ctx=ctx)

        return rvar_for_rel(wrapper, ctx=ctx)

    dml_source = irutils.get_nearest_dml_stmt(ir_set)
    set_rvar = range_for_typeref(typeref,
                                 ir_set.path_id,
                                 dml_source=dml_source,
                                 ctx=ctx)
    pathctx.put_rvar_path_bond(set_rvar, ir_set.path_id)
    set_rvar.query.value_scope.add(ir_set.path_id)

    if ir_set.rptr and ir_set.rptr.is_inbound:
        ptrref = ir_set.rptr.ptrref
        ptr_info = pg_types.get_ptrref_storage_info(ptrref,
                                                    resolve_type=False,
                                                    link_bias=False)

        if ptr_info.table_type == 'ObjectType':
            # Inline link
            prefix_path_id = ir_set.path_id.src_path()
            assert prefix_path_id is not None, 'expected a path'
            rref = pgast.ColumnRef(name=[ptr_info.column_name],
                                   nullable=not ptrref.required)
            pathctx.put_rvar_path_bond(set_rvar, prefix_path_id)
            pathctx.put_rvar_path_output(set_rvar,
                                         prefix_path_id,
                                         aspect='identity',
                                         var=rref,
                                         env=ctx.env)

            if astutils.is_set_op_query(set_rvar.query):
                assert isinstance(set_rvar.query, pgast.SelectStmt)
                astutils.for_each_query_in_set(
                    set_rvar.query, lambda qry: qry.target_list.append(
                        pgast.ResTarget(
                            val=rref,
                            name=ptr_info.column_name,
                        )))

    return set_rvar
示例#3
0
def new_primitive_rvar(
    ir_set: irast.Set,
    *,
    path_id: irast.PathId,
    ctx: context.CompilerContextLevel,
) -> pgast.PathRangeVar:
    if not ir_set.path_id.is_objtype_path():
        raise ValueError('cannot create root rvar for non-object path')

    typeref = ir_set.typeref
    dml_source = irutils.get_nearest_dml_stmt(ir_set)
    set_rvar = range_for_typeref(typeref,
                                 path_id,
                                 dml_source=dml_source,
                                 ctx=ctx)
    pathctx.put_rvar_path_bond(set_rvar, path_id)

    if ir_set.rptr is not None:
        ptr_ref_map: Dict[uuid.UUID, irast.BasePointerRef] = {}
        p: irast.BasePointerRef

        rptrref = ir_set.rptr.ptrref
        if isinstance(rptrref, irast.TypeIntersectionPointerRef):
            if rptrref.rptr_specialization:
                for p in rptrref.rptr_specialization:
                    ptr_ref_map[p.dir_target.id] = p

            src_set = ir_set.rptr.source
            if src_set.rptr is not None:
                src_rptrref = src_set.rptr.ptrref
                if src_rptrref.union_components:
                    for p in src_rptrref.union_components:
                        ptr_ref_map[p.dir_target.id] = p
                else:
                    ptr_ref_map[src_rptrref.dir_target.id] = src_rptrref
                rptrref = src_rptrref
            else:
                ptr_ref_map[rptrref.dir_target.id] = rptrref
        else:
            if rptrref.union_components:
                for p in rptrref.union_components:
                    ptr_ref_map[p.dir_target.id] = p
            else:
                ptr_ref_map[rptrref.dir_target.id] = rptrref

        if (set_rvar.typeref is not None
                and (narrow_rptrref := ptr_ref_map.get(set_rvar.typeref.id))):
            rptrref = narrow_rptrref

        ptr_info = pg_types.get_ptrref_storage_info(rptrref,
                                                    resolve_type=False,
                                                    link_bias=False)

        if ptr_info.table_type == 'ObjectType' and rptrref.is_inbound:
            # Inline link
            prefix_path_id = path_id.src_path()
            assert prefix_path_id is not None, 'expected a path'
            rref = pgast.ColumnRef(name=[ptr_info.column_name],
                                   nullable=not rptrref.required)
            pathctx.put_rvar_path_bond(set_rvar, prefix_path_id)
            pathctx.put_rvar_path_output(set_rvar,
                                         prefix_path_id,
                                         aspect='identity',
                                         var=rref,
                                         env=ctx.env)

            if astutils.is_set_op_query(set_rvar.query):
                assert isinstance(set_rvar.query, pgast.SelectStmt)

                def _pull_col(comp_qry: pgast.Query) -> None:
                    rvar = pathctx.get_path_rvar(comp_qry,
                                                 path_id,
                                                 aspect='source',
                                                 env=ctx.env)
                    typeref = rvar.typeref
                    assert typeref is not None
                    comp_ptrref = ptr_ref_map[typeref.id]
                    comp_pi = pg_types.get_ptrref_storage_info(
                        comp_ptrref, resolve_type=False, link_bias=False)

                    comp_qry.target_list.append(
                        pgast.ResTarget(
                            val=pgast.ColumnRef(name=[comp_pi.column_name]),
                            name=ptr_info.column_name,
                        ))

                astutils.for_each_query_in_set(
                    set_rvar.query,
                    _pull_col,
                )
            elif isinstance(set_rvar, pgast.RangeSubselect):
                rvar_path_var = pathctx.maybe_get_path_rvar(
                    set_rvar.query,
                    path_id=path_id,
                    aspect='identity',
                    env=ctx.env,
                )

                if isinstance(rvar_path_var, pgast.IntersectionRangeVar):
                    for comp_rvar in rvar_path_var.component_rvars:
                        if comp_rvar.typeref is None:
                            continue
                        comp_ptrref = ptr_ref_map.get(comp_rvar.typeref.id)
                        if comp_ptrref is None:
                            continue
                        comp_pi = pg_types.get_ptrref_storage_info(
                            comp_ptrref, resolve_type=False)

                        set_rvar.query.target_list.append(
                            pgast.ResTarget(
                                val=pgast.ColumnRef(name=[
                                    comp_rvar.alias.aliasname,
                                    comp_pi.column_name,
                                ]),
                                name=ptr_info.column_name,
                            ))