-
Notifications
You must be signed in to change notification settings - Fork 3.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sql/schemachanger: implement DROP OWNED BY #82936
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: complete! 0 of 0 LGTMs obtained (waiting on @jasonmchan and @Xiang-Gu)
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 44 at r1 (raw file):
var toCheckBackrefs []descpb.ID // Lookup all objects in the current database.
curious: can a user own objects across databases? If so, what's the expected behavior if we DRO OWNED BY him
?
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 56 at r1 (raw file):
}) objects = append(objects, sp.SchemaID) })
Is this block used to retrieve all object IDs in db
?
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 61 at r1 (raw file):
for _, id := range objects { elts := b.QueryByID(id) _, _, owner := scpb.FindOwner(elts)
is it possible that elts
does not have a Owner element?
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 88 at r1 (raw file):
for _, role := range normalizedRoles { if e.UserName == role.Normalized() && e.UserName != b.SessionData().User().Normalized() { dropElement(b, e)
you probably need to change this to simply b.Drop(e)
with #82907 coming out soon.
pkg/sql/logictest/testdata/logic_test/drop_owned_by
line 83 at r1 (raw file):
SHOW TABLES FROM public ----
-
when
testuser
drops all objects he owned, why areu
andv1
also dropped (which are owned bytestuser2
)? -
in addition to dropping the objects, we also revoke the privileges from users. Do we tests this behavior in the logic test?
pkg/sql/logictest/testdata/logic_test/drop_owned_by
line 212 at r1 (raw file):
statement error pq: cannot drop objects owned by role "admin" because they are required by the database system DROP OWNED BY admin
Can we add some more comments on the test? It's a bit hard to follow and remember what's been dropped and what's been created by which user.
You can break up the tests into subtests and each subtest focus on a pattern/theme/case of tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job! Keep up the good work!
Reviewable status: complete! 0 of 0 LGTMs obtained (waiting on @jasonmchan and @Xiang-Gu)
eb377e6
to
37304b7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TFTR!
Reviewable status: complete! 0 of 0 LGTMs obtained (waiting on @Xiang-Gu)
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 44 at r1 (raw file):
Previously, Xiang-Gu (Xiang Gu) wrote…
curious: can a user own objects across databases? If so, what's the expected behavior if we
DRO OWNED BY him
?
Yes. DROP OWNED BY drops objects in the current database (see Postgres docs)
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 56 at r1 (raw file):
Previously, Xiang-Gu (Xiang Gu) wrote…
Is this block used to retrieve all object IDs in
db
?
Yes, would it be clearer if I renamed objects
to objectIDs
?
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 61 at r1 (raw file):
Previously, Xiang-Gu (Xiang Gu) wrote…
is it possible that
elts
does not have a Owner element?
I've been working under this assumption, but maybe someone else can confirm. My understanding is that all objects have owners, which is enforced when we decompose descriptors into elements.
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 88 at r1 (raw file):
Previously, Xiang-Gu (Xiang Gu) wrote…
you probably need to change this to simply
b.Drop(e)
with #82907 coming out soon.
Thanks for letting me know! I didn't pay close attention to the difference 😅
pkg/sql/logictest/testdata/logic_test/drop_owned_by
line 83 at r1 (raw file):
Previously, Xiang-Gu (Xiang Gu) wrote…
when
testuser
drops all objects he owned, why areu
andv1
also dropped (which are owned bytestuser2
)?in addition to dropping the objects, we also revoke the privileges from users. Do we tests this behavior in the logic test?
- The previous statement
DROP OWNED BY testuser2
drops them. The intention here was to testCASCADE
; I've added a TODO comment to indicate this. - Yes
pkg/sql/logictest/testdata/logic_test/drop_owned_by
line 212 at r1 (raw file):
Previously, Xiang-Gu (Xiang Gu) wrote…
Can we add some more comments on the test? It's a bit hard to follow and remember what's been dropped and what's been created by which user.
You can break up the tests into subtests and each subtest focus on a pattern/theme/case of tests.
I've attempted to improve the readability of the tests. Hopefully they're clearer now!
37304b7
to
f93df50
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work :)
Reviewable status: complete! 0 of 0 LGTMs obtained (waiting on @chengxiong-ruan, @jasonmchan, and @Xiang-Gu)
pkg/sql/schemachanger/scbuild/dependencies.go
line 172 at r2 (raw file):
// MemberOfWithAdminOption looks up the roles that 'member' is a member of. MemberOfWithAdminOption(ctx context.Context, member username.SQLUsername) (map[username.SQLUsername]bool, error)
the go convention is to use map[username.SQLUsername]struct{}
here to avoid the confusion of true
and false
boolean values :)
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/dependencies.go
line 177 at r2 (raw file):
// CheckMemberOf returns true iff the current user has membership in the // specified role. IsMemberOf(member username.SQLUsername) bool
IsMemberOf
-> CurrentUserIsMemberOf
?
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 88 at r1 (raw file):
Previously, jasonmchan (Jason Chan) wrote…
Thanks for letting me know! I didn't pay close attention to the difference 😅
ha, nice
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 27 at r2 (raw file):
// DropOwnedBy implements DROP OWNED BY. func DropOwnedBy(b BuildCtx, n *tree.DropOwnedBy) { normalizedRoles, err := decodeusername.FromRoleSpecList(
what does normalized
mean here?
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 36 at r2 (raw file):
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))
Is it legit to drop non-system objects though?
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 39 at r2 (raw file):
} if role != b.SessionData().User() && !b.IsMemberOf(role) { panic(pgerror.New(pgcode.InsufficientPrivilege, "permission denied to drop objects"))
Is it legit for admin/root perform this operation if they are not part the input roles
?
pkg/sql/logictest/testdata/logic_test/schema_change_feature_flags
line 249 at r2 (raw file):
REASSIGN OWNED BY root TO testuser # Test DROP OWNED BY.
Could you add DROP OWNED BY
a special case here as well so that it still use its SchemaFeatureName
which is DROP OWNED BY
?:
case *CommentOnDatabase, *CommentOnSchema, *CommentOnTable, |
We'd need to refactor this better somehow. I haven't thought about it yet :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: complete! 0 of 0 LGTMs obtained (waiting on @chengxiong-ruan and @Xiang-Gu)
pkg/sql/schemachanger/scbuild/dependencies.go
line 172 at r2 (raw file):
Previously, chengxiong-ruan (Chengxiong Ruan) wrote…
the go convention is to use
map[username.SQLUsername]struct{}
here to avoid the confusion oftrue
andfalse
boolean values :)
My comment was misleading, the boolean value actually indicates whether the member is an admin of the role. I've updated the comment. Leaving the signature as is to maintain parity with the AuthorizationAccessor
in authorization.go
.
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/dependencies.go
line 177 at r2 (raw file):
Previously, chengxiong-ruan (Chengxiong Ruan) wrote…
IsMemberOf
->CurrentUserIsMemberOf
?
Done.
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 27 at r2 (raw file):
Previously, chengxiong-ruan (Chengxiong Ruan) wrote…
what does
normalized
mean here?
It's referring to the username being normalized.
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 36 at r2 (raw file):
Previously, chengxiong-ruan (Chengxiong Ruan) wrote…
Is it legit to drop non-system objects though?
Postgres won't drop non-system objects for these roles. I'm not sure if there's a case where these roles don't own any system objects and so the statement would succeed, but I think that erroring here is the safe option.
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 39 at r2 (raw file):
Previously, chengxiong-ruan (Chengxiong Ruan) wrote…
Is it legit for admin/root perform this operation if they are not part the input
roles
?
Yes. The check for this is in the CurrentUserIsMemberOf
function, although maybe it would be clearer if the check were elsewhere. Here's a logictest for this scenario.
pkg/sql/logictest/testdata/logic_test/schema_change_feature_flags
line 249 at r2 (raw file):
Previously, chengxiong-ruan (Chengxiong Ruan) wrote…
Could you add
DROP OWNED BY
a special case here as well so that it still use itsSchemaFeatureName
which isDROP OWNED BY
?:?
case *CommentOnDatabase, *CommentOnSchema, *CommentOnTable,
We'd need to refactor this better somehow. I haven't thought about it yet :(
Done.
f93df50
to
44f2326
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: complete! 0 of 0 LGTMs obtained (waiting on @chengxiong-ruan, @jasonmchan, and @Xiang-Gu)
pkg/sql/schemachanger/scbuild/dependencies.go
line 172 at r2 (raw file):
Previously, jasonmchan (Jason Chan) wrote…
My comment was misleading, the boolean value actually indicates whether the member is an admin of the role. I've updated the comment. Leaving the signature as is to maintain parity with the
AuthorizationAccessor
inauthorization.go
.
ah, interesting. thanks for explaining that.
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 36 at r2 (raw file):
Previously, jasonmchan (Jason Chan) wrote…
Postgres won't drop non-system objects for these roles. I'm not sure if there's a case where these roles don't own any system objects and so the statement would succeed, but I think that erroring here is the safe option.
yeah, that make sense, thanks.
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 39 at r2 (raw file):
Previously, jasonmchan (Jason Chan) wrote…
Yes. The check for this is in the
CurrentUserIsMemberOf
function, although maybe it would be clearer if the check were elsewhere. Here's a logictest for this scenario.
Hmm. wait.. I thought CurrentUserIsMemberOf
only checks if current is a member of role
, but don't really care about if it's an admin or not?
Oh.. does MemberOfWithAdminOption
actually also return admin
even the role
is not an admin? heh...
pkg/sql/schemachanger/scplan/testdata/drop_owned_by
line 1 at r4 (raw file):
setup
Sorry, I should have noticed this earlier but just realized that we need a builder test similar to these as well
44f2326
to
3dac516
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: complete! 0 of 0 LGTMs obtained (waiting on @chengxiong-ruan, @jasonmchan, and @Xiang-Gu)
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 39 at r2 (raw file):
Previously, chengxiong-ruan (Chengxiong Ruan) wrote…
Hmm. wait.. I thought
CurrentUserIsMemberOf
only checks if current is a member ofrole
, but don't really care about if it's an admin or not?
Oh.. doesMemberOfWithAdminOption
actually also returnadmin
even therole
is not an admin? heh...
It's actually because I put a separate check here for the admin case. I renamed the function to CurrentUserHasAdminOrIsMemberOf
, is this better?
pkg/sql/schemachanger/scplan/testdata/drop_owned_by
line 1 at r4 (raw file):
Previously, chengxiong-ruan (Chengxiong Ruan) wrote…
Sorry, I should have noticed this earlier but just realized that we need a builder test similar to these as well
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewable status: complete! 1 of 0 LGTMs obtained (waiting on @chengxiong-ruan, @jasonmchan, and @Xiang-Gu)
pkg/sql/schemachanger/scbuild/internal/scbuildstmt/drop_owned_by.go
line 39 at r2 (raw file):
Previously, jasonmchan (Jason Chan) wrote…
It's actually because I put a separate check here for the admin case. I renamed the function to
CurrentUserHasAdminOrIsMemberOf
, is this better?
Thanks that's much better!
bors r+ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good, nicely done! I have a few comments but nothing big, they should be straightforward for you to address
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to see more test cases involving:
- databases
- schemas
- tables, views and types referencing each other but owned by different roles.
The latter case is arguably more interesting for CASCADE but still.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you're not implementing CASCADE you should probably have a case that checks for a nice error message (search for statement error unimplemented:
for examples). Also add a case in the unimplemented_drop
data-driven test suite in the scbuild
package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed the unimplemented error from the one in scerror
to the one in unimplemented
, since it seems like the former causes us to try to fall back to the old schema changer, which ends up throwing a less descriptive error message for DROP OWNED BY
. I added the logictest check but not the unimplemented_drop
one--is this the right call?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I hear you. I'm good with this approach since we're going to implement it anyway. But I'm wondering if you could just set new schema changer's mode to unsafe_always
since you disable the legacy schema changer configuration in this logic test :) also cc @postamar if you have strong opinion on the options here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like your idea @chengxiong-ruan. The purpose of these tests is to check which schema changes aren't implemented by the declarative schema changer. It would be fine to ignore the legacy schema changer, in my opinion.
I don't have strong opinions either. @jasonmchan please do what you think is best and go ahead and bors.
mutationOp | ||
DescID descpb.ID | ||
User string | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
User privileges are implicitly removed when dropping something, so you can remove this op altogether.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe DROP OWNED BY
should revoke user privileges for the role(s) on objects that aren't owned, so we need this op to drop those privileges without dropping the entire objects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, right. In that case, you should update the rules to avoid emitting this op for dropped objects. Look for op_rules.go
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. @jasonmchan see rules in pkg/sql/schemachanger/scplan/internal/rules/op_drop.go
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this rule should handle this, since user privileges are part of the descriptor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing. Good find.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Excellent!
bors r- Sorry for the late review! Please address my comments and feel free to re-bors. |
Canceled. |
3dac516
to
c9edde5
Compare
@jasonmchan feel free to go ahead and bors this again. |
bors r+ |
Build failed (retrying...): |
Build failed (retrying...): |
I think this has some merge skew on generated output. bors r- |
Canceled. |
Previously, we did not support the DROP OWNED BY statement (cockroachdb#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`.
c9edde5
to
421856b
Compare
Merge conflict should be fixed! bors r+ |
Build succeeded: |
By all means! |
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
.