Exemple #1
0
    async def run_ddl_command(self, ddl_plan):
        schema = self.schema

        if debug.flags.delta_plan_input:
            debug.header('Delta Plan Input')
            debug.dump(ddl_plan)

        # Do a dry-run on test_schema to canonicalize
        # the schema delta-commands.
        test_schema = schema
        context = self.create_context()
        canonical_ddl_plan = ddl_plan.copy()
        canonical_ddl_plan.apply(test_schema, context=context)

        # Apply and adapt delta, build native delta plan, which
        # will also update the schema.
        schema, plan = self.process_delta(canonical_ddl_plan, schema)

        context = self.create_context(delta_cmds)

        if isinstance(plan, (s_db.CreateDatabase, s_db.DropDatabase)):
            block = dbops.SQLBlock()
        else:
            block = dbops.PLTopBlock()

        plan.generate(block)
        ql_text = block.to_string()

        await self._execute_ddl(ql_text)
        self.schema = schema
Exemple #2
0
    async def run_ddl_command(self, ddl_plan):
        schema = await self.getschema()

        if debug.flags.delta_plan_input:
            debug.header('Delta Plan Input')
            debug.dump(ddl_plan)

        # Do a dry-run on test_schema to canonicalize
        # the schema delta-commands.
        test_schema = await self._intro_mech.readschema()
        context = sd.CommandContext()
        canonical_ddl_plan = ddl_plan.copy()
        canonical_ddl_plan.apply(test_schema, context=context)

        # Apply and adapt delta, build native delta plan, which
        # will also update the schema.
        plan = self.process_delta(canonical_ddl_plan, schema)

        context = delta_cmds.CommandContext(self.connection)

        try:
            if not isinstance(plan, (s_db.CreateDatabase, s_db.DropDatabase)):
                async with self.connection.transaction():
                    # Execute all pgsql/delta commands.
                    await plan.execute(context)
            else:
                await plan.execute(context)
        except Exception as e:
            raise RuntimeError('failed to apply delta to data backend') from e
        finally:
            # Exception or not, re-read the schema from Postgres.
            await self.invalidate_schema_cache()
            await self.getschema()
Exemple #3
0
    def _compile_and_apply_ddl_command(self, ctx: CompileContext, cmd):
        current_tx = ctx.state.current_tx()
        schema = current_tx.get_schema()

        if debug.flags.delta_plan_input:
            debug.header('Delta Plan Input')
            debug.dump(cmd)

        # Do a dry-run on test_schema to canonicalize
        # the schema delta-commands.
        test_schema = schema
        context = self._new_delta_context(ctx)
        cmd.apply(test_schema, context=context)

        # Apply and adapt delta, build native delta plan, which
        # will also update the schema.
        schema, plan = self._process_delta(ctx, cmd, schema)

        if isinstance(plan, (s_db.CreateDatabase, s_db.DropDatabase)):
            block = pg_dbops.SQLBlock()
        else:
            block = pg_dbops.PLTopBlock()

        plan.generate(block)
        sql = block.to_string().encode('utf-8')

        current_tx.update_schema(schema)

        return dbstate.DDLQuery(sql=sql)
Exemple #4
0
    async def _load_std(self):
        schema = s_schema.Schema()

        current_block = None

        std_texts = []
        for modname in s_schema.STD_LIB + ['stdgraphql']:
            std_texts.append(s_std.get_std_module_text(modname))

        ddl_text = '\n'.join(std_texts)

        for ddl_cmd in edgeql.parse_block(ddl_text):
            delta_command = s_ddl.delta_from_ddl(
                ddl_cmd, schema=schema, modaliases={None: 'std'}, stdmode=True)

            if debug.flags.delta_plan_input:
                debug.header('Delta Plan Input')
                debug.dump(delta_command)

            # Do a dry-run on test_schema to canonicalize
            # the schema delta-commands.
            test_schema = schema
            context = self.create_context(stdmode=True)
            canonical_delta = delta_command.copy()
            canonical_delta.apply(test_schema, context=context)

            # Apply and adapt delta, build native delta plan, which
            # will also update the schema.
            schema, plan = self.process_delta(canonical_delta, schema,
                                              stdmode=True)

            if isinstance(plan, (s_db.CreateDatabase, s_db.DropDatabase)):
                if (current_block is not None and
                        not isinstance(current_block, dbops.SQLBlock)):
                    raise errors.QueryError(
                        'cannot mix DATABASE commands with regular DDL '
                        'commands in a single block')
                if current_block is None:
                    current_block = dbops.SQLBlock()

            else:
                if (current_block is not None and
                        not isinstance(current_block, dbops.PLTopBlock)):
                    raise errors.QueryError(
                        'cannot mix DATABASE commands with regular DDL '
                        'commands in a single block')
                if current_block is None:
                    current_block = dbops.PLTopBlock()

            plan.generate(current_block)

        sql_text = current_block.to_string()

        return schema, sql_text
Exemple #5
0
def compile_ast_to_ir(tree,
                      schema,
                      *,
                      anchors=None,
                      singletons=None,
                      func=None,
                      security_context=None,
                      derived_target_module=None,
                      result_view_name=None,
                      modaliases=None,
                      implicit_id_in_shapes=False,
                      schema_view_mode=False):
    """Compile given EdgeQL AST into EdgeDB IR."""

    if debug.flags.edgeql_compile:
        debug.header('EdgeQL AST')
        debug.dump(tree, schema=schema)

    ctx = stmtctx.init_context(schema=schema,
                               anchors=anchors,
                               singletons=singletons,
                               modaliases=modaliases,
                               security_context=security_context,
                               func=func,
                               derived_target_module=derived_target_module,
                               result_view_name=result_view_name,
                               implicit_id_in_shapes=implicit_id_in_shapes,
                               schema_view_mode=schema_view_mode)

    ir_set = dispatch.compile(tree, ctx=ctx)
    ir_expr = stmtctx.fini_expression(ir_set, ctx=ctx)

    if ctx.env.query_parameters:
        first_argname = next(iter(ctx.env.query_parameters))
        if first_argname.isdecimal():
            args_decnames = {int(arg) for arg in ctx.env.query_parameters}
            args_tpl = set(range(len(ctx.env.query_parameters)))
            if args_decnames != args_tpl:
                missing_args = args_tpl - args_decnames
                missing_args_repr = ', '.join(f'${a}' for a in missing_args)
                raise errors.QueryError(
                    f'missing {missing_args_repr} positional argument'
                    f'{"s" if len(missing_args) > 1 else ""}')

    if debug.flags.edgeql_compile:
        debug.header('Scope Tree')
        if ctx.path_scope is not None:
            print(ctx.path_scope.pdebugformat())
        else:
            print('N/A')
        debug.header('EdgeDB IR')
        debug.dump(ir_expr, schema=getattr(ir_expr, 'schema', None))

    return ir_expr
Exemple #6
0
    def process_delta(self, delta, schema, *, stdmode=None):
        """Adapt and process the delta command."""

        if debug.flags.delta_plan:
            debug.header('Delta Plan')
            debug.dump(delta, schema=schema)

        delta = self.adapt_delta(delta)
        context = self.create_context(delta_cmds, stdmode)
        schema, _ = delta.apply(schema, context)

        if debug.flags.delta_pgsql_plan:
            debug.header('PgSQL Delta Plan')
            debug.dump(delta, schema=schema)

        return schema, delta
Exemple #7
0
    def process_delta(self, delta, schema):
        """Adapt and process the delta command."""

        if debug.flags.delta_plan:
            debug.header('Delta Plan')
            debug.dump(delta)

        delta = self.adapt_delta(delta)
        context = delta_cmds.CommandContext(self.connection)
        delta.apply(schema, context)

        if debug.flags.delta_pgsql_plan:
            debug.header('PgSQL Delta Plan')
            debug.dump(delta)

        return delta
Exemple #8
0
    def _process_delta(self, ctx: CompileContext, delta, schema):
        """Adapt and process the delta command."""

        if debug.flags.delta_plan:
            debug.header('Delta Plan')
            debug.dump(delta, schema=schema)

        delta = pg_delta.CommandMeta.adapt(delta)
        context = self._new_delta_context(ctx)
        schema, _ = delta.apply(schema, context)

        if debug.flags.delta_pgsql_plan:
            debug.header('PgSQL Delta Plan')
            debug.dump(delta, schema=schema)

        return schema, delta
Exemple #9
0
def compile_ir_to_sql(
        ir_expr: irast.Base,
        *,
        schema: s_schema.Schema,
        output_format: typing.Optional[OutputFormat] = None,
        ignore_shapes: bool = False,
        timer=None,
        use_named_params: bool = False,
        pretty: bool = True) -> typing.Tuple[str, typing.Dict[str, int]]:

    if timer is None:
        qtree = compile_ir_to_sql_tree(ir_expr,
                                       schema=schema,
                                       output_format=output_format,
                                       ignore_shapes=ignore_shapes,
                                       use_named_params=use_named_params)
    else:
        with timer.timeit('compile_ir_to_sql'):
            qtree = compile_ir_to_sql_tree(ir_expr,
                                           schema=schema,
                                           output_format=output_format,
                                           ignore_shapes=ignore_shapes,
                                           use_named_params=use_named_params)

    if debug.flags.edgeql_compile:  # pragma: no cover
        debug.header('SQL Tree')
        debug.dump(qtree, schema=schema)

    argmap = qtree.argnames

    # Generate query text
    if timer is None:
        codegen = _run_codegen(qtree, pretty=pretty)
    else:
        with timer.timeit('compile_ir_to_sql'):
            codegen = _run_codegen(qtree, pretty=pretty)

    sql_text = ''.join(codegen.result)

    if debug.flags.edgeql_compile:  # pragma: no cover
        debug.header('SQL')
        debug.dump_code(sql_text, lexer='sql')

    return sql_text, argmap
Exemple #10
0
def compile_ast_to_ir(tree,
                      schema,
                      *,
                      anchors=None,
                      arg_types=None,
                      security_context=None,
                      derived_target_module=None,
                      result_view_name=None,
                      modaliases=None,
                      implicit_id_in_shapes=False):
    """Compile given EdgeQL AST into EdgeDB IR."""

    if debug.flags.edgeql_compile:
        debug.header('EdgeQL AST')
        debug.dump(tree)

    ctx = stmtctx.init_context(schema=schema,
                               anchors=anchors,
                               modaliases=modaliases,
                               security_context=security_context,
                               arg_types=arg_types,
                               derived_target_module=derived_target_module,
                               result_view_name=result_view_name,
                               implicit_id_in_shapes=implicit_id_in_shapes)

    ir_set = dispatch.compile(tree, ctx=ctx)
    ir_expr = stmtctx.fini_expression(ir_set, ctx=ctx)

    if debug.flags.edgeql_compile:
        debug.header('Scope Tree')
        if ctx.path_scope is not None:
            print(ctx.path_scope.pdebugformat())
        else:
            print('N/A')
        debug.header('EdgeDB IR')
        debug.dump(ir_expr)

    return ir_expr
Exemple #11
0
    def send_error(self, err):
        try:
            srcctx = exceptions.get_context(err, parsing.ParserContext)
        except LookupError:
            srcctx = None

        try:
            hintctx = exceptions.get_context(
                err, exceptions.DefaultExceptionContext)
        except LookupError:
            hintctx = None

        if debug.flags.server:
            debug.header('Error')
            debug.dump(err)

        self.send_message({
            '__type__': 'error',
            'data': {
                'C':
                getattr(err, 'code', 0),
                'M':
                str(err),
                'D':
                hintctx.details if hintctx is not None else None,
                'H':
                hintctx.hint if hintctx is not None else None,
                'P': (srcctx.start.pointer if srcctx is not None
                      and srcctx.start is not None else None),
                'p': (srcctx.end.pointer if srcctx is not None
                      and srcctx.end is not None else None),
                'Q':
                markup.dumps(srcctx) if srcctx is not None else None,
                'T':
                traceback.format_tb(err.__traceback__),
            }
        })