statement ok
GRANT CREATE ON DATABASE test TO testuser;
CREATE USER testuser2

statement ok
CREATE SCHEMA IF NOT EXISTS derp

# Don't run these tests as an admin.
user testuser

# Check pg_catalog grants.
query TTTTB colnames
SHOW GRANTS ON SCHEMA pg_catalog
----
database_name  schema_name  grantee  privilege_type  is_grantable
test           pg_catalog   public   USAGE           false

# Check information_schema grants.
query TTTTB colnames
SHOW GRANTS ON SCHEMA information_schema
----
database_name  schema_name         grantee  privilege_type  is_grantable
test           information_schema  public   USAGE           false

# Check public schema grants.
query TTTTB colnames,rowsort
SHOW GRANTS ON SCHEMA public
----
database_name  schema_name  grantee  privilege_type  is_grantable
test           public       admin    ALL             true
test           public       public   CREATE          false
test           public       public   USAGE           false
test           public       root     ALL             true

query TTTTB colnames,rowsort
SHOW GRANTS ON SCHEMA test.*
----
database_name  schema_name  grantee  privilege_type  is_grantable
test           derp         admin    ALL             true
test           derp         root     ALL             true
test           public       admin    ALL             true
test           public       public   CREATE          false
test           public       public   USAGE           false
test           public       root     ALL             true

statement ok
SET experimental_enable_temp_tables = true;

statement ok
CREATE TEMP TABLE t(a INT)

let $temp_schema
SELECT schema_name FROM [show schemas] WHERE schema_name LIKE '%pg_temp%'

# Check pg_temp grants.
query TT colnames,rowsort
SELECT grantee, privilege_type FROM [SHOW GRANTS ON SCHEMA $temp_schema]
----
grantee  privilege_type
admin    ALL
public   CREATE
public   USAGE
root     ALL

statement ok
CREATE SCHEMA s;
GRANT CREATE ON SCHEMA s TO testuser2

# Check user-defined schema grants.
query TTTTB colnames,rowsort
SHOW GRANTS ON SCHEMA s
----
database_name  schema_name  grantee    privilege_type  is_grantable
test           s            admin      ALL             true
test           s            root       ALL             true
test           s            testuser   ALL             true
test           s            testuser2  CREATE          false

# Check grant information in backing table. We have to strip off the session
# identifying information from the end of the pg_temp schema name.
query TTTTT colnames,rowsort
SELECT
  grantee,
  table_catalog,
  IF(table_schema LIKE 'pg_temp%', 'pg_temp', table_schema) AS table_schema,
  privilege_type,
  is_grantable
FROM information_schema.schema_privileges
----
grantee    table_catalog  table_schema        privilege_type  is_grantable
public     test           crdb_internal       USAGE           NO
admin      test           derp                ALL             YES
root       test           derp                ALL             YES
public     test           information_schema  USAGE           NO
public     test           pg_catalog          USAGE           NO
public     test           pg_extension        USAGE           NO
admin      test           pg_temp             ALL             YES
public     test           pg_temp             CREATE          NO
public     test           pg_temp             USAGE           NO
root       test           pg_temp             ALL             YES
admin      test           public              ALL             YES
public     test           public              CREATE          NO
public     test           public              USAGE           NO
root       test           public              ALL             YES
admin      test           s                   ALL             YES
root       test           s                   ALL             YES
testuser2  test           s                   CREATE          NO
testuser   test           s                   ALL             YES

# Check grants for testuser2, which should inherit from the public role.
query TBB colnames,rowsort
WITH schema_names(schema_name) AS (
   SELECT n.nspname AS schema_name
     FROM pg_catalog.pg_namespace n
) SELECT IF(schema_name LIKE 'pg_temp%', 'pg_temp', schema_name) AS schema_name,
  pg_catalog.has_schema_privilege('testuser2', schema_name, 'CREATE') AS has_create,
  pg_catalog.has_schema_privilege('testuser2', schema_name, 'USAGE') AS has_usage
FROM schema_names
----
schema_name         has_create  has_usage
crdb_internal       false       true
derp                false       false
information_schema  false       true
pg_catalog          false       true
pg_extension        false       true
pg_temp             true        true
public              true        true
s                   true        false

# Verify that owner and child of owner have is_grantable implicitly.

user root

statement ok
CREATE USER owner_grant_option_child

statement ok
GRANT testuser to owner_grant_option_child

user testuser

statement ok
CREATE SCHEMA owner_grant_option

statement ok
GRANT USAGE ON SCHEMA owner_grant_option TO owner_grant_option_child

query TTTTB colnames,rowsort
SHOW GRANTS ON SCHEMA owner_grant_option
----
database_name  schema_name         grantee                   privilege_type  is_grantable
test           owner_grant_option  admin                     ALL             true
test           owner_grant_option  owner_grant_option_child  USAGE           true
test           owner_grant_option  root                      ALL             true
test           owner_grant_option  testuser                  ALL             true

# Verify that is_grantable moves to the new owner.

user root

statement ok
CREATE ROLE other_owner

statement ok
ALTER SCHEMA owner_grant_option OWNER TO other_owner

query TTTTB colnames,rowsort
SHOW GRANTS ON SCHEMA owner_grant_option
----
database_name  schema_name         grantee                   privilege_type  is_grantable
test           owner_grant_option  admin                     ALL             true
test           owner_grant_option  other_owner               ALL             true
test           owner_grant_option  owner_grant_option_child  USAGE           false
test           owner_grant_option  root                      ALL             true

# Regression test to cover checking schema-level privileges at role drop time
subtest regression_102962

statement ok
CREATE SCHEMA sc102962

statement ok
CREATE ROLE r102962

statement ok
GRANT USAGE ON SCHEMA sc102962 TO r102962

query TTTTB colnames,rowsort
SHOW GRANTS ON SCHEMA sc102962
----
database_name  schema_name  grantee  privilege_type  is_grantable
test           sc102962     admin    ALL             true
test           sc102962     r102962  USAGE           false
test           sc102962     root     ALL             true

statement error pgcode 2BP01 pq: cannot drop role/user r102962: grants still exist on test.sc102962
DROP ROLE r102962

statement ok
CREATE USER ROACH;
CREATE SCHEMA ROACHHOUSE;
CREATE SCHEMA ROACHLAYER;
CREATE SCHEMA ROACHSTATION;
BEGIN;
GRANT ALL ON SCHEMA ROACHHOUSE TO ROACH;
GRANT ALL ON SCHEMA ROACHLAYER TO ROACH;
GRANT ALL ON SCHEMA ROACHSTATION TO ROACH;
COMMIT;

query T
SELECT description FROM [SHOW JOBS] WHERE description LIKE  '%updating privileges for schema%';
----

query TTTTTTB colnames,rowsort
WITH roach_grants AS (
  SHOW GRANTS FOR roach
)
SELECT database_name,
  IF(schema_name LIKE 'pg_temp%', 'pg_temp', schema_name) AS schema_name,
  object_name,
  object_type,
  grantee,
  privilege_type,
  is_grantable
FROM roach_grants
----
database_name  schema_name                    object_name  object_type  grantee  privilege_type  is_grantable
test           pg_temp                        NULL         schema       public   CREATE          false
test           pg_temp                        NULL         schema       public   USAGE           false
test           public                         NULL         schema       public   CREATE          false
test           public                         NULL         schema       public   USAGE           false
test           roachhouse                     NULL         schema       roach    ALL             false
test           roachlayer                     NULL         schema       roach    ALL             false
test           roachstation                   NULL         schema       roach    ALL             false

subtest has_*_privilege_works_for_public

statement ok
CREATE SCHEMA roachema;
GRANT USAGE ON SCHEMA roachema TO public;

query B colnames
SELECT has_schema_privilege('public', 'roachema', 'USAGE');
----
has_schema_privilege
true

subtest end
