Repository: edgedb/edgedb

Issue:
`InternalServerError` when creating a migration for a simple schema with a mutation rewrite
<!-- Please search existing issues to avoid creating duplicates. -->
Maybe I jumped the gun trying to document migration rewrites? I assumed since #4937 is closed, that meant it was ready to go.

Whatever the case, we have an ISE when I try to create a migration for the schema at the bottom of the ticket.

Stack trace:
```
edgedb error: InternalServerError: 'NoneType' object has no attribute 'module'
  Hint: This is most likely a bug in EdgeDB. Please consider opening an issue ticket at https://github.com/edgedb/edgedb/issues/new?template=bug_report.md
  Server traceback:
      Traceback (most recent call last):
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/server/compiler_pool/worker_proc.py", line 55, in worker
          res = meth(*args)
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/server/compiler_pool/worker.py", line 161, in compile
          units, cstate = COMPILER.compile(
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 742, in compile
          unit_group = compile(ctx=ctx, source=source)
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 1847, in compile
          return _try_compile(ctx=ctx, source=source)
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 1915, in _try_compile
          comp, capabilities = _compile_dispatch_ql(
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 1759, in _compile_dispatch_ql
          query = ddl.compile_dispatch_ql_migration(
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/server/compiler/ddl.py", line 380, in compile_dispatch_ql_migration
          return _start_migration(ctx, ql, in_script)
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/server/compiler/ddl.py", line 461, in _start_migration
          target_schema = s_ddl.apply_sdl(
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/schema/ddl.py", line 451, in apply_sdl
          ddl_stmts = s_decl.sdl_to_ddl(current_schema, documents)
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/edgeql/declarative.py", line 449, in sdl_to_ddl
          trace_dependencies(decl_ast, ctx=tracectx)
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/functools.py", line 889, in wrapper
          return dispatch(args[0].__class__)(*args, **kw)
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/edgeql/declarative.py", line 1023, in trace_default
          _register_item(node, ctx=ctx)
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/edgeql/declarative.py", line 1155, in _register_item
          trace_dependencies(cmd, ctx=ctx)
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/functools.py", line 889, in wrapper
          return dispatch(args[0].__class__)(*args, **kw)
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/edgeql/declarative.py", line 935, in trace_ConcretePointer
          _register_item(
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/edgeql/declarative.py", line 1155, in _register_item
          trace_dependencies(cmd, ctx=ctx)
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/functools.py", line 889, in wrapper
          return dispatch(args[0].__class__)(*args, **kw)
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/edgeql/declarative.py", line 888, in trace_Rewrite
          _register_item(
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/edgeql/declarative.py", line 1045, in _register_item
          name, fq_name = ctx.get_fq_name(decl)
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/edgeql/declarative.py", line 141, in get_fq_name
          fq_name = self.get_local_name(decl.name)
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/edgeql/declarative.py", line 103, in get_local_name
          return qltracer.resolve_name(
        File "/Users/raddevon/Library/Application Support/edgedb/portable/3.0-dev.7347/lib/python3.10/site-packages/edb/edgeql/tracer.py", line 355, in resolve_name
          module = ref.module
      AttributeError: 'NoneType' object has no attribute 'module'
```

<!--
For the EdgeDB Version: run `edgedb query 'select sys::get_version_as_str()'` from your project directory (or run `select sys::get_version_as_str();` in the EdgeDB interactive shell).
For the EdgeDB CLI Version: Run `edgedb --version` from anywhere
-->

- EdgeDB Version: 3.0-dev.7347+d606ad0
- EdgeDB CLI Version: 3.0.0-dev.942+88ca902
- OS Version: macOS 13.2.1

Steps to Reproduce:

1. Create a new project on nightly with `edgedb project init --non-interactive --server-version nightly`
2. Add the schema below to `default.esdl`
3. Run `edgedb migration create`

<!-- If the issue is about a query error, please also provide your schema -->

Schema:

```
module default {
  type Post {
    required title: str;
    modified: datetime {
      rewrite insert, update using (datetime_of_statement())
    }
  }
}
```



Discussion:

Resolving patch:
diff --git a/edb/edgeql/parser/grammar/sdl.py b/edb/edgeql/parser/grammar/sdl.py
--- a/edb/edgeql/parser/grammar/sdl.py
+++ b/edb/edgeql/parser/grammar/sdl.py
@@ -727,7 +727,11 @@ def reduce_CreateRewrite(self, _r, kinds, _u, expr, commands):
             USING ParenExpr
             CreateRewriteSDLCommandsBlock
         """
+        # The name isn't important (it gets replaced) but we need to
+        # have one.
+        name = '/'.join(str(kind) for kind in kinds.val)
         self.val = qlast.CreateRewrite(
+            name=qlast.ObjectRef(name=name),
             kinds=kinds.val,
             expr=expr.val,
             commands=commands.val,
@@ -740,7 +744,11 @@ def reduce_CreateRewrite(self, _r, kinds, _u, expr):
             REWRITE RewriteKindList
             USING ParenExpr
         """
+        # The name isn't important (it gets replaced) but we need to
+        # have one.
+        name = '/'.join(str(kind) for kind in kinds.val)
         self.val = qlast.CreateRewrite(
+            name=qlast.ObjectRef(name=name),
             kinds=kinds.val,
             expr=expr.val,
         )
diff --git a/edb/pgsql/delta.py b/edb/pgsql/delta.py
--- a/edb/pgsql/delta.py
+++ b/edb/pgsql/delta.py
@@ -863,6 +863,13 @@ class RebaseRewrite(
     pass
 
 
+class RenameRewrite(
+    RewriteCommand,
+    adapts=s_rewrites.RenameRewrite,
+):
+    pass
+
+
 class AlterRewrite(
     RewriteCommand,
     adapts=s_rewrites.AlterRewrite,
diff --git a/edb/schema/rewrites.py b/edb/schema/rewrites.py
--- a/edb/schema/rewrites.py
+++ b/edb/schema/rewrites.py
@@ -52,9 +52,10 @@ class Rewrite(
         special_ddl_syntax=True,
     )
 
+    # 0.0 because we don't support ALTER yet
     expr = so.SchemaField(
         s_expr.Expression,
-        compcoef=0.909,
+        compcoef=0.0,
         special_ddl_syntax=True,
     )
 
@@ -239,9 +240,12 @@ def _cmd_tree_from_ast(
 
         for kind in astnode.kinds:
             # use kind for the name
-            astnode.name = qlast.ObjectRef(name=str(kind))
+            newnode = astnode.replace(
+                name=qlast.ObjectRef(module='__', name=str(kind)),
+                kinds=kind,
+            )
 
-            cmd = super()._cmd_tree_from_ast(schema, astnode, context)
+            cmd = super()._cmd_tree_from_ast(schema, newnode, context)
             assert isinstance(cmd, RewriteCommand)
 
             cmd.set_attribute_value('kind', kind)
@@ -293,6 +297,19 @@ def _cmd_tree_from_ast(
             )
         return group
 
+    def _apply_field_ast(
+        self,
+        schema: s_schema.Schema,
+        context: sd.CommandContext,
+        node: qlast.DDLOperation,
+        op: sd.AlterObjectProperty,
+    ) -> None:
+        if op.property == 'kind':
+            assert isinstance(node, qlast.CreateRewrite)
+            node.kinds = [self.get_attribute_value('kind')]
+        else:
+            super()._apply_field_ast(schema, context, node, op)
+
 
 class RebaseRewrite(
     RewriteCommand,
@@ -301,6 +318,13 @@ class RebaseRewrite(
     pass
 
 
+class RenameRewrite(
+    RewriteCommand,
+    referencing.RenameReferencedInheritingObject[Rewrite],
+):
+    pass
+
+
 class AlterRewrite(
     RewriteCommand,
     referencing.AlterReferencedInheritingObject[Rewrite],
@@ -333,3 +357,16 @@ class DeleteRewrite(
     referencing.DeleteReferencedInheritingObject[Rewrite],
 ):
     referenced_astnode = astnode = qlast.DropRewrite
+
+    def _get_ast(
+        self,
+        schema: s_schema.Schema,
+        context: sd.CommandContext,
+        *,
+        parent_node: Optional[qlast.DDLOperation] = None,
+    ) -> Optional[qlast.DDLOperation]:
+        node = super()._get_ast(schema, context, parent_node=parent_node)
+        assert isinstance(node, qlast.DropRewrite)
+        skind = sn.shortname_from_fullname(self.classname).name
+        node.kinds = [qltypes.RewriteKind(skind)]
+        return node


Test patch:
diff --git a/tests/test_edgeql_data_migration.py b/tests/test_edgeql_data_migration.py
--- a/tests/test_edgeql_data_migration.py
+++ b/tests/test_edgeql_data_migration.py
@@ -11181,6 +11181,33 @@ async def test_edgeql_migration_globals_01(self):
         await self.migrate(schema)
         await self.migrate(schema)
 
+    async def test_edgeql_migration_dml_rewrites_01(self):
+        await self.migrate(r"""
+            type Post {
+              required title: str;
+              modified: datetime {
+                rewrite insert, update using (datetime_of_statement())
+              }
+            }
+        """)
+        await self.migrate(r"""
+            type BlogPost {
+              required title: str;
+              modified: datetime {
+                rewrite insert, update using (datetime_of_statement())
+              }
+            }
+        """)
+        await self.migrate(r"""
+            type BlogPost {
+              required title: str;
+              modified: datetime {
+                rewrite insert, update using (datetime_of_transaction())
+              }
+            }
+        """)
+        await self.migrate('')
+
     async def test_edgeql_migration_globals_02(self):
         await self.migrate(r"""
             global current_user_id -> uuid;