diff --git a/pkg/ccl/logictestccl/testdata/logic_test/multi_region_privileges b/pkg/ccl/logictestccl/testdata/logic_test/multi_region_privileges index cd6307276aa2..5d77bb2cbd52 100644 --- a/pkg/ccl/logictestccl/testdata/logic_test/multi_region_privileges +++ b/pkg/ccl/logictestccl/testdata/logic_test/multi_region_privileges @@ -268,3 +268,50 @@ user testuser statement ok ALTER DATABASE repartition_privs ADD REGION "ap-southeast-2"; ALTER DATABASE repartition_privs DROP REGION "us-east-1" + +subtest revalidate_privs + +user root + +statement ok +CREATE DATABASE revalidate_privs PRIMARY REGION "ca-central-1" REGIONS "us-east-1" + +statement ok +CREATE TABLE revalidate_privs.rbr () LOCALITY REGIONAL BY ROW + +user testuser + +statement ok +USE revalidate_privs + +# Check that revalidate_unique_constraint* builtins respect privileges. +query error user testuser does not have SELECT privilege on relation rbr +SELECT crdb_internal.revalidate_unique_constraints_in_all_tables() + +query error user testuser does not have SELECT privilege on relation rbr +SELECT crdb_internal.revalidate_unique_constraints_in_table('revalidate_privs.rbr') + +query error user testuser does not have SELECT privilege on relation rbr +SELECT crdb_internal.revalidate_unique_constraint('revalidate_privs.rbr', 'rbr_pkey') + +user root + +statement ok +GRANT SELECT ON revalidate_privs.rbr TO testuser + +user testuser + +query T +SELECT crdb_internal.revalidate_unique_constraints_in_all_tables() +---- +· + +query T +SELECT crdb_internal.revalidate_unique_constraints_in_table('repartition_privs.rbr') +---- +· + +query T +SELECT crdb_internal.revalidate_unique_constraint('repartition_privs.rbr', 'rbr_pkey') +---- +· diff --git a/pkg/sql/alter_table.go b/pkg/sql/alter_table.go index 5482123f0402..6719fbdf148b 100644 --- a/pkg/sql/alter_table.go +++ b/pkg/sql/alter_table.go @@ -609,7 +609,7 @@ func (n *alterTableNode) startExec(params runParams) error { if err := validateUniqueWithoutIndexConstraintInTxn( params.ctx, params.ExecCfg().InternalExecutorFactory( params.ctx, params.SessionData(), - ), n.tableDesc, params.p.Txn(), name, + ), n.tableDesc, params.p.Txn(), params.p.User(), name, ); err != nil { return err } diff --git a/pkg/sql/backfill.go b/pkg/sql/backfill.go index b46a9f157191..79deadd00385 100644 --- a/pkg/sql/backfill.go +++ b/pkg/sql/backfill.go @@ -23,6 +23,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/kv" "github.com/cockroachdb/cockroach/pkg/kv/kvclient/kvcoord" "github.com/cockroachdb/cockroach/pkg/roachpb" + "github.com/cockroachdb/cockroach/pkg/security/username" "github.com/cockroachdb/cockroach/pkg/settings" "github.com/cockroachdb/cockroach/pkg/sql/backfill" "github.com/cockroachdb/cockroach/pkg/sql/catalog" @@ -763,7 +764,9 @@ func (sc *SchemaChanger) validateConstraints( return err } } else if c.IsUniqueWithoutIndex() { - if err := validateUniqueWithoutIndexConstraintInTxn(ctx, sc.ieFactory(ctx, evalCtx.SessionData()), desc, txn, c.GetName()); err != nil { + if err := validateUniqueWithoutIndexConstraintInTxn( + ctx, sc.ieFactory(ctx, evalCtx.SessionData()), desc, txn, evalCtx.SessionData().User(), c.GetName(), + ); err != nil { return err } } else if c.IsNotNull() { @@ -1941,6 +1944,7 @@ func countIndexRowsAndMaybeCheckUniqueness( idx.GetPredicate(), ie, txn, + username.NodeUserName(), false, /* preExisting */ ); err != nil { return err @@ -2416,7 +2420,7 @@ func runSchemaChangesInTxn( uwi := &c.ConstraintToUpdateDesc().UniqueWithoutIndexConstraint if uwi.Validity == descpb.ConstraintValidity_Validating { if err := validateUniqueWithoutIndexConstraintInTxn( - ctx, planner.ExecCfg().InternalExecutor, tableDesc, planner.txn, c.GetName(), + ctx, planner.ExecCfg().InternalExecutor, tableDesc, planner.txn, planner.User(), c.GetName(), ); err != nil { return err } @@ -2575,6 +2579,7 @@ func validateUniqueWithoutIndexConstraintInTxn( ie sqlutil.InternalExecutor, tableDesc *tabledesc.Mutable, txn *kv.Txn, + user username.SQLUsername, constraintName string, ) error { var syntheticDescs []catalog.Descriptor @@ -2596,7 +2601,15 @@ func validateUniqueWithoutIndexConstraintInTxn( return ie.WithSyntheticDescriptors(syntheticDescs, func() error { return validateUniqueConstraint( - ctx, tableDesc, uc.Name, uc.ColumnIDs, uc.Predicate, ie, txn, false, /* preExisting */ + ctx, + tableDesc, + uc.Name, + uc.ColumnIDs, + uc.Predicate, + ie, + txn, + user, + false, /* preExisting */ ) }) } diff --git a/pkg/sql/check.go b/pkg/sql/check.go index 9d6ff4fae646..5819ac19405c 100644 --- a/pkg/sql/check.go +++ b/pkg/sql/check.go @@ -18,6 +18,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/jobs" "github.com/cockroachdb/cockroach/pkg/kv" + "github.com/cockroachdb/cockroach/pkg/security/username" "github.com/cockroachdb/cockroach/pkg/sql/catalog" "github.com/cockroachdb/cockroach/pkg/sql/catalog/catpb" "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" @@ -381,7 +382,9 @@ func (p *planner) RevalidateUniqueConstraintsInCurrentDB(ctx context.Context) er } for _, tableDesc := range tableDescs { - if err = RevalidateUniqueConstraintsInTable(ctx, p.Txn(), p.ExecCfg().InternalExecutor, tableDesc); err != nil { + if err = RevalidateUniqueConstraintsInTable( + ctx, p.Txn(), p.User(), p.ExecCfg().InternalExecutor, tableDesc, + ); err != nil { return err } } @@ -402,7 +405,9 @@ func (p *planner) RevalidateUniqueConstraintsInTable(ctx context.Context, tableI if err != nil { return err } - return RevalidateUniqueConstraintsInTable(ctx, p.Txn(), p.ExecCfg().InternalExecutor, tableDesc) + return RevalidateUniqueConstraintsInTable( + ctx, p.Txn(), p.User(), p.ExecCfg().InternalExecutor, tableDesc, + ) } // RevalidateUniqueConstraint verifies that the given unique constraint on the @@ -438,6 +443,7 @@ func (p *planner) RevalidateUniqueConstraint( index.GetPredicate(), p.ExecCfg().InternalExecutor, p.Txn(), + p.User(), true, /* preExisting */ ) } @@ -457,6 +463,7 @@ func (p *planner) RevalidateUniqueConstraint( uc.Predicate, p.ExecCfg().InternalExecutor, p.Txn(), + p.User(), true, /* preExisting */ ) } @@ -531,7 +538,11 @@ func HasVirtualUniqueConstraints(tableDesc catalog.TableDescriptor) bool { // enforced by an index. This includes implicitly partitioned UNIQUE indexes // and UNIQUE WITHOUT INDEX constraints. func RevalidateUniqueConstraintsInTable( - ctx context.Context, txn *kv.Txn, ie sqlutil.InternalExecutor, tableDesc catalog.TableDescriptor, + ctx context.Context, + txn *kv.Txn, + user username.SQLUsername, + ie sqlutil.InternalExecutor, + tableDesc catalog.TableDescriptor, ) error { // Check implicitly partitioned UNIQUE indexes. for _, index := range tableDesc.ActiveIndexes() { @@ -544,6 +555,7 @@ func RevalidateUniqueConstraintsInTable( index.GetPredicate(), ie, txn, + user, true, /* preExisting */ ); err != nil { log.Errorf(ctx, "validation of unique constraints failed for table %s: %s", tableDesc.GetName(), err) @@ -563,6 +575,7 @@ func RevalidateUniqueConstraintsInTable( uc.Predicate, ie, txn, + user, true, /* preExisting */ ); err != nil { log.Errorf(ctx, "validation of unique constraints failed for table %s: %s", tableDesc.GetName(), err) @@ -591,6 +604,7 @@ func validateUniqueConstraint( pred string, ie sqlutil.InternalExecutor, txn *kv.Txn, + user username.SQLUsername, preExisting bool, ) error { query, colNames, err := duplicateRowQuery( @@ -607,8 +621,9 @@ func validateUniqueConstraint( query, ) - values, err := ie.QueryRowEx(ctx, "validate unique constraint", txn, - sessiondata.NodeUserSessionDataOverride, query) + sessionDataOverride := sessiondata.NoSessionDataOverride + sessionDataOverride.User = user + values, err := ie.QueryRowEx(ctx, "validate unique constraint", txn, sessionDataOverride, query) if err != nil { return err } diff --git a/pkg/sql/importer/import_job.go b/pkg/sql/importer/import_job.go index e752c9ba27a6..4b5ee97f20c8 100644 --- a/pkg/sql/importer/import_job.go +++ b/pkg/sql/importer/import_job.go @@ -305,7 +305,7 @@ func (r *importResumer) Resume(ctx context.Context, execCtx interface{}) error { return err } - if err := r.checkVirtualConstraints(ctx, p.ExecCfg(), r.job); err != nil { + if err := r.checkVirtualConstraints(ctx, p.ExecCfg(), r.job, p.User()); err != nil { return err } @@ -1103,8 +1103,8 @@ func (r *importResumer) publishSchemas(ctx context.Context, execCfg *sql.Executo // checkVirtualConstraints checks constraints that are enforced via runtime // checks, such as uniqueness checks that are not directly backed by an index. -func (*importResumer) checkVirtualConstraints( - ctx context.Context, execCfg *sql.ExecutorConfig, job *jobs.Job, +func (r *importResumer) checkVirtualConstraints( + ctx context.Context, execCfg *sql.ExecutorConfig, job *jobs.Job, user username.SQLUsername, ) error { for _, tbl := range job.Details().(jobspb.ImportDetails).Tables { desc := tabledesc.NewBuilder(tbl.Desc).BuildExistingMutableTable() @@ -1121,7 +1121,7 @@ func (*importResumer) checkVirtualConstraints( if err := execCfg.DB.Txn(ctx, func(ctx context.Context, txn *kv.Txn) error { ie := execCfg.InternalExecutorFactory(ctx, sql.NewFakeSessionData(execCfg.SV())) return ie.WithSyntheticDescriptors([]catalog.Descriptor{desc}, func() error { - return sql.RevalidateUniqueConstraintsInTable(ctx, txn, ie, desc) + return sql.RevalidateUniqueConstraintsInTable(ctx, txn, user, ie, desc) }) }); err != nil { return err