Repository: edgedb/edgedb

Issue:
Role created in a transaction is not picked up
* EdgeDB 3.2+bb17a05

1. Create a role in a transaction:

```
edgedb> start transaction; create superuser role first { set password := 'test' }; commit;
OK: START TRANSACTION
OK: CREATE ROLE
OK: COMMIT TRANSACTION
```

2. Further role creation fails:

```
edgedb> create superuser role second { set password := 'test' };
edgedb error: TransactionSerializationError: Cannot serialize global DDL: 9c163644-3d42-11ee-b687-cf8f6c6f80f7
```

3. Cannot connect with the newly-created role:

```
$ echo test | edgedb --user first --password-from-stdin query 'select 42'
edgedb error: AuthenticationError: authentication failed
  Server traceback:
      Traceback (most recent call last):
        File "edb/server/protocol/frontend.pyx", line 294, in edb.server.protocol.frontend.FrontendConnection.main
        File "edb/server/protocol/binary.pyx", line 1022, in authenticate
        File "edb/server/protocol/binary.pyx", line 282, in auth
        File "edb/server/protocol/frontend.pyx", line 534, in _authenticate
        File "edb/server/protocol/frontend.pyx", line 643, in _auth_scram
      edb.errors.AuthenticationError: authentication failed
```

4. Restart the instance:

```
$ edgedb instance restart  -I instance_name
[systemctl] Warning: Stopping edgedb-server@new.service, but it can still be activated by:
[systemctl]   edgedb-server@new.socket
```

5. The newly-created role is picked up by the server:

```
$ echo test | edgedb --user first --password-from-stdin query 'select 42'
42
```


Discussion:

Resolving patch:
diff --git a/edb/server/compiler/compiler.py b/edb/server/compiler/compiler.py
--- a/edb/server/compiler/compiler.py
+++ b/edb/server/compiler/compiler.py
@@ -2222,6 +2222,8 @@ def _try_compile(
             if comp.cached_reflection is not None:
                 unit.cached_reflection = \
                     pickle.dumps(comp.cached_reflection, -1)
+            if comp.global_schema is not None:
+                unit.global_schema = pickle.dumps(comp.global_schema, -1)
 
             if comp.modaliases is not None:
                 unit.modaliases = comp.modaliases


Test patch:
diff --git a/tests/test_server_auth.py b/tests/test_server_auth.py
--- a/tests/test_server_auth.py
+++ b/tests/test_server_auth.py
@@ -390,3 +390,25 @@ async def test_server_auth_jwt_2(self):
                 'authentication failed: revoked key',
             ):
                 await sd.connect(secret_key=sk)
+
+    async def test_server_auth_in_transaction(self):
+        if not self.has_create_role:
+            self.skipTest('create role is not supported by the backend')
+
+        async with self.con.transaction():
+            await self.con.query('''
+                CREATE SUPERUSER ROLE foo {
+                    SET password := 'foo-pass';
+                };
+            ''')
+
+        try:
+            conn = await self.connect(
+                user='foo',
+                password='foo-pass',
+            )
+            await conn.aclose()
+        finally:
+            await self.con.query('''
+                DROP ROLE foo;
+            ''')