Skip to content

Commit 424ffca

Browse files
committed
Merge branch 'revoke'
2 parents 60216ee + aba25cf commit 424ffca

File tree

5 files changed

+210
-22
lines changed

5 files changed

+210
-22
lines changed

src/cst/Dcl.ts

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,11 @@ export type AllDclNodes =
1010
| GrantResource
1111
| GrantedByClause;
1212

13-
export type AllDclStatements = GrantRoleStmt | GrantPrivilegeStmt | RevokeStmt;
13+
export type AllDclStatements =
14+
| GrantRoleStmt
15+
| GrantPrivilegeStmt
16+
| RevokeRoleStmt
17+
| RevokePrivilegeStmt;
1418

1519
// GRANT role ON resource TO user
1620
export interface GrantRoleStmt extends BaseNode {
@@ -211,9 +215,9 @@ export interface GrantedByClause extends BaseNode {
211215

212216
type GrantRoleSpecification = Identifier;
213217

214-
// REVOKE
215-
export interface RevokeStmt extends BaseNode {
216-
type: "revoke_stmt";
218+
// REVOKE role ON resource FROM user
219+
export interface RevokeRoleStmt extends BaseNode {
220+
type: "revoke_role_stmt";
217221
revokeKw: Keyword<"REVOKE">;
218222
roles: ListExpr<Identifier>;
219223
onKw: Keyword<"ON">;
@@ -224,3 +228,17 @@ export interface RevokeStmt extends BaseNode {
224228
fromKw: Keyword<"FROM">;
225229
users: ListExpr<StringLiteral>;
226230
}
231+
232+
// REVOKE privilege ON resource FROM roles
233+
export interface RevokePrivilegeStmt extends BaseNode {
234+
type: "revoke_privilege_stmt";
235+
revokeKw: Keyword<"REVOKE">;
236+
grantOptionForKw?: [Keyword<"GRANT">, Keyword<"OPTION">, Keyword<"FOR">];
237+
privileges: ListExpr<Privilege> | AllPrivileges;
238+
onKw: Keyword<"ON">;
239+
resource: GrantResource;
240+
fromKw: Keyword<"FROM">;
241+
roles: ListExpr<GrantRoleSpecification>;
242+
grantedBy?: GrantedByClause;
243+
behaviorKw: Keyword<"CASCADE" | "RESTRICT">;
244+
}

src/parser.pegjs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4732,8 +4732,8 @@ release_savepoint_stmt
47324732
* ------------------------------------------------------------------------------------ *
47334733
*/
47344734
dcl_statement
4735-
= &bigquery x:(grant_role_stmt / revoke_stmt) { return x; }
4736-
/ &postgres x:(grant_privilege_stmt) { return x; }
4735+
= &bigquery x:(grant_role_stmt / revoke_role_stmt) { return x; }
4736+
/ &postgres x:(grant_privilege_stmt / revoke_privilege_stmt) { return x; }
47374737

47384738
grant_role_stmt
47394739
= kw:(GRANT __) roles:(list$ident __)
@@ -4858,12 +4858,12 @@ granted_by_clause
48584858
return loc({ type: "granted_by_clause", grantedByKw: read(kw), role });
48594859
}
48604860

4861-
revoke_stmt
4861+
revoke_role_stmt
48624862
= kw:(REVOKE __) roles:(list$ident __)
48634863
onKw:(ON __) resType:(resource_type_kw __) resName:(entity_name __)
48644864
fromKw:(FROM __) users:(list$string_literal) {
48654865
return loc({
4866-
type: "revoke_stmt",
4866+
type: "revoke_role_stmt",
48674867
revokeKw: read(kw),
48684868
roles: read(roles),
48694869
onKw: read(onKw),
@@ -4880,6 +4880,27 @@ resource_type_kw
48804880
/ VIEW
48814881
/ kw:(EXTERNAL __ TABLE) { return read(kw); }
48824882

4883+
revoke_privilege_stmt
4884+
= kw:(REVOKE __) grantOptionForKw:(GRANT __ OPTION __ FOR __)?
4885+
privileges:((list$privilege / all_privileges) __)
4886+
onKw:(ON __) resource:(grant_resource __)
4887+
fromKw:(FROM __) roles:list$role_specification
4888+
grantedBy:(__ granted_by_clause)?
4889+
behaviorKw:(__ (CASCADE / RESTRICT))? {
4890+
return loc({
4891+
type: "revoke_privilege_stmt",
4892+
revokeKw: read(kw),
4893+
grantOptionForKw: read(grantOptionForKw),
4894+
privileges: read(privileges),
4895+
onKw: read(onKw),
4896+
resource: read(resource),
4897+
fromKw: read(fromKw),
4898+
roles,
4899+
grantedBy: read(grantedBy),
4900+
behaviorKw: read(behaviorKw),
4901+
});
4902+
}
4903+
48834904
/**
48844905
* ------------------------------------------------------------------------------------ *
48854906
* *

src/showNode/dcl.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export const dclMap: FullTransformMap<string, AllDclNodes> = {
5151
grant_resource_type: (node) => show([node.typeKw, node.types]),
5252
granted_by_clause: (node) => show([node.grantedByKw, node.role]),
5353

54-
revoke_stmt: (node) =>
54+
revoke_role_stmt: (node) =>
5555
show([
5656
node.revokeKw,
5757
node.roles,
@@ -61,4 +61,16 @@ export const dclMap: FullTransformMap<string, AllDclNodes> = {
6161
node.fromKw,
6262
node.users,
6363
]),
64+
revoke_privilege_stmt: (node) =>
65+
show([
66+
node.revokeKw,
67+
node.grantOptionForKw,
68+
node.privileges,
69+
node.onKw,
70+
node.resource,
71+
node.fromKw,
72+
node.roles,
73+
node.grantedBy,
74+
node.behaviorKw,
75+
]),
6476
};

test/dcl/grant.test.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,4 @@ describe("GRANT", () => {
170170
expect(() => parse("GRANT `role` ON TABLE foo TO 'user:blah'")).toThrowError();
171171
});
172172
});
173-
174-
dialect("postgresql", () => {
175-
it.skip("TODO:postgres", () => {
176-
expect(true).toBe(true);
177-
});
178-
});
179173
});

test/dcl/revoke.test.ts

Lines changed: 150 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { dialect, parse, testWc } from "../test_utils";
1+
import { dialect, includeAll, parse, testWc } from "../test_utils";
22

33
describe("REVOKE", () => {
44
dialect("bigquery", () => {
@@ -21,15 +21,158 @@ describe("REVOKE", () => {
2121
});
2222
});
2323

24-
dialect(["mysql", "mariadb", "sqlite"], () => {
25-
it("does not support REVOKE", () => {
26-
expect(() => parse("REVOKE `role` ON TABLE foo FROM 'user:blah'")).toThrowError();
24+
dialect("postgresql", () => {
25+
[
26+
"SELECT",
27+
"INSERT",
28+
"UPDATE",
29+
"DELETE",
30+
"TRUNCATE",
31+
"REFERENCES",
32+
"TRIGGER",
33+
"MAINTAIN",
34+
].forEach((privilege) => {
35+
it(`supports REVOKE ${privilege} ON TABLE ... FROM role`, () => {
36+
testWc(`REVOKE ${privilege} ON TABLE schm.tbl FROM john_doe`);
37+
});
38+
});
39+
40+
it(`supports revoking multiple privileges`, () => {
41+
testWc(`REVOKE SELECT, UPDATE, INSERT ON TABLE tbl FROM john`);
42+
});
43+
44+
it(`supports REVOKE ALL PRIVILEGES ON TABLE ... FROM role`, () => {
45+
testWc(`REVOKE ALL ON TABLE schm.tbl FROM john_doe`);
46+
testWc(`REVOKE ALL PRIVILEGES ON TABLE schm.tbl FROM john_doe`);
47+
});
48+
49+
it(`supports ALL TABLES IN SCHEMA`, () => {
50+
testWc(`REVOKE INSERT ON ALL TABLES IN SCHEMA my_schema FROM peter_pan`);
51+
testWc(`REVOKE INSERT ON ALL TABLES IN SCHEMA schm1, schm2 FROM peter_pan`);
52+
});
53+
54+
it(`supports multiple tables and roles`, () => {
55+
testWc(`REVOKE UPDATE ON TABLE tbl1, tbl2, tbl3 FROM john_doe, mary_jane`);
56+
});
57+
58+
it(`supports optional TABLE keyword`, () => {
59+
testWc(`REVOKE DELETE ON tbl FROM johnny`);
60+
});
61+
62+
["SELECT", "INSERT", "UPDATE", "REFERENCES"].forEach((privilege) => {
63+
it(`supports REVOKE ${privilege} (cols) ON TABLE ... FROM role`, () => {
64+
testWc(`REVOKE ${privilege} (col1, col2) ON TABLE my_tbl FROM john`);
65+
});
66+
});
67+
68+
it(`supports granting multiple privileges per column`, () => {
69+
testWc(`REVOKE SELECT (col1, col2), UPDATE (col1, col2) ON TABLE my_tbl FROM john`);
70+
});
71+
72+
it(`supports granting all privileges on columns`, () => {
73+
testWc(`REVOKE ALL (col1, col2) ON TABLE my_tbl FROM john`);
74+
testWc(`REVOKE ALL PRIVILEGES (col1) ON TABLE my_tbl FROM john`);
75+
});
76+
77+
["USAGE", "SELECT", "UPDATE"].forEach((privilege) => {
78+
it(`supports REVOKE ${privilege} ON SEQUENCE ... FROM role`, () => {
79+
testWc(`REVOKE ${privilege} ON SEQUENCE schm.seq1, seq2 FROM john_doe`);
80+
});
81+
});
82+
83+
it(`supports ALL SEQUENCES IN SCHEMA`, () => {
84+
testWc(`REVOKE USAGE ON ALL SEQUENCES IN SCHEMA my_schema FROM peter_pan`);
85+
testWc(`REVOKE USAGE, UPDATE ON ALL SEQUENCES IN SCHEMA schm1, schm2 FROM peter_pan`);
86+
});
87+
88+
["CREATE", "CONNECT", "TEMPORARY", "TEMP"].forEach((privilege) => {
89+
it(`supports REVOKE ${privilege} ON DATABASE ... FROM role`, () => {
90+
testWc(`REVOKE ${privilege} ON DATABASE db1, db2 FROM john_doe`);
91+
});
92+
});
93+
94+
it(`supports REVOKE USAGE ON DOMAIN ... FROM role`, () => {
95+
testWc(`REVOKE USAGE ON DOMAIN schm.dom1, dom2 FROM john_doe`);
96+
});
97+
98+
it(`supports REVOKE USAGE ON FOREIGN DATA WRAPPER ... FROM role`, () => {
99+
testWc(`REVOKE USAGE ON FOREIGN DATA WRAPPER wrap1, wrap2 FROM john_doe`);
100+
});
101+
102+
it(`supports REVOKE USAGE ON FOREIGN SERVER ... FROM role`, () => {
103+
testWc(`REVOKE USAGE ON FOREIGN SERVER serv1, serv2 FROM john_doe`);
104+
});
105+
106+
["FUNCTION", "PROCEDURE", "ROUTINE"].forEach((functionKw) => {
107+
it(`supports REVOKE EXECUTE ON ${functionKw} ... FROM role`, () => {
108+
testWc(`REVOKE EXECUTE ON ${functionKw} fibo, fobo FROM john`);
109+
testWc(`REVOKE EXECUTE ON ${functionKw} fn() FROM john`);
110+
testWc(`REVOKE EXECUTE ON ${functionKw} schm.fn (INT, FLOAT) FROM john`);
111+
testWc(`REVOKE EXECUTE ON ${functionKw} fn(a INT, b INT) FROM john`);
112+
testWc(`REVOKE EXECUTE ON ${functionKw} fn(IN a INT, OUT b INT, INOUT c INT) FROM john`);
113+
});
114+
});
115+
116+
["FUNCTIONS", "PROCEDURES", "ROUTINES"].forEach((functionKw) => {
117+
it(`supports REVOKE EXECUTE ON ALL ${functionKw} IN SCHEMA ... FROM role`, () => {
118+
testWc(`REVOKE EXECUTE ON ALL ${functionKw} IN SCHEMA my_schema FROM john`);
119+
testWc(`REVOKE EXECUTE ON ALL ${functionKw} IN SCHEMA schm1, schm2 FROM john`);
120+
});
121+
});
122+
123+
it(`supports REVOKE USAGE ON LANGUAGE ... FROM role`, () => {
124+
testWc(`REVOKE USAGE ON LANGUAGE php, perl FROM script_kiddie`);
125+
});
126+
127+
["SELECT", "UPDATE"].forEach((privilege) => {
128+
it(`supports REVOKE ${privilege} ON LARGE OBJECT ... FROM role`, () => {
129+
testWc(`REVOKE ${privilege} ON LARGE OBJECT 128, 920 FROM john_doe`);
130+
});
131+
});
132+
it(`supports REVOKE ... ON LARGE OBJECT with parameter`, () => {
133+
testWc(`REVOKE UPDATE ON LARGE OBJECT :oid FROM john_doe`, {
134+
...includeAll,
135+
paramTypes: [":name"],
136+
});
137+
});
138+
139+
["SET", "ALTER SYSTEM"].forEach((privilege) => {
140+
it(`supports REVOKE ${privilege} ON PARAMETER ... FROM role`, () => {
141+
testWc(`REVOKE ${privilege} ON PARAMETER foo, bar FROM john_doe`);
142+
});
143+
});
144+
145+
["CREATE", "USAGE"].forEach((privilege) => {
146+
it(`supports REVOKE ${privilege} ON SCHEMA ... FROM role`, () => {
147+
testWc(`REVOKE ${privilege} ON SCHEMA foo, bar FROM john_doe`);
148+
});
149+
});
150+
151+
it(`supports REVOKE CREATE ON TABLESPACE ... FROM role`, () => {
152+
testWc(`REVOKE CREATE ON TABLESPACE spc1, spc2 FROM john_doe`);
153+
});
154+
155+
it(`supports REVOKE USAGE ON TYPE ... FROM role`, () => {
156+
testWc(`REVOKE USAGE ON TYPE schm.typ1, typ2 FROM john_doe`);
157+
});
158+
159+
it(`supports GRANT OPTION FOR clause`, () => {
160+
testWc(`REVOKE GRANT OPTION FOR DELETE ON tbl FROM johnny`);
161+
});
162+
163+
it(`supports GRANTED BY clause`, () => {
164+
testWc(`REVOKE DELETE ON tbl FROM johnny GRANTED BY happy_admin`);
165+
});
166+
167+
it(`supports RESTRICT/CASCADE`, () => {
168+
testWc(`REVOKE DELETE ON tbl FROM johnny RESTRICT`);
169+
testWc(`REVOKE DELETE ON tbl FROM johnny GRANTED BY foo CASCADE`);
27170
});
28171
});
29172

30-
dialect("postgresql", () => {
31-
it.skip("TODO:postgres", () => {
32-
expect(true).toBe(true);
173+
dialect(["mysql", "mariadb", "sqlite"], () => {
174+
it("does not support REVOKE", () => {
175+
expect(() => parse("REVOKE `role` ON TABLE foo FROM 'user:blah'")).toThrowError();
33176
});
34177
});
35178
});

0 commit comments

Comments
 (0)