Example #1
0
def init_context(
        *,
        schema: s_schema.Schema,
        func_params: typing.Optional[s_func.FuncParameterList]=None,
        parent_object_type: typing.Optional[s_obj.ObjectMeta]=None,
        modaliases: typing.Optional[typing.Dict[str, str]]=None,
        anchors: typing.Optional[typing.Dict[str, s_obj.Object]]=None,
        singletons: typing.Optional[typing.Iterable[s_types.Type]]=None,
        security_context: typing.Optional[str]=None,
        derived_target_module: typing.Optional[str]=None,
        result_view_name: typing.Optional[str]=None,
        schema_view_mode: bool=False,
        disable_constant_folding: bool=False,
        allow_generic_type_output: bool=False,
        allow_abstract_operators: bool=False,
        implicit_id_in_shapes: bool=False,
        implicit_tid_in_shapes: bool=False,
        json_parameters: bool=False,
        session_mode: bool=False) -> \
        context.ContextLevel:
    stack = context.CompilerContext()
    ctx = stack.current
    if not schema.get_global(s_mod.Module, '__derived__', None):
        schema, _ = s_mod.Module.create_in_schema(schema, name='__derived__')
    ctx.env = context.Environment(
        schema=schema,
        path_scope=irast.new_scope_tree(),
        constant_folding=not disable_constant_folding,
        func_params=func_params,
        parent_object_type=parent_object_type,
        schema_view_mode=schema_view_mode,
        json_parameters=json_parameters,
        session_mode=session_mode,
        allow_abstract_operators=allow_abstract_operators,
        allow_generic_type_output=allow_generic_type_output)

    if singletons:
        # The caller wants us to treat these type references
        # as singletons for the purposes of the overall expression
        # cardinality inference, so we set up the scope tree in
        # the necessary fashion.
        for singleton in singletons:
            path_id = pathctx.get_path_id(singleton, ctx=ctx)
            ctx.env.path_scope.attach_path(path_id)

        ctx.path_scope = ctx.env.path_scope.attach_fence()

    if modaliases:
        ctx.modaliases.update(modaliases)

    if anchors:
        with ctx.newscope(fenced=True) as subctx:
            populate_anchors(anchors, ctx=subctx)

    ctx.derived_target_module = derived_target_module
    ctx.toplevel_result_view_name = result_view_name
    ctx.implicit_id_in_shapes = implicit_id_in_shapes
    ctx.implicit_tid_in_shapes = implicit_tid_in_shapes

    return ctx
Example #2
0
def init_stmt(
        irstmt: irast.Stmt, qlstmt: qlast.Statement, *,
        ctx: context.ContextLevel, parent_ctx: context.ContextLevel) -> None:

    ctx.stmt = irstmt
    if ctx.toplevel_stmt is None:
        parent_ctx.toplevel_stmt = ctx.toplevel_stmt = irstmt
        if parent_ctx.path_scope is None:
            parent_ctx.path_scope = ctx.path_scope = irast.new_scope_tree()
    else:
        ctx.path_scope = parent_ctx.path_scope.attach_fence()

    pending_own_ns = parent_ctx.pending_stmt_own_path_id_namespace
    if pending_own_ns:
        ctx.path_scope.add_namespaces(pending_own_ns)

    pending_full_ns = parent_ctx.pending_stmt_full_path_id_namespace
    if pending_full_ns:
        ctx.path_id_namespace |= pending_full_ns

    metadata = ctx.stmt_metadata.get(qlstmt)
    if metadata is not None and metadata.is_unnest_fence:
        ctx.path_scope.unnest_fence = True

    irstmt.parent_stmt = parent_ctx.stmt

    process_with_block(qlstmt, ctx=ctx, parent_ctx=parent_ctx)
Example #3
0
def compile_ir_to_sql_tree(
    ir_expr: irast.Base,
    *,
    output_format: Optional[OutputFormat] = None,
    ignore_shapes: bool = False,
    explicit_top_cast: Optional[irast.TypeRef] = None,
    singleton_mode: bool = False,
    use_named_params: bool = False,
    expected_cardinality_one: bool = False,
    external_rvars: Optional[
        Mapping[Tuple[irast.PathId, str], pgast.PathRangeVar]
    ] = None,
) -> pgast.Base:
    try:
        # Transform to sql tree
        query_params = []
        type_rewrites = {}

        if isinstance(ir_expr, irast.Statement):
            scope_tree = ir_expr.scope_tree
            query_params = list(ir_expr.params)
            type_rewrites = ir_expr.type_rewrites
            ir_expr = ir_expr.expr
        elif isinstance(ir_expr, irast.ConfigCommand):
            scope_tree = ir_expr.scope_tree
        else:
            scope_tree = irast.new_scope_tree()

        env = context.Environment(
            output_format=output_format,
            expected_cardinality_one=expected_cardinality_one,
            use_named_params=use_named_params,
            query_params=query_params,
            type_rewrites=type_rewrites,
            ignore_object_shapes=ignore_shapes,
            explicit_top_cast=explicit_top_cast,
            singleton_mode=singleton_mode,
            external_rvars=external_rvars,
        )

        ctx = context.CompilerContextLevel(
            None,
            context.ContextSwitchMode.TRANSPARENT,
            env=env,
            scope_tree=scope_tree,
        )

        _ = context.CompilerContext(initial=ctx)
        ctx.singleton_mode = singleton_mode
        ctx.expr_exposed = True
        qtree = dispatch.compile(ir_expr, ctx=ctx)

    except Exception as e:  # pragma: no cover
        try:
            args = [e.args[0]]
        except (AttributeError, IndexError):
            args = []
        raise errors.InternalServerError(*args) from e

    return qtree
Example #4
0
def init_context(
    *,
    schema: s_schema.Schema,
    options: coptions.CompilerOptions,
) -> context.ContextLevel:

    if not schema.get_global(s_mod.Module, '__derived__', None):
        schema, _ = s_mod.Module.create_in_schema(schema, name='__derived__')
    env = context.Environment(
        schema=schema,
        path_scope=irast.new_scope_tree(),
        options=options,
    )
    ctx = context.ContextLevel(None, context.ContextSwitchMode.NEW, env=env)
    _ = context.CompilerContext(initial=ctx)

    if options.singletons:
        # The caller wants us to treat these type references
        # as singletons for the purposes of the overall expression
        # cardinality inference, so we set up the scope tree in
        # the necessary fashion.
        for singleton in options.singletons:
            path_id = pathctx.get_path_id(singleton, ctx=ctx)
            ctx.env.path_scope.attach_path(path_id, context=None)

        ctx.path_scope = ctx.env.path_scope.attach_fence()

    ctx.modaliases.update(options.modaliases)

    if options.anchors:
        with ctx.newscope(fenced=True) as subctx:
            populate_anchors(options.anchors, ctx=subctx)

    if options.path_prefix_anchor is not None:
        path_prefix = options.anchors[options.path_prefix_anchor]
        assert isinstance(path_prefix, s_types.Type)
        ctx.partial_path_prefix = setgen.class_set(path_prefix, ctx=ctx)
        ctx.partial_path_prefix.anchor = options.path_prefix_anchor
        ctx.partial_path_prefix.show_as_anchor = options.path_prefix_anchor

    ctx.derived_target_module = options.derived_target_module
    ctx.toplevel_result_view_name = options.result_view_name
    ctx.implicit_id_in_shapes = options.implicit_id_in_shapes
    ctx.implicit_tid_in_shapes = options.implicit_tid_in_shapes
    ctx.implicit_limit = options.implicit_limit

    return ctx
Example #5
0
def fuse_scope_branch(ir_set: irast.Set, parent: irast.ScopeTreeNode,
                      branch: irast.ScopeTreeNode, *,
                      ctx: context.ContextLevel) -> None:
    if parent.path_id is None:
        parent.attach_subtree(branch)
    else:
        if branch.path_id is None and len(branch.children) == 1:
            target_branch = next(iter(branch.children))
        else:
            target_branch = branch

        if parent.path_id == target_branch.path_id:
            new_root = irast.new_scope_tree()
            for child in tuple(target_branch.children):
                new_root.attach_child(child)

            parent.attach_subtree(new_root)
        else:
            parent.attach_subtree(branch)
Example #6
0
    def __init__(
        self,
        *,
        schema: s_schema.Schema,
        path_scope: Optional[irast.ScopeTreeNode] = None,
        alias_result_view_name: Optional[s_name.QualName] = None,
        options: Optional[GlobalCompilerOptions] = None,
    ) -> None:
        if options is None:
            options = GlobalCompilerOptions()

        if path_scope is None:
            path_scope = irast.new_scope_tree()

        self.options = options
        self.schema = schema
        self.orig_schema = schema
        self.path_scope = path_scope
        self.schema_view_cache = {}
        self.query_parameters = {}
        self.query_globals = {}
        self.set_types = {}
        self.type_origins = {}
        self.inferred_types = {}
        self.inferred_volatility = {}
        self.view_shapes = collections.defaultdict(list)
        self.view_shapes_metadata = collections.defaultdict(
            irast.ViewShapeMetadata)
        self.schema_refs = set()
        self.schema_ref_exprs = {} if options.track_schema_ref_exprs else None
        self.created_schema_objects = set()
        self.ptr_ref_cache = PointerRefCache()
        self.type_ref_cache = {}
        self.dml_exprs = []
        self.dml_stmts = set()
        self.pointer_derivation_map = collections.defaultdict(list)
        self.pointer_specified_info = {}
        self.singletons = []
        self.scope_tree_nodes = weakref.WeakValueDictionary()
        self.materialized_sets = {}
        self.compiled_stmts = {}
        self.alias_result_view_name = alias_result_view_name
Example #7
0
    def __init__(
        self,
        prevlevel: Optional[ContextLevel],
        mode: ContextSwitchMode,
        *,
        env: Optional[Environment] = None,
    ) -> None:

        self.mode = mode

        if prevlevel is None:
            assert env is not None
            self.env = env
            self.derived_target_module = None
            self.aliases = compiler.AliasGenerator()
            self.anchors = {}
            self.modaliases = {}
            self.stmt_metadata = {}
            self.completion_work = []
            self.pending_cardinality = {}
            self.pointer_derivation_map = collections.defaultdict(list)

            self.source_map = {}
            self.view_nodes = {}
            self.view_sets = {}
            self.aliased_views = collections.ChainMap()
            self.must_use_views = {}
            self.expr_view_cache = {}
            self.shape_type_cache = {}
            self.class_view_overrides = {}

            self.toplevel_stmt = None
            self.stmt = None
            self.path_id_namespace = frozenset()
            self.pending_stmt_own_path_id_namespace = frozenset()
            self.pending_stmt_full_path_id_namespace = frozenset()
            self.banned_paths = set()
            self.view_map = collections.ChainMap()
            self.path_scope = irast.new_scope_tree()
            self.path_scope_map = {}
            self.iterator_ctx = None
            self.iterator_path_ids = frozenset()
            self.scope_id_ctr = compiler.SimpleCounter()
            self.view_scls = None
            self.expr_exposed = False

            self.partial_path_prefix = None

            self.view_rptr = None
            self.toplevel_result_view_name = None
            self.implicit_id_in_shapes = False
            self.implicit_tid_in_shapes = False
            self.implicit_limit = 0
            self.inhibit_implicit_limit = False
            self.special_computables_in_mutation_shape = frozenset()
            self.empty_result_type_hint = None
            self.defining_view = None
            self.compiling_update_shape = False
            self.in_conditional = None
            self.in_temp_scope = False
            self.tentative_work = []
            self.disable_shadowing = set()
            self.path_log = None

        else:
            self.env = prevlevel.env
            self.derived_target_module = prevlevel.derived_target_module
            self.aliases = prevlevel.aliases
            self.stmt_metadata = prevlevel.stmt_metadata
            self.completion_work = prevlevel.completion_work
            self.pending_cardinality = prevlevel.pending_cardinality
            self.pointer_derivation_map = prevlevel.pointer_derivation_map

            self.source_map = prevlevel.source_map
            self.view_nodes = prevlevel.view_nodes
            self.view_sets = prevlevel.view_sets
            self.must_use_views = prevlevel.must_use_views
            self.expr_view_cache = prevlevel.expr_view_cache
            self.shape_type_cache = prevlevel.shape_type_cache

            self.iterator_ctx = prevlevel.iterator_ctx
            self.iterator_path_ids = prevlevel.iterator_path_ids
            self.path_id_namespace = prevlevel.path_id_namespace
            self.pending_stmt_own_path_id_namespace = \
                prevlevel.pending_stmt_own_path_id_namespace
            self.pending_stmt_full_path_id_namespace = \
                prevlevel.pending_stmt_full_path_id_namespace
            self.banned_paths = prevlevel.banned_paths
            self.view_map = prevlevel.view_map
            if prevlevel.path_scope is None:
                prevlevel.path_scope = self.env.path_scope
            self.path_scope = prevlevel.path_scope
            self.path_scope_map = prevlevel.path_scope_map
            self.scope_id_ctr = prevlevel.scope_id_ctr
            self.view_scls = prevlevel.view_scls
            self.expr_exposed = prevlevel.expr_exposed
            self.partial_path_prefix = prevlevel.partial_path_prefix
            self.toplevel_stmt = prevlevel.toplevel_stmt
            self.implicit_id_in_shapes = prevlevel.implicit_id_in_shapes
            self.implicit_tid_in_shapes = prevlevel.implicit_tid_in_shapes
            self.implicit_limit = prevlevel.implicit_limit
            self.inhibit_implicit_limit = prevlevel.inhibit_implicit_limit
            self.special_computables_in_mutation_shape = \
                prevlevel.special_computables_in_mutation_shape
            self.empty_result_type_hint = prevlevel.empty_result_type_hint
            self.defining_view = prevlevel.defining_view
            self.compiling_update_shape = prevlevel.compiling_update_shape
            self.in_conditional = prevlevel.in_conditional
            self.in_temp_scope = prevlevel.in_temp_scope
            self.tentative_work = prevlevel.tentative_work
            self.disable_shadowing = prevlevel.disable_shadowing
            self.path_log = prevlevel.path_log

            if mode == ContextSwitchMode.SUBQUERY:
                self.anchors = prevlevel.anchors.copy()
                self.modaliases = prevlevel.modaliases.copy()
                self.aliased_views = prevlevel.aliased_views.new_child()
                self.class_view_overrides = \
                    prevlevel.class_view_overrides.copy()

                self.pending_stmt_own_path_id_namespace = frozenset()
                self.pending_stmt_full_path_id_namespace = frozenset()
                self.banned_paths = prevlevel.banned_paths.copy()

                self.view_rptr = None
                self.view_scls = None
                self.stmt = None

                self.view_rptr = None
                self.toplevel_result_view_name = None

            elif mode == ContextSwitchMode.DETACHED:
                self.anchors = prevlevel.anchors.copy()
                self.modaliases = prevlevel.modaliases.copy()
                self.aliased_views = collections.ChainMap()
                self.class_view_overrides = {}
                self.expr_exposed = prevlevel.expr_exposed

                self.view_nodes = {}
                self.view_sets = {}
                self.path_id_namespace = frozenset({self.aliases.get('ns')})
                self.pending_stmt_own_path_id_namespace = frozenset()
                self.pending_stmt_full_path_id_namespace = frozenset()
                self.banned_paths = set()

                self.iterator_ctx = None
                self.iterator_path_ids = frozenset()

                self.view_rptr = None
                self.view_scls = None
                self.stmt = prevlevel.stmt

                self.partial_path_prefix = None

                self.view_rptr = None
                self.toplevel_result_view_name = None
                self.disable_shadowing = prevlevel.disable_shadowing.copy()
            else:
                self.anchors = prevlevel.anchors
                self.modaliases = prevlevel.modaliases
                self.aliased_views = prevlevel.aliased_views
                self.class_view_overrides = prevlevel.class_view_overrides

                self.stmt = prevlevel.stmt

                self.view_rptr = prevlevel.view_rptr
                self.toplevel_result_view_name = \
                    prevlevel.toplevel_result_view_name

            if mode in {ContextSwitchMode.NEWFENCE_TEMP,
                        ContextSwitchMode.NEWSCOPE_TEMP}:
                # Make a copy of the entire tree and set path_scope to
                # be the copy of the current node. Stash the root in
                # an attribute to keep it from being freed, since
                # scope tree parent pointers are weak pointers.
                self._stash, self.path_scope = self.path_scope.copy_all()
                self.in_temp_scope = True
                self.tentative_work = list(prevlevel.tentative_work)

            if mode in {ContextSwitchMode.NEWFENCE,
                        ContextSwitchMode.NEWFENCE_TEMP}:
                self.path_scope = self.path_scope.attach_fence()

            if mode in {ContextSwitchMode.NEWSCOPE,
                        ContextSwitchMode.NEWSCOPE_TEMP}:
                self.path_scope = self.path_scope.attach_branch()
Example #8
0
def init_context(
        *,
        schema: s_schema.Schema,
        func_params: Optional[s_func.ParameterLikeList]=None,
        parent_object_type: Optional[s_obj.ObjectMeta]=None,
        modaliases: Optional[Mapping[Optional[str], str]]=None,
        anchors: Optional[
            Mapping[
                Union[str, qlast.SpecialAnchorT],
                Union[s_obj.Object, irast.Base],
            ],
        ]=None,
        singletons: Optional[Iterable[s_types.Type]]=None,
        security_context: Optional[str]=None,
        derived_target_module: Optional[str]=None,
        result_view_name: Optional[s_name.SchemaName]=None,
        schema_view_mode: bool=False,
        disable_constant_folding: bool=False,
        allow_generic_type_output: bool=False,
        implicit_limit: int=0,
        implicit_id_in_shapes: bool=False,
        implicit_tid_in_shapes: bool=False,
        json_parameters: bool=False,
        session_mode: bool=False) -> \
        context.ContextLevel:
    if not schema.get_global(s_mod.Module, '__derived__', None):
        schema, _ = s_mod.Module.create_in_schema(schema, name='__derived__')
    env = context.Environment(
        schema=schema,
        path_scope=irast.new_scope_tree(),
        constant_folding=not disable_constant_folding,
        func_params=func_params,
        parent_object_type=parent_object_type,
        schema_view_mode=schema_view_mode,
        json_parameters=json_parameters,
        session_mode=session_mode,
        allow_generic_type_output=allow_generic_type_output)
    ctx = context.ContextLevel(None, context.ContextSwitchMode.NEW, env=env)
    _ = context.CompilerContext(initial=ctx)

    if singletons:
        # The caller wants us to treat these type references
        # as singletons for the purposes of the overall expression
        # cardinality inference, so we set up the scope tree in
        # the necessary fashion.
        for singleton in singletons:
            path_id = pathctx.get_path_id(singleton, ctx=ctx)
            ctx.env.path_scope.attach_path(path_id)

        ctx.path_scope = ctx.env.path_scope.attach_fence()

    if modaliases:
        ctx.modaliases.update(modaliases)

    if anchors:
        with ctx.newscope(fenced=True) as subctx:
            populate_anchors(anchors, ctx=subctx)

    ctx.derived_target_module = derived_target_module
    ctx.toplevel_result_view_name = result_view_name
    ctx.implicit_id_in_shapes = implicit_id_in_shapes
    ctx.implicit_tid_in_shapes = implicit_tid_in_shapes
    ctx.implicit_limit = implicit_limit

    return ctx
Example #9
0
def compile_ir_to_sql_tree(
    ir_expr: irast.Base,
    *,
    output_format: Optional[OutputFormat] = None,
    ignore_shapes: bool = False,
    explicit_top_cast: Optional[irast.TypeRef] = None,
    singleton_mode: bool = False,
    use_named_params: bool = False,
    expected_cardinality_one: bool = False,
    external_rvars: Optional[Mapping[Tuple[irast.PathId, str],
                                     pgast.PathRangeVar]] = None,
    backend_runtime_params: Optional[pgparams.BackendRuntimeParams] = None,
) -> pgast.Base:
    try:
        # Transform to sql tree
        query_params = []
        query_globals = []
        type_rewrites = {}

        singletons = []
        if isinstance(ir_expr, irast.Statement):
            scope_tree = ir_expr.scope_tree
            query_params = list(ir_expr.params)
            query_globals = list(ir_expr.globals)
            type_rewrites = ir_expr.type_rewrites
            singletons = ir_expr.singletons
            ir_expr = ir_expr.expr
        elif isinstance(ir_expr, irast.ConfigCommand):
            assert ir_expr.scope_tree
            scope_tree = ir_expr.scope_tree
        else:
            scope_tree = irast.new_scope_tree()

        scope_tree_nodes = {
            node.unique_id: node
            for node in scope_tree.descendants if node.unique_id is not None
        }

        if backend_runtime_params is None:
            backend_runtime_params = pgparams.get_default_runtime_params()

        env = context.Environment(
            output_format=output_format,
            expected_cardinality_one=expected_cardinality_one,
            use_named_params=use_named_params,
            query_params=list(tuple(query_params) + tuple(query_globals)),
            type_rewrites=type_rewrites,
            ignore_object_shapes=ignore_shapes,
            explicit_top_cast=explicit_top_cast,
            singleton_mode=singleton_mode,
            scope_tree_nodes=scope_tree_nodes,
            external_rvars=external_rvars,
            backend_runtime_params=backend_runtime_params,
        )

        ctx = context.CompilerContextLevel(
            None,
            context.ContextSwitchMode.TRANSPARENT,
            env=env,
            scope_tree=scope_tree,
        )
        ctx.rel = pgast.SelectStmt()

        _ = context.CompilerContext(initial=ctx)

        ctx.singleton_mode = singleton_mode
        ctx.expr_exposed = True
        for sing in singletons:
            ctx.path_scope[sing] = ctx.rel
        clauses.populate_argmap(query_params, query_globals, ctx=ctx)

        qtree = dispatch.compile(ir_expr, ctx=ctx)
        if isinstance(ir_expr, irast.Set) and not singleton_mode:
            assert isinstance(qtree, pgast.Query)
            clauses.fini_toplevel(qtree, ctx)

    except errors.EdgeDBError:
        # Don't wrap propertly typed EdgeDB errors into
        # InternalServerError; raise them as is.
        raise

    except Exception as e:  # pragma: no cover
        try:
            args = [e.args[0]]
        except (AttributeError, IndexError):
            args = []
        raise errors.InternalServerError(*args) from e

    return qtree