Repository: edgedb/edgedb

Issue:
ISE when validation within a rewrite fails
- EdgeDB Version: Current master
- EdgeDB CLI Version: dev
- OS Version: Linux

Steps to Reproduce:

1. Just migrate to this schema


Schema:

```
module default {

    
    type User {
        
        required password: str;
        
        multi link projects := .<owner[is Project];

        link default_project: Project {
            rewrite insert using (
                insert Project {
                    
                    owner := __subject__,
                }
            )
        };
    }

    type Project {
        required name: str;
        required owner: User;

        constraint exclusive on ( (.name, .owner) );
    }
}
```


Discussion:
Oh huh, it's not an internal server error, but since the error it is an `ExecutionError`, the CLI doesn't think it makes sense to happen during migrations. It doesn't have an error context either!

Resolving patch:
diff --git a/edb/edgeql/compiler/stmt.py b/edb/edgeql/compiler/stmt.py
--- a/edb/edgeql/compiler/stmt.py
+++ b/edb/edgeql/compiler/stmt.py
@@ -479,7 +479,9 @@ def compile_InsertQuery(
                 view_rptr=ctx.view_rptr,
                 compile_views=True,
                 exprtype=s_types.ExprType.Insert,
-                ctx=bodyctx)
+                ctx=bodyctx,
+                parser_context=expr.context,
+            )
 
         stmt_subject_stype = setgen.get_set_type(subject, ctx=ictx)
         assert isinstance(stmt_subject_stype, s_objtypes.ObjectType)
@@ -510,6 +512,7 @@ def compile_InsertQuery(
                 view_name=ctx.toplevel_result_view_name,
                 compile_views=ictx.stmt is ictx.toplevel_stmt,
                 ctx=resultctx,
+                parser_context=expr.context,
             )
 
         if pol_condition := policies.compile_dml_write_policies(
@@ -537,7 +540,8 @@ def compile_InsertQuery(
                     view_name=ctx.toplevel_result_view_name,
                     compile_views=ictx.stmt is ctx.toplevel_stmt,
                     ctx=resultctx,
-                    parser_context=result.context)
+                    parser_context=result.context,
+                )
 
     return result
 
@@ -619,7 +623,9 @@ def compile_UpdateQuery(
                 view_rptr=ctx.view_rptr,
                 compile_views=True,
                 exprtype=s_types.ExprType.Update,
-                ctx=bodyctx)
+                ctx=bodyctx,
+                parser_context=expr.context,
+            )
 
         result = setgen.class_set(
             mat_stype, path_id=stmt.subject.path_id, ctx=ctx,
@@ -632,6 +638,7 @@ def compile_UpdateQuery(
                 view_name=ctx.toplevel_result_view_name,
                 compile_views=ictx.stmt is ictx.toplevel_stmt,
                 ctx=resultctx,
+                parser_context=expr.context,
             )
 
         for dtype in schemactx.get_all_concrete(mat_stype, ctx=ctx):
@@ -743,6 +750,7 @@ def compile_DeleteQuery(
                 shape=None,
                 exprtype=s_types.ExprType.Delete,
                 ctx=bodyctx,
+                parser_context=expr.context,
             )
 
         result = setgen.class_set(
@@ -756,6 +764,7 @@ def compile_DeleteQuery(
                 view_name=ctx.toplevel_result_view_name,
                 compile_views=ictx.stmt is ictx.toplevel_stmt,
                 ctx=resultctx,
+                parser_context=expr.context,
             )
 
         for dtype in schemactx.get_all_concrete(mat_stype, ctx=ctx):
@@ -1357,7 +1366,7 @@ def compile_query_subject(
         exprtype: s_types.ExprType = s_types.ExprType.Select,
         allow_select_shape_inject: bool=True,
         forward_rptr: bool=False,
-        parser_context: Optional[pctx.ParserContext]=None,
+        parser_context: Optional[pctx.ParserContext],
         ctx: context.ContextLevel) -> irast.Set:
 
     expr_stype = setgen.get_set_type(expr, ctx=ctx)
@@ -1475,6 +1484,7 @@ def compile_query_subject(
             view_name=view_name,
             exprtype=exprtype,
             ctx=ctx,
+            srcctx=parser_context,
         )
 
     if view_scls is not None:
@@ -1510,6 +1520,7 @@ def maybe_add_view(ir: irast.Set, *, ctx: context.ContextLevel) -> irast.Set:
         and ir.path_id.is_objtype_path()
     ):
         return compile_query_subject(
-            ir, allow_select_shape_inject=True, compile_views=False, ctx=ctx)
+            ir, allow_select_shape_inject=True, compile_views=False, ctx=ctx,
+            parser_context=ir.context)
     else:
         return ir
diff --git a/edb/edgeql/compiler/viewgen.py b/edb/edgeql/compiler/viewgen.py
--- a/edb/edgeql/compiler/viewgen.py
+++ b/edb/edgeql/compiler/viewgen.py
@@ -29,6 +29,7 @@
 
 from edb import errors
 from edb.common import ast
+from edb.common import parsing
 from edb.common import topological
 from edb.common.typeutils import downcast, not_none
 
@@ -121,6 +122,7 @@ def process_view(
     view_name: Optional[sn.QualName] = None,
     exprtype: s_types.ExprType = s_types.ExprType.Select,
     ctx: context.ContextLevel,
+    srcctx: Optional[parsing.ParserContext],
 ) -> Tuple[s_objtypes.ObjectType, irast.Set]:
 
     cache_key = (stype, exprtype, tuple(elements))
@@ -154,6 +156,7 @@ def process_view(
         elements=elements,
         ctx=ctx,
         s_ctx=s_ctx,
+        srcctx=srcctx,
     )
 
     ctx.env.shape_type_cache[cache_key] = view_scls
@@ -168,6 +171,7 @@ def _process_view(
     elements: Optional[Sequence[qlast.ShapeElement]],
     s_ctx: ShapeContext,
     ctx: context.ContextLevel,
+    srcctx: Optional[parsing.ParserContext],
 ) -> Tuple[s_objtypes.ObjectType, irast.Set]:
     path_id = ir_set.path_id
     view_rptr = s_ctx.view_rptr
@@ -437,7 +441,7 @@ def _process_view(
         rewrites = None
 
     if s_ctx.exprtype.is_insert():
-        _raise_on_missing(pointers, stype, rewrites, ctx)
+        _raise_on_missing(pointers, stype, rewrites, ctx, srcctx=srcctx)
 
     set_shape = []
     shape_ptrs: List[ShapePtr] = []
@@ -801,6 +805,7 @@ def _raise_on_missing(
     stype: s_objtypes.ObjectType,
     rewrites: Optional[irast.Rewrites],
     ctx: context.ContextLevel,
+    srcctx: Optional[parsing.ParserContext],
 ) -> None:
     pointer_names = {
         ptr.get_local_name(ctx.env.schema) for ptr in pointers
@@ -838,8 +843,16 @@ def _raise_on_missing(
                 continue
 
         vn = ptrcls.get_verbosename(ctx.env.schema, with_parent=True)
-        raise errors.MissingRequiredError(
-            f"missing value for required {vn}"
+        # If this is happening in the context of DDL, report a
+        # QueryError because it is weird to report an ExecutionError
+        # (MissingRequiredError) when nothing is really executing.
+        errcls = (
+            errors.SchemaDefinitionError
+            if ctx.env.options.schema_object_context
+            else errors.MissingRequiredError
+        )
+        raise errcls(
+            f"missing value for required {vn}", context=srcctx
         )
 
 


Test patch:
diff --git a/tests/test_schema.py b/tests/test_schema.py
--- a/tests/test_schema.py
+++ b/tests/test_schema.py
@@ -1336,6 +1336,27 @@ def test_schema_constraint_inheritance_13(self):
             }
         """
 
+    @tb.must_fail(errors.SchemaDefinitionError,
+                  "missing value for required property",
+                  line=9, col=42)
+    def test_schema_rewrite_missing_required_01(self):
+        """
+            type Project {
+                required name: str;
+                required owner: User;
+            }
+
+            type User {
+                link default_project: Project {
+                    rewrite insert using (
+                        insert Project {
+                            owner := __subject__,
+                        }
+                    )
+                };
+            }
+        """
+
     def test_schema_property_cardinality_alter_01(self):
         schema = self.load_schema('''
             type Foo {