# This tests ensures that transactions to perform grants on entities created
# inside of a transaction do not get blocked and take a very long time.

# We've seen this test fail under race due to a timeout, which is likely
# to happen in slower builds since the transaction is a large operation.
skip under race

statement ok
SET statement_timeout = '10s';

statement ok
CREATE DATABASE IF NOT EXISTS db1;

statement ok
CREATE DATABASE IF NOT EXISTS db2;

statement ok
BEGIN;

statement ok
CREATE TABLE IF NOT EXISTS db1.t ();

statement ok
CREATE TABLE IF NOT EXISTS db2.t ();

statement ok
CREATE USER user1;

statement ok
CREATE USER user2;

statement ok
CREATE USER user3;

statement ok
CREATE USER user4;

statement ok
CREATE USER user5;

statement ok
CREATE USER user6;

statement ok
CREATE USER user7;

statement ok
CREATE ROLE role1;

statement ok
CREATE ROLE role2;

statement ok
CREATE ROLE role3;

statement ok
CREATE ROLE role4;

statement ok
CREATE ROLE role5;

statement ok
CREATE ROLE role6;

statement ok
CREATE ROLE role7;

statement ok
CREATE ROLE role8;

statement ok
GRANT CREATE ON DATABASE db1 TO role1;

statement ok
GRANT CREATE ON TABLE db1.* TO role1;

statement ok
GRANT CREATE ON DATABASE db2 TO role1;

statement ok
GRANT select, insert, delete, update ON TABLE db2.* TO role1;

statement ok
GRANT role1 TO user5;

statement ok
GRANT role2 TO user7;

statement ok
GRANT CREATE ON DATABASE db1 TO role3;

statement ok
GRANT SELECT, INSERT, DELETE, UPDATE ON TABLE db1.* TO role3;

statement ok
GRANT ALL ON DATABASE db1 TO role4;

statement ok
GRANT ALL ON TABLE db1.* TO role4;

statement ok
GRANT ALL ON DATABASE db1 TO role5;

statement ok
GRANT ALL ON TABLE db1.* TO role5;

statement ok
GRANT role5 TO user1;

statement ok
GRANT CREATE ON DATABASE db2 TO role6;

statement ok
GRANT SELECT, INSERT, DELETE, UPDATE ON TABLE db2.* TO role6;

statement ok
GRANT ALL ON DATABASE db2 TO role7;

statement ok
GRANT ALL ON TABLE db2.* TO role7;

statement ok
GRANT ALL ON DATABASE db2 TO role8;

statement ok
GRANT ALL ON TABLE db2.* TO role8;

statement ok
GRANT admin TO user2;

statement ok
GRANT admin TO user4;

statement ok
GRANT admin TO role2;

statement ok
CREATE ROLE role9;

statement ok
GRANT role3 TO role9;

statement ok
GRANT role6 TO role9;

statement ok
GRANT role9 TO user1;

statement ok
CREATE ROLE role10;

statement ok
GRANT role4 TO role10;

statement ok
GRANT role7 TO role10;

statement ok
CREATE ROLE role11;

statement ok
GRANT role5 TO role11;

statement ok
GRANT role8 TO role11;

statement ok
GRANT role11 TO user6;

statement ok
DROP TABLE db1.t;

statement ok
DROP TABLE db2.t;

statement ok
COMMIT;

# Ensure that we can inspect information_schema.applicable_roles inside of a
# transaction. Prior to the change which introduces this

statement ok;
CREATE ROLE role_foo;

statement ok;
CREATE ROLE role_bar;

statement ok
GRANT role_bar TO role_foo WITH ADMIN OPTION;

statement ok;
GRANT role_foo TO testuser WITH ADMIN OPTION;

# switch to testuser

user testuser

statement ok
BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;

query TTT colnames
SELECT * FROM information_schema.applicable_roles ORDER BY role_name;
----
grantee   role_name  is_grantable
role_foo  role_bar   YES
testuser  role_foo   YES

statement ok
REVOKE role_foo FROM testuser;

statement ok
SAVEPOINT before_invalid_grant

# This grant should fail as testuser no longer has right to this grant
# via role_foo.

statement error testuser must have CREATEROLE or have admin option on role \"role_bar\"
GRANT role_bar TO testuser;

statement ok
ROLLBACK TO SAVEPOINT before_invalid_grant

query TTT colnames
SELECT * FROM information_schema.applicable_roles;
----
grantee  role_name  is_grantable

statement ok
COMMIT
