Skip to content

Commit

Permalink
feat(spanner/spansql): support grant/revoke view, change stream, tabl…
Browse files Browse the repository at this point in the history
…e function (#7533)

* feat(spanner/spansql): support grant/revoke table function

* feat(spanner/spansql): support grant/revoke view, change stream

---------

Co-authored-by: rahul2393 <irahul@google.com>
  • Loading branch information
nktks and rahul2393 committed Mar 13, 2023
1 parent 88d3eda commit 9c61215
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 18 deletions.
36 changes: 36 additions & 0 deletions spanner/spansql/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,24 @@ func (p *parser) parseGrantRole() (*GrantRole, *parseError) {
return nil, err
}
g.GrantRoleNames = roleList
} else if p.eat("EXECUTE", "ON", "TABLE", "FUNCTION") {
tvfList, err := p.parseGrantOrRevokeRoleList("TO")
if err != nil {
return nil, err
}
g.TvfNames = tvfList
} else if p.eat("SELECT", "ON", "VIEW") {
viewList, err := p.parseGrantOrRevokeRoleList("TO")
if err != nil {
return nil, err
}
g.ViewNames = viewList
} else if p.eat("SELECT", "ON", "CHANGE", "STREAM") {
csList, err := p.parseGrantOrRevokeRoleList("TO")
if err != nil {
return nil, err
}
g.ChangeStreamNames = csList
} else {
var privs []Privilege
privs, err := p.parsePrivileges()
Expand Down Expand Up @@ -1392,6 +1410,24 @@ func (p *parser) parseRevokeRole() (*RevokeRole, *parseError) {
return nil, err
}
r.RevokeRoleNames = roleList
} else if p.eat("EXECUTE", "ON", "TABLE", "FUNCTION") {
tvfList, err := p.parseGrantOrRevokeRoleList("FROM")
if err != nil {
return nil, err
}
r.TvfNames = tvfList
} else if p.eat("SELECT", "ON", "VIEW") {
viewList, err := p.parseGrantOrRevokeRoleList("FROM")
if err != nil {
return nil, err
}
r.ViewNames = viewList
} else if p.eat("SELECT", "ON", "CHANGE", "STREAM") {
csList, err := p.parseGrantOrRevokeRoleList("FROM")
if err != nil {
return nil, err
}
r.ChangeStreamNames = csList
} else {
var privs []Privilege
privs, err := p.parsePrivileges()
Expand Down
58 changes: 50 additions & 8 deletions spanner/spansql/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -675,12 +675,18 @@ func TestParseDDL(t *testing.T) {
GRANT SELECT, UPDATE(location), DELETE ON TABLE employees TO ROLE hr_manager;
GRANT SELECT(name, level, location), UPDATE(location) ON TABLE employees, contractors TO ROLE hr_manager;
GRANT ROLE pii_access, pii_update TO ROLE hr_manager, hr_director;
GRANT EXECUTE ON TABLE FUNCTION tvf_name_one, tvf_name_two TO ROLE hr_manager, hr_director;
GRANT SELECT ON VIEW view_name_one, view_name_two TO ROLE hr_manager, hr_director;
GRANT SELECT ON CHANGE STREAM cs_name_one, cs_name_two TO ROLE hr_manager, hr_director;
REVOKE SELECT ON TABLE employees FROM ROLE hr_rep;
REVOKE SELECT(name, address, phone) ON TABLE contractors FROM ROLE hr_rep;
REVOKE SELECT, UPDATE(location), DELETE ON TABLE employees FROM ROLE hr_manager;
REVOKE SELECT(name, level, location), UPDATE(location) ON TABLE employees, contractors FROM ROLE hr_manager;
REVOKE ROLE pii_access, pii_update FROM ROLE hr_manager, hr_director;
REVOKE EXECUTE ON TABLE FUNCTION tvf_name_one, tvf_name_two FROM ROLE hr_manager, hr_director;
REVOKE SELECT ON VIEW view_name_one, view_name_two FROM ROLE hr_manager, hr_director;
REVOKE SELECT ON CHANGE STREAM cs_name_one, cs_name_two FROM ROLE hr_manager, hr_director;
ALTER INDEX MyFirstIndex ADD STORED COLUMN UpdatedAt;
ALTER INDEX MyFirstIndex DROP STORED COLUMN UpdatedAt;
Expand Down Expand Up @@ -1020,14 +1026,32 @@ func TestParseDDL(t *testing.T) {

Position: line(91),
},
&GrantRole{
ToRoleNames: []ID{"hr_manager", "hr_director"},
TvfNames: []ID{"tvf_name_one", "tvf_name_two"},

Position: line(92),
},
&GrantRole{
ToRoleNames: []ID{"hr_manager", "hr_director"},
ViewNames: []ID{"view_name_one", "view_name_two"},

Position: line(93),
},
&GrantRole{
ToRoleNames: []ID{"hr_manager", "hr_director"},
ChangeStreamNames: []ID{"cs_name_one", "cs_name_two"},

Position: line(94),
},
&RevokeRole{
FromRoleNames: []ID{"hr_rep"},
Privileges: []Privilege{
{Type: PrivilegeTypeSelect},
},
TableNames: []ID{"employees"},

Position: line(93),
Position: line(96),
},
&RevokeRole{
FromRoleNames: []ID{"hr_rep"},
Expand All @@ -1036,7 +1060,7 @@ func TestParseDDL(t *testing.T) {
},
TableNames: []ID{"contractors"},

Position: line(94),
Position: line(97),
},
&RevokeRole{
FromRoleNames: []ID{"hr_manager"},
Expand All @@ -1047,7 +1071,7 @@ func TestParseDDL(t *testing.T) {
},
TableNames: []ID{"employees"},

Position: line(95),
Position: line(98),
},
&RevokeRole{
FromRoleNames: []ID{"hr_manager"},
Expand All @@ -1057,23 +1081,41 @@ func TestParseDDL(t *testing.T) {
},
TableNames: []ID{"employees", "contractors"},

Position: line(96),
Position: line(99),
},
&RevokeRole{
FromRoleNames: []ID{"hr_manager", "hr_director"},
RevokeRoleNames: []ID{"pii_access", "pii_update"},

Position: line(97),
Position: line(100),
},
&RevokeRole{
FromRoleNames: []ID{"hr_manager", "hr_director"},
TvfNames: []ID{"tvf_name_one", "tvf_name_two"},

Position: line(101),
},
&RevokeRole{
FromRoleNames: []ID{"hr_manager", "hr_director"},
ViewNames: []ID{"view_name_one", "view_name_two"},

Position: line(102),
},
&RevokeRole{
FromRoleNames: []ID{"hr_manager", "hr_director"},
ChangeStreamNames: []ID{"cs_name_one", "cs_name_two"},

Position: line(103),
},
&AlterIndex{
Name: "MyFirstIndex",
Alteration: AddStoredColumn{Name: "UpdatedAt"},
Position: line(99),
Position: line(105),
},
&AlterIndex{
Name: "MyFirstIndex",
Alteration: DropStoredColumn{Name: "UpdatedAt"},
Position: line(100),
Position: line(106),
},
}, Comments: []*Comment{
{
Expand Down Expand Up @@ -1110,7 +1152,7 @@ func TestParseDDL(t *testing.T) {
{Marker: "--", Isolated: true, Start: line(75), End: line(75), Text: []string{"Table has a column with a default value."}},

// Comment after everything else.
{Marker: "--", Isolated: true, Start: line(102), End: line(102), Text: []string{"Trailing comment at end of file."}},
{Marker: "--", Isolated: true, Start: line(108), End: line(108), Text: []string{"Trailing comment at end of file."}},
}}},
// No trailing comma:
{`ALTER TABLE T ADD COLUMN C2 INT64`, &DDL{Filename: "filename", List: []DDLStmt{
Expand Down
12 changes: 12 additions & 0 deletions spanner/spansql/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,12 @@ func (gr GrantRole) SQL() string {
}
}
sql += " ON TABLE " + idList(gr.TableNames, ", ")
} else if len(gr.TvfNames) > 0 {
sql += "EXECUTE ON TABLE FUNCTION " + idList(gr.TvfNames, ", ")
} else if len(gr.ViewNames) > 0 {
sql += "SELECT ON VIEW " + idList(gr.ViewNames, ", ")
} else if len(gr.ChangeStreamNames) > 0 {
sql += "SELECT ON CHANGE STREAM " + idList(gr.ChangeStreamNames, ", ")
} else {
sql += "ROLE " + idList(gr.GrantRoleNames, ", ")
}
Expand All @@ -186,6 +192,12 @@ func (rr RevokeRole) SQL() string {
}
}
sql += " ON TABLE " + idList(rr.TableNames, ", ")
} else if len(rr.TvfNames) > 0 {
sql += "EXECUTE ON TABLE FUNCTION " + idList(rr.TvfNames, ", ")
} else if len(rr.ViewNames) > 0 {
sql += "SELECT ON VIEW " + idList(rr.ViewNames, ", ")
} else if len(rr.ChangeStreamNames) > 0 {
sql += "SELECT ON CHANGE STREAM " + idList(rr.ChangeStreamNames, ", ")
} else {
sql += "ROLE " + idList(rr.RevokeRoleNames, ", ")
}
Expand Down
60 changes: 60 additions & 0 deletions spanner/spansql/sql_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,36 @@ func TestSQL(t *testing.T) {
"GRANT SELECT(name, level, location), UPDATE(location) ON TABLE employees, contractors TO ROLE hr_manager",
reparseDDL,
},
{
&GrantRole{
ToRoleNames: []ID{"hr_manager"},
TvfNames: []ID{"tvf_name_one", "tvf_name_two"},

Position: line(1),
},
"GRANT EXECUTE ON TABLE FUNCTION tvf_name_one, tvf_name_two TO ROLE hr_manager",
reparseDDL,
},
{
&GrantRole{
ToRoleNames: []ID{"hr_manager"},
ViewNames: []ID{"view_name_one", "view_name_two"},

Position: line(1),
},
"GRANT SELECT ON VIEW view_name_one, view_name_two TO ROLE hr_manager",
reparseDDL,
},
{
&GrantRole{
ToRoleNames: []ID{"hr_manager"},
ChangeStreamNames: []ID{"cs_name_one", "cs_name_two"},

Position: line(1),
},
"GRANT SELECT ON CHANGE STREAM cs_name_one, cs_name_two TO ROLE hr_manager",
reparseDDL,
},
{
&RevokeRole{
FromRoleNames: []ID{"hr_manager"},
Expand All @@ -262,6 +292,36 @@ func TestSQL(t *testing.T) {
"REVOKE SELECT(name, level, location), UPDATE(location) ON TABLE employees, contractors FROM ROLE hr_manager",
reparseDDL,
},
{
&RevokeRole{
FromRoleNames: []ID{"hr_manager"},
TvfNames: []ID{"tvf_name_one", "tvf_name_two"},

Position: line(1),
},
"REVOKE EXECUTE ON TABLE FUNCTION tvf_name_one, tvf_name_two FROM ROLE hr_manager",
reparseDDL,
},
{
&RevokeRole{
FromRoleNames: []ID{"hr_manager"},
ViewNames: []ID{"view_name_one", "view_name_two"},

Position: line(1),
},
"REVOKE SELECT ON VIEW view_name_one, view_name_two FROM ROLE hr_manager",
reparseDDL,
},
{
&RevokeRole{
FromRoleNames: []ID{"hr_manager"},
ChangeStreamNames: []ID{"cs_name_one", "cs_name_two"},

Position: line(1),
},
"REVOKE SELECT ON CHANGE STREAM cs_name_one, cs_name_two FROM ROLE hr_manager",
reparseDDL,
},
{
&AlterTable{
Name: "Ta",
Expand Down
25 changes: 15 additions & 10 deletions spanner/spansql/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,13 @@ func (dr *DropRole) clearOffset() { dr.Position.Offset = 0 }
// GrantRole represents a GRANT statement.
// https://cloud.google.com/spanner/docs/reference/standard-sql/data-definition-language#grant_statement
type GrantRole struct {
ToRoleNames []ID
GrantRoleNames []ID
Privileges []Privilege
TableNames []ID
ToRoleNames []ID
GrantRoleNames []ID
Privileges []Privilege
TableNames []ID
TvfNames []ID
ViewNames []ID
ChangeStreamNames []ID

Position Position // position of the "GRANT" token
}
Expand All @@ -217,12 +220,14 @@ func (gr *GrantRole) clearOffset() { gr.Position.Offset = 0 }
// RevokeRole represents a REVOKE statement.
// https://cloud.google.com/spanner/docs/reference/standard-sql/data-definition-language#revoke_statement
type RevokeRole struct {
FromRoleNames []ID
RevokeRoleNames []ID
Privileges []Privilege
TableNames []ID

Position Position // position of the "REVOKE" token
FromRoleNames []ID
RevokeRoleNames []ID
Privileges []Privilege
TableNames []ID
TvfNames []ID
ViewNames []ID
ChangeStreamNames []ID
Position Position // position of the "REVOKE" token
}

func (rr *RevokeRole) String() string { return fmt.Sprintf("%#v", rr) }
Expand Down

0 comments on commit 9c61215

Please sign in to comment.