Repository: edgedb/edgedb

Issue:
ISE on `unless conflict` when setting custom `id`
On 2.0, the following causes an ISE. I've enabled `allow_user_specified_id`.

```
INSERT default::Hero {
   name := "asdf",
   id := <uuid>"00000000-0000-0000-0000-000000000000"
} 
UNLESS CONFLICT;
```

This works with `unless conflict on (.id)` or when not setting a custom `id`.

-------


Full traceback:


```
edgedb> INSERT default::Hero {
.......    name := "asdf",
.......    id := <uuid>"00000000-0000-0000-0000-000000000000"
....... } 
....... UNLESS CONFLICT;
edgedb error: InternalServerError: 
  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/colinmcd94/Library/Application Support/edgedb/portable/2.0/lib/python3.10/site-packages/edb/server/compiler_pool/worker_proc.py", line 55, in worker
          res = meth(*args)
        File "/Users/colinmcd94/Library/Application Support/edgedb/portable/2.0/lib/python3.10/site-packages/edb/server/compiler_pool/worker.py", line 160, in compile
          units, cstate = COMPILER.compile(
        File "/Users/colinmcd94/Library/Application Support/edgedb/portable/2.0/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 2207, in compile
          unit_group = self._compile(ctx=ctx, source=source)
        File "/Users/colinmcd94/Library/Application Support/edgedb/portable/2.0/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 1738, in _compile
          return self._try_compile(ctx=ctx, source=source)
        File "/Users/colinmcd94/Library/Application Support/edgedb/portable/2.0/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 1802, in _try_compile
          comp, capabilities = self._compile_dispatch_ql(
        File "/Users/colinmcd94/Library/Application Support/edgedb/portable/2.0/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 1712, in _compile_dispatch_ql
          query = self._compile_ql_query(ctx, ql, script_info=script_info)
        File "/Users/colinmcd94/Library/Application Support/edgedb/portable/2.0/lib/python3.10/site-packages/edb/server/compiler/compiler.py", line 621, in _compile_ql_query
          ir = qlcompiler.compile_ast_to_ir(
        File "/Users/colinmcd94/Library/Application Support/edgedb/portable/2.0/lib/python3.10/site-packages/edb/edgeql/compiler/__init__.py", line 179, in wrapper
          return func(*args, **kwargs)
        File "/Users/colinmcd94/Library/Application Support/edgedb/portable/2.0/lib/python3.10/site-packages/edb/edgeql/compiler/__init__.py", line 237, in compile_ast_to_ir
          ir_set = dispatch_mod.compile(tree, ctx=ctx)
        File "/Users/colinmcd94/Library/Application Support/edgedb/portable/2.0/lib/python3.10/functools.py", line 889, in wrapper
          return dispatch(args[0].__class__)(*args, **kw)
        File "/Users/colinmcd94/Library/Application Support/edgedb/portable/2.0/lib/python3.10/site-packages/edb/edgeql/compiler/stmt.py", line 507, in compile_InsertQuery
          stmt.on_conflict = conflicts.compile_insert_unless_conflict(
        File "/Users/colinmcd94/Library/Application Support/edgedb/portable/2.0/lib/python3.10/site-packages/edb/edgeql/compiler/conflicts.py", line 430, in compile_insert_unless_conflict
          assert not _has_explicit_id_write(stmt)
      AssertionError
```


Discussion:

Resolving patch:
diff --git a/edb/edgeql/compiler/conflicts.py b/edb/edgeql/compiler/conflicts.py
--- a/edb/edgeql/compiler/conflicts.py
+++ b/edb/edgeql/compiler/conflicts.py
@@ -419,7 +419,9 @@ def compile_insert_unless_conflict(
     This requires synthesizing a conditional based on all the exclusive
     constraints on the object.
     """
-    pointers = _get_exclusive_ptr_constraints(typ, include_id=False, ctx=ctx)
+    has_id_write = _has_explicit_id_write(stmt)
+    pointers = _get_exclusive_ptr_constraints(
+        typ, include_id=has_id_write, ctx=ctx)
     obj_constrs = typ.get_constraints(ctx.env.schema).objects(ctx.env.schema)
 
     select_ir, always_check, _ = compile_conflict_select(
@@ -427,7 +429,6 @@ def compile_insert_unless_conflict(
         constrs=pointers,
         obj_constrs=obj_constrs,
         parser_context=stmt.context, ctx=ctx)
-    assert not _has_explicit_id_write(stmt)
 
     return irast.OnConflictClause(
         constraint=None, select_ir=select_ir, always_check=always_check,


Test patch:
diff --git a/tests/test_edgeql_insert.py b/tests/test_edgeql_insert.py
--- a/tests/test_edgeql_insert.py
+++ b/tests/test_edgeql_insert.py
@@ -5324,6 +5324,58 @@ async def test_edgeql_insert_explicit_id_04(self):
                 };
             ''')
 
+    async def test_edgeql_insert_explicit_id_05(self):
+        await self.con.execute('''
+            configure session set allow_user_specified_id := true
+        ''')
+
+        await self.con.execute('''
+            INSERT Person {
+                id := <uuid>'ffffffff-ffff-ffff-ffff-ffffffffffff',
+                name := "test",
+             }
+        ''')
+
+        await self.assert_query_result(
+            r'''
+                INSERT Person {
+                    id := <uuid>'ffffffff-ffff-ffff-ffff-ffffffffffff',
+                    name := "test",
+                 } UNLESS CONFLICT
+            ''',
+            []
+        )
+
+        await self.assert_query_result(
+            r'''
+                INSERT Person {
+                    id := <uuid>'ffffffff-ffff-ffff-ffff-ffffffffffff',
+                    name := "test",
+                 } UNLESS CONFLICT ON (.id)
+            ''',
+            []
+        )
+
+        await self.assert_query_result(
+            r'''
+                INSERT Note {
+                    id := <uuid>'ffffffff-ffff-ffff-ffff-ffffffffffff',
+                    name := "test",
+                 } UNLESS CONFLICT
+            ''',
+            []
+        )
+
+        await self.assert_query_result(
+            r'''
+                INSERT Note {
+                    id := <uuid>'ffffffff-ffff-ffff-ffff-ffffffffffff',
+                    name := "test",
+                 } UNLESS CONFLICT ON (.id)
+            ''',
+            []
+        )
+
     async def test_edgeql_insert_except_constraint_01(self):
         # Test basic behavior of a constraint using except
         await self.con.execute('''