From c9edde5c461dfaf455316db16d2287bf76586527 Mon Sep 17 00:00:00 2001 From: Jason Chan Date: Wed, 15 Jun 2022 07:34:36 -0700 Subject: [PATCH] sql/schemachanger: implement DROP OWNED BY Previously, we did not support the DROP OWNED BY statement (#55381). This commit adds partial support for DROP OWNED BY in the declarative schema changer. Followup work is needed to support the CASCADE modifier. Release note (sql change): Support `DROP OWNED BY`. --- .../testdata/logic_test/drop_owned_by | 626 ++++++++++++++ .../schemachanger/scbuild/builder_state.go | 14 + pkg/sql/schemachanger/scbuild/dependencies.go | 4 + .../scbuild/internal/scbuildstmt/BUILD.bazel | 3 + .../internal/scbuildstmt/dependencies.go | 8 + .../internal/scbuildstmt/drop_owned_by.go | 106 +++ .../scbuild/internal/scbuildstmt/process.go | 1 + .../scbuild/testdata/drop_owned_by | 776 ++++++++++++++++++ pkg/sql/schemachanger/scdeps/build_deps.go | 5 + .../scdeps/sctestdeps/test_deps.go | 12 + .../scexec/scmutationexec/BUILD.bazel | 1 + .../scexec/scmutationexec/drop.go | 14 + pkg/sql/schemachanger/scop/mutation.go | 7 + .../scop/mutation_visitor_generated.go | 6 + .../internal/opgen/opgen_user_privileges.go | 5 +- .../scplan/testdata/drop_owned_by | 747 +++++++++++++++++ pkg/sql/sem/tree/schema_feature_name.go | 2 +- pkg/sql/testdata/telemetry/drop_owned_by | 2 - 18 files changed, 2335 insertions(+), 4 deletions(-) create mode 100644 pkg/sql/logictest/testdata/logic_test/drop_owned_by create mode 100644 pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go create mode 100644 pkg/sql/schemachanger/scbuild/testdata/drop_owned_by create mode 100644 pkg/sql/schemachanger/scplan/testdata/drop_owned_by diff --git a/pkg/sql/logictest/testdata/logic_test/drop_owned_by b/pkg/sql/logictest/testdata/logic_test/drop_owned_by new file mode 100644 index 000000000000..b490053ce535 --- /dev/null +++ b/pkg/sql/logictest/testdata/logic_test/drop_owned_by @@ -0,0 +1,626 @@ +# LogicTest: !local-legacy-schema-changer + +# Test dropping nothing. +statement ok +DROP OWNED BY testuser + +statement ok +CREATE USER testuser2 + +# DROP-OBJECTS: Test that DROP OWNED BY drops objects owned by the specified +# roles. +# +# In this test, testuser creates multiple objects and drops all of them in one +# go. Additionally, testuser2 owns a table that shouldn't be dropped by +# testuser's DROP OWNED BY. +subtest drop-objects + +user testuser2 + +statement ok +CREATE TABLE u() + +user root + +statement ok +GRANT CREATE ON DATABASE test TO testuser WITH GRANT OPTION + +user testuser + +statement ok +CREATE TABLE t(a INT) + +statement ok +CREATE VIEW v AS SELECT 1 + +statement ok +CREATE SEQUENCE seq + +statement ok +CREATE TYPE enum AS ENUM('a', 'b') + +query TTTTIT +SHOW TABLES FROM public +---- +public seq sequence testuser 0 NULL +public t table testuser 0 NULL +public u table testuser2 0 NULL +public v view testuser 0 NULL + +query TTTT +SHOW ENUMS +---- +public enum {a,b} testuser + +statement ok +DROP OWNED BY testuser + +query TTTTIT +SHOW TABLES FROM public +---- +public u table testuser2 0 NULL + +query error pgcode 42P01 relation "t" does not exist +SELECT * FROM t + +query error pgcode 42P01 relation "v" does not exist +SELECT * FROM v + +query TTTT +SHOW ENUMS +---- + +user testuser2 + +statement ok +DROP OWNED BY testuser2 + +query TTTTIT +SHOW TABLES FROM public +---- + +# DROP-BEHAVIOR-VIEW: Test RESTRICT/CASCADE. +# +# In this test, testuser2 creates a view dependent on a table owned by +# testuser. Under RESTRICT, testuser cannot DROP OWNED BY due to this +# dependency. Under CASCADE, testuser can DROP OWNED BY, which drops both +# testuser's table and testuser2's view. +subtest drop-behavior-view + +user testuser + +statement ok +CREATE TABLE t(a INT) + +statement ok +GRANT SELECT ON t TO testuser2 WITH GRANT OPTION + +user testuser2 + +statement ok +CREATE VIEW v AS SELECT a FROM t + +user testuser + +statement error pq: cannot drop desired object\(s\) because other objects depend on them +DROP OWNED BY testuser + +statement error pq: cannot drop desired object\(s\) because other objects depend on them +DROP OWNED BY testuser RESTRICT + +query TTTTIT +SHOW TABLES FROM public +---- +public t table testuser 0 NULL +public v view testuser2 0 NULL + +user root + +statement error unimplemented: DROP OWNED BY CASCADE is not yet supported +DROP OWNED BY testuser2 CASCADE + +statement ok +DROP OWNED BY testuser, testuser2 + +query TTTTIT +SHOW TABLES FROM public +---- + +# DROP-BEHAVIOR-TYPE-1: Test RESTRICT behavior by trying to drop a table +# dependent on a type owned by another role. +subtest drop-behavior-type-1 + +user root + +statement ok +GRANT CREATE ON DATABASE test TO testuser WITH GRANT OPTION + +user testuser + +statement ok +CREATE TYPE type AS ENUM ('hello') + +statement ok +GRANT USAGE ON TYPE type TO testuser2 + +user testuser2 + +statement ok +CREATE TABLE t(x type) + +user root + +statement error pq: cannot drop desired object\(s\) because other objects depend on them +DROP OWNED BY testuser + +statement ok +DROP OWNED BY testuser, testuser2 + +query TTTTIT +SHOW TABLES FROM public +---- + +query TTT +SHOW TYPES +---- + +# DROP-BEHAVIOR-TYPE-2: Test RESTRICT behavior by trying to drop a view +# dependent on a type owned by another role. +subtest drop-behavior-type-2 + +user root + +statement ok +GRANT CREATE ON DATABASE test TO testuser WITH GRANT OPTION + +user testuser + +statement ok +CREATE TYPE type AS ENUM ('hello') + +statement ok +GRANT USAGE ON TYPE type TO testuser2 + +user testuser2 + +statement ok +CREATE TABLE t(a int) + +statement ok +CREATE VIEW v AS SELECT a, 'hello'::type FROM t + +user root + +statement error pq: cannot drop desired object\(s\) because other objects depend on them +DROP OWNED BY testuser + +statement ok +DROP OWNED BY testuser, testuser2 + +query TTTTIT +SHOW TABLES FROM public +---- + +query TTT +SHOW TYPES +---- + +# DROP-SCHEMA: Test that schemas and the objects that they contain can all be +# dropped together by a single DROP OWNED BY (when they are all owned by the +# specified roles). +subtest drop-schema + +user root + +statement ok +GRANT ALL ON DATABASE test TO testuser WITH GRANT OPTION + +user testuser + +statement ok +CREATE SCHEMA s + +statement ok +CREATE TABLE s.t1() + +statement ok +CREATE TABLE s.t2() + +statement ok +DROP OWNED BY testuser + +statement error pq: target database or schema does not exist +SHOW TABLES FROM s + +user root + +# REVOKE-PRIVILEGES-DB: Test that DROP OWNED BY revokes privileges on the +# current database. +# +# The DROP OWNED BY from the previous subtest did not revoke testuser's +# privileges for the DATABASE. This is because a user should not revoke its own +# database privileges. However, the root user should be able to drop testuser's +# database privileges via DROP OWNED BY. +subtest revoke-privileges-db + +query TTTB +SHOW GRANTS ON DATABASE test +---- +test admin ALL true +test public CONNECT false +test root ALL true +test testuser ALL true + +user root + +statement ok +DROP OWNED BY testuser + +query TTTB +SHOW GRANTS ON DATABASE test +---- +test admin ALL true +test public CONNECT false +test root ALL true + +# REVOKE-PRIVILEGES-SCHEMA: Test that DROP OWNED BY revokes privileges on +# schemas in the current database. +# +# In this test, root creates a schema and grants privileges for the schema to +# testuser. When testuser issues a DROP OWNED BY, those privileges should be +# revoked. +subtest revoke-privileges-schema + +user root + +statement ok +CREATE SCHEMA s + +statement ok +GRANT CREATE ON SCHEMA s TO testuser WITH GRANT OPTION + +user testuser + +statement ok +CREATE TABLE s.t() + +statement ok +DROP OWNED BY testuser + +query TTTTB +SHOW GRANTS ON SCHEMA s +---- +test s admin ALL true +test s root ALL true + +query TTTTIT +SHOW TABLES FROM s +---- + +user root + +statement ok +DROP SCHEMA s + +# REVOKE-PRIVILEGES-TABLE: Test that DROP OWNED BY revokes privileges on +# objects in the database. +subtest revoke-privileges-table + +user root + +statement ok +CREATE TABLE t() + +statement ok +GRANT ALL ON t TO testuser WITH GRANT OPTION + +user testuser + +query TTTTTB +SHOW GRANTS ON t +---- +test public t admin ALL true +test public t root ALL true +test public t testuser ALL true + +statement ok +DROP OWNED BY testuser + +query TTTTTB +SHOW GRANTS ON t +---- +test public t admin ALL true +test public t root ALL true + +user root + +statement ok +DROP TABLE t + +# MUTIROLE: Test DROP OWNED BY with multiple roles. +subtest multirole + +statement ok +CREATE ROLE r1 + +statement ok +CREATE ROLE r2 + +statement ok +SET ROLE r1 + +statement ok +CREATE TABLE t1() + +statement ok +SET ROLE r2 + +statement ok +CREATE TABLE t2() + +statement ok +SET ROLE root + +query TTTTIT +SHOW TABLES FROM public +---- +public t1 table r1 0 NULL +public t2 table r2 0 NULL + +statement ok +DROP OWNED BY r1, r2 + +query TTTTIT +SHOW TABLES FROM public +---- + +# ROLES: Test that the current user is a member of all the specified roles. The +# admin role and the root user are off-limits. +subtest roles + +user testuser + +statement error pq: permission denied to drop objects +DROP OWNED BY testuser2 + +statement error pq: permission denied to drop objects +DROP OWNED BY testuser, testuser2 + +statement error pq: cannot drop objects owned by role "root" because they are required by the database system +DROP OWNED BY root + +statement error pq: cannot drop objects owned by role "admin" because they are required by the database system +DROP OWNED BY admin + +# KITCHEN-SINK: Test DROP OWNED BY when there are multiple databases/schemas. +# Only objects/privileges in the current database should be dropped. +subtest kitchen-sink + +user root + +statement ok +CREATE DATABASE d1 + +statement ok +CREATE DATABASE d2 + +statement ok +CREATE DATABASE d3 + +statement ok +CREATE DATABASE d4 + +statement ok +CREATE SCHEMA d1.s1 + +statement ok +CREATE SCHEMA d1.s2 + +statement ok +GRANT CREATE, DROP ON DATABASE d1 TO testuser WITH GRANT OPTION + +statement ok +GRANT ALL ON DATABASE d2 TO testuser WITH GRANT OPTION + +statement ok +GRANT CREATE ON DATABASE d3 TO testuser WITH GRANT OPTION + +statement ok +GRANT CREATE ON SCHEMA d1.s1 TO testuser WITH GRANT OPTION + +statement ok +CREATE TABLE d1.t1 (k STRING PRIMARY KEY, v STRING) + +statement ok +CREATE VIEW d1.v1 AS SELECT k,v FROM d1.t1 + +statement ok +CREATE TABLE d1.s1.t1 (a INT) + +statement ok +CREATE SCHEMA d2.s1 + +user testuser + +statement ok +CREATE SCHEMA d1.s3 + +statement ok +CREATE SCHEMA d1.s4 + +statement ok +CREATE TABLE d1.t2 (k STRING PRIMARY KEY, v STRING) + +statement ok +CREATE VIEW d1.v2 AS SELECT k,v FROM d1.t2 + +statement ok +CREATE TABLE d1.s1.t2 (a INT) + +statement ok +CREATE SCHEMA d2.s2 + +statement ok +CREATE TABLE d2.t1() + +user root + +query TTTTT +SHOW DATABASES +---- +d1 root NULL {} NULL +d2 root NULL {} NULL +d3 root NULL {} NULL +d4 root NULL {} NULL +defaultdb root NULL {} NULL +postgres root NULL {} NULL +system node NULL {} NULL +test root NULL {} NULL + +statement ok +SET DATABASE = d1 + +query TT +SHOW SCHEMAS FROM d1 +---- +crdb_internal NULL +information_schema NULL +pg_catalog NULL +pg_extension NULL +public admin +s1 root +s2 root +s3 testuser +s4 testuser + +query TTTTIT +SHOW TABLES FROM d1 +---- +public t1 table root 0 NULL +public t2 table testuser 0 NULL +public v1 view root 0 NULL +public v2 view testuser 0 NULL +s1 t1 table root 0 NULL +s1 t2 table testuser 0 NULL + +query TTTB +SHOW GRANTS ON DATABASE d1 +---- +d1 admin ALL true +d1 public CONNECT false +d1 root ALL true +d1 testuser CREATE true +d1 testuser DROP true + +query TTTTB +SHOW GRANTS ON SCHEMA d1.s1 +---- +d1 s1 admin ALL true +d1 s1 root ALL true +d1 s1 testuser CREATE true + +statement ok +DROP OWNED BY testuser + +query TT +SHOW SCHEMAS FROM d1 +---- +crdb_internal NULL +information_schema NULL +pg_catalog NULL +pg_extension NULL +public admin +s1 root +s2 root + +query TTTTIT +SHOW TABLES FROM d1 +---- +public t1 table root 0 NULL +public v1 view root 0 NULL +s1 t1 table root 0 NULL + +query TTTTB +SHOW GRANTS ON SCHEMA d1.s1 +---- +d1 s1 admin ALL true +d1 s1 root ALL true + +query TTTB +SHOW GRANTS ON DATABASE d1 +---- +d1 admin ALL true +d1 public CONNECT false +d1 root ALL true + +statement ok +SET DATABASE = d2 + +query TT +SHOW SCHEMAS FROM d2 +---- +crdb_internal NULL +information_schema NULL +pg_catalog NULL +pg_extension NULL +public admin +s1 root +s2 testuser + +query TTTTIT +SHOW TABLES FROM d2 +---- +public t1 table testuser 0 NULL + +query TTTB +SHOW GRANTS ON DATABASE d2 +---- +d2 admin ALL true +d2 public CONNECT false +d2 root ALL true +d2 testuser ALL true + +statement ok +DROP OWNED BY testuser + +query TT +SHOW SCHEMAS FROM d2 +---- +crdb_internal NULL +information_schema NULL +pg_catalog NULL +pg_extension NULL +public admin +s1 root + +query TTTTIT +SHOW TABLES FROM d2 +---- + +query TTTB +SHOW GRANTS ON DATABASE d2 +---- +d2 admin ALL true +d2 public CONNECT false +d2 root ALL true + +statement ok +SET DATABASE = d3 + +query TTTB +SHOW GRANTS ON DATABASE d3 +---- +d3 admin ALL true +d3 public CONNECT false +d3 root ALL true +d3 testuser CREATE true + +statement ok +DROP OWNED BY testuser + +query TTTB +SHOW GRANTS ON DATABASE d3 +---- +d3 admin ALL true +d3 public CONNECT false +d3 root ALL true diff --git a/pkg/sql/schemachanger/scbuild/builder_state.go b/pkg/sql/schemachanger/scbuild/builder_state.go index ad0d1dcbef80..0f63e3c5d55b 100644 --- a/pkg/sql/schemachanger/scbuild/builder_state.go +++ b/pkg/sql/schemachanger/scbuild/builder_state.go @@ -14,6 +14,7 @@ import ( "strings" "github.com/cockroachdb/cockroach/pkg/keys" + "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" @@ -155,6 +156,19 @@ func (b *builderState) checkPrivilege(id catid.DescID, priv privilege.Kind) { } } +// CurrentUserHasAdminOrIsMemberOf implements the scbuildstmt.PrivilegeChecker interface. +func (b *builderState) CurrentUserHasAdminOrIsMemberOf(role username.SQLUsername) bool { + if b.hasAdmin { + return true + } + memberships, err := b.auth.MemberOfWithAdminOption(b.ctx, role) + if err != nil { + panic(err) + } + _, ok := memberships[b.evalCtx.SessionData().User()] + return ok +} + var _ scbuildstmt.TableHelpers = (*builderState)(nil) // NextTableColumnID implements the scbuildstmt.TableHelpers interface. diff --git a/pkg/sql/schemachanger/scbuild/dependencies.go b/pkg/sql/schemachanger/scbuild/dependencies.go index 9bc31e766593..cff767c01196 100644 --- a/pkg/sql/schemachanger/scbuild/dependencies.go +++ b/pkg/sql/schemachanger/scbuild/dependencies.go @@ -167,6 +167,10 @@ type AuthorizationAccessor interface { CheckPrivilegeForUser( ctx context.Context, descriptor catalog.Descriptor, privilege privilege.Kind, user username.SQLUsername, ) error + + // MemberOfWithAdminOption looks up all the roles 'member' belongs to (direct + // and indirect) and returns a map of "role" -> "isAdmin". + MemberOfWithAdminOption(ctx context.Context, member username.SQLUsername) (map[username.SQLUsername]bool, error) } // AstFormatter provides interfaces for formatting AST nodes. diff --git a/pkg/sql/schemachanger/scbuild/internal/scbuildstmt/BUILD.bazel b/pkg/sql/schemachanger/scbuild/internal/scbuildstmt/BUILD.bazel index 397dca826e5a..1c6e2e1f1cc4 100644 --- a/pkg/sql/schemachanger/scbuild/internal/scbuildstmt/BUILD.bazel +++ b/pkg/sql/schemachanger/scbuild/internal/scbuildstmt/BUILD.bazel @@ -9,6 +9,7 @@ go_library( "create_index.go", "dependencies.go", "drop_database.go", + "drop_owned_by.go", "drop_schema.go", "drop_sequence.go", "drop_table.go", @@ -20,6 +21,7 @@ go_library( importpath = "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scbuild/internal/scbuildstmt", visibility = ["//pkg/sql/schemachanger/scbuild:__subpackages__"], deps = [ + "//pkg/security/username", "//pkg/server/telemetry", "//pkg/settings/cluster", "//pkg/sql/catalog", @@ -29,6 +31,7 @@ go_library( "//pkg/sql/catalog/schemaexpr", "//pkg/sql/catalog/tabledesc", "//pkg/sql/catalog/typedesc", + "//pkg/sql/decodeusername", "//pkg/sql/parser", "//pkg/sql/pgwire/pgcode", "//pkg/sql/pgwire/pgerror", diff --git a/pkg/sql/schemachanger/scbuild/internal/scbuildstmt/dependencies.go b/pkg/sql/schemachanger/scbuild/internal/scbuildstmt/dependencies.go index e4f136168f8a..095b38b16998 100644 --- a/pkg/sql/schemachanger/scbuild/internal/scbuildstmt/dependencies.go +++ b/pkg/sql/schemachanger/scbuild/internal/scbuildstmt/dependencies.go @@ -13,6 +13,7 @@ package scbuildstmt import ( "context" + "github.com/cockroachdb/cockroach/pkg/security/username" "github.com/cockroachdb/cockroach/pkg/settings/cluster" "github.com/cockroachdb/cockroach/pkg/sql/catalog/catpb" "github.com/cockroachdb/cockroach/pkg/sql/privilege" @@ -148,6 +149,9 @@ type Telemetry interface { // IncrementEnumCounter increments the selected enum telemetry counter. IncrementEnumCounter(counterType sqltelemetry.EnumTelemetryType) + + // IncrementDropOwnedByCounter increments the DROP OWNED BY telemetry counter. + IncrementDropOwnedByCounter() } // SchemaFeatureChecker checks if a schema change feature is allowed by the @@ -167,6 +171,10 @@ type PrivilegeChecker interface { // CheckPrivilege panics if the current user does not have the specified // privilege for the element. CheckPrivilege(e scpb.Element, privilege privilege.Kind) + + // CurrentUserHasAdminOrIsMemberOf returns true iff the current user is (1) + // an admin or (2) has membership in the specified role. + CurrentUserHasAdminOrIsMemberOf(member username.SQLUsername) bool } // TableHelpers has methods useful for creating new table elements. diff --git a/pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go b/pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go new file mode 100644 index 000000000000..8e2971de0914 --- /dev/null +++ b/pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go @@ -0,0 +1,106 @@ +// Copyright 2022 The Cockroach Authors. +// +// Use of this software is governed by the Business Source License +// included in the file licenses/BSL.txt. +// +// As of the Change Date specified in that file, in accordance with +// the Business Source License, use of this software will be governed +// by the Apache License, Version 2.0, included in the file +// licenses/APL.txt. + +package scbuildstmt + +import ( + "github.com/cockroachdb/cockroach/pkg/security/username" + "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" + "github.com/cockroachdb/cockroach/pkg/sql/decodeusername" + "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode" + "github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror" + "github.com/cockroachdb/cockroach/pkg/sql/privilege" + "github.com/cockroachdb/cockroach/pkg/sql/schemachanger/scpb" + "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" + "github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented" +) + +// DropOwnedBy implements DROP OWNED BY. +func DropOwnedBy(b BuildCtx, n *tree.DropOwnedBy) { + normalizedRoles, err := decodeusername.FromRoleSpecList( + b.SessionData(), username.PurposeValidation, n.Roles, + ) + if err != nil { + panic(err) + } + for _, role := range normalizedRoles { + if role.IsAdminRole() || role.IsRootUser() || role.IsNodeUser() { + panic(pgerror.Newf(pgcode.DependentObjectsStillExist, + "cannot drop objects owned by role %q because they are required by the database system", role)) + } + if role != b.SessionData().User() && !b.CurrentUserHasAdminOrIsMemberOf(role) { + panic(pgerror.New(pgcode.InsufficientPrivilege, "permission denied to drop objects")) + } + } + + var objects []descpb.ID + var toCheckBackrefs []descpb.ID + + // Lookup all objects in the current database. + _, _, db := scpb.FindDatabase(b.ResolveDatabase(tree.Name(b.SessionData().Database), ResolveParams{ + IsExistenceOptional: false, + RequiredPrivilege: privilege.CONNECT, + })) + dbRefs := undroppedBackrefs(b, db.DatabaseID) + scpb.ForEachSchemaParent(dbRefs, func(_ scpb.Status, _ scpb.TargetStatus, sp *scpb.SchemaParent) { + schemaRefs := undroppedBackrefs(b, sp.SchemaID) + scpb.ForEachObjectParent(schemaRefs, func(_ scpb.Status, _ scpb.TargetStatus, op *scpb.ObjectParent) { + objects = append(objects, op.ObjectID) + }) + objects = append(objects, sp.SchemaID) + }) + + // Drop owned objects and revoke user privileges for the specified roles. + for _, id := range objects { + elts := b.QueryByID(id) + _, _, owner := scpb.FindOwner(elts) + for _, role := range normalizedRoles { + if owner.Owner == role.Normalized() { + if n.DropBehavior == tree.DropCascade { + panic(unimplemented.NewWithIssue(55908, "DROP OWNED BY CASCADE is not yet supported")) + } else { + if dropRestrictDescriptor(b, id) { + toCheckBackrefs = append(toCheckBackrefs, id) + } + } + break + } + scpb.ForEachUserPrivileges(elts, func(_ scpb.Status, _ scpb.TargetStatus, e *scpb.UserPrivileges) { + if e.UserName == role.Normalized() { + b.Drop(e) + } + }) + } + } + + // Revoke privileges for the database. The current user shouldn't revoke + // their own database privileges. + dbElts := b.QueryByID(db.DatabaseID) + scpb.ForEachUserPrivileges(dbElts, func(_ scpb.Status, _ scpb.TargetStatus, e *scpb.UserPrivileges) { + for _, role := range normalizedRoles { + if e.UserName == role.Normalized() && e.UserName != b.SessionData().User().Normalized() { + b.Drop(e) + break + } + } + }) + + b.IncrementSubWorkID() + b.IncrementDropOwnedByCounter() + + // Enforce RESTRICT semantics by checking for backreferences. + for _, id := range toCheckBackrefs { + backrefs := undroppedBackrefs(b, id) + if !backrefs.IsEmpty() { + panic(pgerror.New(pgcode.DependentObjectsStillExist, + "cannot drop desired object(s) because other objects depend on them")) + } + } +} diff --git a/pkg/sql/schemachanger/scbuild/internal/scbuildstmt/process.go b/pkg/sql/schemachanger/scbuild/internal/scbuildstmt/process.go index 196410ebd1d6..5ca420776a44 100644 --- a/pkg/sql/schemachanger/scbuild/internal/scbuildstmt/process.go +++ b/pkg/sql/schemachanger/scbuild/internal/scbuildstmt/process.go @@ -49,6 +49,7 @@ var supportedStatements = map[reflect.Type]supportedStatement{ reflect.TypeOf((*tree.AlterTable)(nil)): {AlterTable, true}, reflect.TypeOf((*tree.CreateIndex)(nil)): {CreateIndex, false}, reflect.TypeOf((*tree.DropDatabase)(nil)): {DropDatabase, true}, + reflect.TypeOf((*tree.DropOwnedBy)(nil)): {DropOwnedBy, true}, reflect.TypeOf((*tree.DropSchema)(nil)): {DropSchema, true}, reflect.TypeOf((*tree.DropSequence)(nil)): {DropSequence, true}, reflect.TypeOf((*tree.DropTable)(nil)): {DropTable, true}, diff --git a/pkg/sql/schemachanger/scbuild/testdata/drop_owned_by b/pkg/sql/schemachanger/scbuild/testdata/drop_owned_by new file mode 100644 index 000000000000..a88a98f34aae --- /dev/null +++ b/pkg/sql/schemachanger/scbuild/testdata/drop_owned_by @@ -0,0 +1,776 @@ +setup +CREATE ROLE r; +CREATE TABLE tab(); +GRANT ALL ON tab TO r; +GRANT CREATE ON DATABASE defaultdb TO r WITH GRANT OPTION; +SET ROLE r; +CREATE SCHEMA s; +CREATE SEQUENCE public.sq; +CREATE SEQUENCE s.sq; +CREATE TABLE s.t (id INT PRIMARY KEY, name VARCHAR(256), val INT DEFAULT nextval('s.sq')); +CREATE TABLE public.t (id INT PRIMARY KEY, name VARCHAR(256), val INT DEFAULT nextval('public.sq')); +CREATE VIEW s.v1 AS (SELECT name FROM s.t); +CREATE TYPE s.typ AS ENUM('a'); +CREATE VIEW s.v2 AS (SELECT 'a'::s.typ::string AS k, name FROM s.v1); +SET ROLE root; +---- + +build +DROP OWNED BY r +---- +- [[AliasType:{DescID: 112}, ABSENT], PUBLIC] + details: + embeddedTypeT: + closedTypeIds: + - 111 + - 112 + type: + arrayContents: + family: EnumFamily + oid: 100111 + udtMetadata: + arrayTypeOid: 100112 + arrayElemType: EnumFamily + family: ArrayFamily + oid: 100112 + typeId: 112 +- [[Column:{DescID: 108, ColumnID: 1}, ABSENT], PUBLIC] + details: + columnId: 1 + pgAttributeNum: 1 + tableId: 108 +- [[Column:{DescID: 108, ColumnID: 2}, ABSENT], PUBLIC] + details: + columnId: 2 + pgAttributeNum: 2 + tableId: 108 +- [[Column:{DescID: 108, ColumnID: 3}, ABSENT], PUBLIC] + details: + columnId: 3 + pgAttributeNum: 3 + tableId: 108 +- [[Column:{DescID: 108, ColumnID: 4294967294}, ABSENT], PUBLIC] + details: + columnId: 4.294967294e+09 + isHidden: true + isSystemColumn: true + pgAttributeNum: 4.294967294e+09 + tableId: 108 +- [[Column:{DescID: 108, ColumnID: 4294967295}, ABSENT], PUBLIC] + details: + columnId: 4.294967295e+09 + isHidden: true + isSystemColumn: true + pgAttributeNum: 4.294967295e+09 + tableId: 108 +- [[Column:{DescID: 109, ColumnID: 1}, ABSENT], PUBLIC] + details: + columnId: 1 + pgAttributeNum: 1 + tableId: 109 +- [[Column:{DescID: 109, ColumnID: 2}, ABSENT], PUBLIC] + details: + columnId: 2 + pgAttributeNum: 2 + tableId: 109 +- [[Column:{DescID: 109, ColumnID: 3}, ABSENT], PUBLIC] + details: + columnId: 3 + pgAttributeNum: 3 + tableId: 109 +- [[Column:{DescID: 109, ColumnID: 4294967294}, ABSENT], PUBLIC] + details: + columnId: 4.294967294e+09 + isHidden: true + isSystemColumn: true + pgAttributeNum: 4.294967294e+09 + tableId: 109 +- [[Column:{DescID: 109, ColumnID: 4294967295}, ABSENT], PUBLIC] + details: + columnId: 4.294967295e+09 + isHidden: true + isSystemColumn: true + pgAttributeNum: 4.294967295e+09 + tableId: 109 +- [[Column:{DescID: 110, ColumnID: 1}, ABSENT], PUBLIC] + details: + columnId: 1 + pgAttributeNum: 1 + tableId: 110 +- [[Column:{DescID: 110, ColumnID: 4294967294}, ABSENT], PUBLIC] + details: + columnId: 4.294967294e+09 + isHidden: true + isSystemColumn: true + pgAttributeNum: 4.294967294e+09 + tableId: 110 +- [[Column:{DescID: 110, ColumnID: 4294967295}, ABSENT], PUBLIC] + details: + columnId: 4.294967295e+09 + isHidden: true + isSystemColumn: true + pgAttributeNum: 4.294967295e+09 + tableId: 110 +- [[Column:{DescID: 113, ColumnID: 1}, ABSENT], PUBLIC] + details: + columnId: 1 + pgAttributeNum: 1 + tableId: 113 +- [[Column:{DescID: 113, ColumnID: 2}, ABSENT], PUBLIC] + details: + columnId: 2 + pgAttributeNum: 2 + tableId: 113 +- [[Column:{DescID: 113, ColumnID: 4294967294}, ABSENT], PUBLIC] + details: + columnId: 4.294967294e+09 + isHidden: true + isSystemColumn: true + pgAttributeNum: 4.294967294e+09 + tableId: 113 +- [[Column:{DescID: 113, ColumnID: 4294967295}, ABSENT], PUBLIC] + details: + columnId: 4.294967295e+09 + isHidden: true + isSystemColumn: true + pgAttributeNum: 4.294967295e+09 + tableId: 113 +- [[ColumnDefaultExpression:{DescID: 108, ColumnID: 3}, ABSENT], PUBLIC] + details: + columnId: 3 + embeddedExpr: + expr: nextval(107:::REGCLASS) + usesSequenceIds: + - 107 + tableId: 108 +- [[ColumnDefaultExpression:{DescID: 109, ColumnID: 3}, ABSENT], PUBLIC] + details: + columnId: 3 + embeddedExpr: + expr: nextval(106:::REGCLASS) + usesSequenceIds: + - 106 + tableId: 109 +- [[ColumnFamily:{DescID: 108, ColumnFamilyID: 0, Name: primary}, ABSENT], PUBLIC] + details: + name: primary + tableId: 108 +- [[ColumnFamily:{DescID: 109, ColumnFamilyID: 0, Name: primary}, ABSENT], PUBLIC] + details: + name: primary + tableId: 109 +- [[ColumnName:{DescID: 108, Name: crdb_internal_mvcc_timestamp, ColumnID: 4294967295}, ABSENT], PUBLIC] + details: + columnId: 4.294967295e+09 + name: crdb_internal_mvcc_timestamp + tableId: 108 +- [[ColumnName:{DescID: 108, Name: id, ColumnID: 1}, ABSENT], PUBLIC] + details: + columnId: 1 + name: id + tableId: 108 +- [[ColumnName:{DescID: 108, Name: name, ColumnID: 2}, ABSENT], PUBLIC] + details: + columnId: 2 + name: name + tableId: 108 +- [[ColumnName:{DescID: 108, Name: tableoid, ColumnID: 4294967294}, ABSENT], PUBLIC] + details: + columnId: 4.294967294e+09 + name: tableoid + tableId: 108 +- [[ColumnName:{DescID: 108, Name: val, ColumnID: 3}, ABSENT], PUBLIC] + details: + columnId: 3 + name: val + tableId: 108 +- [[ColumnName:{DescID: 109, Name: crdb_internal_mvcc_timestamp, ColumnID: 4294967295}, ABSENT], PUBLIC] + details: + columnId: 4.294967295e+09 + name: crdb_internal_mvcc_timestamp + tableId: 109 +- [[ColumnName:{DescID: 109, Name: id, ColumnID: 1}, ABSENT], PUBLIC] + details: + columnId: 1 + name: id + tableId: 109 +- [[ColumnName:{DescID: 109, Name: name, ColumnID: 2}, ABSENT], PUBLIC] + details: + columnId: 2 + name: name + tableId: 109 +- [[ColumnName:{DescID: 109, Name: tableoid, ColumnID: 4294967294}, ABSENT], PUBLIC] + details: + columnId: 4.294967294e+09 + name: tableoid + tableId: 109 +- [[ColumnName:{DescID: 109, Name: val, ColumnID: 3}, ABSENT], PUBLIC] + details: + columnId: 3 + name: val + tableId: 109 +- [[ColumnName:{DescID: 110, Name: crdb_internal_mvcc_timestamp, ColumnID: 4294967295}, ABSENT], PUBLIC] + details: + columnId: 4.294967295e+09 + name: crdb_internal_mvcc_timestamp + tableId: 110 +- [[ColumnName:{DescID: 110, Name: name, ColumnID: 1}, ABSENT], PUBLIC] + details: + columnId: 1 + name: name + tableId: 110 +- [[ColumnName:{DescID: 110, Name: tableoid, ColumnID: 4294967294}, ABSENT], PUBLIC] + details: + columnId: 4.294967294e+09 + name: tableoid + tableId: 110 +- [[ColumnName:{DescID: 113, Name: crdb_internal_mvcc_timestamp, ColumnID: 4294967295}, ABSENT], PUBLIC] + details: + columnId: 4.294967295e+09 + name: crdb_internal_mvcc_timestamp + tableId: 113 +- [[ColumnName:{DescID: 113, Name: k, ColumnID: 1}, ABSENT], PUBLIC] + details: + columnId: 1 + name: k + tableId: 113 +- [[ColumnName:{DescID: 113, Name: name, ColumnID: 2}, ABSENT], PUBLIC] + details: + columnId: 2 + name: name + tableId: 113 +- [[ColumnName:{DescID: 113, Name: tableoid, ColumnID: 4294967294}, ABSENT], PUBLIC] + details: + columnId: 4.294967294e+09 + name: tableoid + tableId: 113 +- [[ColumnType:{DescID: 108, ColumnFamilyID: 0, ColumnID: 1}, ABSENT], PUBLIC] + details: + columnId: 1 + embeddedTypeT: + type: + family: IntFamily + oid: 20 + width: 64 + isRelationBeingDropped: true + tableId: 108 +- [[ColumnType:{DescID: 108, ColumnFamilyID: 0, ColumnID: 2}, ABSENT], PUBLIC] + details: + columnId: 2 + embeddedTypeT: + type: + family: StringFamily + oid: 1043 + visibleType: 7 + width: 256 + isNullable: true + isRelationBeingDropped: true + tableId: 108 +- [[ColumnType:{DescID: 108, ColumnFamilyID: 0, ColumnID: 3}, ABSENT], PUBLIC] + details: + columnId: 3 + embeddedTypeT: + type: + family: IntFamily + oid: 20 + width: 64 + isNullable: true + isRelationBeingDropped: true + tableId: 108 +- [[ColumnType:{DescID: 108, ColumnFamilyID: 0, ColumnID: 4294967294}, ABSENT], PUBLIC] + details: + columnId: 4.294967294e+09 + embeddedTypeT: + type: + family: OidFamily + oid: 26 + isNullable: true + isRelationBeingDropped: true + tableId: 108 +- [[ColumnType:{DescID: 108, ColumnFamilyID: 0, ColumnID: 4294967295}, ABSENT], PUBLIC] + details: + columnId: 4.294967295e+09 + embeddedTypeT: + type: + family: DecimalFamily + oid: 1700 + isNullable: true + isRelationBeingDropped: true + tableId: 108 +- [[ColumnType:{DescID: 109, ColumnFamilyID: 0, ColumnID: 1}, ABSENT], PUBLIC] + details: + columnId: 1 + embeddedTypeT: + type: + family: IntFamily + oid: 20 + width: 64 + isRelationBeingDropped: true + tableId: 109 +- [[ColumnType:{DescID: 109, ColumnFamilyID: 0, ColumnID: 2}, ABSENT], PUBLIC] + details: + columnId: 2 + embeddedTypeT: + type: + family: StringFamily + oid: 1043 + visibleType: 7 + width: 256 + isNullable: true + isRelationBeingDropped: true + tableId: 109 +- [[ColumnType:{DescID: 109, ColumnFamilyID: 0, ColumnID: 3}, ABSENT], PUBLIC] + details: + columnId: 3 + embeddedTypeT: + type: + family: IntFamily + oid: 20 + width: 64 + isNullable: true + isRelationBeingDropped: true + tableId: 109 +- [[ColumnType:{DescID: 109, ColumnFamilyID: 0, ColumnID: 4294967294}, ABSENT], PUBLIC] + details: + columnId: 4.294967294e+09 + embeddedTypeT: + type: + family: OidFamily + oid: 26 + isNullable: true + isRelationBeingDropped: true + tableId: 109 +- [[ColumnType:{DescID: 109, ColumnFamilyID: 0, ColumnID: 4294967295}, ABSENT], PUBLIC] + details: + columnId: 4.294967295e+09 + embeddedTypeT: + type: + family: DecimalFamily + oid: 1700 + isNullable: true + isRelationBeingDropped: true + tableId: 109 +- [[ColumnType:{DescID: 110, ColumnFamilyID: 0, ColumnID: 1}, ABSENT], PUBLIC] + details: + columnId: 1 + embeddedTypeT: + type: + family: StringFamily + oid: 1043 + visibleType: 7 + width: 256 + isNullable: true + isRelationBeingDropped: true + tableId: 110 +- [[ColumnType:{DescID: 110, ColumnFamilyID: 0, ColumnID: 4294967294}, ABSENT], PUBLIC] + details: + columnId: 4.294967294e+09 + embeddedTypeT: + type: + family: OidFamily + oid: 26 + isNullable: true + isRelationBeingDropped: true + tableId: 110 +- [[ColumnType:{DescID: 110, ColumnFamilyID: 0, ColumnID: 4294967295}, ABSENT], PUBLIC] + details: + columnId: 4.294967295e+09 + embeddedTypeT: + type: + family: DecimalFamily + oid: 1700 + isNullable: true + isRelationBeingDropped: true + tableId: 110 +- [[ColumnType:{DescID: 113, ColumnFamilyID: 0, ColumnID: 1}, ABSENT], PUBLIC] + details: + columnId: 1 + embeddedTypeT: + type: + family: StringFamily + oid: 25 + isNullable: true + isRelationBeingDropped: true + tableId: 113 +- [[ColumnType:{DescID: 113, ColumnFamilyID: 0, ColumnID: 2}, ABSENT], PUBLIC] + details: + columnId: 2 + embeddedTypeT: + type: + family: StringFamily + oid: 1043 + visibleType: 7 + width: 256 + isNullable: true + isRelationBeingDropped: true + tableId: 113 +- [[ColumnType:{DescID: 113, ColumnFamilyID: 0, ColumnID: 4294967294}, ABSENT], PUBLIC] + details: + columnId: 4.294967294e+09 + embeddedTypeT: + type: + family: OidFamily + oid: 26 + isNullable: true + isRelationBeingDropped: true + tableId: 113 +- [[ColumnType:{DescID: 113, ColumnFamilyID: 0, ColumnID: 4294967295}, ABSENT], PUBLIC] + details: + columnId: 4.294967295e+09 + embeddedTypeT: + type: + family: DecimalFamily + oid: 1700 + isNullable: true + isRelationBeingDropped: true + tableId: 113 +- [[EnumType:{DescID: 111}, ABSENT], PUBLIC] + details: + arrayTypeId: 112 + typeId: 111 +- [[IndexName:{DescID: 108, Name: t_pkey, IndexID: 1}, ABSENT], PUBLIC] + details: + indexId: 1 + name: t_pkey + tableId: 108 +- [[IndexName:{DescID: 109, Name: t_pkey, IndexID: 1}, ABSENT], PUBLIC] + details: + indexId: 1 + name: t_pkey + tableId: 109 +- [[Namespace:{DescID: 105, Name: s, ReferencedDescID: 100}, ABSENT], PUBLIC] + details: + databaseId: 100 + descriptorId: 105 + name: s +- [[Namespace:{DescID: 106, Name: sq, ReferencedDescID: 100}, ABSENT], PUBLIC] + details: + databaseId: 100 + descriptorId: 106 + name: sq + schemaId: 101 +- [[Namespace:{DescID: 107, Name: sq, ReferencedDescID: 100}, ABSENT], PUBLIC] + details: + databaseId: 100 + descriptorId: 107 + name: sq + schemaId: 105 +- [[Namespace:{DescID: 108, Name: t, ReferencedDescID: 100}, ABSENT], PUBLIC] + details: + databaseId: 100 + descriptorId: 108 + name: t + schemaId: 105 +- [[Namespace:{DescID: 109, Name: t, ReferencedDescID: 100}, ABSENT], PUBLIC] + details: + databaseId: 100 + descriptorId: 109 + name: t + schemaId: 101 +- [[Namespace:{DescID: 110, Name: v1, ReferencedDescID: 100}, ABSENT], PUBLIC] + details: + databaseId: 100 + descriptorId: 110 + name: v1 + schemaId: 105 +- [[Namespace:{DescID: 111, Name: typ, ReferencedDescID: 100}, ABSENT], PUBLIC] + details: + databaseId: 100 + descriptorId: 111 + name: typ + schemaId: 105 +- [[Namespace:{DescID: 112, Name: _typ, ReferencedDescID: 100}, ABSENT], PUBLIC] + details: + databaseId: 100 + descriptorId: 112 + name: _typ + schemaId: 105 +- [[Namespace:{DescID: 113, Name: v2, ReferencedDescID: 100}, ABSENT], PUBLIC] + details: + databaseId: 100 + descriptorId: 113 + name: v2 + schemaId: 105 +- [[ObjectParent:{DescID: 106, ReferencedDescID: 101}, ABSENT], PUBLIC] + details: + objectId: 106 + parentSchemaId: 101 +- [[ObjectParent:{DescID: 107, ReferencedDescID: 105}, ABSENT], PUBLIC] + details: + objectId: 107 + parentSchemaId: 105 +- [[ObjectParent:{DescID: 108, ReferencedDescID: 105}, ABSENT], PUBLIC] + details: + objectId: 108 + parentSchemaId: 105 +- [[ObjectParent:{DescID: 109, ReferencedDescID: 101}, ABSENT], PUBLIC] + details: + objectId: 109 + parentSchemaId: 101 +- [[ObjectParent:{DescID: 110, ReferencedDescID: 105}, ABSENT], PUBLIC] + details: + objectId: 110 + parentSchemaId: 105 +- [[ObjectParent:{DescID: 111, ReferencedDescID: 105}, ABSENT], PUBLIC] + details: + objectId: 111 + parentSchemaId: 105 +- [[ObjectParent:{DescID: 112, ReferencedDescID: 105}, ABSENT], PUBLIC] + details: + objectId: 112 + parentSchemaId: 105 +- [[ObjectParent:{DescID: 113, ReferencedDescID: 105}, ABSENT], PUBLIC] + details: + objectId: 113 + parentSchemaId: 105 +- [[Owner:{DescID: 105}, ABSENT], PUBLIC] + details: + descriptorId: 105 + owner: r +- [[Owner:{DescID: 106}, ABSENT], PUBLIC] + details: + descriptorId: 106 + owner: r +- [[Owner:{DescID: 107}, ABSENT], PUBLIC] + details: + descriptorId: 107 + owner: r +- [[Owner:{DescID: 108}, ABSENT], PUBLIC] + details: + descriptorId: 108 + owner: r +- [[Owner:{DescID: 109}, ABSENT], PUBLIC] + details: + descriptorId: 109 + owner: r +- [[Owner:{DescID: 110}, ABSENT], PUBLIC] + details: + descriptorId: 110 + owner: r +- [[Owner:{DescID: 111}, ABSENT], PUBLIC] + details: + descriptorId: 111 + owner: r +- [[Owner:{DescID: 112}, ABSENT], PUBLIC] + details: + descriptorId: 112 + owner: r +- [[Owner:{DescID: 113}, ABSENT], PUBLIC] + details: + descriptorId: 113 + owner: r +- [[PrimaryIndex:{DescID: 108, IndexID: 1, ConstraintID: 1}, ABSENT], PUBLIC] + details: + embeddedIndex: + constraintId: 1 + indexId: 1 + isUnique: true + keyColumnDirections: + - ASC + keyColumnIds: + - 1 + storingColumnIds: + - 2 + - 3 + tableId: 108 +- [[PrimaryIndex:{DescID: 109, IndexID: 1, ConstraintID: 1}, ABSENT], PUBLIC] + details: + embeddedIndex: + constraintId: 1 + indexId: 1 + isUnique: true + keyColumnDirections: + - ASC + keyColumnIds: + - 1 + storingColumnIds: + - 2 + - 3 + tableId: 109 +- [[Schema:{DescID: 105}, ABSENT], PUBLIC] + details: + schemaId: 105 +- [[SchemaParent:{DescID: 105, ReferencedDescID: 100}, ABSENT], PUBLIC] + details: + parentDatabaseId: 100 + schemaId: 105 +- [[Sequence:{DescID: 106}, ABSENT], PUBLIC] + details: + sequenceId: 106 +- [[Sequence:{DescID: 107}, ABSENT], PUBLIC] + details: + sequenceId: 107 +- [[Table:{DescID: 108}, ABSENT], PUBLIC] + details: + tableId: 108 +- [[Table:{DescID: 109}, ABSENT], PUBLIC] + details: + tableId: 109 +- [[UserPrivileges:{DescID: 100, Name: r}, ABSENT], PUBLIC] + details: + descriptorId: 100 + privileges: 4 + userName: r +- [[UserPrivileges:{DescID: 104, Name: r}, ABSENT], PUBLIC] + details: + descriptorId: 104 + privileges: 2 + userName: r +- [[UserPrivileges:{DescID: 105, Name: admin}, ABSENT], PUBLIC] + details: + descriptorId: 105 + privileges: 2 + userName: admin +- [[UserPrivileges:{DescID: 105, Name: root}, ABSENT], PUBLIC] + details: + descriptorId: 105 + privileges: 2 + userName: root +- [[UserPrivileges:{DescID: 105, Name: r}, ABSENT], PUBLIC] + details: + descriptorId: 105 + privileges: 2 + userName: r +- [[UserPrivileges:{DescID: 106, Name: admin}, ABSENT], PUBLIC] + details: + descriptorId: 106 + privileges: 2 + userName: admin +- [[UserPrivileges:{DescID: 106, Name: root}, ABSENT], PUBLIC] + details: + descriptorId: 106 + privileges: 2 + userName: root +- [[UserPrivileges:{DescID: 106, Name: r}, ABSENT], PUBLIC] + details: + descriptorId: 106 + privileges: 2 + userName: r +- [[UserPrivileges:{DescID: 107, Name: admin}, ABSENT], PUBLIC] + details: + descriptorId: 107 + privileges: 2 + userName: admin +- [[UserPrivileges:{DescID: 107, Name: root}, ABSENT], PUBLIC] + details: + descriptorId: 107 + privileges: 2 + userName: root +- [[UserPrivileges:{DescID: 107, Name: r}, ABSENT], PUBLIC] + details: + descriptorId: 107 + privileges: 2 + userName: r +- [[UserPrivileges:{DescID: 108, Name: admin}, ABSENT], PUBLIC] + details: + descriptorId: 108 + privileges: 2 + userName: admin +- [[UserPrivileges:{DescID: 108, Name: root}, ABSENT], PUBLIC] + details: + descriptorId: 108 + privileges: 2 + userName: root +- [[UserPrivileges:{DescID: 108, Name: r}, ABSENT], PUBLIC] + details: + descriptorId: 108 + privileges: 2 + userName: r +- [[UserPrivileges:{DescID: 109, Name: admin}, ABSENT], PUBLIC] + details: + descriptorId: 109 + privileges: 2 + userName: admin +- [[UserPrivileges:{DescID: 109, Name: root}, ABSENT], PUBLIC] + details: + descriptorId: 109 + privileges: 2 + userName: root +- [[UserPrivileges:{DescID: 109, Name: r}, ABSENT], PUBLIC] + details: + descriptorId: 109 + privileges: 2 + userName: r +- [[UserPrivileges:{DescID: 110, Name: admin}, ABSENT], PUBLIC] + details: + descriptorId: 110 + privileges: 2 + userName: admin +- [[UserPrivileges:{DescID: 110, Name: root}, ABSENT], PUBLIC] + details: + descriptorId: 110 + privileges: 2 + userName: root +- [[UserPrivileges:{DescID: 110, Name: r}, ABSENT], PUBLIC] + details: + descriptorId: 110 + privileges: 2 + userName: r +- [[UserPrivileges:{DescID: 111, Name: admin}, ABSENT], PUBLIC] + details: + descriptorId: 111 + privileges: 2 + userName: admin +- [[UserPrivileges:{DescID: 111, Name: public}, ABSENT], PUBLIC] + details: + descriptorId: 111 + privileges: 512 + userName: public +- [[UserPrivileges:{DescID: 111, Name: root}, ABSENT], PUBLIC] + details: + descriptorId: 111 + privileges: 2 + userName: root +- [[UserPrivileges:{DescID: 111, Name: r}, ABSENT], PUBLIC] + details: + descriptorId: 111 + privileges: 2 + userName: r +- [[UserPrivileges:{DescID: 112, Name: admin}, ABSENT], PUBLIC] + details: + descriptorId: 112 + privileges: 2 + userName: admin +- [[UserPrivileges:{DescID: 112, Name: public}, ABSENT], PUBLIC] + details: + descriptorId: 112 + privileges: 512 + userName: public +- [[UserPrivileges:{DescID: 112, Name: root}, ABSENT], PUBLIC] + details: + descriptorId: 112 + privileges: 2 + userName: root +- [[UserPrivileges:{DescID: 112, Name: r}, ABSENT], PUBLIC] + details: + descriptorId: 112 + privileges: 2 + userName: r +- [[UserPrivileges:{DescID: 113, Name: admin}, ABSENT], PUBLIC] + details: + descriptorId: 113 + privileges: 2 + userName: admin +- [[UserPrivileges:{DescID: 113, Name: root}, ABSENT], PUBLIC] + details: + descriptorId: 113 + privileges: 2 + userName: root +- [[UserPrivileges:{DescID: 113, Name: r}, ABSENT], PUBLIC] + details: + descriptorId: 113 + privileges: 2 + userName: r +- [[View:{DescID: 110}, ABSENT], PUBLIC] + details: + usesRelationIds: + - 108 + viewId: 110 +- [[View:{DescID: 113}, ABSENT], PUBLIC] + details: + usesRelationIds: + - 110 + usesTypeIds: + - 111 + - 112 + viewId: 113 diff --git a/pkg/sql/schemachanger/scdeps/build_deps.go b/pkg/sql/schemachanger/scdeps/build_deps.go index a885f0347b0e..aec9ebf7f62e 100644 --- a/pkg/sql/schemachanger/scdeps/build_deps.go +++ b/pkg/sql/schemachanger/scdeps/build_deps.go @@ -375,6 +375,11 @@ func (d *buildDeps) IncrementEnumCounter(counterType sqltelemetry.EnumTelemetryT sqltelemetry.IncrementEnumCounter(counterType) } +// IncrementDropOwnedByCounter implements the scbuild.Dependencies interface. +func (d *buildDeps) IncrementDropOwnedByCounter() { + telemetry.Inc(sqltelemetry.CreateDropOwnedByCounter()) +} + func (d *buildDeps) DescriptorCommentCache() scbuild.CommentCache { return descmetadata.NewCommentCache(d.txn, d.internalExecutor) } diff --git a/pkg/sql/schemachanger/scdeps/sctestdeps/test_deps.go b/pkg/sql/schemachanger/scdeps/sctestdeps/test_deps.go index 019552c7098a..8896f08edd2f 100644 --- a/pkg/sql/schemachanger/scdeps/sctestdeps/test_deps.go +++ b/pkg/sql/schemachanger/scdeps/sctestdeps/test_deps.go @@ -127,6 +127,11 @@ func (s *TestState) IncrementEnumCounter(counterType sqltelemetry.EnumTelemetryT s.LogSideEffectf("increment telemetry for sql.udts.%s", counterType) } +// IncrementDropOwnedByCounter implements the scbuild.Dependencies interface. +func (s *TestState) IncrementDropOwnedByCounter() { + s.LogSideEffectf("increment telemetry for sql.drop_owned_by") +} + var _ scbuild.AuthorizationAccessor = (*TestState)(nil) // CheckPrivilege implements the scbuild.AuthorizationAccessor interface. @@ -156,6 +161,13 @@ func (s *TestState) CheckPrivilegeForUser( return nil } +// MemberOfWithAdminOption implements the scbuild.AuthorizationAccessor interface. +func (s *TestState) MemberOfWithAdminOption( + ctx context.Context, member username.SQLUsername, +) (map[username.SQLUsername]bool, error) { + return nil, nil +} + // IndexPartitioningCCLCallback implements the scbuild.Dependencies interface. func (s *TestState) IndexPartitioningCCLCallback() scbuild.CreatePartitioningCCLCallback { if ccl := scdeps.CreatePartitioningCCL; ccl != nil { diff --git a/pkg/sql/schemachanger/scexec/scmutationexec/BUILD.bazel b/pkg/sql/schemachanger/scexec/scmutationexec/BUILD.bazel index 6ab4547ef1ca..09c68b278532 100644 --- a/pkg/sql/schemachanger/scexec/scmutationexec/BUILD.bazel +++ b/pkg/sql/schemachanger/scexec/scmutationexec/BUILD.bazel @@ -20,6 +20,7 @@ go_library( deps = [ "//pkg/jobs/jobspb", "//pkg/keys", + "//pkg/security/username", "//pkg/sql/catalog", "//pkg/sql/catalog/dbdesc", "//pkg/sql/catalog/descpb", diff --git a/pkg/sql/schemachanger/scexec/scmutationexec/drop.go b/pkg/sql/schemachanger/scexec/scmutationexec/drop.go index 4156c24c4c59..053959a33d17 100644 --- a/pkg/sql/schemachanger/scexec/scmutationexec/drop.go +++ b/pkg/sql/schemachanger/scexec/scmutationexec/drop.go @@ -14,6 +14,7 @@ import ( "context" "github.com/cockroachdb/cockroach/pkg/keys" + "github.com/cockroachdb/cockroach/pkg/security/username" "github.com/cockroachdb/cockroach/pkg/sql/catalog" "github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb" "github.com/cockroachdb/cockroach/pkg/sql/catalog/tabledesc" @@ -132,6 +133,19 @@ func (m *visitor) RemoveDatabaseRoleSettings( return m.s.DeleteDatabaseRoleSettings(ctx, op.DatabaseID) } +func (m *visitor) RemoveUserPrivileges(ctx context.Context, op scop.RemoveUserPrivileges) error { + desc, err := m.s.CheckOutDescriptor(ctx, op.DescID) + if err != nil { + return err + } + user, err := username.MakeSQLUsernameFromUserInput(op.User, username.PurposeValidation) + if err != nil { + return err + } + desc.GetPrivileges().RemoveUser(user) + return nil +} + func (m *visitor) DeleteSchedule(_ context.Context, op scop.DeleteSchedule) error { if op.ScheduleID != 0 { m.s.DeleteSchedule(op.ScheduleID) diff --git a/pkg/sql/schemachanger/scop/mutation.go b/pkg/sql/schemachanger/scop/mutation.go index fb416aa30beb..e237c88727b9 100644 --- a/pkg/sql/schemachanger/scop/mutation.go +++ b/pkg/sql/schemachanger/scop/mutation.go @@ -530,6 +530,13 @@ type RemoveDatabaseRoleSettings struct { DatabaseID descpb.ID } +// RemoveUserPrivileges is used to revoke a user's privileges. +type RemoveUserPrivileges struct { + mutationOp + DescID descpb.ID + User string +} + // DeleteSchedule is used to delete a schedule ID from the database. type DeleteSchedule struct { mutationOp diff --git a/pkg/sql/schemachanger/scop/mutation_visitor_generated.go b/pkg/sql/schemachanger/scop/mutation_visitor_generated.go index 15b5f0a40f98..dfbc0a70e6b5 100644 --- a/pkg/sql/schemachanger/scop/mutation_visitor_generated.go +++ b/pkg/sql/schemachanger/scop/mutation_visitor_generated.go @@ -86,6 +86,7 @@ type MutationVisitor interface { UpsertConstraintComment(context.Context, UpsertConstraintComment) error RemoveConstraintComment(context.Context, RemoveConstraintComment) error RemoveDatabaseRoleSettings(context.Context, RemoveDatabaseRoleSettings) error + RemoveUserPrivileges(context.Context, RemoveUserPrivileges) error DeleteSchedule(context.Context, DeleteSchedule) error RefreshStats(context.Context, RefreshStats) error } @@ -410,6 +411,11 @@ func (op RemoveDatabaseRoleSettings) Visit(ctx context.Context, v MutationVisito return v.RemoveDatabaseRoleSettings(ctx, op) } +// Visit is part of the MutationOp interface. +func (op RemoveUserPrivileges) Visit(ctx context.Context, v MutationVisitor) error { + return v.RemoveUserPrivileges(ctx, op) +} + // Visit is part of the MutationOp interface. func (op DeleteSchedule) Visit(ctx context.Context, v MutationVisitor) error { return v.DeleteSchedule(ctx, op) diff --git a/pkg/sql/schemachanger/scplan/internal/opgen/opgen_user_privileges.go b/pkg/sql/schemachanger/scplan/internal/opgen/opgen_user_privileges.go index f71f7ea9429c..ddbdcd9d6cd5 100644 --- a/pkg/sql/schemachanger/scplan/internal/opgen/opgen_user_privileges.go +++ b/pkg/sql/schemachanger/scplan/internal/opgen/opgen_user_privileges.go @@ -31,7 +31,10 @@ func init() { // TODO(postamar): remove revertibility constraint when possible revertible(false), emit(func(this *scpb.UserPrivileges) scop.Op { - return notImplemented(this) + return &scop.RemoveUserPrivileges{ + DescID: this.DescriptorID, + User: this.UserName, + } }), ), ), diff --git a/pkg/sql/schemachanger/scplan/testdata/drop_owned_by b/pkg/sql/schemachanger/scplan/testdata/drop_owned_by new file mode 100644 index 000000000000..760cf32c03af --- /dev/null +++ b/pkg/sql/schemachanger/scplan/testdata/drop_owned_by @@ -0,0 +1,747 @@ +setup +CREATE ROLE r; +CREATE TABLE tab(); +GRANT ALL ON tab TO r; +GRANT CREATE ON DATABASE defaultdb TO r WITH GRANT OPTION; +SET ROLE r; +CREATE SCHEMA s; +CREATE SEQUENCE public.sq; +CREATE SEQUENCE s.sq; +CREATE TABLE s.t (id INT PRIMARY KEY, name VARCHAR(256), val INT DEFAULT nextval('s.sq')); +CREATE TABLE public.t (id INT PRIMARY KEY, name VARCHAR(256), val INT DEFAULT nextval('public.sq')); +CREATE VIEW s.v1 AS (SELECT name FROM s.t); +CREATE TYPE s.typ AS ENUM('a'); +CREATE VIEW s.v2 AS (SELECT 'a'::s.typ::string AS k, name FROM s.v1); +---- + +ops +DROP OWNED BY r +---- +StatementPhase stage 1 of 1 with 34 MutationType ops + transitions: + [[UserPrivileges:{DescID: 100, Name: r}, ABSENT], PUBLIC] -> ABSENT + [[Namespace:{DescID: 105, Name: s, ReferencedDescID: 100}, ABSENT], PUBLIC] -> ABSENT + [[Owner:{DescID: 105}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 105, Name: admin}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 105, Name: r}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 105, Name: root}, ABSENT], PUBLIC] -> ABSENT + [[Schema:{DescID: 105}, ABSENT], PUBLIC] -> DROPPED + [[SchemaParent:{DescID: 105, ReferencedDescID: 100}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 104, Name: r}, ABSENT], PUBLIC] -> ABSENT + [[Namespace:{DescID: 106, Name: sq, ReferencedDescID: 100}, ABSENT], PUBLIC] -> ABSENT + [[Owner:{DescID: 106}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 106, Name: admin}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 106, Name: r}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 106, Name: root}, ABSENT], PUBLIC] -> ABSENT + [[Sequence:{DescID: 106}, ABSENT], PUBLIC] -> DROPPED + [[ObjectParent:{DescID: 106, ReferencedDescID: 101}, ABSENT], PUBLIC] -> ABSENT + [[Namespace:{DescID: 109, Name: t, ReferencedDescID: 100}, ABSENT], PUBLIC] -> ABSENT + [[Owner:{DescID: 109}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 109, Name: admin}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 109, Name: r}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 109, Name: root}, ABSENT], PUBLIC] -> ABSENT + [[Table:{DescID: 109}, ABSENT], PUBLIC] -> DROPPED + [[ObjectParent:{DescID: 109, ReferencedDescID: 101}, ABSENT], PUBLIC] -> ABSENT + [[ColumnFamily:{DescID: 109, ColumnFamilyID: 0, Name: primary}, ABSENT], PUBLIC] -> ABSENT + [[Column:{DescID: 109, ColumnID: 1}, ABSENT], PUBLIC] -> WRITE_ONLY + [[ColumnName:{DescID: 109, Name: id, ColumnID: 1}, ABSENT], PUBLIC] -> ABSENT + [[ColumnType:{DescID: 109, ColumnFamilyID: 0, ColumnID: 1}, ABSENT], PUBLIC] -> ABSENT + [[Column:{DescID: 109, ColumnID: 2}, ABSENT], PUBLIC] -> WRITE_ONLY + [[ColumnName:{DescID: 109, Name: name, ColumnID: 2}, ABSENT], PUBLIC] -> ABSENT + [[ColumnType:{DescID: 109, ColumnFamilyID: 0, ColumnID: 2}, ABSENT], PUBLIC] -> ABSENT + [[Column:{DescID: 109, ColumnID: 3}, ABSENT], PUBLIC] -> WRITE_ONLY + [[ColumnName:{DescID: 109, Name: val, ColumnID: 3}, ABSENT], PUBLIC] -> ABSENT + [[ColumnType:{DescID: 109, ColumnFamilyID: 0, ColumnID: 3}, ABSENT], PUBLIC] -> ABSENT + [[ColumnDefaultExpression:{DescID: 109, ColumnID: 3}, ABSENT], PUBLIC] -> ABSENT + [[Column:{DescID: 109, ColumnID: 4294967295}, ABSENT], PUBLIC] -> WRITE_ONLY + [[ColumnName:{DescID: 109, Name: crdb_internal_mvcc_timestamp, ColumnID: 4294967295}, ABSENT], PUBLIC] -> ABSENT + [[ColumnType:{DescID: 109, ColumnFamilyID: 0, ColumnID: 4294967295}, ABSENT], PUBLIC] -> ABSENT + [[Column:{DescID: 109, ColumnID: 4294967294}, ABSENT], PUBLIC] -> WRITE_ONLY + [[ColumnName:{DescID: 109, Name: tableoid, ColumnID: 4294967294}, ABSENT], PUBLIC] -> ABSENT + [[ColumnType:{DescID: 109, ColumnFamilyID: 0, ColumnID: 4294967294}, ABSENT], PUBLIC] -> ABSENT + [[PrimaryIndex:{DescID: 109, IndexID: 1, ConstraintID: 1}, ABSENT], PUBLIC] -> VALIDATED + [[IndexName:{DescID: 109, Name: t_pkey, IndexID: 1}, ABSENT], PUBLIC] -> ABSENT + [[Namespace:{DescID: 107, Name: sq, ReferencedDescID: 100}, ABSENT], PUBLIC] -> ABSENT + [[Owner:{DescID: 107}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 107, Name: admin}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 107, Name: r}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 107, Name: root}, ABSENT], PUBLIC] -> ABSENT + [[Sequence:{DescID: 107}, ABSENT], PUBLIC] -> DROPPED + [[ObjectParent:{DescID: 107, ReferencedDescID: 105}, ABSENT], PUBLIC] -> ABSENT + [[Namespace:{DescID: 108, Name: t, ReferencedDescID: 100}, ABSENT], PUBLIC] -> ABSENT + [[Owner:{DescID: 108}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 108, Name: admin}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 108, Name: r}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 108, Name: root}, ABSENT], PUBLIC] -> ABSENT + [[Table:{DescID: 108}, ABSENT], PUBLIC] -> DROPPED + [[ObjectParent:{DescID: 108, ReferencedDescID: 105}, ABSENT], PUBLIC] -> ABSENT + [[ColumnFamily:{DescID: 108, ColumnFamilyID: 0, Name: primary}, ABSENT], PUBLIC] -> ABSENT + [[Column:{DescID: 108, ColumnID: 1}, ABSENT], PUBLIC] -> WRITE_ONLY + [[ColumnName:{DescID: 108, Name: id, ColumnID: 1}, ABSENT], PUBLIC] -> ABSENT + [[ColumnType:{DescID: 108, ColumnFamilyID: 0, ColumnID: 1}, ABSENT], PUBLIC] -> ABSENT + [[Column:{DescID: 108, ColumnID: 2}, ABSENT], PUBLIC] -> WRITE_ONLY + [[ColumnName:{DescID: 108, Name: name, ColumnID: 2}, ABSENT], PUBLIC] -> ABSENT + [[ColumnType:{DescID: 108, ColumnFamilyID: 0, ColumnID: 2}, ABSENT], PUBLIC] -> ABSENT + [[Column:{DescID: 108, ColumnID: 3}, ABSENT], PUBLIC] -> WRITE_ONLY + [[ColumnName:{DescID: 108, Name: val, ColumnID: 3}, ABSENT], PUBLIC] -> ABSENT + [[ColumnType:{DescID: 108, ColumnFamilyID: 0, ColumnID: 3}, ABSENT], PUBLIC] -> ABSENT + [[ColumnDefaultExpression:{DescID: 108, ColumnID: 3}, ABSENT], PUBLIC] -> ABSENT + [[Column:{DescID: 108, ColumnID: 4294967295}, ABSENT], PUBLIC] -> WRITE_ONLY + [[ColumnName:{DescID: 108, Name: crdb_internal_mvcc_timestamp, ColumnID: 4294967295}, ABSENT], PUBLIC] -> ABSENT + [[ColumnType:{DescID: 108, ColumnFamilyID: 0, ColumnID: 4294967295}, ABSENT], PUBLIC] -> ABSENT + [[Column:{DescID: 108, ColumnID: 4294967294}, ABSENT], PUBLIC] -> WRITE_ONLY + [[ColumnName:{DescID: 108, Name: tableoid, ColumnID: 4294967294}, ABSENT], PUBLIC] -> ABSENT + [[ColumnType:{DescID: 108, ColumnFamilyID: 0, ColumnID: 4294967294}, ABSENT], PUBLIC] -> ABSENT + [[PrimaryIndex:{DescID: 108, IndexID: 1, ConstraintID: 1}, ABSENT], PUBLIC] -> VALIDATED + [[IndexName:{DescID: 108, Name: t_pkey, IndexID: 1}, ABSENT], PUBLIC] -> ABSENT + [[Namespace:{DescID: 110, Name: v1, ReferencedDescID: 100}, ABSENT], PUBLIC] -> ABSENT + [[Owner:{DescID: 110}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 110, Name: admin}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 110, Name: r}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 110, Name: root}, ABSENT], PUBLIC] -> ABSENT + [[View:{DescID: 110}, ABSENT], PUBLIC] -> DROPPED + [[ObjectParent:{DescID: 110, ReferencedDescID: 105}, ABSENT], PUBLIC] -> ABSENT + [[Column:{DescID: 110, ColumnID: 1}, ABSENT], PUBLIC] -> WRITE_ONLY + [[ColumnName:{DescID: 110, Name: name, ColumnID: 1}, ABSENT], PUBLIC] -> ABSENT + [[ColumnType:{DescID: 110, ColumnFamilyID: 0, ColumnID: 1}, ABSENT], PUBLIC] -> ABSENT + [[Column:{DescID: 110, ColumnID: 4294967295}, ABSENT], PUBLIC] -> WRITE_ONLY + [[ColumnName:{DescID: 110, Name: crdb_internal_mvcc_timestamp, ColumnID: 4294967295}, ABSENT], PUBLIC] -> ABSENT + [[ColumnType:{DescID: 110, ColumnFamilyID: 0, ColumnID: 4294967295}, ABSENT], PUBLIC] -> ABSENT + [[Column:{DescID: 110, ColumnID: 4294967294}, ABSENT], PUBLIC] -> WRITE_ONLY + [[ColumnName:{DescID: 110, Name: tableoid, ColumnID: 4294967294}, ABSENT], PUBLIC] -> ABSENT + [[ColumnType:{DescID: 110, ColumnFamilyID: 0, ColumnID: 4294967294}, ABSENT], PUBLIC] -> ABSENT + [[Namespace:{DescID: 111, Name: typ, ReferencedDescID: 100}, ABSENT], PUBLIC] -> ABSENT + [[Owner:{DescID: 111}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 111, Name: admin}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 111, Name: public}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 111, Name: r}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 111, Name: root}, ABSENT], PUBLIC] -> ABSENT + [[EnumType:{DescID: 111}, ABSENT], PUBLIC] -> DROPPED + [[ObjectParent:{DescID: 111, ReferencedDescID: 105}, ABSENT], PUBLIC] -> ABSENT + [[Namespace:{DescID: 112, Name: _typ, ReferencedDescID: 100}, ABSENT], PUBLIC] -> ABSENT + [[Owner:{DescID: 112}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 112, Name: admin}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 112, Name: public}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 112, Name: r}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 112, Name: root}, ABSENT], PUBLIC] -> ABSENT + [[AliasType:{DescID: 112}, ABSENT], PUBLIC] -> DROPPED + [[ObjectParent:{DescID: 112, ReferencedDescID: 105}, ABSENT], PUBLIC] -> ABSENT + [[Namespace:{DescID: 113, Name: v2, ReferencedDescID: 100}, ABSENT], PUBLIC] -> ABSENT + [[Owner:{DescID: 113}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 113, Name: admin}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 113, Name: r}, ABSENT], PUBLIC] -> ABSENT + [[UserPrivileges:{DescID: 113, Name: root}, ABSENT], PUBLIC] -> ABSENT + [[View:{DescID: 113}, ABSENT], PUBLIC] -> DROPPED + [[ObjectParent:{DescID: 113, ReferencedDescID: 105}, ABSENT], PUBLIC] -> ABSENT + [[Column:{DescID: 113, ColumnID: 1}, ABSENT], PUBLIC] -> WRITE_ONLY + [[ColumnName:{DescID: 113, Name: k, ColumnID: 1}, ABSENT], PUBLIC] -> ABSENT + [[ColumnType:{DescID: 113, ColumnFamilyID: 0, ColumnID: 1}, ABSENT], PUBLIC] -> ABSENT + [[Column:{DescID: 113, ColumnID: 2}, ABSENT], PUBLIC] -> WRITE_ONLY + [[ColumnName:{DescID: 113, Name: name, ColumnID: 2}, ABSENT], PUBLIC] -> ABSENT + [[ColumnType:{DescID: 113, ColumnFamilyID: 0, ColumnID: 2}, ABSENT], PUBLIC] -> ABSENT + [[Column:{DescID: 113, ColumnID: 4294967295}, ABSENT], PUBLIC] -> WRITE_ONLY + [[ColumnName:{DescID: 113, Name: crdb_internal_mvcc_timestamp, ColumnID: 4294967295}, ABSENT], PUBLIC] -> ABSENT + [[ColumnType:{DescID: 113, ColumnFamilyID: 0, ColumnID: 4294967295}, ABSENT], PUBLIC] -> ABSENT + [[Column:{DescID: 113, ColumnID: 4294967294}, ABSENT], PUBLIC] -> WRITE_ONLY + [[ColumnName:{DescID: 113, Name: tableoid, ColumnID: 4294967294}, ABSENT], PUBLIC] -> ABSENT + [[ColumnType:{DescID: 113, ColumnFamilyID: 0, ColumnID: 4294967294}, ABSENT], PUBLIC] -> ABSENT + ops: + *scop.RemoveUserPrivileges + DescID: 100 + User: r + *scop.RemoveUserPrivileges + DescID: 104 + User: r + *scop.MarkDescriptorAsDropped + DescID: 105 + *scop.RemoveSchemaParent + Parent: + ParentDatabaseID: 100 + SchemaID: 105 + *scop.MarkDescriptorAsDropped + DescID: 106 + *scop.RemoveAllTableComments + TableID: 106 + *scop.MarkDescriptorAsDropped + DescID: 109 + *scop.RemoveAllTableComments + TableID: 109 + *scop.RemoveColumnDefaultExpression + ColumnID: 3 + TableID: 109 + *scop.UpdateBackReferencesInSequences + BackReferencedColumnID: 3 + BackReferencedTableID: 109 + SequenceIDs: + - 106 + *scop.MarkDescriptorAsDropped + DescID: 107 + *scop.RemoveAllTableComments + TableID: 107 + *scop.MarkDescriptorAsDropped + DescID: 108 + *scop.RemoveAllTableComments + TableID: 108 + *scop.RemoveColumnDefaultExpression + ColumnID: 3 + TableID: 108 + *scop.UpdateBackReferencesInSequences + BackReferencedColumnID: 3 + BackReferencedTableID: 108 + SequenceIDs: + - 107 + *scop.MarkDescriptorAsDropped + DescID: 110 + *scop.RemoveViewBackReferencesInRelations + BackReferencedViewID: 110 + RelationIDs: + - 108 + *scop.RemoveAllTableComments + TableID: 110 + *scop.MarkDescriptorAsDropped + DescID: 111 + *scop.MarkDescriptorAsDropped + DescID: 112 + *scop.MarkDescriptorAsDropped + DescID: 113 + *scop.RemoveBackReferenceInTypes + BackReferencedDescID: 113 + TypeIDs: + - 111 + - 112 + *scop.RemoveViewBackReferencesInRelations + BackReferencedViewID: 113 + RelationIDs: + - 110 + *scop.RemoveAllTableComments + TableID: 113 + *scop.DrainDescriptorName + Namespace: + DatabaseID: 100 + DescriptorID: 105 + Name: s + *scop.DrainDescriptorName + Namespace: + DatabaseID: 100 + DescriptorID: 106 + Name: sq + SchemaID: 101 + *scop.DrainDescriptorName + Namespace: + DatabaseID: 100 + DescriptorID: 109 + Name: t + SchemaID: 101 + *scop.DrainDescriptorName + Namespace: + DatabaseID: 100 + DescriptorID: 107 + Name: sq + SchemaID: 105 + *scop.DrainDescriptorName + Namespace: + DatabaseID: 100 + DescriptorID: 108 + Name: t + SchemaID: 105 + *scop.DrainDescriptorName + Namespace: + DatabaseID: 100 + DescriptorID: 110 + Name: v1 + SchemaID: 105 + *scop.DrainDescriptorName + Namespace: + DatabaseID: 100 + DescriptorID: 111 + Name: typ + SchemaID: 105 + *scop.DrainDescriptorName + Namespace: + DatabaseID: 100 + DescriptorID: 112 + Name: _typ + SchemaID: 105 + *scop.DrainDescriptorName + Namespace: + DatabaseID: 100 + DescriptorID: 113 + Name: v2 + SchemaID: 105 +PreCommitPhase stage 1 of 1 with 12 MutationType ops + transitions: + ops: + *scop.SetJobStateOnDescriptor + DescriptorID: 100 + Initialize: true + *scop.SetJobStateOnDescriptor + DescriptorID: 104 + Initialize: true + *scop.SetJobStateOnDescriptor + DescriptorID: 105 + Initialize: true + *scop.SetJobStateOnDescriptor + DescriptorID: 106 + Initialize: true + *scop.SetJobStateOnDescriptor + DescriptorID: 107 + Initialize: true + *scop.SetJobStateOnDescriptor + DescriptorID: 108 + Initialize: true + *scop.SetJobStateOnDescriptor + DescriptorID: 109 + Initialize: true + *scop.SetJobStateOnDescriptor + DescriptorID: 110 + Initialize: true + *scop.SetJobStateOnDescriptor + DescriptorID: 111 + Initialize: true + *scop.SetJobStateOnDescriptor + DescriptorID: 112 + Initialize: true + *scop.SetJobStateOnDescriptor + DescriptorID: 113 + Initialize: true + *scop.CreateSchemaChangerJob + Authorization: + UserName: root + DescriptorIDs: + - 100 + - 104 + - 105 + - 106 + - 107 + - 108 + - 109 + - 110 + - 111 + - 112 + - 113 + JobID: 1 + NonCancelable: true + RunningStatus: PostCommitNonRevertiblePhase stage 1 of 1 with 35 MutationType ops + pending + Statements: + - statement: DROP OWNED BY r + redactedstatement: DROP OWNED BY r + statementtag: DROP OWNED BY +PostCommitNonRevertiblePhase stage 1 of 1 with 47 MutationType ops + transitions: + [[Schema:{DescID: 105}, ABSENT], DROPPED] -> ABSENT + [[Sequence:{DescID: 106}, ABSENT], DROPPED] -> ABSENT + [[Table:{DescID: 109}, ABSENT], DROPPED] -> ABSENT + [[Column:{DescID: 109, ColumnID: 1}, ABSENT], WRITE_ONLY] -> ABSENT + [[Column:{DescID: 109, ColumnID: 2}, ABSENT], WRITE_ONLY] -> ABSENT + [[Column:{DescID: 109, ColumnID: 3}, ABSENT], WRITE_ONLY] -> ABSENT + [[Column:{DescID: 109, ColumnID: 4294967295}, ABSENT], WRITE_ONLY] -> ABSENT + [[Column:{DescID: 109, ColumnID: 4294967294}, ABSENT], WRITE_ONLY] -> ABSENT + [[PrimaryIndex:{DescID: 109, IndexID: 1, ConstraintID: 1}, ABSENT], VALIDATED] -> ABSENT + [[Sequence:{DescID: 107}, ABSENT], DROPPED] -> ABSENT + [[Table:{DescID: 108}, ABSENT], DROPPED] -> ABSENT + [[Column:{DescID: 108, ColumnID: 1}, ABSENT], WRITE_ONLY] -> ABSENT + [[Column:{DescID: 108, ColumnID: 2}, ABSENT], WRITE_ONLY] -> ABSENT + [[Column:{DescID: 108, ColumnID: 3}, ABSENT], WRITE_ONLY] -> ABSENT + [[Column:{DescID: 108, ColumnID: 4294967295}, ABSENT], WRITE_ONLY] -> ABSENT + [[Column:{DescID: 108, ColumnID: 4294967294}, ABSENT], WRITE_ONLY] -> ABSENT + [[PrimaryIndex:{DescID: 108, IndexID: 1, ConstraintID: 1}, ABSENT], VALIDATED] -> ABSENT + [[View:{DescID: 110}, ABSENT], DROPPED] -> ABSENT + [[Column:{DescID: 110, ColumnID: 1}, ABSENT], WRITE_ONLY] -> ABSENT + [[Column:{DescID: 110, ColumnID: 4294967295}, ABSENT], WRITE_ONLY] -> ABSENT + [[Column:{DescID: 110, ColumnID: 4294967294}, ABSENT], WRITE_ONLY] -> ABSENT + [[EnumType:{DescID: 111}, ABSENT], DROPPED] -> ABSENT + [[AliasType:{DescID: 112}, ABSENT], DROPPED] -> ABSENT + [[View:{DescID: 113}, ABSENT], DROPPED] -> ABSENT + [[Column:{DescID: 113, ColumnID: 1}, ABSENT], WRITE_ONLY] -> ABSENT + [[Column:{DescID: 113, ColumnID: 2}, ABSENT], WRITE_ONLY] -> ABSENT + [[Column:{DescID: 113, ColumnID: 4294967295}, ABSENT], WRITE_ONLY] -> ABSENT + [[Column:{DescID: 113, ColumnID: 4294967294}, ABSENT], WRITE_ONLY] -> ABSENT + ops: + *scop.LogEvent + Element: + Schema: + schemaId: 105 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TargetStatus: 1 + *scop.DeleteDescriptor + DescriptorID: 105 + *scop.LogEvent + Element: + Sequence: + sequenceId: 106 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TargetStatus: 1 + *scop.CreateGcJobForTable + StatementForDropJob: + Statement: DROP OWNED BY r + TableID: 106 + *scop.LogEvent + Element: + Sequence: + sequenceId: 107 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TargetStatus: 1 + *scop.CreateGcJobForTable + StatementForDropJob: + Statement: DROP OWNED BY r + TableID: 107 + *scop.LogEvent + Element: + EnumType: + arrayTypeId: 112 + typeId: 111 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TargetStatus: 1 + *scop.DeleteDescriptor + DescriptorID: 111 + *scop.LogEvent + Element: + AliasType: + embeddedTypeT: + closedTypeIds: + - 111 + - 112 + type: + arrayContents: + family: EnumFamily + oid: 100111 + udtMetadata: + arrayTypeOid: 100112 + arrayElemType: EnumFamily + family: ArrayFamily + oid: 100112 + typeId: 112 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TargetStatus: 1 + *scop.DeleteDescriptor + DescriptorID: 112 + *scop.LogEvent + Element: + View: + usesRelationIds: + - 108 + viewId: 110 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TargetStatus: 1 + *scop.DeleteDescriptor + DescriptorID: 110 + *scop.MakeColumnAbsent + ColumnID: 1 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TableID: 110 + *scop.MakeColumnAbsent + ColumnID: 4294967295 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TableID: 110 + *scop.MakeColumnAbsent + ColumnID: 4294967294 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TableID: 110 + *scop.LogEvent + Element: + View: + usesRelationIds: + - 110 + usesTypeIds: + - 111 + - 112 + viewId: 113 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TargetStatus: 1 + *scop.DeleteDescriptor + DescriptorID: 113 + *scop.MakeColumnAbsent + ColumnID: 1 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TableID: 113 + *scop.MakeColumnAbsent + ColumnID: 2 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TableID: 113 + *scop.MakeColumnAbsent + ColumnID: 4294967295 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TableID: 113 + *scop.MakeColumnAbsent + ColumnID: 4294967294 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TableID: 113 + *scop.LogEvent + Element: + Table: + tableId: 109 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TargetStatus: 1 + *scop.CreateGcJobForTable + StatementForDropJob: + Statement: DROP OWNED BY r + TableID: 109 + *scop.MakeColumnAbsent + ColumnID: 1 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TableID: 109 + *scop.MakeColumnAbsent + ColumnID: 2 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TableID: 109 + *scop.MakeColumnAbsent + ColumnID: 3 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TableID: 109 + *scop.MakeColumnAbsent + ColumnID: 4294967295 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TableID: 109 + *scop.MakeColumnAbsent + ColumnID: 4294967294 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TableID: 109 + *scop.LogEvent + Element: + Table: + tableId: 108 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TargetStatus: 1 + *scop.CreateGcJobForTable + StatementForDropJob: + Statement: DROP OWNED BY r + TableID: 108 + *scop.MakeColumnAbsent + ColumnID: 1 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TableID: 108 + *scop.MakeColumnAbsent + ColumnID: 2 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TableID: 108 + *scop.MakeColumnAbsent + ColumnID: 3 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TableID: 108 + *scop.MakeColumnAbsent + ColumnID: 4294967295 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TableID: 108 + *scop.MakeColumnAbsent + ColumnID: 4294967294 + EventBase: + Authorization: + UserName: root + Statement: DROP OWNED BY r + StatementTag: DROP OWNED BY + TargetMetadata: + SourceElementID: 1 + SubWorkID: 1 + TableID: 108 + *scop.RemoveJobStateFromDescriptor + DescriptorID: 100 + JobID: 1 + *scop.RemoveJobStateFromDescriptor + DescriptorID: 104 + JobID: 1 + *scop.RemoveJobStateFromDescriptor + DescriptorID: 105 + JobID: 1 + *scop.RemoveJobStateFromDescriptor + DescriptorID: 106 + JobID: 1 + *scop.RemoveJobStateFromDescriptor + DescriptorID: 107 + JobID: 1 + *scop.RemoveJobStateFromDescriptor + DescriptorID: 108 + JobID: 1 + *scop.RemoveJobStateFromDescriptor + DescriptorID: 109 + JobID: 1 + *scop.RemoveJobStateFromDescriptor + DescriptorID: 110 + JobID: 1 + *scop.RemoveJobStateFromDescriptor + DescriptorID: 111 + JobID: 1 + *scop.RemoveJobStateFromDescriptor + DescriptorID: 112 + JobID: 1 + *scop.RemoveJobStateFromDescriptor + DescriptorID: 113 + JobID: 1 + *scop.UpdateSchemaChangerJob + IsNonCancelable: true + JobID: 1 diff --git a/pkg/sql/sem/tree/schema_feature_name.go b/pkg/sql/sem/tree/schema_feature_name.go index 769e71bd0e3c..8dfb9cdd5b74 100644 --- a/pkg/sql/sem/tree/schema_feature_name.go +++ b/pkg/sql/sem/tree/schema_feature_name.go @@ -24,7 +24,7 @@ func GetSchemaFeatureNameFromStmt(stmt Statement) SchemaFeatureName { switch stmt.(type) { case *CommentOnDatabase, *CommentOnSchema, *CommentOnTable, - *CommentOnColumn, *CommentOnIndex, *CommentOnConstraint: + *CommentOnColumn, *CommentOnIndex, *CommentOnConstraint, *DropOwnedBy: return SchemaFeatureName(statementTag) } // Only grab the first two words (i.e. ALTER TABLE, etc..). diff --git a/pkg/sql/testdata/telemetry/drop_owned_by b/pkg/sql/testdata/telemetry/drop_owned_by index 1da9d9586212..bddbb209f7f8 100644 --- a/pkg/sql/testdata/telemetry/drop_owned_by +++ b/pkg/sql/testdata/telemetry/drop_owned_by @@ -11,9 +11,7 @@ GRANT CREATE ON DATABASE defaultdb TO testuser; ALTER TABLE t OWNER TO testuser ---- -# TODO(angelaw): Remove unimplemented message after implementation. feature-usage DROP OWNED BY testuser ---- -error: pq: unimplemented: drop owned by is not yet implemented sql.drop_owned_by