예제 #1
0
파일: viewgen.py 프로젝트: zhutony/edgedb
def process_view(
        *,
        stype: s_objtypes.ObjectType,
        path_id: irast.PathId,
        elements: List[qlast.ShapeElement],
        view_rptr: Optional[context.ViewRPtr]=None,
        view_name: Optional[sn.SchemaName]=None,
        is_insert: bool=False,
        is_update: bool=False,
        ctx: context.ContextLevel) -> s_objtypes.ObjectType:

    cache_key = (stype, tuple(elements))
    view_scls = ctx.shape_type_cache.get(cache_key)
    if view_scls is not None:
        return view_scls

    with ctx.newscope(fenced=True, temporary=True) as scopectx:
        scopectx.path_scope.attach_path(path_id)
        view_path_id_ns = None
        if ctx.expr_exposed or is_insert or is_update:
            view_path_id_ns = irast.WeakNamespace(ctx.aliases.get('ns'))
            scopectx.path_id_namespace |= {view_path_id_ns}
            scopectx.path_scope.add_namespaces({view_path_id_ns})

        view_scls = _process_view(
            stype=stype, path_id=path_id, elements=elements,
            view_rptr=view_rptr, view_name=view_name,
            is_insert=is_insert, is_update=is_update,
            path_id_namespace=view_path_id_ns, ctx=scopectx
        )

    ctx.shape_type_cache[cache_key] = view_scls

    return view_scls
예제 #2
0
파일: stmtctx.py 프로젝트: joe2hpimn/edgedb
def declare_view(
        expr: qlast.Base, alias: str, *,
        fully_detached: bool=False,
        temporary_scope: bool=True,
        ctx: context.ContextLevel) -> irast.Set:

    with ctx.newscope(temporary=temporary_scope, fenced=True) as subctx:
        if not fully_detached:
            cached_view_set = ctx.expr_view_cache.get((expr, alias))
            # Detach the view namespace and record the prefix
            # in the parent statement's fence node.
            view_path_id_ns = irast.WeakNamespace(ctx.aliases.get('ns'))
            subctx.path_id_namespace |= {view_path_id_ns}
            ctx.path_scope.add_namespaces((view_path_id_ns,))
        else:
            cached_view_set = None

        if ctx.stmt is not None:
            subctx.stmt = ctx.stmt.parent_stmt

        if cached_view_set is not None:
            subctx.view_scls = setgen.get_set_type(cached_view_set, ctx=ctx)
            view_name = subctx.view_scls.get_name(ctx.env.schema)
        else:
            if isinstance(alias, s_name.SchemaName):
                basename = alias
            else:
                basename = s_name.SchemaName(module='__derived__', name=alias)

            view_name = s_name.SchemaName(
                module=ctx.derived_target_module or '__derived__',
                name=s_name.get_specialized_name(
                    basename,
                    ctx.aliases.get('w')
                )
            )

        subctx.toplevel_result_view_name = view_name

        view_set = dispatch.compile(astutils.ensure_qlstmt(expr), ctx=subctx)

        if not fully_detached:
            # The view path id _itself_ should not be in the nested namespace.
            # The fully_detached case should be handled by the caller.
            view_set.path_id = view_set.path_id.replace_namespace(
                ctx.path_id_namespace)

        ctx.aliased_views[alias] = setgen.get_set_type(view_set, ctx=ctx)
        ctx.path_scope_map[view_set] = subctx.path_scope
        ctx.expr_view_cache[expr, alias] = view_set

    return view_set
예제 #3
0
    def newctx() -> Iterator[context.ContextLevel]:
        with ctx.new() as subctx:
            subctx.class_view_overrides = {}
            subctx.partial_path_prefix = None

            subctx.modaliases = qlctx.modaliases.copy()
            subctx.aliased_views = qlctx.aliased_views.new_child()
            source_stype = get_set_type(source, ctx=ctx)

            if source_scls.is_view(ctx.env.schema):
                scls_name = source_stype.get_name(ctx.env.schema)
                subctx.aliased_views[scls_name] = None
            subctx.source_map = qlctx.source_map.copy()
            subctx.view_nodes = qlctx.view_nodes.copy()
            subctx.view_map = qlctx.view_map.new_child()

            source_scope = pathctx.get_set_scope(rptr.source, ctx=ctx)
            if source_scope and source_scope.namespaces:
                subctx.path_id_namespace |= source_scope.namespaces

            if path_id_ns is not None:
                subctx.path_id_namespace |= {path_id_ns}

            pending_pid_ns: Set[irast.AnyNamespace] = {
                irast.WeakNamespace(ctx.aliases.get('ns')),
            }

            if path_id_ns is not None and same_scope:
                pending_pid_ns.add(path_id_ns)

            subctx.pending_stmt_own_path_id_namespace = (
                frozenset(pending_pid_ns))

            subns = set(pending_pid_ns)

            self_view = ctx.view_sets.get(source_stype)
            if self_view:
                if self_view.path_id.namespace:
                    subns.update(self_view.path_id.namespace)
                inner_path_id = self_view.path_id.merge_namespace(
                    subctx.path_id_namespace | subns)
            else:
                if source.path_id.namespace:
                    subns.update(source.path_id.namespace)

                if inner_source_path_id is not None:
                    # The path id recorded in the source map may
                    # contain namespaces referring to a temporary
                    # scope subtree used by `process_view()`.
                    # Since we recompile the computable expression
                    # using the current path id namespace, the
                    # original source path id needs to be fixed.
                    inner_path_id = inner_source_path_id \
                        .strip_namespace(qlctx.path_id_namespace) \
                        .merge_namespace(subctx.path_id_namespace)
                else:
                    inner_path_id = pathctx.get_path_id(source_stype,
                                                        ctx=subctx)

                inner_path_id = inner_path_id.merge_namespace(subns)

            subctx.pending_stmt_full_path_id_namespace = frozenset(subns)

            remapped_source = new_set_from_set(rptr.source,
                                               rptr=rptr.source.rptr,
                                               preserve_scope_ns=True,
                                               ctx=ctx)
            subctx.view_map[inner_path_id] = remapped_source
            yield subctx
예제 #4
0
def declare_view(
    expr: qlast.Expr,
    alias: s_name.Name,
    *,
    factoring_fence: bool = False,
    fully_detached: bool = False,
    must_be_used: bool = False,
    path_id_namespace: Optional[FrozenSet[str]] = None,
    ctx: context.ContextLevel,
) -> irast.Set:

    pinned_pid_ns = path_id_namespace

    with ctx.newscope(fenced=True) as subctx:
        subctx.path_scope.factoring_fence = factoring_fence
        if path_id_namespace is not None:
            subctx.path_id_namespace = path_id_namespace

        if not fully_detached:
            cached_view_set = ctx.expr_view_cache.get((expr, alias))
            # Detach the view namespace and record the prefix
            # in the parent statement's fence node.
            view_path_id_ns = irast.WeakNamespace(ctx.aliases.get('ns'))
            subctx.path_id_namespace |= {view_path_id_ns}
            ctx.path_scope.add_namespaces({view_path_id_ns})
        else:
            cached_view_set = None

        if ctx.stmt is not None:
            subctx.stmt = ctx.stmt.parent_stmt

        if cached_view_set is not None:
            subctx.view_scls = setgen.get_set_type(cached_view_set, ctx=ctx)
            view_name = subctx.view_scls.get_name(ctx.env.schema)
            assert isinstance(view_name, s_name.QualName)
        else:
            if isinstance(alias, s_name.QualName):
                basename = alias
            else:
                basename = s_name.QualName(module='__derived__',
                                           name=alias.name)

            if (isinstance(alias, s_name.QualName)
                    and subctx.env.options.schema_view_mode):
                view_name = basename
                subctx.recompiling_schema_alias = True
            else:
                view_name = s_name.QualName(
                    module=ctx.derived_target_module or '__derived__',
                    name=s_name.get_specialized_name(basename,
                                                     ctx.aliases.get('w')))

        subctx.toplevel_result_view_name = view_name

        view_set = dispatch.compile(astutils.ensure_qlstmt(expr), ctx=subctx)
        assert isinstance(view_set, irast.Set)

        ctx.path_scope_map[view_set] = context.ScopeInfo(
            path_scope=subctx.path_scope,
            pinned_path_id_ns=pinned_pid_ns,
        )

        if not fully_detached:
            # The view path id _itself_ should not be in the nested namespace.
            # The fully_detached case should be handled by the caller.
            if path_id_namespace is None:
                path_id_namespace = ctx.path_id_namespace
            view_set.path_id = view_set.path_id.replace_namespace(
                path_id_namespace)

        view_type = setgen.get_set_type(view_set, ctx=ctx)
        ctx.aliased_views[alias] = view_type
        ctx.expr_view_cache[expr, alias] = view_set

        if must_be_used:
            ctx.must_use_views[view_type] = (alias, expr.context)

    return view_set