Exemple #1
0
    def _add(
        self,
        id: uuid.UUID,
        scls: so.Object,
        data: Mapping[str, Any],
    ) -> Schema:
        name = data['name']

        if name in self._name_to_id:
            raise errors.SchemaError(
                f'{type(scls).__name__} {name!r} is already present '
                f'in the schema {self!r}')

        data = immu.Map(data)

        name_to_id, shortname_to_id, globalname_to_id = self._update_obj_name(
            id, scls, None, name)

        updates = dict(
            id_to_data=self._id_to_data.set(id, data),
            id_to_type=self._id_to_type.set(id, scls),
            name_to_id=name_to_id,
            shortname_to_id=shortname_to_id,
            globalname_to_id=globalname_to_id,
            refs_to=self._update_refs_to(scls, None, data),
        )

        if (isinstance(scls, so.QualifiedObject)
                and not self.has_module(name.module)):
            raise errors.UnknownModuleError(
                f'module {name.module!r} is not in this schema')

        return self._replace(**updates)  # type: ignore
Exemple #2
0
    def _compile_ql_sess_state(self, ctx: CompileContext,
                               ql: qlast.SetSessionState):
        current_tx = ctx.state.current_tx()
        schema = current_tx.get_schema()

        aliases = {}
        config_vals = {}

        for item in ql.items:
            if isinstance(item, qlast.SessionSettingModuleDecl):
                try:
                    schema.get(item.module)
                except errors.InvalidReferenceError:
                    raise errors.UnknownModuleError(
                        f'module {item.module!r} does not exist') from None

                aliases[item.alias] = item.module

            elif isinstance(item, qlast.SessionSettingConfigDecl):
                name = item.alias

                try:
                    desc = config.configs[name]
                except KeyError:
                    raise errors.ConfigurationError(
                        f'invalid SET expression: '
                        f'unknown CONFIG setting {name!r}')

                try:
                    val_ir = ql_compiler.compile_ast_fragment_to_ir(
                        item.expr, schema=schema)
                    val = ireval.evaluate_to_python_val(val_ir.expr,
                                                        schema=schema)
                except ireval.StaticEvaluationError:
                    raise RuntimeError('invalid SET expression')
                else:
                    if not isinstance(val, desc.type):
                        dispname = val_ir.stype.get_displayname(schema)
                        raise errors.ConfigurationError(
                            f'expected a {desc.type.__name__} value, '
                            f'got {dispname!r}')
                    else:
                        config_vals[name] = val

            else:
                raise RuntimeError(
                    f'unsupported SET command type {type(item)!r}')

        aliases = immutables.Map(aliases)
        config_vals = immutables.Map(config_vals)

        if aliases:
            ctx.state.current_tx().update_modaliases(
                ctx.state.current_tx().get_modaliases().update(aliases))
        if config_vals:
            ctx.state.current_tx().update_config(
                ctx.state.current_tx().get_config().update(config_vals))

        return dbstate.SessionStateQuery(sess_set_modaliases=aliases,
                                         sess_set_config=config_vals)
Exemple #3
0
    def _add(self, id, scls, data) -> 'Schema':
        name = data['name']

        if name in self._name_to_id:
            raise errors.SchemaError(
                f'{type(scls).__name__} {name!r} is already present '
                f'in the schema {self!r}')

        data = immu.Map(data)

        name_to_id, shortname_to_id = self._update_obj_name(
            id, scls, None, name)

        updates = dict(
            id_to_data=self._id_to_data.set(id, data),
            id_to_type=self._id_to_type.set(id, scls),
            name_to_id=name_to_id,
            shortname_to_id=shortname_to_id,
            refs_to=self._update_refs_to(scls, None, data),
        )

        if isinstance(scls, s_modules.Module):
            updates['modules'] = self._modules.set(name, id)
        elif name.module not in self._modules:
            raise errors.UnknownModuleError(
                f'module {name.module!r} is not in this schema')

        return self._replace(**updates)
Exemple #4
0
    def _compile_ql_sess_state(self, ctx: CompileContext,
                               ql: qlast.BaseSessionCommand):
        current_tx = ctx.state.current_tx()
        schema = current_tx.get_schema()

        aliases = ctx.state.current_tx().get_modaliases()

        sqlbuf = []

        alias_tpl = lambda alias, module: f'''
            INSERT INTO _edgecon_state(name, value, type)
            VALUES (
                {pg_ql(alias or '')},
                {pg_ql(module)},
                'A'
            )
            ON CONFLICT (name, type) DO
            UPDATE
                SET value = {pg_ql(module)};
        '''.encode()

        if isinstance(ql, qlast.SessionSetAliasDecl):
            try:
                schema.get_global(s_mod.Module, ql.module)
            except errors.InvalidReferenceError:
                raise errors.UnknownModuleError(
                    f'module {ql.module!r} does not exist') from None

            aliases = aliases.set(ql.alias, ql.module)

            if not self._bootstrap_mode:
                sql = alias_tpl(ql.alias, ql.module)
                sqlbuf.append(sql)

        elif isinstance(ql, qlast.SessionResetModule):
            aliases = aliases.set(None, defines.DEFAULT_MODULE_ALIAS)

            if not self._bootstrap_mode:
                sql = alias_tpl('', defines.DEFAULT_MODULE_ALIAS)
                sqlbuf.append(sql)

        elif isinstance(ql, qlast.SessionResetAllAliases):
            aliases = DEFAULT_MODULE_ALIASES_MAP

            if not self._bootstrap_mode:
                sqlbuf.append(
                    b"DELETE FROM _edgecon_state s WHERE s.type = 'A';")
                sqlbuf.append(alias_tpl('', defines.DEFAULT_MODULE_ALIAS))

        elif isinstance(ql, qlast.SessionResetAliasDecl):
            aliases = aliases.delete(ql.alias)

            if not self._bootstrap_mode:
                sql = f'''
                    DELETE FROM _edgecon_state s
                    WHERE s.name = {pg_ql(ql.alias)} AND s.type = 'A';
                '''.encode()
                sqlbuf.append(sql)

        else:  # pragma: no cover
            raise errors.InternalServerError(
                f'unsupported SET command type {type(ql)!r}')

        ctx.state.current_tx().update_modaliases(aliases)

        if len(sqlbuf) == 1:
            sql = sqlbuf[0]
        else:
            sql = b'''
            DO LANGUAGE plpgsql $$ BEGIN
            %b
            END; $$;
            ''' % (b''.join(sqlbuf))

        return dbstate.SessionStateQuery(sql=(sql, ), )