vibesql_executor/
revoke.rs1use vibesql_ast::*;
4use vibesql_storage::Database;
5
6use crate::errors::ExecutorError;
7
8pub struct RevokeExecutor;
10
11impl RevokeExecutor {
12 pub fn execute_revoke(
16 stmt: &RevokeStmt,
17 database: &mut Database,
18 ) -> Result<String, ExecutorError> {
19 match stmt.object_type {
21 ObjectType::Table => {
22 if !database.catalog.table_exists(&stmt.object_name) {
23 return Err(ExecutorError::TableNotFound(stmt.object_name.clone()));
24 }
25 }
26 ObjectType::Schema => {
27 if !database.catalog.schema_exists(&stmt.object_name) {
28 return Err(ExecutorError::SchemaNotFound(stmt.object_name.clone()));
29 }
30 }
31 ObjectType::Domain
34 | ObjectType::Collation
35 | ObjectType::CharacterSet
36 | ObjectType::Translation
37 | ObjectType::Type
38 | ObjectType::Sequence => {
39 }
41 ObjectType::Function | ObjectType::SpecificFunction => {
43 }
46 ObjectType::Procedure | ObjectType::SpecificProcedure => {
48 }
51 ObjectType::Routine | ObjectType::SpecificRoutine => {
53 }
56 ObjectType::Method
59 | ObjectType::ConstructorMethod
60 | ObjectType::StaticMethod
61 | ObjectType::InstanceMethod
62 | ObjectType::SpecificMethod
63 | ObjectType::SpecificConstructorMethod
64 | ObjectType::SpecificStaticMethod
65 | ObjectType::SpecificInstanceMethod => {
66 }
69 }
70
71 for grantee in &stmt.grantees {
73 if !database.catalog.role_exists(grantee) {
74 return Err(ExecutorError::RoleNotFound(grantee.clone()));
75 }
76 }
77
78 let expanded_privileges = if stmt.privileges.contains(&PrivilegeType::AllPrivileges) {
80 match stmt.object_type {
81 ObjectType::Table => vec![
82 PrivilegeType::Select(None),
83 PrivilegeType::Insert(None),
84 PrivilegeType::Update(None),
85 PrivilegeType::Delete,
86 PrivilegeType::References(None),
87 ],
88 ObjectType::Schema => vec![PrivilegeType::Usage, PrivilegeType::Create],
89 ObjectType::Domain
92 | ObjectType::Collation
93 | ObjectType::CharacterSet
94 | ObjectType::Translation
95 | ObjectType::Type
96 | ObjectType::Sequence => vec![PrivilegeType::Usage],
97 ObjectType::Function
100 | ObjectType::Procedure
101 | ObjectType::Routine
102 | ObjectType::Method
103 | ObjectType::ConstructorMethod
104 | ObjectType::StaticMethod
105 | ObjectType::InstanceMethod
106 | ObjectType::SpecificFunction
107 | ObjectType::SpecificProcedure
108 | ObjectType::SpecificRoutine
109 | ObjectType::SpecificMethod
110 | ObjectType::SpecificConstructorMethod
111 | ObjectType::SpecificStaticMethod
112 | ObjectType::SpecificInstanceMethod => vec![PrivilegeType::Execute],
113 }
114 } else {
115 stmt.privileges.clone()
116 };
117
118 if matches!(stmt.cascade_option, CascadeOption::Restrict) {
120 for grantee in &stmt.grantees {
121 for privilege in &expanded_privileges {
122 if database.catalog.has_dependent_grants(&stmt.object_name, grantee, privilege)
123 {
124 return Err(ExecutorError::DependentPrivilegesExist(format!(
125 "Cannot revoke {:?} on {} from {} - dependent grants exist (use CASCADE to revoke dependent grants)",
126 privilege,
127 stmt.object_name,
128 grantee
129 )));
130 }
131 }
132 }
133 }
134
135 let mut total_removed = 0;
137 for grantee in &stmt.grantees {
138 for privilege in &expanded_privileges {
139 let removed = database.catalog.remove_grants(
141 &stmt.object_name,
142 grantee,
143 privilege,
144 stmt.grant_option_for,
145 );
146 total_removed += removed;
147
148 if matches!(stmt.cascade_option, CascadeOption::Cascade) {
150 Self::revoke_cascade(
151 database,
152 &stmt.object_name,
153 grantee,
154 privilege,
155 stmt.grant_option_for,
156 )?;
157 }
158 }
159 }
160
161 let grantees_str = stmt.grantees.join(", ");
162 let privileges_str =
163 stmt.privileges.iter().map(|p| format!("{:?}", p)).collect::<Vec<_>>().join(", ");
164
165 let action = if stmt.grant_option_for { "Revoked grant option for" } else { "Revoked" };
166
167 Ok(format!(
168 "{} {} on {} from {} ({} grants affected)",
169 action, privileges_str, stmt.object_name, grantees_str, total_removed
170 ))
171 }
172
173 fn revoke_cascade(
175 database: &mut Database,
176 object: &str,
177 grantor: &str,
178 privilege: &PrivilegeType,
179 grant_option_only: bool,
180 ) -> Result<(), ExecutorError> {
181 let dependent_grants: Vec<String> = database
183 .catalog
184 .get_all_grants()
185 .iter()
186 .filter(|g| g.object == object && g.grantor == grantor && g.privilege == *privilege)
187 .map(|g| g.grantee.clone())
188 .collect();
189
190 for dependent_grantee in dependent_grants {
192 database.catalog.remove_grants(
193 object,
194 &dependent_grantee,
195 privilege,
196 grant_option_only,
197 );
198
199 Self::revoke_cascade(
201 database,
202 object,
203 &dependent_grantee,
204 privilege,
205 grant_option_only,
206 )?;
207 }
208
209 Ok(())
210 }
211}