# Should error when a role that does not exist is provided.
statement error pq: role/user "who" does not exist
ALTER DEFAULT PRIVILEGES FOR ROLE who GRANT SELECT ON TABLES to testuser

statement error pq: role/user "who" does not exist
ALTER DEFAULT PRIVILEGES GRANT SELECT ON TABLES to who

statement error pq: role/user "who" does not exist
ALTER DEFAULT PRIVILEGES FOR ROLE testuser GRANT SELECT ON TABLES to who

statement error pq: role/user "who" does not exist
ALTER DEFAULT PRIVILEGES FOR ROLE testuser GRANT SELECT ON TABLES to testuser, who

# Should not be able to use invalid privileges.
statement error pq: invalid privilege type USAGE for table
ALTER DEFAULT PRIVILEGES GRANT USAGE ON TABLES to testuser

# Should not be able to alter system database.
statement ok
USE system

statement error cannot alter system database
ALTER DEFAULT PRIVILEGES FOR ROLE testuser REVOKE ALL ON TABLES FROM testuser

statement ok
RESET database

# For Tables.
statement ok
CREATE DATABASE d;
GRANT CREATE ON DATABASE d TO testuser;

# By default, testuser should have ALL privileges on a table it creates.
user testuser

statement ok
USE d;

statement ok
CREATE TABLE testuser_t();

query TTTTTB colnames,rowsort
SHOW GRANTS ON testuser_t
----
database_name  schema_name  table_name  grantee   privilege_type  is_grantable
d              public       testuser_t  admin     ALL             true
d              public       testuser_t  root      ALL             true
d              public       testuser_t  testuser  ALL             true

statement ok
ALTER DEFAULT PRIVILEGES REVOKE ALL ON TABLES FROM testuser;
ALTER DEFAULT PRIVILEGES IN SCHEMA public REVOKE ALL ON TABLES FROM testuser;

statement ok
CREATE TABLE testuser_t2();

query TTTTTB colnames,rowsort
SHOW GRANTS ON testuser_t2
----
database_name  schema_name  table_name   grantee   privilege_type  is_grantable
d              public       testuser_t2  admin     ALL             true
d              public       testuser_t2  root      ALL             true
d              public       testuser_t2  testuser  ALL             true

user root

statement ok
USE test;

statement ok
ALTER DEFAULT PRIVILEGES GRANT SELECT ON TABLES to testuser

statement ok
CREATE TABLE t()

query TTTTTB colnames,rowsort
SHOW GRANTS ON t
----
database_name  schema_name  table_name  grantee   privilege_type  is_grantable
test           public       t           admin     ALL             true
test           public       t           root      ALL             true
test           public       t           testuser  SELECT          false

statement ok
CREATE SEQUENCE s

statement ok
CREATE VIEW vx AS SELECT 1

query TTTTTB colnames,rowsort
SHOW GRANTS ON s
----
database_name  schema_name  table_name  grantee  privilege_type  is_grantable
test           public       s           admin    ALL             true
test           public       s           root     ALL             true

query TTTTTB colnames,rowsort
SHOW GRANTS ON vx
----
database_name  schema_name  table_name  grantee   privilege_type  is_grantable
test           public       vx          admin     ALL             true
test           public       vx          root      ALL             true
test           public       vx          testuser  SELECT          false

statement ok
ALTER DEFAULT PRIVILEGES REVOKE SELECT ON TABLES FROM testuser

statement ok
CREATE TABLE t2()

query TTTTTB colnames,rowsort
SHOW GRANTS ON t2
----
database_name  schema_name  table_name  grantee  privilege_type  is_grantable
test           public       t2          admin    ALL             true
test           public       t2          root     ALL             true

statement ok
CREATE SEQUENCE s2

query TTTTTB colnames,rowsort
SHOW GRANTS ON s2
----
database_name  schema_name  table_name  grantee  privilege_type  is_grantable
test           public       s2          admin    ALL             true
test           public       s2          root     ALL             true


# Multiple users.
statement ok
CREATE USER testuser2;

statement ok
ALTER DEFAULT PRIVILEGES GRANT SELECT ON TABLES TO testuser, testuser2

statement ok
CREATE TABLE t3()

query TTTTTB colnames,rowsort
SHOW GRANTS ON t3
----
database_name  schema_name  table_name  grantee    privilege_type  is_grantable
test           public       t3          admin      ALL             true
test           public       t3          root       ALL             true
test           public       t3          testuser   SELECT          false
test           public       t3          testuser2  SELECT          false

statement ok
CREATE SEQUENCE s3

query TTTTTB colnames,rowsort
SHOW GRANTS ON s3
----
database_name  schema_name  table_name  grantee  privilege_type  is_grantable
test           public       s3          admin    ALL             true
test           public       s3          root     ALL             true

statement ok
ALTER DEFAULT PRIVILEGES REVOKE SELECT ON TABLES FROM testuser, testuser2

statement ok
CREATE TABLE t4()

query TTTTTB colnames,rowsort
SHOW GRANTS ON t4
----
database_name  schema_name  table_name  grantee  privilege_type  is_grantable
test           public       t4          admin    ALL             true
test           public       t4          root     ALL             true

statement ok
CREATE SEQUENCE s4

query TTTTTB colnames,rowsort
SHOW GRANTS ON s4
----
database_name  schema_name  table_name  grantee  privilege_type  is_grantable
test           public       s4          admin    ALL             true
test           public       s4          root     ALL             true

# ALTER DEFAULT PRIVILEGES FOR ROLE.
statement ok
use d

statement ok
GRANT CREATE ON DATABASE d TO testuser

statement ok
ALTER DEFAULT PRIVILEGES FOR ROLE testuser GRANT SELECT ON TABLES to testuser, testuser2

user testuser

statement ok
USE d;

statement ok
CREATE TABLE t5()

# testuser has ALL privileges since by default, ALL is defined as a default
# privilege for the creator role of an object..
query TTTTTB colnames,rowsort
SHOW GRANTS ON t5
----
database_name  schema_name  table_name  grantee    privilege_type  is_grantable
d              public       t5          admin      ALL             true
d              public       t5          root       ALL             true
d              public       t5          testuser   ALL             true
d              public       t5          testuser2  SELECT          false

user root

statement ok
USE d;

statement ok
ALTER DEFAULT PRIVILEGES FOR ROLE testuser REVOKE SELECT ON TABLES FROM testuser, testuser2

user testuser

statement ok
USE d;

statement ok
CREATE TABLE t6()

query TTTTTB colnames,rowsort
SHOW GRANTS ON t6
----
database_name  schema_name  table_name  grantee   privilege_type  is_grantable
d              public       t6          admin     ALL             true
d              public       t6          root      ALL             true
d              public       t6          testuser  ALL             true

user root

statement ok
ALTER DEFAULT PRIVILEGES GRANT ALL ON TABLES TO testuser, testuser2

statement ok
CREATE TABLE t7()

query TTTTTB colnames,rowsort
SHOW GRANTS ON t7
----
database_name  schema_name  table_name  grantee    privilege_type  is_grantable
d              public       t7          admin      ALL             true
d              public       t7          root       ALL             true
d              public       t7          testuser   ALL             false
d              public       t7          testuser2  ALL             false

statement ok
ALTER DEFAULT PRIVILEGES REVOKE SELECT ON TABLES FROM testuser, testuser2

statement ok
CREATE TABLE t8()

query TTTTTB colnames,rowsort
SHOW GRANTS ON t8
----
database_name  schema_name  table_name  grantee    privilege_type  is_grantable
d              public       t8          admin      ALL             true
d              public       t8          root       ALL             true
d              public       t8          testuser   BACKUP          false
d              public       t8          testuser   CHANGEFEED      false
d              public       t8          testuser   CREATE          false
d              public       t8          testuser   DELETE          false
d              public       t8          testuser   DROP            false
d              public       t8          testuser   INSERT          false
d              public       t8          testuser   TRIGGER         false
d              public       t8          testuser   UPDATE          false
d              public       t8          testuser   ZONECONFIG      false
d              public       t8          testuser2  BACKUP          false
d              public       t8          testuser2  CHANGEFEED      false
d              public       t8          testuser2  CREATE          false
d              public       t8          testuser2  DELETE          false
d              public       t8          testuser2  DROP            false
d              public       t8          testuser2  INSERT          false
d              public       t8          testuser2  TRIGGER         false
d              public       t8          testuser2  UPDATE          false
d              public       t8          testuser2  ZONECONFIG      false

# Ensure you can only ALTER DEFAULT PRIVILEGES for a role you're a part of.
user testuser2

statement ok
USE d

statement error pq: must be an admin or member of root
ALTER DEFAULT PRIVILEGES FOR ROLE root GRANT SELECT ON TABLES TO testuser

# Ensure you can ALTER DEFAULT PRIVILEGES for multiple roles.
user root

statement ok
CREATE USER testuser3

statement ok
ALTER DEFAULT PRIVILEGES FOR ROLE root, testuser REVOKE ALL ON TABLES FROM testuser, testuser2, testuser3

statement ok
ALTER DEFAULT PRIVILEGES FOR ROLE root, testuser GRANT SELECT ON TABLES TO testuser2, testuser3

statement ok
CREATE TABLE t9()

query TTTTTB colnames,rowsort
SHOW GRANTS ON t9
----
database_name  schema_name  table_name  grantee    privilege_type  is_grantable
d              public       t9          admin      ALL             true
d              public       t9          root       ALL             true
d              public       t9          testuser2  SELECT          false
d              public       t9          testuser3  SELECT          false

user testuser

statement ok
CREATE TABLE t10()

query TTTTTB colnames,rowsort
SHOW GRANTS ON t10
----
database_name  schema_name  table_name  grantee    privilege_type  is_grantable
d              public       t10         admin      ALL             true
d              public       t10         root       ALL             true
d              public       t10         testuser   ALL             true
d              public       t10         testuser2  SELECT          false
d              public       t10         testuser3  SELECT          false

user root

statement ok
ALTER DEFAULT PRIVILEGES FOR ROLE root, testuser REVOKE SELECT ON TABLES FROM testuser2, testuser3

statement ok
CREATE TABLE t11()

query TTTTTB colnames,rowsort
SHOW GRANTS ON t11
----
database_name  schema_name  table_name  grantee  privilege_type  is_grantable
d              public       t11         admin    ALL             true
d              public       t11         root     ALL             true

user testuser

statement ok
CREATE TABLE t12()

query TTTTTB colnames,rowsort
SHOW GRANTS ON t12
----
database_name  schema_name  table_name  grantee   privilege_type  is_grantable
d              public       t12         admin     ALL             true
d              public       t12         root      ALL             true
d              public       t12         testuser  ALL             true

# Cannot specify PUBLIC as the target role.
statement error pq: role/user "public" does not exist
ALTER DEFAULT PRIVILEGES FOR ROLE public REVOKE SELECT ON TABLES FROM testuser2, testuser3

# Can specify PUBLIC as a grantee.
statement ok
ALTER DEFAULT PRIVILEGES REVOKE SELECT ON TABLES FROM public

# Admins can ALTER DEFAULT PRIVILEGES for any role.
user root

# Confirm that root is not a member of testuser. We avoid using pg_has_role
# to check, since that has a special case for all admin users.
query TTB
SELECT role, inheriting_member, member_is_explicit
FROM crdb_internal.kv_inherited_role_members
WHERE inheriting_member = 'root'
ORDER BY role
----
admin  root  true

statement ok
ALTER DEFAULT PRIVILEGES FOR ROLE testuser GRANT ALL ON TABLES TO testuser2

statement ok
ALTER DEFAULT PRIVILEGES FOR ROLE testuser REVOKE ALL ON TABLES FROM testuser2
