1use crate::{
13 Identifier, SString, Span, Spanned,
14 create_option::CreateOption,
15 keywords::Keyword,
16 lexer::Token,
17 parser::{ParseError, Parser},
18};
19use alloc::vec::Vec;
20
21#[derive(Clone, Debug)]
23pub enum RoleOption<'a> {
24 SuperUser(Span),
25 NoSuperUser(Span),
26 CreateDb(Span),
27 NoCreateDb(Span),
28 CreateRole(Span),
29 NoCreateRole(Span),
30 Inherit(Span),
31 NoInherit(Span),
32 Login(Span),
33 NoLogin(Span),
34 Replication(Span),
35 NoReplication(Span),
36 BypassRls(Span),
37 NoBypassRls(Span),
38 ConnectionLimit {
40 connection_span: Span,
41 limit_span: Span,
42 value: i64,
43 value_span: Span,
44 },
45 EncryptedPassword {
47 encrypted_span: Span,
48 password_span: Span,
49 password: SString<'a>,
50 },
51 Password {
53 password_span: Span,
54 password: SString<'a>,
55 },
56 PasswordNull(Span),
58 ValidUntil {
60 valid_span: Span,
61 until_span: Span,
62 timestamp: SString<'a>,
63 },
64 Sysid {
66 sysid_span: Span,
67 value: i64,
68 value_span: Span,
69 },
70}
71
72impl<'a> Spanned for RoleOption<'a> {
73 fn span(&self) -> Span {
74 match self {
75 RoleOption::SuperUser(s) => s.span(),
76 RoleOption::NoSuperUser(s) => s.span(),
77 RoleOption::CreateDb(s) => s.span(),
78 RoleOption::NoCreateDb(s) => s.span(),
79 RoleOption::CreateRole(s) => s.span(),
80 RoleOption::NoCreateRole(s) => s.span(),
81 RoleOption::Inherit(s) => s.span(),
82 RoleOption::NoInherit(s) => s.span(),
83 RoleOption::Login(s) => s.span(),
84 RoleOption::NoLogin(s) => s.span(),
85 RoleOption::Replication(s) => s.span(),
86 RoleOption::NoReplication(s) => s.span(),
87 RoleOption::BypassRls(s) => s.span(),
88 RoleOption::NoBypassRls(s) => s.span(),
89 RoleOption::ConnectionLimit {
90 connection_span,
91 value_span,
92 ..
93 } => connection_span.join_span(value_span),
94 RoleOption::EncryptedPassword {
95 encrypted_span,
96 password,
97 ..
98 } => encrypted_span.join_span(password),
99 RoleOption::Password {
100 password_span,
101 password,
102 } => password_span.join_span(password),
103 RoleOption::PasswordNull(s) => s.span(),
104 RoleOption::ValidUntil {
105 valid_span,
106 timestamp,
107 ..
108 } => valid_span.join_span(timestamp),
109 RoleOption::Sysid {
110 sysid_span,
111 value_span,
112 ..
113 } => sysid_span.join_span(value_span),
114 }
115 }
116}
117
118pub(crate) fn parse_role_option<'a>(
120 parser: &mut Parser<'a, '_>,
121) -> Result<Option<RoleOption<'a>>, ParseError> {
122 Ok(match &parser.token {
123 Token::Ident(_, Keyword::SUPERUSER) => {
124 let span = parser.consume_keyword(Keyword::SUPERUSER)?;
125 Some(RoleOption::SuperUser(span))
126 }
127 Token::Ident(_, Keyword::NOSUPERUSER) => {
128 let span = parser.consume_keyword(Keyword::NOSUPERUSER)?;
129 Some(RoleOption::NoSuperUser(span))
130 }
131 Token::Ident(_, Keyword::CREATEDB) => {
132 let span = parser.consume_keyword(Keyword::CREATEDB)?;
133 Some(RoleOption::CreateDb(span))
134 }
135 Token::Ident(_, Keyword::NOCREATEDB) => {
136 let span = parser.consume_keyword(Keyword::NOCREATEDB)?;
137 Some(RoleOption::NoCreateDb(span))
138 }
139 Token::Ident(_, Keyword::CREATEROLE) => {
140 let span = parser.consume_keyword(Keyword::CREATEROLE)?;
141 Some(RoleOption::CreateRole(span))
142 }
143 Token::Ident(_, Keyword::NOCREATEROLE) => {
144 let span = parser.consume_keyword(Keyword::NOCREATEROLE)?;
145 Some(RoleOption::NoCreateRole(span))
146 }
147 Token::Ident(_, Keyword::INHERIT) => {
148 let span = parser.consume_keyword(Keyword::INHERIT)?;
149 Some(RoleOption::Inherit(span))
150 }
151 Token::Ident(_, Keyword::NOINHERIT) => {
152 let span = parser.consume_keyword(Keyword::NOINHERIT)?;
153 Some(RoleOption::NoInherit(span))
154 }
155 Token::Ident(_, Keyword::LOGIN) => {
156 let span = parser.consume_keyword(Keyword::LOGIN)?;
157 Some(RoleOption::Login(span))
158 }
159 Token::Ident(_, Keyword::NOLOGIN) => {
160 let span = parser.consume_keyword(Keyword::NOLOGIN)?;
161 Some(RoleOption::NoLogin(span))
162 }
163 Token::Ident(_, Keyword::REPLICATION) => {
164 let span = parser.consume_keyword(Keyword::REPLICATION)?;
165 Some(RoleOption::Replication(span))
166 }
167 Token::Ident(_, Keyword::NOREPLICATION) => {
168 let span = parser.consume_keyword(Keyword::NOREPLICATION)?;
169 Some(RoleOption::NoReplication(span))
170 }
171 Token::Ident(_, Keyword::BYPASSRLS) => {
172 let span = parser.consume_keyword(Keyword::BYPASSRLS)?;
173 Some(RoleOption::BypassRls(span))
174 }
175 Token::Ident(_, Keyword::NOBYPASSRLS) => {
176 let span = parser.consume_keyword(Keyword::NOBYPASSRLS)?;
177 Some(RoleOption::NoBypassRls(span))
178 }
179 Token::Ident(_, Keyword::CONNECTION) => {
180 let connection_span = parser.consume_keyword(Keyword::CONNECTION)?;
181 let limit_span = parser.consume_keyword(Keyword::LIMIT)?;
182 let (value, value_span) = parser.consume_signed_int::<i64>()?;
183 Some(RoleOption::ConnectionLimit {
184 connection_span,
185 limit_span,
186 value,
187 value_span,
188 })
189 }
190 Token::Ident(_, Keyword::ENCRYPTED) => {
191 let encrypted_span = parser.consume_keyword(Keyword::ENCRYPTED)?;
192 let password_span = parser.consume_keyword(Keyword::PASSWORD)?;
193 let password = parser.consume_string()?;
194 Some(RoleOption::EncryptedPassword {
195 encrypted_span,
196 password_span,
197 password,
198 })
199 }
200 Token::Ident(_, Keyword::PASSWORD) => {
201 let password_span = parser.consume_keyword(Keyword::PASSWORD)?;
202 if parser.skip_keyword(Keyword::NULL).is_some() {
203 Some(RoleOption::PasswordNull(password_span))
204 } else {
205 let password = parser.consume_string()?;
206 Some(RoleOption::Password {
207 password_span,
208 password,
209 })
210 }
211 }
212 Token::Ident(_, Keyword::VALID) => {
213 let valid_span = parser.consume_keyword(Keyword::VALID)?;
214 let until_span = parser.consume_keyword(Keyword::UNTIL)?;
215 let timestamp = parser.consume_string()?;
216 Some(RoleOption::ValidUntil {
217 valid_span,
218 until_span,
219 timestamp,
220 })
221 }
222 Token::Ident(_, Keyword::SYSID) => {
223 let sysid_span = parser.consume_keyword(Keyword::SYSID)?;
224 let (value, value_span) = parser.consume_signed_int::<i64>()?;
225 Some(RoleOption::Sysid {
226 sysid_span,
227 value,
228 value_span,
229 })
230 }
231 _ => None,
232 })
233}
234
235#[derive(Clone, Debug)]
237pub enum RoleMembershipType {
238 User(Span),
239 Role(Span),
240 Admin(Span),
241 InRole(Span),
242}
243
244impl Spanned for RoleMembershipType {
245 fn span(&self) -> Span {
246 match self {
247 RoleMembershipType::User(s) => s.span(),
248 RoleMembershipType::Role(s) => s.span(),
249 RoleMembershipType::Admin(s) => s.span(),
250 RoleMembershipType::InRole(s) => s.span(),
251 }
252 }
253}
254
255#[derive(Clone, Debug)]
257pub struct RoleMembership<'a> {
258 pub type_: RoleMembershipType,
259 pub roles: Vec<Identifier<'a>>,
260}
261
262impl<'a> Spanned for RoleMembership<'a> {
263 fn span(&self) -> Span {
264 self.type_.join_span(&self.roles)
265 }
266}
267
268#[derive(Clone, Debug)]
270pub struct CreateRole<'a> {
271 pub create_span: Span,
273 pub role_span: Span,
275 pub if_not_exists: Option<Span>,
277 pub role_names: Vec<Identifier<'a>>,
279 pub with_span: Option<Span>,
281 pub options: Vec<RoleOption<'a>>,
283 pub memberships: Vec<RoleMembership<'a>>,
285}
286
287impl<'a> Spanned for CreateRole<'a> {
288 fn span(&self) -> Span {
289 self.create_span
290 .join_span(&self.role_span)
291 .join_span(&self.if_not_exists)
292 .join_span(&self.role_names)
293 .join_span(&self.with_span)
294 .join_span(&self.options)
295 .join_span(&self.memberships)
296 }
297}
298
299pub(crate) fn parse_create_role<'a>(
300 parser: &mut Parser<'a, '_>,
301 create_span: Span,
302 create_options: Vec<CreateOption<'a>>,
303) -> Result<CreateRole<'a>, ParseError> {
304 let role_span = parser.consume_keyword(Keyword::ROLE)?;
305 parser.postgres_only(&role_span);
306
307 for option in create_options {
308 parser.err("Not supported for CREATE ROLE", &option.span());
309 }
310
311 let if_not_exists = if let Some(if_span) = parser.skip_keyword(Keyword::IF) {
312 Some(
313 parser
314 .consume_keywords(&[Keyword::NOT, Keyword::EXISTS])?
315 .join_span(&if_span),
316 )
317 } else {
318 None
319 };
320
321 let mut role_names = Vec::new();
323 loop {
324 role_names.push(parser.consume_plain_identifier_unreserved()?);
325 if parser.skip_token(Token::Comma).is_none() {
326 break;
327 }
328 }
329
330 let with_span = parser.skip_keyword(Keyword::WITH);
332
333 let mut options = Vec::new();
335 let mut memberships = Vec::new();
336
337 loop {
338 match &parser.token {
339 Token::Ident(_, Keyword::USER) => {
340 let user_span = parser.consume_keyword(Keyword::USER)?;
341 let mut roles = Vec::new();
342 loop {
343 roles.push(parser.consume_plain_identifier_unreserved()?);
344 if parser.skip_token(Token::Comma).is_none() {
345 break;
346 }
347 }
348 memberships.push(RoleMembership {
349 type_: RoleMembershipType::User(user_span),
350 roles,
351 });
352 }
353 Token::Ident(_, Keyword::ROLE) => {
354 let role_span = parser.consume_keyword(Keyword::ROLE)?;
355 let mut roles = Vec::new();
356 loop {
357 roles.push(parser.consume_plain_identifier_unreserved()?);
358 if parser.skip_token(Token::Comma).is_none() {
359 break;
360 }
361 }
362 memberships.push(RoleMembership {
363 type_: RoleMembershipType::Role(role_span),
364 roles,
365 });
366 }
367 Token::Ident(_, Keyword::ADMIN) => {
368 let admin_span = parser.consume_keyword(Keyword::ADMIN)?;
369 let mut roles = Vec::new();
370 loop {
371 roles.push(parser.consume_plain_identifier_unreserved()?);
372 if parser.skip_token(Token::Comma).is_none() {
373 break;
374 }
375 }
376 memberships.push(RoleMembership {
377 type_: RoleMembershipType::Admin(admin_span),
378 roles,
379 });
380 }
381 Token::Ident(_, Keyword::IN) => {
382 let in_role_span = parser.consume_keywords(&[Keyword::IN, Keyword::ROLE])?;
383 let mut roles = Vec::new();
384 loop {
385 roles.push(parser.consume_plain_identifier_unreserved()?);
386 if parser.skip_token(Token::Comma).is_none() {
387 break;
388 }
389 }
390 memberships.push(RoleMembership {
391 type_: RoleMembershipType::InRole(in_role_span),
392 roles,
393 });
394 }
395 _ => {
396 if let Some(opt) = parse_role_option(parser)? {
398 options.push(opt);
399 continue;
400 } else {
401 break;
403 }
404 }
405 }
406 }
407
408 Ok(CreateRole {
409 create_span,
410 role_span,
411 if_not_exists,
412 role_names,
413 with_span,
414 options,
415 memberships,
416 })
417}