Skip to content

Commit 9c61215

Browse files
nktksrahul2393
andauthored
feat(spanner/spansql): support grant/revoke view, change stream, table function (#7533)
* feat(spanner/spansql): support grant/revoke table function * feat(spanner/spansql): support grant/revoke view, change stream --------- Co-authored-by: rahul2393 <[email protected]>
1 parent 88d3eda commit 9c61215

File tree

5 files changed

+173
-18
lines changed

5 files changed

+173
-18
lines changed

spanner/spansql/parser.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,6 +1351,24 @@ func (p *parser) parseGrantRole() (*GrantRole, *parseError) {
13511351
return nil, err
13521352
}
13531353
g.GrantRoleNames = roleList
1354+
} else if p.eat("EXECUTE", "ON", "TABLE", "FUNCTION") {
1355+
tvfList, err := p.parseGrantOrRevokeRoleList("TO")
1356+
if err != nil {
1357+
return nil, err
1358+
}
1359+
g.TvfNames = tvfList
1360+
} else if p.eat("SELECT", "ON", "VIEW") {
1361+
viewList, err := p.parseGrantOrRevokeRoleList("TO")
1362+
if err != nil {
1363+
return nil, err
1364+
}
1365+
g.ViewNames = viewList
1366+
} else if p.eat("SELECT", "ON", "CHANGE", "STREAM") {
1367+
csList, err := p.parseGrantOrRevokeRoleList("TO")
1368+
if err != nil {
1369+
return nil, err
1370+
}
1371+
g.ChangeStreamNames = csList
13541372
} else {
13551373
var privs []Privilege
13561374
privs, err := p.parsePrivileges()
@@ -1392,6 +1410,24 @@ func (p *parser) parseRevokeRole() (*RevokeRole, *parseError) {
13921410
return nil, err
13931411
}
13941412
r.RevokeRoleNames = roleList
1413+
} else if p.eat("EXECUTE", "ON", "TABLE", "FUNCTION") {
1414+
tvfList, err := p.parseGrantOrRevokeRoleList("FROM")
1415+
if err != nil {
1416+
return nil, err
1417+
}
1418+
r.TvfNames = tvfList
1419+
} else if p.eat("SELECT", "ON", "VIEW") {
1420+
viewList, err := p.parseGrantOrRevokeRoleList("FROM")
1421+
if err != nil {
1422+
return nil, err
1423+
}
1424+
r.ViewNames = viewList
1425+
} else if p.eat("SELECT", "ON", "CHANGE", "STREAM") {
1426+
csList, err := p.parseGrantOrRevokeRoleList("FROM")
1427+
if err != nil {
1428+
return nil, err
1429+
}
1430+
r.ChangeStreamNames = csList
13951431
} else {
13961432
var privs []Privilege
13971433
privs, err := p.parsePrivileges()

spanner/spansql/parser_test.go

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -675,12 +675,18 @@ func TestParseDDL(t *testing.T) {
675675
GRANT SELECT, UPDATE(location), DELETE ON TABLE employees TO ROLE hr_manager;
676676
GRANT SELECT(name, level, location), UPDATE(location) ON TABLE employees, contractors TO ROLE hr_manager;
677677
GRANT ROLE pii_access, pii_update TO ROLE hr_manager, hr_director;
678+
GRANT EXECUTE ON TABLE FUNCTION tvf_name_one, tvf_name_two TO ROLE hr_manager, hr_director;
679+
GRANT SELECT ON VIEW view_name_one, view_name_two TO ROLE hr_manager, hr_director;
680+
GRANT SELECT ON CHANGE STREAM cs_name_one, cs_name_two TO ROLE hr_manager, hr_director;
678681
679682
REVOKE SELECT ON TABLE employees FROM ROLE hr_rep;
680683
REVOKE SELECT(name, address, phone) ON TABLE contractors FROM ROLE hr_rep;
681684
REVOKE SELECT, UPDATE(location), DELETE ON TABLE employees FROM ROLE hr_manager;
682685
REVOKE SELECT(name, level, location), UPDATE(location) ON TABLE employees, contractors FROM ROLE hr_manager;
683686
REVOKE ROLE pii_access, pii_update FROM ROLE hr_manager, hr_director;
687+
REVOKE EXECUTE ON TABLE FUNCTION tvf_name_one, tvf_name_two FROM ROLE hr_manager, hr_director;
688+
REVOKE SELECT ON VIEW view_name_one, view_name_two FROM ROLE hr_manager, hr_director;
689+
REVOKE SELECT ON CHANGE STREAM cs_name_one, cs_name_two FROM ROLE hr_manager, hr_director;
684690
685691
ALTER INDEX MyFirstIndex ADD STORED COLUMN UpdatedAt;
686692
ALTER INDEX MyFirstIndex DROP STORED COLUMN UpdatedAt;
@@ -1020,14 +1026,32 @@ func TestParseDDL(t *testing.T) {
10201026

10211027
Position: line(91),
10221028
},
1029+
&GrantRole{
1030+
ToRoleNames: []ID{"hr_manager", "hr_director"},
1031+
TvfNames: []ID{"tvf_name_one", "tvf_name_two"},
1032+
1033+
Position: line(92),
1034+
},
1035+
&GrantRole{
1036+
ToRoleNames: []ID{"hr_manager", "hr_director"},
1037+
ViewNames: []ID{"view_name_one", "view_name_two"},
1038+
1039+
Position: line(93),
1040+
},
1041+
&GrantRole{
1042+
ToRoleNames: []ID{"hr_manager", "hr_director"},
1043+
ChangeStreamNames: []ID{"cs_name_one", "cs_name_two"},
1044+
1045+
Position: line(94),
1046+
},
10231047
&RevokeRole{
10241048
FromRoleNames: []ID{"hr_rep"},
10251049
Privileges: []Privilege{
10261050
{Type: PrivilegeTypeSelect},
10271051
},
10281052
TableNames: []ID{"employees"},
10291053

1030-
Position: line(93),
1054+
Position: line(96),
10311055
},
10321056
&RevokeRole{
10331057
FromRoleNames: []ID{"hr_rep"},
@@ -1036,7 +1060,7 @@ func TestParseDDL(t *testing.T) {
10361060
},
10371061
TableNames: []ID{"contractors"},
10381062

1039-
Position: line(94),
1063+
Position: line(97),
10401064
},
10411065
&RevokeRole{
10421066
FromRoleNames: []ID{"hr_manager"},
@@ -1047,7 +1071,7 @@ func TestParseDDL(t *testing.T) {
10471071
},
10481072
TableNames: []ID{"employees"},
10491073

1050-
Position: line(95),
1074+
Position: line(98),
10511075
},
10521076
&RevokeRole{
10531077
FromRoleNames: []ID{"hr_manager"},
@@ -1057,23 +1081,41 @@ func TestParseDDL(t *testing.T) {
10571081
},
10581082
TableNames: []ID{"employees", "contractors"},
10591083

1060-
Position: line(96),
1084+
Position: line(99),
10611085
},
10621086
&RevokeRole{
10631087
FromRoleNames: []ID{"hr_manager", "hr_director"},
10641088
RevokeRoleNames: []ID{"pii_access", "pii_update"},
10651089

1066-
Position: line(97),
1090+
Position: line(100),
1091+
},
1092+
&RevokeRole{
1093+
FromRoleNames: []ID{"hr_manager", "hr_director"},
1094+
TvfNames: []ID{"tvf_name_one", "tvf_name_two"},
1095+
1096+
Position: line(101),
1097+
},
1098+
&RevokeRole{
1099+
FromRoleNames: []ID{"hr_manager", "hr_director"},
1100+
ViewNames: []ID{"view_name_one", "view_name_two"},
1101+
1102+
Position: line(102),
1103+
},
1104+
&RevokeRole{
1105+
FromRoleNames: []ID{"hr_manager", "hr_director"},
1106+
ChangeStreamNames: []ID{"cs_name_one", "cs_name_two"},
1107+
1108+
Position: line(103),
10671109
},
10681110
&AlterIndex{
10691111
Name: "MyFirstIndex",
10701112
Alteration: AddStoredColumn{Name: "UpdatedAt"},
1071-
Position: line(99),
1113+
Position: line(105),
10721114
},
10731115
&AlterIndex{
10741116
Name: "MyFirstIndex",
10751117
Alteration: DropStoredColumn{Name: "UpdatedAt"},
1076-
Position: line(100),
1118+
Position: line(106),
10771119
},
10781120
}, Comments: []*Comment{
10791121
{
@@ -1110,7 +1152,7 @@ func TestParseDDL(t *testing.T) {
11101152
{Marker: "--", Isolated: true, Start: line(75), End: line(75), Text: []string{"Table has a column with a default value."}},
11111153

11121154
// Comment after everything else.
1113-
{Marker: "--", Isolated: true, Start: line(102), End: line(102), Text: []string{"Trailing comment at end of file."}},
1155+
{Marker: "--", Isolated: true, Start: line(108), End: line(108), Text: []string{"Trailing comment at end of file."}},
11141156
}}},
11151157
// No trailing comma:
11161158
{`ALTER TABLE T ADD COLUMN C2 INT64`, &DDL{Filename: "filename", List: []DDLStmt{

spanner/spansql/sql.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,12 @@ func (gr GrantRole) SQL() string {
166166
}
167167
}
168168
sql += " ON TABLE " + idList(gr.TableNames, ", ")
169+
} else if len(gr.TvfNames) > 0 {
170+
sql += "EXECUTE ON TABLE FUNCTION " + idList(gr.TvfNames, ", ")
171+
} else if len(gr.ViewNames) > 0 {
172+
sql += "SELECT ON VIEW " + idList(gr.ViewNames, ", ")
173+
} else if len(gr.ChangeStreamNames) > 0 {
174+
sql += "SELECT ON CHANGE STREAM " + idList(gr.ChangeStreamNames, ", ")
169175
} else {
170176
sql += "ROLE " + idList(gr.GrantRoleNames, ", ")
171177
}
@@ -186,6 +192,12 @@ func (rr RevokeRole) SQL() string {
186192
}
187193
}
188194
sql += " ON TABLE " + idList(rr.TableNames, ", ")
195+
} else if len(rr.TvfNames) > 0 {
196+
sql += "EXECUTE ON TABLE FUNCTION " + idList(rr.TvfNames, ", ")
197+
} else if len(rr.ViewNames) > 0 {
198+
sql += "SELECT ON VIEW " + idList(rr.ViewNames, ", ")
199+
} else if len(rr.ChangeStreamNames) > 0 {
200+
sql += "SELECT ON CHANGE STREAM " + idList(rr.ChangeStreamNames, ", ")
189201
} else {
190202
sql += "ROLE " + idList(rr.RevokeRoleNames, ", ")
191203
}

spanner/spansql/sql_test.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,36 @@ func TestSQL(t *testing.T) {
248248
"GRANT SELECT(name, level, location), UPDATE(location) ON TABLE employees, contractors TO ROLE hr_manager",
249249
reparseDDL,
250250
},
251+
{
252+
&GrantRole{
253+
ToRoleNames: []ID{"hr_manager"},
254+
TvfNames: []ID{"tvf_name_one", "tvf_name_two"},
255+
256+
Position: line(1),
257+
},
258+
"GRANT EXECUTE ON TABLE FUNCTION tvf_name_one, tvf_name_two TO ROLE hr_manager",
259+
reparseDDL,
260+
},
261+
{
262+
&GrantRole{
263+
ToRoleNames: []ID{"hr_manager"},
264+
ViewNames: []ID{"view_name_one", "view_name_two"},
265+
266+
Position: line(1),
267+
},
268+
"GRANT SELECT ON VIEW view_name_one, view_name_two TO ROLE hr_manager",
269+
reparseDDL,
270+
},
271+
{
272+
&GrantRole{
273+
ToRoleNames: []ID{"hr_manager"},
274+
ChangeStreamNames: []ID{"cs_name_one", "cs_name_two"},
275+
276+
Position: line(1),
277+
},
278+
"GRANT SELECT ON CHANGE STREAM cs_name_one, cs_name_two TO ROLE hr_manager",
279+
reparseDDL,
280+
},
251281
{
252282
&RevokeRole{
253283
FromRoleNames: []ID{"hr_manager"},
@@ -262,6 +292,36 @@ func TestSQL(t *testing.T) {
262292
"REVOKE SELECT(name, level, location), UPDATE(location) ON TABLE employees, contractors FROM ROLE hr_manager",
263293
reparseDDL,
264294
},
295+
{
296+
&RevokeRole{
297+
FromRoleNames: []ID{"hr_manager"},
298+
TvfNames: []ID{"tvf_name_one", "tvf_name_two"},
299+
300+
Position: line(1),
301+
},
302+
"REVOKE EXECUTE ON TABLE FUNCTION tvf_name_one, tvf_name_two FROM ROLE hr_manager",
303+
reparseDDL,
304+
},
305+
{
306+
&RevokeRole{
307+
FromRoleNames: []ID{"hr_manager"},
308+
ViewNames: []ID{"view_name_one", "view_name_two"},
309+
310+
Position: line(1),
311+
},
312+
"REVOKE SELECT ON VIEW view_name_one, view_name_two FROM ROLE hr_manager",
313+
reparseDDL,
314+
},
315+
{
316+
&RevokeRole{
317+
FromRoleNames: []ID{"hr_manager"},
318+
ChangeStreamNames: []ID{"cs_name_one", "cs_name_two"},
319+
320+
Position: line(1),
321+
},
322+
"REVOKE SELECT ON CHANGE STREAM cs_name_one, cs_name_two FROM ROLE hr_manager",
323+
reparseDDL,
324+
},
265325
{
266326
&AlterTable{
267327
Name: "Ta",

spanner/spansql/types.go

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -201,10 +201,13 @@ func (dr *DropRole) clearOffset() { dr.Position.Offset = 0 }
201201
// GrantRole represents a GRANT statement.
202202
// https://cloud.google.com/spanner/docs/reference/standard-sql/data-definition-language#grant_statement
203203
type GrantRole struct {
204-
ToRoleNames []ID
205-
GrantRoleNames []ID
206-
Privileges []Privilege
207-
TableNames []ID
204+
ToRoleNames []ID
205+
GrantRoleNames []ID
206+
Privileges []Privilege
207+
TableNames []ID
208+
TvfNames []ID
209+
ViewNames []ID
210+
ChangeStreamNames []ID
208211

209212
Position Position // position of the "GRANT" token
210213
}
@@ -217,12 +220,14 @@ func (gr *GrantRole) clearOffset() { gr.Position.Offset = 0 }
217220
// RevokeRole represents a REVOKE statement.
218221
// https://cloud.google.com/spanner/docs/reference/standard-sql/data-definition-language#revoke_statement
219222
type RevokeRole struct {
220-
FromRoleNames []ID
221-
RevokeRoleNames []ID
222-
Privileges []Privilege
223-
TableNames []ID
224-
225-
Position Position // position of the "REVOKE" token
223+
FromRoleNames []ID
224+
RevokeRoleNames []ID
225+
Privileges []Privilege
226+
TableNames []ID
227+
TvfNames []ID
228+
ViewNames []ID
229+
ChangeStreamNames []ID
230+
Position Position // position of the "REVOKE" token
226231
}
227232

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

0 commit comments

Comments
 (0)