diff --git a/pkg/ccl/logictestccl/testdata/logic_test/partitioning_constrained_scans b/pkg/ccl/logictestccl/testdata/logic_test/partitioning_constrained_scans index 4840f4cff051..d586035403ae 100644 --- a/pkg/ccl/logictestccl/testdata/logic_test/partitioning_constrained_scans +++ b/pkg/ccl/logictestccl/testdata/logic_test/partitioning_constrained_scans @@ -317,4 +317,3 @@ select │ └── [/'foo'/e'bar\x00'/5 - ] └── filters └── c = 5 - diff --git a/pkg/sql/crdb_internal.go b/pkg/sql/crdb_internal.go index fc825a27076c..e8969b4a26dc 100644 --- a/pkg/sql/crdb_internal.go +++ b/pkg/sql/crdb_internal.go @@ -5023,38 +5023,78 @@ CREATE TABLE crdb_internal.cluster_database_privileges ( database_name STRING NOT NULL, grantee STRING NOT NULL, privilege_type STRING NOT NULL, - is_grantable STRING + is_grantable STRING, + INDEX(database_name) )`, populate: func(ctx context.Context, p *planner, dbContext catalog.DatabaseDescriptor, addRow func(...tree.Datum) error) error { return forEachDatabaseDesc(ctx, p, dbContext, true, /* requiresPrivileges */ - func(db catalog.DatabaseDescriptor) error { - privs := db.GetPrivileges().Show(privilege.Database, true /* showImplicitOwnerPrivs */) - dbNameStr := tree.NewDString(db.GetName()) - // TODO(knz): This should filter for the current user, see - // https://github.com/cockroachdb/cockroach/issues/35572 - for _, u := range privs { - userNameStr := tree.NewDString(u.User.Normalized()) - for _, priv := range u.Privileges { - // We use this function to check for the grant option so that the - // object owner also gets is_grantable=true. - grantOptionErr := p.CheckGrantOptionsForUser( - ctx, db.GetPrivileges(), db, []privilege.Kind{priv.Kind}, u.User, true, /* isGrant */ - ) - if err := addRow( - dbNameStr, // database_name - userNameStr, // grantee - tree.NewDString(priv.Kind.String()), // privilege_type - yesOrNoDatum(grantOptionErr == nil), // is_grantable - ); err != nil { - return err - } - } - } - return nil - }) + makeClusterDatabasePrivilegesFromDescriptor(ctx, p, addRow)) + }, + indexes: []virtualIndex{ + {populate: func(ctx context.Context, unwrappedConstraint tree.Datum, p *planner, dbContext catalog.DatabaseDescriptor, addRow func(...tree.Datum) error) (matched bool, err error) { + if unwrappedConstraint == tree.DNull { + return false, nil + } + dbName := string(tree.MustBeDString(unwrappedConstraint)) + if dbContext != nil && dbContext.GetName() != dbName { + return false, nil + } + + flags := tree.CommonLookupFlags{ + AvoidLeased: true, + } + dbDesc, err := p.Descriptors().GetImmutableDatabaseByName(ctx, p.Txn(), dbName, flags) + if err != nil || dbDesc == nil { + return false, err + } + hasPriv, err := userCanSeeDescriptor(ctx, p, dbDesc, nil /* parentDBDesc */, false /* allowAdding */) + if err != nil || !hasPriv { + return false, err + } + var called bool + if err := makeClusterDatabasePrivilegesFromDescriptor( + ctx, p, func(datum ...tree.Datum) error { + called = true + return addRow(datum...) + }, + )(dbDesc); err != nil { + return false, err + } + return called, nil + }}, }, } +func makeClusterDatabasePrivilegesFromDescriptor( + ctx context.Context, p *planner, addRow func(...tree.Datum) error, +) func(catalog.DatabaseDescriptor) error { + return func(db catalog.DatabaseDescriptor) error { + privs := db.GetPrivileges().Show(privilege.Database, true /* showImplicitOwnerPrivs */) + dbNameStr := tree.NewDString(db.GetName()) + // TODO(knz): This should filter for the current user, see + // https://github.com/cockroachdb/cockroach/issues/35572 + for _, u := range privs { + userNameStr := tree.NewDString(u.User.Normalized()) + for _, priv := range u.Privileges { + // We use this function to check for the grant option so that the + // object owner also gets is_grantable=true. + grantOptionErr := p.CheckGrantOptionsForUser( + ctx, db.GetPrivileges(), db, []privilege.Kind{priv.Kind}, u.User, true, /* isGrant */ + ) + if err := addRow( + dbNameStr, // database_name + userNameStr, // grantee + tree.NewDString(priv.Kind.String()), // privilege_type + yesOrNoDatum(grantOptionErr == nil), // is_grantable + ); err != nil { + return err + } + } + } + return nil + } +} + var crdbInternalCrossDbReferences = virtualSchemaTable{ comment: `virtual table with cross db references`, schema: ` diff --git a/pkg/sql/logictest/testdata/logic_test/create_statements b/pkg/sql/logictest/testdata/logic_test/create_statements index baddaa970d23..f6ad62e9bc55 100644 --- a/pkg/sql/logictest/testdata/logic_test/create_statements +++ b/pkg/sql/logictest/testdata/logic_test/create_statements @@ -227,12 +227,14 @@ CREATE TABLE crdb_internal.cluster_database_privileges ( database_name STRING NOT NULL, grantee STRING NOT NULL, privilege_type STRING NOT NULL, - is_grantable STRING NULL + is_grantable STRING NULL, + INDEX cluster_database_privileges_database_name_idx (database_name ASC) STORING (grantee, privilege_type, is_grantable) ) CREATE TABLE crdb_internal.cluster_database_privileges ( database_name STRING NOT NULL, grantee STRING NOT NULL, privilege_type STRING NOT NULL, - is_grantable STRING NULL + is_grantable STRING NULL, + INDEX cluster_database_privileges_database_name_idx (database_name ASC) STORING (grantee, privilege_type, is_grantable) ) {} {} CREATE TABLE crdb_internal.cluster_distsql_flows ( flow_id UUID NOT NULL, diff --git a/pkg/sql/logictest/testdata/logic_test/drop_owned_by b/pkg/sql/logictest/testdata/logic_test/drop_owned_by index 6cd744f07c77..2bee9e0906d2 100644 --- a/pkg/sql/logictest/testdata/logic_test/drop_owned_by +++ b/pkg/sql/logictest/testdata/logic_test/drop_owned_by @@ -622,9 +622,9 @@ DROP OWNED BY testuser query TTTB SHOW GRANTS ON DATABASE d3 ---- -d3 admin ALL true -d3 public CONNECT false -d3 root ALL true +d3 admin ALL true +d3 public CONNECT false +d3 root ALL true # Drop owned by should not work if the user has synthetic privileges. diff --git a/pkg/sql/opt/exec/execbuilder/testdata/virtual b/pkg/sql/opt/exec/execbuilder/testdata/virtual index ec89e0c9659a..73fd93bcb1ce 100644 --- a/pkg/sql/opt/exec/execbuilder/testdata/virtual +++ b/pkg/sql/opt/exec/execbuilder/testdata/virtual @@ -193,3 +193,23 @@ vectorized: true table: pg_class@pg_class_oid_idx spans: [/50 - /50] limit: 1 + +# Test that the virtual index is used when looking up database grants + +statement ok +CREATE DATABASE t + +query T +EXPLAIN SHOW GRANTS ON DATABASE t +---- +distribution: local +vectorized: true +· +• sort +│ order: +grantee,+privilege_type +│ +└── • render + │ + └── • virtual table + table: cluster_database_privileges@cluster_database_privileges_database_name_idx + spans: [/'t' - /'t']