1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
use crate::{
ast::CreateRoleStmt,
common::symbol::Symbol,
lexer::TokenKind,
parser::{parser::Parser, parser_error::ParserError},
};
impl<'a> Parser<'a> {
/// Parses a `CREATE ROLE` or `CREATE USER` statement.
///
/// Syntax:
/// ```sql
/// CREATE ROLE name [IF NOT EXISTS]
/// [LOGIN | NOLOGIN]
/// [PASSWORD 'secret']
/// [SUPERUSER | NOSUPERUSER]
/// [CREATEDB | NOCREATEDB]
/// [CREATEROLE | NOCREATEROLE]
/// [INHERIT | NOINHERIT]
/// [REPLICATION | NOREPLICATION]
/// [CONNECTION LIMIT n]
/// [VALID UNTIL 'timestamp']
/// [IN ROLE role1, role2]
/// [ROLE role1, role2]
/// ```
///
/// `is_user` is true when called from `CREATE USER` — functionally
/// identical to `CREATE ROLE` but stored for round-trip accuracy.
///
/// The `ROLE` or `USER` keyword is consumed by the caller (`create.rs`).
pub fn parse_create_role(&mut self, is_user: bool) -> Result<CreateRoleStmt, ParserError> {
// Optional IF NOT EXISTS clause
let if_not_exists = self.parse_if_not_exist()?;
// Role name — required
let name = self.expect_identifier()?;
// All options default to None — only set if explicitly specified.
// This lets the executor distinguish "not specified" from "false".
let mut login = None;
let mut password = None;
let mut superuser = None;
let mut createdb = None;
let mut createrole = None;
let mut inherit = None;
let mut replication = None;
let mut connection_limit = None;
let mut valid_until = None;
let mut in_role: Vec<Symbol> = vec![];
let mut roles: Vec<Symbol> = vec![];
loop {
match self.current_token().clone() {
// LOGIN — role can log in
TokenKind::Login => {
self.advance();
login = Some(true);
}
// NOLOGIN — role cannot log in
TokenKind::NoLogin => {
self.advance();
login = Some(false);
}
// PASSWORD 'secret' — sets the login password
// = is optional, value must be a string literal
TokenKind::Password => {
self.advance();
self.consume(&TokenKind::Eq);
password = Some(self.expect_string_literal()?);
}
// SUPERUSER — grants superuser privileges
TokenKind::Superuser => {
self.advance();
superuser = Some(true);
}
// NOSUPERUSER — explicitly denies superuser
TokenKind::NoSuperuser => {
self.advance();
superuser = Some(false);
}
// CREATEDB — allows creating databases
TokenKind::CreateDb => {
self.advance();
createdb = Some(true);
}
// NOCREATEDB — disallows creating databases
TokenKind::NoCreateDb => {
self.advance();
createdb = Some(false);
}
// CREATEROLE — allows creating other roles
TokenKind::CreateRole => {
self.advance();
createrole = Some(true);
}
// NOCREATEROLE — disallows creating other roles
TokenKind::NoCreateRole => {
self.advance();
createrole = Some(false);
}
// INHERIT — role inherits privileges of roles it belongs to
TokenKind::Inherit => {
self.advance();
inherit = Some(true);
}
// NOINHERIT — role does not inherit privileges
TokenKind::NoInherit => {
self.advance();
inherit = Some(false);
}
// REPLICATION — role can initiate streaming replication
TokenKind::Replication => {
self.advance();
replication = Some(true);
}
// NOREPLICATION — role cannot initiate replication
TokenKind::NoReplication => {
self.advance();
replication = Some(false);
}
// CONNECTION LIMIT n — max concurrent connections, -1 = unlimited
TokenKind::Connection => {
self.advance();
self.expect(TokenKind::Limit)?;
self.consume(&TokenKind::Eq);
connection_limit = Some(self.expect_int()?);
}
// VALID UNTIL 'timestamp' — role expires after this time
TokenKind::Valid => {
self.advance();
self.expect(TokenKind::Until)?;
self.consume(&TokenKind::Eq);
valid_until = Some(self.expect_string_literal()?);
}
// IN ROLE role1, role2 — immediately adds role as member of listed roles
TokenKind::In => {
self.advance();
self.expect(TokenKind::Role)?;
loop {
in_role.push(self.expect_identifier()?);
if !self.consume(&TokenKind::Comma) {
break;
}
}
}
// ROLE role1, role2 — adds listed roles as members of this role
TokenKind::Role => {
self.advance();
loop {
roles.push(self.expect_identifier()?);
if !self.consume(&TokenKind::Comma) {
break;
}
}
}
// No more recognized options — stop parsing
_ => break,
}
}
Ok(CreateRoleStmt {
name,
if_not_exists,
is_user,
login,
password,
superuser,
createdb,
createrole,
inherit,
replication,
connection_limit,
valid_until,
in_role,
roles,
})
}
}