Skip to content

Commit

Permalink
Merge #55816
Browse files Browse the repository at this point in the history
55816: sql: allow parsing of DROP OWNED BY r=otan a=angelapwen

Part 1 of addressing #55381.

Add parsing and telemetry support for DROP OWNED BY command.
Includes small refactors of the related REASSIGN OWNED BY
command such as appending "_by" to some instances of
"reassign_owned" for readability.

Plan to follow up with implementation of DROP OWNED BY for
feature parity with PostgresQL, which will resolve the issue
linked.

Note that this command is also making use of `role_spec_list` 
which as noted in #54696 does not properly parse 
`CURRENT_USER` or `SESSION_USER` and uses strings for
roles/usernames rather than expressions. This issue is out of 
scope for this PR and will be resolved separately.

Release note: None

Co-authored-by: angelapwen <angelaw@cockroachlabs.com>
  • Loading branch information
craig[bot] and angelapwen committed Oct 21, 2020
2 parents 11bbfb6 + 740f73d commit 37188b0
Show file tree
Hide file tree
Showing 14 changed files with 183 additions and 31 deletions.
18 changes: 11 additions & 7 deletions docs/generated/sql/bnf/stmt_block.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ stmt ::=
| prepare_stmt
| revoke_stmt
| savepoint_stmt
| reassign_owned_stmt
| reassign_owned_by_stmt
| drop_owned_by_stmt
| release_stmt
| refresh_stmt
| nonpreparable_set_stmt
Expand Down Expand Up @@ -90,9 +91,12 @@ revoke_stmt ::=
savepoint_stmt ::=
'SAVEPOINT' name

reassign_owned_stmt ::=
reassign_owned_by_stmt ::=
'REASSIGN' 'OWNED' 'BY' role_spec_list 'TO' role_spec

drop_owned_by_stmt ::=
'DROP' 'OWNED' 'BY' role_spec_list opt_drop_behavior

release_stmt ::=
'RELEASE' savepoint_name

Expand Down Expand Up @@ -314,6 +318,11 @@ role_spec ::=
| 'CURRENT_USER'
| 'SESSION_USER'

opt_drop_behavior ::=
'CASCADE'
| 'RESTRICT'
|

savepoint_name ::=
'SAVEPOINT' name
| name
Expand Down Expand Up @@ -709,11 +718,6 @@ opt_table ::=
relation_expr_list ::=
( relation_expr ) ( ( ',' relation_expr ) )*

opt_drop_behavior ::=
'CASCADE'
| 'RESTRICT'
|

set_clause_list ::=
( set_clause ) ( ( ',' set_clause ) )*

Expand Down
40 changes: 40 additions & 0 deletions pkg/sql/drop_owned_by.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright 2020 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 sql

import (
"context"

"github.com/cockroachdb/cockroach/pkg/server/telemetry"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
"github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry"
"github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented"
)

// dropOwnedByNode represents a DROP OWNED BY <role(s)> statement.
type dropOwnedByNode struct {
// TODO(angelaw): Uncomment when implementing - commenting out due to linting error.
// n *tree.DropOwnedBy
}

func (p *planner) DropOwnedBy(ctx context.Context) (planNode, error) {
telemetry.Inc(sqltelemetry.CreateDropOwnedByCounter())
// TODO(angelaw): Implementation.
return nil, unimplemented.NewWithIssue(55381, "drop owned by is not yet implemented")
}

func (n *dropOwnedByNode) startExec(params runParams) error {
// TODO(angelaw): Implementation.
return nil
}
func (n *dropOwnedByNode) Next(runParams) (bool, error) { return false, nil }
func (n *dropOwnedByNode) Values() tree.Datums { return tree.Datums{} }
func (n *dropOwnedByNode) Close(context.Context) {}
11 changes: 7 additions & 4 deletions pkg/sql/opaque.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,18 +105,20 @@ func buildOpaque(
plan, err = p.DropDatabase(ctx, n)
case *tree.DropIndex:
plan, err = p.DropIndex(ctx, n)
case *tree.DropOwnedBy:
plan, err = p.DropOwnedBy(ctx)
case *tree.DropRole:
plan, err = p.DropRole(ctx, n)
case *tree.DropSchema:
plan, err = p.DropSchema(ctx, n)
case *tree.DropSequence:
plan, err = p.DropSequence(ctx, n)
case *tree.DropTable:
plan, err = p.DropTable(ctx, n)
case *tree.DropType:
plan, err = p.DropType(ctx, n)
case *tree.DropView:
plan, err = p.DropView(ctx, n)
case *tree.DropSequence:
plan, err = p.DropSequence(ctx, n)
case *tree.Grant:
plan, err = p.Grant(ctx, n)
case *tree.GrantRole:
Expand Down Expand Up @@ -219,12 +221,13 @@ func init() {
&tree.Discard{},
&tree.DropDatabase{},
&tree.DropIndex{},
&tree.DropOwnedBy{},
&tree.DropRole{},
&tree.DropSchema{},
&tree.DropSequence{},
&tree.DropTable{},
&tree.DropType{},
&tree.DropView{},
&tree.DropRole{},
&tree.DropSequence{},
&tree.Grant{},
&tree.GrantRole{},
&tree.ReassignOwnedBy{},
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/parser/help_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ func TestContextualHelp(t *testing.T) {

{`REASSIGN OWNED BY ?? TO ??`, `REASSIGN OWNED BY`},
{`REASSIGN OWNED BY foo, bar TO ??`, `REASSIGN OWNED BY`},
{`DROP OWNED BY ??`, `DROP OWNED BY`},

{`RESUME ??`, `RESUME`},
{`RESUME JOB ??`, `RESUME JOBS`},
Expand Down
6 changes: 6 additions & 0 deletions pkg/sql/parser/parse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1555,6 +1555,10 @@ func TestParse(t *testing.T) {

{`REASSIGN OWNED BY foo TO bar`},
{`REASSIGN OWNED BY foo, bar TO third`},
{`DROP OWNED BY foo`},
{`DROP OWNED BY foo, bar`},
{`DROP OWNED BY foo CASCADE`},
{`DROP OWNED BY foo RESTRICT`},

{`COMMENT ON COLUMN a.b IS 'a'`},
{`COMMENT ON COLUMN a.b IS NULL`},
Expand Down Expand Up @@ -2673,6 +2677,8 @@ SKIP_MISSING_FOREIGN_KEYS, SKIP_MISSING_SEQUENCES, SKIP_MISSING_SEQUENCE_OWNERS,

{`REASSIGN OWNED BY CURRENT_USER TO foo`, `REASSIGN OWNED BY "current_user" TO foo`},
{`REASSIGN OWNED BY SESSION_USER TO foo`, `REASSIGN OWNED BY "session_user" TO foo`},
{`DROP OWNED BY CURRENT_USER`, `DROP OWNED BY "current_user"`},
{`DROP OWNED BY SESSION_USER`, `DROP OWNED BY "session_user"`},

// Validate that GRANT and REVOKE can accept optional PRIVILEGES syntax
{`GRANT ALL PRIVILEGES ON DATABASE foo TO root`, `GRANT ALL ON DATABASE foo TO root`},
Expand Down
50 changes: 34 additions & 16 deletions pkg/sql/parser/sql.y
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,8 @@ func (u *sqlSymUnion) survive() tree.Survive {
%type <tree.Statement> import_stmt
%type <tree.Statement> pause_stmt pause_jobs_stmt pause_schedules_stmt
%type <*tree.Select> for_schedules_clause
%type <tree.Statement> reassign_owned_stmt
%type <tree.Statement> reassign_owned_by_stmt
%type <tree.Statement> drop_owned_by_stmt
%type <tree.Statement> release_stmt
%type <tree.Statement> reset_stmt reset_session_stmt reset_csetting_stmt
%type <tree.Statement> resume_stmt resume_jobs_stmt resume_schedules_stmt
Expand Down Expand Up @@ -1254,22 +1255,23 @@ stmt_block:

stmt:
HELPTOKEN { return helpWith(sqllex, "") }
| preparable_stmt // help texts in sub-rule
| analyze_stmt // EXTEND WITH HELP: ANALYZE
| preparable_stmt // help texts in sub-rule
| analyze_stmt // EXTEND WITH HELP: ANALYZE
| copy_from_stmt
| comment_stmt
| execute_stmt // EXTEND WITH HELP: EXECUTE
| deallocate_stmt // EXTEND WITH HELP: DEALLOCATE
| discard_stmt // EXTEND WITH HELP: DISCARD
| grant_stmt // EXTEND WITH HELP: GRANT
| prepare_stmt // EXTEND WITH HELP: PREPARE
| revoke_stmt // EXTEND WITH HELP: REVOKE
| savepoint_stmt // EXTEND WITH HELP: SAVEPOINT
| reassign_owned_stmt // EXTEND WITH HELP: REASSIGN OWNED BY
| release_stmt // EXTEND WITH HELP: RELEASE
| refresh_stmt // EXTEND WITH HELP: REFRESH
| nonpreparable_set_stmt // help texts in sub-rule
| transaction_stmt // help texts in sub-rule
| execute_stmt // EXTEND WITH HELP: EXECUTE
| deallocate_stmt // EXTEND WITH HELP: DEALLOCATE
| discard_stmt // EXTEND WITH HELP: DISCARD
| grant_stmt // EXTEND WITH HELP: GRANT
| prepare_stmt // EXTEND WITH HELP: PREPARE
| revoke_stmt // EXTEND WITH HELP: REVOKE
| savepoint_stmt // EXTEND WITH HELP: SAVEPOINT
| reassign_owned_by_stmt // EXTEND WITH HELP: REASSIGN OWNED BY
| drop_owned_by_stmt // EXTEND WITH HELP: DROP OWNED BY
| release_stmt // EXTEND WITH HELP: RELEASE
| refresh_stmt // EXTEND WITH HELP: REFRESH
| nonpreparable_set_stmt // help texts in sub-rule
| transaction_stmt // help texts in sub-rule
| close_cursor_stmt
| declare_cursor_stmt
| reindex_stmt
Expand Down Expand Up @@ -7723,7 +7725,8 @@ multiple_set_clause:
// %Category: Priv
// %Text: REASSIGN OWNED BY {<name> | CURRENT_USER | SESSION_USER}[,...]
// TO {<name> | CURRENT_USER | SESSION_USER}
reassign_owned_stmt:
// %SeeAlso: DROP OWNED BY
reassign_owned_by_stmt:
REASSIGN OWNED BY role_spec_list TO role_spec
{
$$.val = &tree.ReassignOwnedBy{
Expand All @@ -7733,6 +7736,21 @@ reassign_owned_stmt:
}
| REASSIGN OWNED BY error // SHOW HELP: REASSIGN OWNED BY

// %Help: DROP OWNED BY - remove database objects owned by role(s).
// %Category: Priv
// %Text: DROP OWNED BY {<name> | CURRENT_USER | SESSION_USER}[,...]
// [RESTRICT | CASCADE]
// %SeeAlso: REASSIGN OWNED BY
drop_owned_by_stmt:
DROP OWNED BY role_spec_list opt_drop_behavior
{
$$.val = &tree.DropOwnedBy{
Roles: $4.strs(),
DropBehavior: $5.dropBehavior(),
}
}
| DROP OWNED BY error // SHOW HELP: DROP OWNED BY

// A complete SELECT statement looks like this.
//
// The rule returns either a single select_stmt node or a tree of them,
Expand Down
2 changes: 1 addition & 1 deletion pkg/sql/reassign_owned_by.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
"github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry"
)

// ReassignOwnedByNode represents a REASSIGN OWNED BY <name> TO <name> statement.
// ReassignOwnedByNode represents a REASSIGN OWNED BY <role(s)> TO <role> statement.
type reassignOwnedByNode struct {
n *tree.ReassignOwnedBy
}
Expand Down
34 changes: 34 additions & 0 deletions pkg/sql/sem/tree/drop_owned_by.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2020 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 tree

// DropOwnedBy represents a DROP OWNED BY command.
type DropOwnedBy struct {
Roles []string
DropBehavior DropBehavior
}

var _ Statement = &DropOwnedBy{}

// Format implements the NodeFormatter interface.
func (node *DropOwnedBy) Format(ctx *FmtCtx) {
ctx.WriteString("DROP OWNED BY ")
for i := range node.Roles {
if i > 0 {
ctx.WriteString(", ")
}
ctx.FormatNameP(&node.Roles[i])
}
if node.DropBehavior != DropDefault {
ctx.WriteString(" ")
ctx.WriteString(node.DropBehavior.String())
}
}
2 changes: 2 additions & 0 deletions pkg/sql/sem/tree/reassign_owned_by.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ type ReassignOwnedBy struct {
NewRole string
}

var _ Statement = &ReassignOwnedBy{}

// Format implements the NodeFormatter interface.
func (node *ReassignOwnedBy) Format(ctx *FmtCtx) {
ctx.WriteString("REASSIGN OWNED BY ")
Expand Down
11 changes: 9 additions & 2 deletions pkg/sql/sem/tree/stmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -602,7 +602,13 @@ func (*Prepare) StatementTag() string { return "PREPARE" }
func (*ReassignOwnedBy) StatementType() StatementType { return DDL }

// StatementTag returns a short string identifying the type of statement.
func (*ReassignOwnedBy) StatementTag() string { return "REASSIGN OWNED" }
func (*ReassignOwnedBy) StatementTag() string { return "REASSIGN OWNED BY" }

// StatementType implements the Statement interface.
func (*DropOwnedBy) StatementType() StatementType { return DDL }

// StatementTag returns a short string identifying the type of statement.
func (*DropOwnedBy) StatementTag() string { return "DROP OWNED BY" }

// StatementType implements the Statement interface.
func (*RefreshMaterializedView) StatementType() StatementType { return DDL }
Expand Down Expand Up @@ -1094,11 +1100,12 @@ func (n *Deallocate) String() string { return AsString(n) }
func (n *Delete) String() string { return AsString(n) }
func (n *DropDatabase) String() string { return AsString(n) }
func (n *DropIndex) String() string { return AsString(n) }
func (n *DropOwnedBy) String() string { return AsString(n) }
func (n *DropSchema) String() string { return AsString(n) }
func (n *DropSequence) String() string { return AsString(n) }
func (n *DropTable) String() string { return AsString(n) }
func (n *DropType) String() string { return AsString(n) }
func (n *DropView) String() string { return AsString(n) }
func (n *DropSequence) String() string { return AsString(n) }
func (n *DropRole) String() string { return AsString(n) }
func (n *Execute) String() string { return AsString(n) }
func (n *Explain) String() string { return AsString(n) }
Expand Down
18 changes: 18 additions & 0 deletions pkg/sql/sqltelemetry/drop_owned_by.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2020 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 sqltelemetry

import "github.com/cockroachdb/cockroach/pkg/server/telemetry"

// CreateDropOwnedByCounter returns a counter to increment for the DROP OWNED BY command.
func CreateDropOwnedByCounter() telemetry.Counter {
return telemetry.GetCounter("sql.drop_owned_by")
}
19 changes: 19 additions & 0 deletions pkg/sql/testdata/telemetry/drop_owned_by
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# This file contains telemetry tests for the sql.drop_owned_by counter.

feature-allowlist
sql.drop_owned_by.*
----

exec
CREATE ROLE testuser;
CREATE TABLE t();
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
1 change: 0 additions & 1 deletion pkg/sql/testdata/telemetry/reassign_owned_by
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ exec
CREATE ROLE testuser;
CREATE ROLE testuser2;
CREATE TABLE t();
GRANT testuser, testuser2 TO root;
GRANT CREATE ON DATABASE defaultdb TO testuser, testuser2;
ALTER TABLE t OWNER TO testuser
----
Expand Down
1 change: 1 addition & 0 deletions pkg/sql/walk.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ var planNodeNames = map[reflect.Type]string{
reflect.TypeOf(&ordinalityNode{}): "ordinality",
reflect.TypeOf(&projectSetNode{}): "project set",
reflect.TypeOf(&reassignOwnedByNode{}): "reassign owned by",
reflect.TypeOf(&dropOwnedByNode{}): "drop owned by",
reflect.TypeOf(&recursiveCTENode{}): "recursive cte",
reflect.TypeOf(&refreshMaterializedViewNode{}): "refresh materialized view",
reflect.TypeOf(&relocateNode{}): "relocate",
Expand Down

0 comments on commit 37188b0

Please sign in to comment.