squonk_ast/ast/dcl.rs
1// SPDX-License-Identifier: MIT
2// Copyright (c) 2026 Moderately AI Inc.
3
4//! Session-configuration and access-control statement AST nodes (ADR-0012 DCL family).
5
6use super::{
7 AccountName, DataType, DropBehavior, Expr, Extension, Ident, Literal, NoExt, ObjectName,
8 TransactionMode,
9};
10use crate::vocab::Meta;
11use thin_vec::ThinVec;
12
13/// A run-time configuration / session statement: `SET`, `RESET`, or `SHOW`.
14///
15/// PostgreSQL groups these as run-time configuration statements; they write, clear,
16/// and read the same session parameters. One canonical shape per construct.
17///
18/// The generic-parameter form is `SET <name> {= | TO} <value>`; the special-cased
19/// subforms whose grammar departs from it each keep their own canonical shape
20/// rather than being forced through the generic one. `SET TRANSACTION`
21/// is transaction control, not a session statement, and lives on
22/// [`TransactionStatement`](super::TransactionStatement); the session-level
23/// [`SET SESSION CHARACTERISTICS`](Self::SetSessionCharacteristics) is its
24/// distinct session counterpart.
25#[derive(Clone, Debug, PartialEq, Eq, Hash)]
26#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
27#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
28pub enum SessionStatement<X: Extension = NoExt> {
29 /// A generic `SET <param> {= | TO} <value>` statement.
30 Set {
31 /// Scope in which this syntax applies.
32 scope: Option<SetScope>,
33 /// Name referenced by this syntax.
34 name: ObjectName,
35 /// Which of the exact-synonym `=` / `TO` separators the source wrote. A
36 /// source-fidelity render replays it; a target re-spell and the redacted
37 /// fingerprint normalize to the canonical `TO`.
38 assignment: SetAssignment,
39 /// Value supplied by this syntax.
40 value: SetValue,
41 /// Source location and node identity.
42 meta: Meta,
43 },
44 /// `SET [SESSION | LOCAL] TIME ZONE { <value> | LOCAL | DEFAULT }`.
45 ///
46 /// A two-word parameter taken with no `=`/`TO` separator; the `LOCAL`/`DEFAULT`
47 /// sentinels are kept distinct from an ordinary value (see [`SpecialSetValue`]).
48 /// The value is boxed to keep the common `SET`/`RESET`/`SHOW` shapes lean.
49 SetTimeZone {
50 /// Scope in which this syntax applies.
51 scope: Option<SetScope>,
52 /// Value supplied by this syntax.
53 value: Box<SpecialSetValue>,
54 /// Source location and node identity.
55 meta: Meta,
56 },
57 /// A `SET ROLE` statement.
58 SetRole {
59 /// Scope in which this syntax applies.
60 scope: Option<SetScope>,
61 /// The target role (`SET ROLE <role>` / `NONE`); see [`SpecialSetValue`].
62 role: Box<SpecialSetValue>,
63 /// Source location and node identity.
64 meta: Meta,
65 },
66 /// A `SET SESSION AUTHORIZATION` statement.
67 SetSessionAuthorization {
68 /// Scope in which this syntax applies.
69 scope: Option<SetScope>,
70 /// The target authorization (`SET SESSION AUTHORIZATION <user>` / `DEFAULT`); see [`SpecialSetValue`].
71 user: Box<SpecialSetValue>,
72 /// Source location and node identity.
73 meta: Meta,
74 },
75 /// `SET CONSTRAINTS { ALL | <name> [, ...] } { DEFERRED | IMMEDIATE }`.
76 ///
77 /// Sets the check timing of the current transaction's deferrable constraints;
78 /// it is its own statement in the grammar and takes no `SESSION`/`LOCAL` scope.
79 SetConstraints {
80 /// Which constraints (`ALL` or a name list); see [`ConstraintsTarget`].
81 constraints: ConstraintsTarget,
82 /// The new check timing (`DEFERRED`/`IMMEDIATE`); see [`ConstraintCheckTime`].
83 check_time: ConstraintCheckTime,
84 /// Source location and node identity.
85 meta: Meta,
86 },
87 /// `SET NAMES { <charset> [COLLATE <collation>] | DEFAULT }` (MySQL): set the
88 /// client connection character set. The value is boxed to keep the common
89 /// `SET`/`RESET`/`SHOW` shapes lean.
90 SetNames {
91 /// Value supplied by this syntax.
92 value: Box<SetNamesValue>,
93 /// Source location and node identity.
94 meta: Meta,
95 },
96 /// `SET SESSION CHARACTERISTICS AS TRANSACTION <mode> [, ...]`.
97 ///
98 /// Sets the default characteristics for subsequent transactions in the
99 /// session, distinct from the per-transaction
100 /// [`SET TRANSACTION`](super::TransactionStatement::SetCharacteristics) — which
101 /// is why it is a session statement reusing the shared [`TransactionMode`].
102 SetSessionCharacteristics {
103 /// modes in source order.
104 modes: ThinVec<TransactionMode>,
105 /// Source location and node identity.
106 meta: Meta,
107 },
108 /// `RESET [SESSION | LOCAL | GLOBAL] <name>` / `RESET ALL`.
109 ///
110 /// The optional scope is a DuckDB extension (gated by
111 /// [`UtilitySyntax::reset_scope`](crate::dialect::UtilitySyntax)); PostgreSQL's
112 /// `RESET` takes no scope qualifier (`RESET SESSION x` is a PG parser error), so
113 /// [`scope`](SessionStatement::Reset::scope) is `None` for every non-DuckDB dialect.
114 Reset {
115 /// Scope in which this syntax applies.
116 scope: Option<SetScope>,
117 /// Object targeted by this syntax.
118 target: ConfigParameter,
119 /// Source location and node identity.
120 meta: Meta,
121 },
122 /// `SHOW { ALL | <name> } [VERBOSE]`.
123 ///
124 /// The `VERBOSE` tail is the sqlparser-rs/DataFusion planner spelling on `SHOW ALL`
125 /// / `SHOW <setting>`; no shipped oracle accepts it (`pg_query` and DuckDB both
126 /// reject `SHOW ALL VERBOSE` and `SHOW <setting> VERBOSE`), so it is admitted only
127 /// under the permissive superset via
128 /// [`ShowSyntax::show_verbose`](crate::dialect::UtilitySyntax) and carried here as
129 /// data — [`verbose`](SessionStatement::Show::verbose) is `false` for every form the
130 /// oracle-backed dialects parse.
131 Show {
132 /// Object targeted by this syntax.
133 target: ConfigParameter,
134 /// Whether the verbose form was present in the source.
135 verbose: bool,
136 /// Source location and node identity.
137 meta: Meta,
138 },
139 /// The MySQL `SET` variable-assignment statement: a comma-separated list of
140 /// heterogeneous assignments, each a system variable (with optional scope) or a
141 /// user-defined `@var`.
142 ///
143 /// Distinct from the generic single-target [`Set`](Self::Set): MySQL assigns a
144 /// *list* (`SET @a = 1, GLOBAL x = 2, SESSION y = 3`), each item carrying its own
145 /// scope and a **full-expression** value — where PostgreSQL's `SET` takes one name
146 /// and a restricted literal/bareword value list. Gated by
147 /// [`SessionVariableSyntax::variable_assignment`](crate::dialect::SessionVariableSyntax).
148 SetVariables {
149 /// The assignments in source order (at least one).
150 assignments: ThinVec<SetVariableAssignment<X>>,
151 /// Source location and node identity.
152 meta: Meta,
153 },
154 /// MySQL `SET { CHARACTER SET | CHARSET } { <charset> | DEFAULT }`: set the client
155 /// connection character set (and reset the collation to that charset's default).
156 ///
157 /// A sibling of [`SetNames`](Self::SetNames) — the same client-charset surface with
158 /// a narrower value (no `COLLATE`) and its own leading keyword spelling. Gated by
159 /// [`SessionVariableSyntax::variable_assignment`](crate::dialect::SessionVariableSyntax).
160 SetCharacterSet {
161 /// Which of the exact-synonym `CHARACTER SET` / `CHARSET` spellings the source wrote.
162 keyword: CharacterSetKeyword,
163 /// Value supplied by this syntax. Boxed to keep the common `SET`/`RESET`/`SHOW`
164 /// shapes lean (mirroring [`SetNames`](Self::SetNames)).
165 value: Box<SetCharacterSetValue>,
166 /// Source location and node identity.
167 meta: Meta,
168 },
169 /// The MySQL `SET RESOURCE GROUP <name> [FOR <thread_id> [, ...]]` statement
170 /// (`sql_yacc.yy` `set_resource_group_stmt`): assign a thread (or the current session)
171 /// to a resource group.
172 ///
173 /// It shares the `SET` statement head with the variable-assignment forms above but is a
174 /// distinct grammar (`SQLCOM_SET_RESOURCE_GROUP`), not a variable assignment — so it is
175 /// dispatched off the `RESOURCE GROUP` two-word lookahead in the `SET` parser and carried
176 /// here rather than in [`SetVariables`](Self::SetVariables). It is the resource-group
177 /// family's session-statement member; its `CREATE`/`ALTER`/`DROP` siblings are top-level
178 /// [`Statement`](super::Statement) DDL. Gated by
179 /// [`StatementDdlGates::resource_group`](crate::dialect::StatementDdlGates::resource_group).
180 SetResourceGroup {
181 /// The resource-group name (`ident`).
182 name: Ident,
183 /// The `FOR <thread_id> [, ...]` thread-id list (`thread_id_list`), or `None` for the
184 /// bare form that binds the current session's thread. Non-empty when present; each id
185 /// is a `real_ulong_num` unsigned-integer literal. The `opt_comma` separator (comma or
186 /// whitespace both parse) is normalized to `, ` on render.
187 thread_ids: Option<ThinVec<Literal>>,
188 /// Source location and node identity.
189 meta: Meta,
190 },
191}
192
193/// One item of a MySQL [`SetVariables`](SessionStatement::SetVariables) list: a system
194/// variable assignment (with an optional scope on either the keyword or `@@` axis) or a
195/// user-defined `@var` assignment.
196#[derive(Clone, Debug, PartialEq, Eq, Hash)]
197#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
198#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
199pub enum SetVariableAssignment<X: Extension = NoExt> {
200 /// A system-variable assignment: `[GLOBAL|SESSION|LOCAL|PERSIST|PERSIST_ONLY] <name>`
201 /// or `@@[scope.]<name>`, then `{= | :=}` and a [`set_expr_or_default`](SetVariableValue)
202 /// value. The scope spelling (keyword prefix vs `@@` sigil) is captured in
203 /// [`scope`](Self::SystemVariable::scope); the two are mutually exclusive in the
204 /// grammar (`SET GLOBAL @@x = 1` is a syntax error).
205 SystemVariable {
206 /// The scope qualifier and its spelling; see [`SystemVariableScope`].
207 scope: SystemVariableScope,
208 /// The (optionally dotted) variable name.
209 name: ObjectName,
210 /// Which of the exact-synonym `=` / `:=` separators the source wrote.
211 assignment: SetAssignment,
212 /// The new value; see [`SetVariableValue`].
213 value: SetVariableValue<X>,
214 /// Source location and node identity.
215 meta: Meta,
216 },
217 /// A user-defined `@var := <expr>` / `@var = <expr>` assignment. The value is a full
218 /// expression (`@v = a + 1`, `@v = (SELECT ...)`); the sentinels a system variable
219 /// admits (`DEFAULT`/`ON`/…) are *not* valid here, matching the grammar's plain `expr`.
220 UserVariable {
221 /// The user-variable name (sigil stripped), with its source quote style for round-trip.
222 name: Ident,
223 /// Which of the exact-synonym `=` / `:=` separators the source wrote.
224 assignment: SetAssignment,
225 /// The assigned expression.
226 value: Box<Expr<X>>,
227 /// Source location and node identity.
228 meta: Meta,
229 },
230}
231
232/// The scope qualifier of a MySQL system-variable assignment, capturing both *which*
233/// scope and *how* it was spelled — a keyword prefix (`GLOBAL x`) or the `@@` sigil
234/// (`@@global.x`). Modelled as one enum so the mutually-exclusive keyword/`@@` spellings
235/// cannot both be present.
236#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
237#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
238#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
239pub enum SystemVariableScope {
240 /// No scope prefix — a bare `SET x = ...` (server-implicit session scope).
241 Implicit,
242 /// A keyword prefix — `SET GLOBAL x = ...` / `SESSION` / `LOCAL` / `PERSIST` /
243 /// `PERSIST_ONLY`.
244 Keyword(SystemVariableScopeKind),
245 /// The `@@` sigil with no explicit scope — `SET @@x = ...`.
246 AtAt,
247 /// The `@@` sigil with an explicit scope — `SET @@global.x = ...` / `@@session.` /
248 /// `@@local.` / `@@persist.` / `@@persist_only.`.
249 AtAtScoped(SystemVariableScopeKind),
250}
251
252/// Which system-variable scope a [`SystemVariableScope`] names.
253#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
254#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
255#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
256pub enum SystemVariableScopeKind {
257 /// `GLOBAL` — the server-wide value.
258 Global,
259 /// `SESSION` — the current session's value.
260 Session,
261 /// `LOCAL` — a `SESSION` synonym, kept distinct for round-trip fidelity.
262 Local,
263 /// `PERSIST` — set the runtime value and persist it to `mysqld-auto.cnf`.
264 Persist,
265 /// `PERSIST_ONLY` — persist without changing the runtime value.
266 PersistOnly,
267}
268
269/// The value of a MySQL system-variable assignment (the grammar's `set_expr_or_default`):
270/// a general expression, the `DEFAULT` reset sentinel, or one of the keyword sentinels the
271/// grammar special-cases into a string value.
272#[derive(Clone, Debug, PartialEq, Eq, Hash)]
273#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
274#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
275pub enum SetVariableValue<X: Extension = NoExt> {
276 /// `DEFAULT` — reset the variable to its compiled/configured default.
277 Default {
278 /// Source location and node identity.
279 meta: Meta,
280 },
281 /// A bareword keyword the SET grammar special-cases into a string value: `ON`, `ALL`,
282 /// `BINARY`, `ROW`, or `SYSTEM`. (`OFF` is not among them — it lexes as an ordinary
283 /// identifier expression.)
284 Keyword {
285 /// Which keyword sentinel; see [`SetVariableKeyword`].
286 keyword: SetVariableKeyword,
287 /// Source location and node identity.
288 meta: Meta,
289 },
290 /// A general value expression (`1`, `1 + 2`, `'utf8'`, `@x`, `(SELECT ...)`).
291 Expr {
292 /// The value expression.
293 expr: Box<Expr<X>>,
294 /// Source location and node identity.
295 meta: Meta,
296 },
297}
298
299/// A keyword the MySQL SET grammar special-cases as a string value in
300/// [`set_expr_or_default`](SetVariableValue) position.
301#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
302#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
303#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
304pub enum SetVariableKeyword {
305 /// `ON`.
306 On,
307 /// `ALL`.
308 All,
309 /// `BINARY`.
310 Binary,
311 /// `ROW`.
312 Row,
313 /// `SYSTEM`.
314 System,
315}
316
317/// Which exact-synonym spelling opened a [`SetCharacterSet`](SessionStatement::SetCharacterSet):
318/// the two-word `CHARACTER SET` or the one-word `CHARSET`.
319#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
320#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
321#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
322pub enum CharacterSetKeyword {
323 /// The two-word `CHARACTER SET` spelling.
324 CharacterSet,
325 /// The one-word `CHARSET` spelling.
326 Charset,
327}
328
329/// The operand of a MySQL [`SetCharacterSet`](SessionStatement::SetCharacterSet): a client
330/// character set (an identifier, string, or `binary`), or `DEFAULT`. Unlike
331/// [`SetNamesValue`] it carries no `COLLATE` (the grammar admits none here).
332#[derive(Clone, Debug, PartialEq, Eq, Hash)]
333#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
334#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
335pub enum SetCharacterSetValue {
336 /// `DEFAULT`: the server's configured character set.
337 Default {
338 /// Source location and node identity.
339 meta: Meta,
340 },
341 /// An explicit character set value.
342 Charset {
343 /// The client character set value.
344 charset: SetParameterValue,
345 /// Source location and node identity.
346 meta: Meta,
347 },
348}
349
350/// The scope qualifier on a `SET`/`RESET`: `SESSION` (the default), `LOCAL`, or
351/// `GLOBAL`.
352///
353/// `SESSION`/`LOCAL` are the PostgreSQL `SET` scopes; `GLOBAL` is a DuckDB `RESET`
354/// scope (`RESET GLOBAL x`), reached only through
355/// [`SessionStatement::Reset`] under
356/// [`UtilitySyntax::reset_scope`](crate::dialect::UtilitySyntax) — the PostgreSQL
357/// `SET` grammar never yields it.
358#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
359#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
360#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
361pub enum SetScope {
362 /// `SET SESSION` — apply for the whole session.
363 Session,
364 /// `SET LOCAL` — apply only until the current transaction ends.
365 Local,
366 /// `SET GLOBAL` — apply server-wide (MySQL).
367 Global,
368}
369
370/// Surface spelling of the `SET <name> {= | TO} <value>` assignment separator
371/// ([`SessionStatement::Set`]).
372///
373/// `=` and `TO` are exact synonyms in PostgreSQL's generic `SET`; the canonical AST
374/// keeps one shape and this tag records which the source wrote so a source-fidelity
375/// render replays it. A fidelity tag, not a validity one — a target re-spell and the
376/// redacted fingerprint normalize to the canonical `TO`.
377#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
378#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
379#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
380pub enum SetAssignment {
381 /// The `TO` keyword (the canonical spelling).
382 To,
383 /// The `=` operator.
384 Equals,
385 /// The `:=` operator — MySQL's `SET_VAR` assignment separator, an exact synonym of
386 /// `=` in `SET` (and in `@v := expr`). Never appears in the PostgreSQL generic `SET`,
387 /// which has no `:=`; a source-fidelity render replays it, a target re-spell and the
388 /// redacted fingerprint normalize it to `=` (MySQL has no `TO` spelling here).
389 ColonEquals,
390}
391
392#[derive(Clone, Debug, PartialEq, Eq, Hash)]
393#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
394#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
395/// The SQL set value forms represented by the AST.
396pub enum SetValue {
397 /// `SET … = DEFAULT` — reset the parameter to its default value.
398 Default {
399 /// Source location and node identity.
400 meta: Meta,
401 },
402 /// `SET … = <value>[, …]` — an explicit value list.
403 Values {
404 /// Values in source order.
405 values: ThinVec<SetParameterValue>,
406 /// Source location and node identity.
407 meta: Meta,
408 },
409}
410
411/// One value in a `SET` value list: a literal, a bareword name, or a DuckDB
412/// bracketed list of values.
413///
414/// PostgreSQL accepts numbers, strings, and barewords such as `on`/`off`/`iso`
415/// here; arbitrary expressions are not valid, so the value is this restricted
416/// literal-or-name shape rather than an [`Expr`]. A leading sign on a
417/// numeric value (PG `NumericOnly`, e.g. `-1`) is folded into the numeric
418/// [`Literal`]'s span rather than modelled as a unary operator.
419///
420/// DuckDB additionally admits a bracketed list value ([`List`](Self::List)) —
421/// `SET allowed_paths = ['a', 'b']`, `SET allowed_directories = []` — reusing the same
422/// `[…]` collection-literal syntax DuckDB accepts in expression position (gated by the
423/// same [`ExpressionSyntax::collection_literals`](crate::dialect::ExpressionSyntax), the
424/// one dialect for which `[` opens a list rather than a quoted identifier). Its elements
425/// are again this restricted value grammar (so nesting is expressible), *not* a general
426/// [`Expr`]: DuckDB's parser accepts richer element expressions but rejects
427/// them at bind, past this validator's parse-level contract.
428#[derive(Clone, Debug, PartialEq, Eq, Hash)]
429#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
430#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
431pub enum SetParameterValue {
432 /// A literal value (a number or string).
433 Literal {
434 /// The literal value; see [`Literal`].
435 literal: Literal,
436 /// Source location and node identity.
437 meta: Meta,
438 },
439 /// A bareword name value (`on`/`off`/`iso`/…).
440 Name {
441 /// Name referenced by this syntax.
442 name: Ident,
443 /// Source location and node identity.
444 meta: Meta,
445 },
446 /// A DuckDB bracketed list value (`['a', 'b']`, `[]`). Empty when the list was
447 /// `[]`; the elements are the same restricted value grammar, so a nested list is
448 /// representable.
449 List {
450 /// Values in source order.
451 values: ThinVec<SetParameterValue>,
452 /// Source location and node identity.
453 meta: Meta,
454 },
455}
456
457/// The operand of a single-valued special `SET` (`TIME ZONE`, `ROLE`, `SESSION
458/// AUTHORIZATION`): an explicit value or a reset-sentinel keyword.
459///
460/// Which sentinel is admissible is a per-form rule the parser enforces — `LOCAL`
461/// and `DEFAULT` for `TIME ZONE`, `NONE` for `ROLE`, `DEFAULT` for `SESSION
462/// AUTHORIZATION`. One shape keeps the near-identical forms uniform; a
463/// sentinel a given form never accepts simply never appears for it.
464#[derive(Clone, Debug, PartialEq, Eq, Hash)]
465#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
466#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
467pub enum SpecialSetValue {
468 /// `DEFAULT` — reset the parameter to its default value.
469 Default {
470 /// Source location and node identity.
471 meta: Meta,
472 },
473 /// `LOCAL` — the `SET TIME ZONE LOCAL` reset sentinel.
474 Local {
475 /// Source location and node identity.
476 meta: Meta,
477 },
478 /// `NONE` — the `SET ROLE NONE` reset sentinel.
479 None {
480 /// Source location and node identity.
481 meta: Meta,
482 },
483 /// An explicit value.
484 Value {
485 /// Value supplied by this syntax.
486 value: SetParameterValue,
487 /// Source location and node identity.
488 meta: Meta,
489 },
490}
491
492#[derive(Clone, Debug, PartialEq, Eq, Hash)]
493#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
494#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
495/// The SQL constraints target forms represented by the AST.
496pub enum ConstraintsTarget {
497 /// `SET CONSTRAINTS ALL …` — every deferrable constraint.
498 All {
499 /// Source location and node identity.
500 meta: Meta,
501 },
502 /// `SET CONSTRAINTS <name>, … …` — the named constraints.
503 Names {
504 /// Names in source order.
505 names: ThinVec<ObjectName>,
506 /// Source location and node identity.
507 meta: Meta,
508 },
509}
510
511#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
512#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
513#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
514/// The SQL constraint check time forms represented by the AST.
515pub enum ConstraintCheckTime {
516 /// `DEFERRED` — check the constraints at transaction commit.
517 Deferred,
518 /// `IMMEDIATE` — check the constraints at the end of each statement.
519 Immediate,
520}
521
522/// The operand of `SET NAMES` (MySQL): a client character set with an optional
523/// collation, or `DEFAULT`.
524#[derive(Clone, Debug, PartialEq, Eq, Hash)]
525#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
526#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
527pub enum SetNamesValue {
528 /// `DEFAULT`: the server's configured character set.
529 Default {
530 /// Source location and node identity.
531 meta: Meta,
532 },
533 /// `<charset> [COLLATE <collation>]`.
534 Charset {
535 /// The client character set value.
536 charset: SetParameterValue,
537 /// Optional collation for this syntax.
538 collation: Option<Ident>,
539 /// Source location and node identity.
540 meta: Meta,
541 },
542}
543
544#[derive(Clone, Debug, PartialEq, Eq, Hash)]
545#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
546#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
547/// The SQL config parameter forms represented by the AST.
548pub enum ConfigParameter {
549 /// `ALL` — every configuration parameter (`SHOW ALL` / `RESET ALL`).
550 All {
551 /// Source location and node identity.
552 meta: Meta,
553 },
554 /// A single named parameter.
555 Named {
556 /// Name referenced by this syntax.
557 name: ObjectName,
558 /// Source location and node identity.
559 meta: Meta,
560 },
561}
562
563/// A PostgreSQL `ALTER SYSTEM { SET <name> {= | TO} <value> | RESET <name> | RESET ALL }`
564/// statement (`AlterSystemStmt`), gated by
565/// [`StatementDdlGates::alter_system`](crate::dialect::StatementDdlGates::alter_system).
566///
567/// `ALTER SYSTEM` writes and clears the *server-wide* persisted configuration (PostgreSQL's
568/// `postgresql.auto.conf`), not a session parameter — but its grammar is a thin wrapper over
569/// the very `generic_set` / `generic_reset` productions the session `SET` / `RESET` use, so
570/// the setting-name / value axis is shared verbatim rather than re-minted. The `SET` form is a
571/// dotted `var_name` plus the `=` / `TO` separator ([`SetAssignment`]) and a `var_list`-or-
572/// `DEFAULT` value ([`SetValue`]); the `RESET` form is the `var_name`-or-`ALL` target
573/// ([`ConfigParameter`]).
574///
575/// Unlike the session `SET`, `ALTER SYSTEM SET` admits no `SESSION` / `LOCAL` scope (a scope
576/// keyword is a reject) and no `SET FROM CURRENT` form — the wrapper is exactly
577/// `generic_set` / `generic_reset`, measured against `pg_query`.
578#[derive(Clone, Debug, PartialEq, Eq, Hash)]
579#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
580#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
581pub struct AlterSystem {
582 /// The change applied to the server-wide configuration — a `SET` assignment or a `RESET`.
583 pub action: AlterSystemAction,
584 /// Source location and node identity.
585 pub meta: Meta,
586}
587
588/// The change an [`AlterSystem`] applies — PostgreSQL's `generic_set` / `generic_reset`.
589#[derive(Clone, Debug, PartialEq, Eq, Hash)]
590#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
591#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
592pub enum AlterSystemAction {
593 /// `SET <name> {= | TO} { <value>[, …] | DEFAULT }` — persist a new server-wide value for
594 /// the named parameter (PostgreSQL's `generic_set`). Reuses the session-`SET` value axis:
595 /// [`name`](Self::Set::name) is the dotted `var_name`, [`assignment`](Self::Set::assignment)
596 /// records the `=` / `TO` spelling, and [`value`](Self::Set::value) is the shared
597 /// [`SetValue`] (a value list or `DEFAULT`).
598 Set {
599 /// The configuration parameter name — a dotted `var_name` (`work_mem`, `myapp.foo`).
600 name: ObjectName,
601 /// Which of the exact-synonym `=` / `TO` separators the source wrote (a fidelity tag).
602 assignment: SetAssignment,
603 /// The new value — a value list or `DEFAULT`; see [`SetValue`].
604 value: SetValue,
605 /// Source location and node identity.
606 meta: Meta,
607 },
608 /// `RESET { <name> | ALL }` — clear the persisted server-wide setting(s), restoring the
609 /// compiled-in / `postgresql.conf` default (PostgreSQL's `generic_reset`). The target is
610 /// the shared [`ConfigParameter`] (`ALL` or a named parameter).
611 Reset {
612 /// The parameter(s) to reset (`ALL` or a named parameter); see [`ConfigParameter`].
613 target: ConfigParameter,
614 /// Source location and node identity.
615 meta: Meta,
616 },
617}
618
619/// An access-control (DCL) statement: `GRANT` or `REVOKE`.
620///
621/// Covers both branches of the SQL access-control grammar. A *privilege* grant
622/// names privileges on a database object ([`Grant`](Self::Grant) /
623/// [`Revoke`](Self::Revoke)); a *role-membership* grant confers membership in one
624/// role on another ([`GrantRole`](Self::GrantRole) /
625/// [`RevokeRole`](Self::RevokeRole)). The two share a leading comma list that only
626/// `ON` (privilege grant) versus a bare `TO`/`FROM` (role grant) disambiguates —
627/// exactly as PostgreSQL's grammar reuses one `privilege_list` production for both,
628/// which is why `GRANT SELECT TO alice` is a role grant whose granted "role" merely
629/// happens to be spelled like a privilege keyword.
630#[derive(Clone, Debug, PartialEq, Eq, Hash)]
631#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
632#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
633pub enum AccessControlStatement<X: Extension = NoExt> {
634 /// A `GRANT <privileges> ON <object> TO <grantees>` statement.
635 Grant {
636 /// The privileges granted/revoked; see [`Privileges`].
637 privileges: Privileges,
638 /// The object the privileges apply to; see [`GrantObject`].
639 object: GrantObject<X>,
640 /// grantees in source order.
641 grantees: ThinVec<Grantee>,
642 /// Whether the with grant option form was present in the source.
643 with_grant_option: bool,
644 /// Optional granted by for this syntax.
645 granted_by: Option<RoleSpec>,
646 /// Source location and node identity.
647 meta: Meta,
648 },
649 /// `REVOKE [GRANT OPTION FOR] <privileges> ON <object> FROM <grantees> [GRANTED BY
650 /// <grantor>] [CASCADE | RESTRICT]`.
651 ///
652 /// `behavior` carries the trailing `<drop behavior>` that governs whether
653 /// dependent grants are revoked too; `GRANT` has no such clause, so it lives only
654 /// on the two `REVOKE` variants.
655 Revoke {
656 /// Whether the grant option for form was present in the source.
657 grant_option_for: bool,
658 /// The privileges granted/revoked; see [`Privileges`].
659 privileges: Privileges,
660 /// The object the privileges apply to; see [`GrantObject`].
661 object: GrantObject<X>,
662 /// grantees in source order.
663 grantees: ThinVec<Grantee>,
664 /// Optional granted by for this syntax.
665 granted_by: Option<RoleSpec>,
666 /// Optional behavior for this syntax.
667 behavior: Option<DropBehavior>,
668 /// Source location and node identity.
669 meta: Meta,
670 },
671 /// A `GRANT <role> TO <grantees>` role-membership statement.
672 GrantRole {
673 /// roles in source order.
674 roles: ThinVec<Ident>,
675 /// grantees in source order.
676 grantees: ThinVec<Grantee>,
677 /// Whether the with admin option form was present in the source.
678 with_admin_option: bool,
679 /// Optional granted by for this syntax.
680 granted_by: Option<RoleSpec>,
681 /// Source location and node identity.
682 meta: Meta,
683 },
684 /// `REVOKE [ADMIN OPTION FOR] <roles> FROM <grantees> [GRANTED BY <grantor>]
685 /// [CASCADE | RESTRICT]`.
686 RevokeRole {
687 /// Whether the admin option for form was present in the source.
688 admin_option_for: bool,
689 /// roles in source order.
690 roles: ThinVec<Ident>,
691 /// grantees in source order.
692 grantees: ThinVec<Grantee>,
693 /// Optional granted by for this syntax.
694 granted_by: Option<RoleSpec>,
695 /// Optional behavior for this syntax.
696 behavior: Option<DropBehavior>,
697 /// Source location and node identity.
698 meta: Meta,
699 },
700 // --- MySQL account-based access control ------------------------------------------------
701 //
702 // The MySQL `GRANT`/`REVOKE` grammar, gated by
703 // [`AccessControlSyntax::access_control_account_grants`](crate::dialect::AccessControlSyntax).
704 // It forks from the standard/PostgreSQL forms above on two axes that admit no shared node —
705 // the object is a `priv_level` ([`PrivilegeLevelObject`], with `*`/`*.*`/`db.*` wildcards) rather
706 // than a typed object with a name list, and every grantee/role is an [`AccountName`]
707 // (`user@host` / `CURRENT_USER`) rather than a [`RoleSpec`]. The privilege list itself reuses
708 // the shared [`Privileges`] axis. MySQL has no `GRANTED BY`, no `CASCADE`/`RESTRICT`, and no
709 // `{GRANT | ADMIN} OPTION FOR` prefix (all engine-measured `ER_PARSE_ERROR` on 8.4.10); it
710 // adds `PROXY` grants, the `AS <user> [WITH ROLE …]` grantor context, and the
711 // `[IF EXISTS] … [IGNORE UNKNOWN USER]` `REVOKE` guards.
712 /// `GRANT <priv> ON [TABLE | FUNCTION | PROCEDURE] <priv_level> TO <user> [, …]
713 /// [WITH GRANT OPTION] [AS <user> [WITH ROLE …]]` — a MySQL object-privilege grant.
714 AccountGrantPrivilege {
715 /// The privileges granted; see [`Privileges`].
716 privileges: Privileges,
717 /// The `priv_level` object the privileges apply to; see [`PrivilegeLevelObject`].
718 object: PrivilegeLevelObject,
719 /// The grantee accounts, in source order (always non-empty).
720 grantees: ThinVec<AccountName>,
721 /// Whether the `WITH GRANT OPTION` trailer was written.
722 with_grant_option: bool,
723 /// The `AS <user> [WITH ROLE …]` grantor context; `None` when omitted. Boxed — it is a
724 /// rare, wide clause (ADR-0007), kept off the common privilege-grant path.
725 grant_as: Option<Box<GrantAs>>,
726 /// Source location and node identity.
727 meta: Meta,
728 },
729 /// `GRANT PROXY ON <user> TO <user> [, …] [WITH GRANT OPTION]` — a MySQL proxy grant.
730 AccountGrantProxy {
731 /// The proxied account (`ON <user>`).
732 proxy: AccountName,
733 /// The grantee accounts, in source order (always non-empty).
734 grantees: ThinVec<AccountName>,
735 /// Whether the `WITH GRANT OPTION` trailer was written.
736 with_grant_option: bool,
737 /// Source location and node identity.
738 meta: Meta,
739 },
740 /// `GRANT <role> [, …] TO <user> [, …] [WITH ADMIN OPTION]` — a MySQL role-membership grant.
741 AccountGrantRole {
742 /// The granted roles, in source order (always non-empty).
743 roles: ThinVec<AccountName>,
744 /// The grantee accounts, in source order (always non-empty).
745 grantees: ThinVec<AccountName>,
746 /// Whether the `WITH ADMIN OPTION` trailer was written.
747 with_admin_option: bool,
748 /// Source location and node identity.
749 meta: Meta,
750 },
751 /// `REVOKE [IF EXISTS] <priv> ON [TABLE | FUNCTION | PROCEDURE] <priv_level> FROM <user> [, …]
752 /// [IGNORE UNKNOWN USER]` — a MySQL object-privilege revoke.
753 AccountRevokePrivilege {
754 /// Whether the `IF EXISTS` guard was written.
755 if_exists: bool,
756 /// The privileges revoked; see [`Privileges`].
757 privileges: Privileges,
758 /// The `priv_level` object; see [`PrivilegeLevelObject`].
759 object: PrivilegeLevelObject,
760 /// The grantee accounts, in source order (always non-empty).
761 grantees: ThinVec<AccountName>,
762 /// Whether the `IGNORE UNKNOWN USER` trailer was written.
763 ignore_unknown_user: bool,
764 /// Source location and node identity.
765 meta: Meta,
766 },
767 /// `REVOKE [IF EXISTS] ALL [PRIVILEGES], GRANT OPTION FROM <user> [, …] [IGNORE UNKNOWN USER]`
768 /// — the MySQL "revoke everything" form, which takes no `ON` object.
769 AccountRevokeAll {
770 /// Whether the `IF EXISTS` guard was written.
771 if_exists: bool,
772 /// Whether the optional `PRIVILEGES` noise word followed `ALL` (fidelity only; the
773 /// canonical render emits `ALL PRIVILEGES, GRANT OPTION`).
774 privileges_keyword: bool,
775 /// The grantee accounts, in source order (always non-empty).
776 grantees: ThinVec<AccountName>,
777 /// Whether the `IGNORE UNKNOWN USER` trailer was written.
778 ignore_unknown_user: bool,
779 /// Source location and node identity.
780 meta: Meta,
781 },
782 /// `REVOKE [IF EXISTS] PROXY ON <user> FROM <user> [, …] [IGNORE UNKNOWN USER]` — a MySQL
783 /// proxy revoke.
784 AccountRevokeProxy {
785 /// Whether the `IF EXISTS` guard was written.
786 if_exists: bool,
787 /// The proxied account (`ON <user>`).
788 proxy: AccountName,
789 /// The grantee accounts, in source order (always non-empty).
790 grantees: ThinVec<AccountName>,
791 /// Whether the `IGNORE UNKNOWN USER` trailer was written.
792 ignore_unknown_user: bool,
793 /// Source location and node identity.
794 meta: Meta,
795 },
796 /// `REVOKE [IF EXISTS] <role> [, …] FROM <user> [, …] [IGNORE UNKNOWN USER]` — a MySQL
797 /// role-membership revoke.
798 AccountRevokeRole {
799 /// Whether the `IF EXISTS` guard was written.
800 if_exists: bool,
801 /// The revoked roles, in source order (always non-empty).
802 roles: ThinVec<AccountName>,
803 /// The grantee accounts, in source order (always non-empty).
804 grantees: ThinVec<AccountName>,
805 /// Whether the `IGNORE UNKNOWN USER` trailer was written.
806 ignore_unknown_user: bool,
807 /// Source location and node identity.
808 meta: Meta,
809 },
810}
811
812/// A MySQL grant object: an object-type keyword and a `priv_level`.
813///
814/// `GRANT … ON [TABLE | FUNCTION | PROCEDURE] <priv_level>` — the optional object-type keyword
815/// defaults to `TABLE`, and the `priv_level` is one of the four spellings in [`PrivilegeLevel`].
816#[derive(Clone, Debug, PartialEq, Eq, Hash)]
817#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
818#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
819pub struct PrivilegeLevelObject {
820 /// The `TABLE`/`FUNCTION`/`PROCEDURE` object type (`TABLE` is the default).
821 pub object_type: PrivilegeObjectType,
822 /// The privilege level (`*`, `*.*`, `db.*`, or a named object).
823 pub level: PrivilegeLevel,
824 /// Source location and node identity.
825 pub meta: Meta,
826}
827
828/// The object-type keyword of a MySQL grant object (`opt_acl_type`).
829#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
830#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
831#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
832pub enum PrivilegeObjectType {
833 /// `TABLE` — the default object type. [`explicit`](Self::Table::explicit) records whether the
834 /// redundant `TABLE` keyword was written so a source-fidelity render replays it.
835 Table {
836 /// Whether the redundant `TABLE` object-type keyword was written.
837 explicit: bool,
838 },
839 /// `FUNCTION`.
840 Function,
841 /// `PROCEDURE`.
842 Procedure,
843}
844
845/// A MySQL `priv_level` — the object a privilege grant/revoke targets.
846#[derive(Clone, Debug, PartialEq, Eq, Hash)]
847#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
848#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
849pub enum PrivilegeLevel {
850 /// `*.*` — global (every database).
851 Global {
852 /// Source location and node identity.
853 meta: Meta,
854 },
855 /// `*` — every object in the default database.
856 CurrentDatabase {
857 /// Source location and node identity.
858 meta: Meta,
859 },
860 /// `<db>.*` — every object in a named database.
861 Database {
862 /// The database name.
863 database: Ident,
864 /// Source location and node identity.
865 meta: Meta,
866 },
867 /// `<obj>` / `<db>.<obj>` — a specific named object.
868 Object {
869 /// The object name (one or two parts).
870 name: ObjectName,
871 /// Source location and node identity.
872 meta: Meta,
873 },
874}
875
876/// A MySQL `AS <user> [WITH ROLE …]` grantor-context clause on a privilege grant.
877#[derive(Clone, Debug, PartialEq, Eq, Hash)]
878#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
879#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
880pub struct GrantAs {
881 /// The grantor account (`AS <user>`).
882 pub user: AccountName,
883 /// The `WITH ROLE …` role restriction; `None` for a bare `AS <user>`.
884 pub with_role: Option<WithRoleSpec>,
885 /// Source location and node identity.
886 pub meta: Meta,
887}
888
889/// The `WITH ROLE …` restriction of a MySQL [`GrantAs`] clause.
890#[derive(Clone, Debug, PartialEq, Eq, Hash)]
891#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
892#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
893pub enum WithRoleSpec {
894 /// `WITH ROLE <role> [, …]` — an explicit role list (always non-empty).
895 Roles {
896 /// The roles, in source order.
897 roles: ThinVec<AccountName>,
898 /// Source location and node identity.
899 meta: Meta,
900 },
901 /// `WITH ROLE ALL [EXCEPT <role> [, …]]` — all roles, minus an optional exception list
902 /// (empty [`except`](Self::All::except) is a bare `WITH ROLE ALL`).
903 All {
904 /// The `EXCEPT` exception roles, in source order; empty when no `EXCEPT` was written.
905 except: ThinVec<AccountName>,
906 /// Source location and node identity.
907 meta: Meta,
908 },
909 /// `WITH ROLE NONE`.
910 None {
911 /// Source location and node identity.
912 meta: Meta,
913 },
914 /// `WITH ROLE DEFAULT`.
915 Default {
916 /// Source location and node identity.
917 meta: Meta,
918 },
919}
920
921#[derive(Clone, Debug, PartialEq, Eq, Hash)]
922#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
923#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
924/// The SQL privileges forms represented by the AST.
925pub enum Privileges {
926 /// `ALL [PRIVILEGES]`. The optional `PRIVILEGES` noise word is exact-synonym
927 /// sugar; [`privileges_keyword`](Self::All::privileges_keyword) records whether it
928 /// was written so a source-fidelity render replays it (the canonical render emits
929 /// `ALL PRIVILEGES`).
930 All {
931 /// Whether the optional `PRIVILEGES` keyword was written (`ALL PRIVILEGES` vs a
932 /// bare `ALL`). Fidelity only; the canonical render emits `PRIVILEGES`.
933 privileges_keyword: bool,
934 /// Source location and node identity.
935 meta: Meta,
936 },
937 /// An explicit privilege list (`SELECT, UPDATE (a, b), …`).
938 List {
939 /// privileges in source order.
940 privileges: ThinVec<Privilege>,
941 /// Source location and node identity.
942 meta: Meta,
943 },
944}
945
946/// One privilege in a `GRANT`/`REVOKE` list, optionally column-scoped.
947///
948/// A built-in privilege word carries a structured [`PrivilegeKind`]; any other
949/// identifier rides [`Other`](Self::Other). PostgreSQL accepts an arbitrary
950/// identifier in privilege position and only rejects an unknown name at execution,
951/// so the [`Other`](Self::Other) escape keeps parse-time acceptance aligned and
952/// captures dialect/extension privileges the built-in set does not name.
953#[derive(Clone, Debug, PartialEq, Eq, Hash)]
954#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
955#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
956pub enum Privilege {
957 /// A built-in privilege keyword, e.g. `SELECT` or `UPDATE (a, b)`.
958 Known {
959 /// Which built-in privilege; see [`PrivilegeKind`].
960 kind: PrivilegeKind,
961 /// Column-level scope (`SELECT (a, b)`); empty for a table-wide privilege.
962 columns: ThinVec<Ident>,
963 /// Source location and node identity.
964 meta: Meta,
965 },
966 /// A privilege named by an arbitrary identifier (a dialect/extension privilege).
967 Other {
968 /// Name referenced by this syntax.
969 name: Ident,
970 /// Column-level scope; empty for a table-wide privilege.
971 columns: ThinVec<Ident>,
972 /// Source location and node identity.
973 meta: Meta,
974 },
975}
976
977/// A built-in privilege keyword.
978///
979/// A closed set of the SQL-standard table privileges (SQL:2016 §12.3) and the
980/// common non-table privileges. Privileges outside this set ride
981/// [`Privilege::Other`], so the enum stays a `Copy` classifier.
982#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
983#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
984#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
985pub enum PrivilegeKind {
986 /// `SELECT` — read rows from the object.
987 Select,
988 /// `INSERT` — add rows to the object.
989 Insert,
990 /// `UPDATE` — modify rows in the object.
991 Update,
992 /// `DELETE` — remove rows from the object.
993 Delete,
994 /// `TRUNCATE` — empty the table.
995 Truncate,
996 /// `REFERENCES` — create foreign keys referencing the object.
997 References,
998 /// `TRIGGER` — create triggers on the object.
999 Trigger,
1000 /// `USAGE` — use a schema, sequence, type, or language.
1001 Usage,
1002 /// `EXECUTE` — call a function or procedure.
1003 Execute,
1004 /// `CREATE` — create objects within the database/schema.
1005 Create,
1006 /// `CONNECT` — connect to the database.
1007 Connect,
1008 /// `TEMPORARY`. The `TEMP` alias is preserved separately as [`Temp`](Self::Temp).
1009 Temporary,
1010 /// `TEMP`, the shorthand alias for `TEMPORARY`, kept distinct so it round-trips.
1011 Temp,
1012 /// `MAINTAIN` — run maintenance commands (`VACUUM`/`ANALYZE`/…, PostgreSQL 17+).
1013 Maintain,
1014 // --- MySQL static privileges ---------------------------------------------------------
1015 //
1016 // The MySQL `role_or_privilege` static-privilege keywords not already named above, each a
1017 // fixed keyword phrase the render reproduces verbatim. Recognized only by the MySQL
1018 // account-grant grammar
1019 // ([`AccessControlSyntax::access_control_account_grants`](crate::dialect::AccessControlSyntax)),
1020 // so the PostgreSQL privilege parser never yields them; MySQL dynamic privileges
1021 // (`BACKUP_ADMIN`, …) and role names ride [`Privilege::Other`] instead. `SELECT`/`INSERT`/
1022 // `UPDATE`/`DELETE`/`REFERENCES`/`USAGE`/`EXECUTE`/`CREATE`/`TRIGGER` reuse the shared
1023 // variants above.
1024 /// `INDEX`.
1025 Index,
1026 /// `ALTER`.
1027 Alter,
1028 /// `DROP`.
1029 Drop,
1030 /// `RELOAD`.
1031 Reload,
1032 /// `SHUTDOWN`.
1033 Shutdown,
1034 /// `PROCESS`.
1035 Process,
1036 /// `FILE`.
1037 File,
1038 /// `SUPER` (deprecated in MySQL, still grammar-valid).
1039 Super,
1040 /// `EVENT`.
1041 Event,
1042 /// `GRANT OPTION` — spelled as a privilege in a `REVOKE`/`GRANT` list (distinct from the
1043 /// `WITH GRANT OPTION` trailer).
1044 GrantOption,
1045 /// `SHOW DATABASES`.
1046 ShowDatabases,
1047 /// `CREATE TEMPORARY TABLES`.
1048 CreateTemporaryTables,
1049 /// `LOCK TABLES`.
1050 LockTables,
1051 /// `REPLICATION SLAVE`.
1052 ReplicationSlave,
1053 /// `REPLICATION CLIENT`.
1054 ReplicationClient,
1055 /// `CREATE VIEW`.
1056 CreateView,
1057 /// `SHOW VIEW`.
1058 ShowView,
1059 /// `CREATE ROUTINE`.
1060 CreateRoutine,
1061 /// `ALTER ROUTINE`.
1062 AlterRoutine,
1063 /// `CREATE USER`.
1064 CreateUser,
1065 /// `CREATE TABLESPACE`.
1066 CreateTablespace,
1067 /// `CREATE ROLE`.
1068 CreateRole,
1069 /// `DROP ROLE`.
1070 DropRole,
1071}
1072
1073/// The object a privilege applies to.
1074///
1075/// `TABLE` is the default object type, so [`Table`](Self::Table) records whether the
1076/// redundant keyword was written; every other object type names its keyword
1077/// explicitly.
1078#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1079#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1080#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1081pub enum GrantObject<X: Extension = NoExt> {
1082 /// A table (or the default object type when the `TABLE` keyword is omitted).
1083 Table {
1084 /// Whether the redundant `TABLE` object-type keyword was written.
1085 explicit: bool,
1086 /// Names in source order.
1087 names: ThinVec<ObjectName>,
1088 /// Source location and node identity.
1089 meta: Meta,
1090 },
1091 /// An object type whose target is a plain name list (`SEQUENCE <name> [, ...]`,
1092 /// `DATABASE …`, `SCHEMA …`, `DOMAIN …`, `TYPE …`, `LANGUAGE …`, `TABLESPACE …`,
1093 /// `FOREIGN DATA WRAPPER …`, `FOREIGN SERVER …`).
1094 Named {
1095 /// Which named object type; see [`NamedObjectKind`].
1096 kind: NamedObjectKind,
1097 /// Names in source order.
1098 names: ThinVec<ObjectName>,
1099 /// Source location and node identity.
1100 meta: Meta,
1101 },
1102 /// Routine targets (`FUNCTION`/`PROCEDURE`/`ROUTINE <name>(<sig>)`).
1103 Routines {
1104 /// Which routine kind; see [`RoutineObjectKind`].
1105 kind: RoutineObjectKind,
1106 /// routines in source order.
1107 routines: ThinVec<RoutineSignature<X>>,
1108 /// Source location and node identity.
1109 meta: Meta,
1110 },
1111 /// `ALL {TABLES | SEQUENCES | FUNCTIONS | PROCEDURES | ROUTINES} IN SCHEMA <name> [, ...]`.
1112 AllInSchema {
1113 /// Which object class is granted schema-wide; see [`SchemaObjectKind`].
1114 kind: SchemaObjectKind,
1115 /// schemas in source order.
1116 schemas: ThinVec<ObjectName>,
1117 /// Source location and node identity.
1118 meta: Meta,
1119 },
1120}
1121
1122#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1123#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1124#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1125/// The SQL named object kind forms represented by the AST.
1126pub enum NamedObjectKind {
1127 /// `SEQUENCE` object.
1128 Sequence,
1129 /// `DATABASE` object.
1130 Database,
1131 /// `SCHEMA` object.
1132 Schema,
1133 /// `DOMAIN` object.
1134 Domain,
1135 /// `TYPE` object.
1136 Type,
1137 /// `LANGUAGE` object.
1138 Language,
1139 /// `TABLESPACE` object.
1140 Tablespace,
1141 /// `FOREIGN DATA WRAPPER` object.
1142 ForeignDataWrapper,
1143 /// `FOREIGN SERVER` object.
1144 ForeignServer,
1145}
1146
1147#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1148#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1149#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1150/// The SQL routine object kind forms represented by the AST.
1151pub enum RoutineObjectKind {
1152 /// `FUNCTION`.
1153 Function,
1154 /// `PROCEDURE`.
1155 Procedure,
1156 /// `ROUTINE` — a function or procedure.
1157 Routine,
1158}
1159
1160#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1161#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1162#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1163/// The SQL schema object kind forms represented by the AST.
1164pub enum SchemaObjectKind {
1165 /// `ALL TABLES IN SCHEMA`.
1166 Tables,
1167 /// `ALL SEQUENCES IN SCHEMA`.
1168 Sequences,
1169 /// `ALL FUNCTIONS IN SCHEMA`.
1170 Functions,
1171 /// `ALL PROCEDURES IN SCHEMA`.
1172 Procedures,
1173 /// `ALL ROUTINES IN SCHEMA`.
1174 Routines,
1175}
1176
1177/// A routine reference in a `FUNCTION`/`PROCEDURE`/`ROUTINE` grant: a name with an
1178/// optional argument-type signature.
1179///
1180/// `arg_types` is `None` when no parenthesized list was written (`FUNCTION foo`) and
1181/// `Some` — possibly empty — when it was (`FUNCTION foo()` / `FUNCTION foo(int, text)`),
1182/// preserving the distinction. Argument names and modes (`IN`/`OUT`/`VARIADIC`) are
1183/// out of scope; only the type list is modelled.
1184#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1185#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1186#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1187pub struct RoutineSignature<X: Extension = NoExt> {
1188 /// Name referenced by this syntax.
1189 pub name: ObjectName,
1190 /// Optional arg types for this syntax.
1191 pub arg_types: Option<ThinVec<DataType<X>>>,
1192 /// Source location and node identity.
1193 pub meta: Meta,
1194}
1195
1196/// A `GRANT`/`REVOKE` grantee: a role specification, optionally with the legacy
1197/// `GROUP` keyword prefix (`GROUP <role>`).
1198#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1199#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1200#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1201pub struct Grantee {
1202 /// Whether the PostgreSQL-legacy `GROUP` keyword preceded the role.
1203 pub group: bool,
1204 /// The role specification; see [`RoleSpec`].
1205 pub spec: RoleSpec,
1206 /// Source location and node identity.
1207 pub meta: Meta,
1208}
1209
1210/// A role specification: a named role, `PUBLIC`, or a session-role pseudo-role.
1211///
1212/// Shared by grantees and the `GRANTED BY` grantor.
1213#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1214#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1215#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1216pub enum RoleSpec {
1217 /// `PUBLIC` — the implicit role every role belongs to.
1218 Public {
1219 /// Source location and node identity.
1220 meta: Meta,
1221 },
1222 /// `CURRENT_ROLE` — the current role.
1223 CurrentRole {
1224 /// Source location and node identity.
1225 meta: Meta,
1226 },
1227 /// `CURRENT_USER` — the current user.
1228 CurrentUser {
1229 /// Source location and node identity.
1230 meta: Meta,
1231 },
1232 /// `SESSION_USER` — the session user.
1233 SessionUser {
1234 /// Source location and node identity.
1235 meta: Meta,
1236 },
1237 /// A named role.
1238 Name {
1239 /// Name referenced by this syntax.
1240 name: Ident,
1241 /// Source location and node identity.
1242 meta: Meta,
1243 },
1244}
1245
1246// --- User / role administration DDL (MySQL) --------------------------------------------
1247//
1248// `CREATE`/`ALTER`/`DROP USER` and `CREATE`/`DROP ROLE` — the MySQL account-management
1249// family, gated by
1250// [`AccessControlSyntax::user_role_management`](crate::dialect::AccessControlSyntax). Every
1251// account reference rides the shared [`AccountName`] axis; the authentication, TLS, resource,
1252// and password/lock option lists below are shared by `CREATE USER` and `ALTER USER`.
1253
1254/// `CREATE USER [IF NOT EXISTS] <user> [<auth>] [, …] [DEFAULT ROLE <role> [, …]]
1255/// [REQUIRE <tls>] [WITH <resource> …] [<password/lock option> …]
1256/// [COMMENT | ATTRIBUTE '<string>']` — the MySQL account-creation statement.
1257///
1258/// The `<user> [<auth>]` elements are a comma list of [`UserSpec`]s. The trailing clauses are
1259/// each written at most once (MySQL's grammar has them as single optional tails, not a
1260/// repeatable option bag), except the resource-limit and password/lock lists, which are
1261/// whitespace-separated repeatable runs.
1262#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1263#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1264#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1265pub struct CreateUser {
1266 /// Whether the `IF NOT EXISTS` guard was written.
1267 pub if_not_exists: bool,
1268 /// The `<user> [<auth>]` account list, in source order (always non-empty).
1269 pub users: ThinVec<UserSpec>,
1270 /// The `DEFAULT ROLE <role> [, …]` roles, in source order; empty when the clause was not
1271 /// written (MySQL rejects an empty `DEFAULT ROLE`, so empty is unambiguously "absent").
1272 pub default_roles: ThinVec<AccountName>,
1273 /// The `REQUIRE …` TLS requirement; `None` when the clause was omitted.
1274 pub require: Option<TlsRequirement>,
1275 /// The `WITH <resource> …` resource limits, in source order; empty when no `WITH` was
1276 /// written.
1277 pub resource_options: ThinVec<ResourceLimit>,
1278 /// The password / account-lock options, in source order; empty when none were written.
1279 pub password_lock_options: ThinVec<PasswordLockOption>,
1280 /// The `COMMENT '…'` / `ATTRIBUTE '…'` account attribute; `None` when neither was written
1281 /// (the two are mutually exclusive in the grammar).
1282 pub attribute: Option<UserAttribute>,
1283 /// Source location and node identity.
1284 pub meta: Meta,
1285}
1286
1287/// One `<user> [<auth>]` element of a [`CreateUser`] list: an account name and its optional
1288/// primary-factor authentication.
1289///
1290/// The multi-factor `AND IDENTIFIED …` tail, the `INITIAL AUTHENTICATION` clause, and the
1291/// `ALTER USER` factor-registration surface are a separate MySQL multi-factor-authentication
1292/// family, deferred from this measured single-factor axis; this spec extends additively when
1293/// that family lands.
1294#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1295#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1296#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1297pub struct UserSpec {
1298 /// The account being created.
1299 pub account: AccountName,
1300 /// The primary-factor authentication (`IDENTIFIED BY …` / `IDENTIFIED WITH …`); `None`
1301 /// for a bare account with no authentication clause.
1302 pub auth: Option<AuthOption>,
1303 /// Source location and node identity.
1304 pub meta: Meta,
1305}
1306
1307/// A primary-factor authentication clause: `IDENTIFIED BY …` / `IDENTIFIED WITH <plugin> …`.
1308///
1309/// The password and auth-string bodies are [`Literal`]s so the exact source spelling
1310/// round-trips from the span (and redacts to `?` under the redacted render). The plugin name
1311/// is a MySQL `ident_or_text`, folded to an [`Ident`] whose quote style round-trips.
1312#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1313#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1314#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1315pub enum AuthOption {
1316 /// `IDENTIFIED BY '<password>'`.
1317 Password {
1318 /// The cleartext password literal.
1319 password: Literal,
1320 /// Source location and node identity.
1321 meta: Meta,
1322 },
1323 /// `IDENTIFIED BY RANDOM PASSWORD` — the server generates and returns a random password.
1324 RandomPassword {
1325 /// Source location and node identity.
1326 meta: Meta,
1327 },
1328 /// `IDENTIFIED WITH <plugin>`.
1329 Plugin {
1330 /// The authentication-plugin name.
1331 plugin: Ident,
1332 /// Source location and node identity.
1333 meta: Meta,
1334 },
1335 /// `IDENTIFIED WITH <plugin> AS '<auth string>'` — a pre-hashed authentication string.
1336 PluginAs {
1337 /// The authentication-plugin name.
1338 plugin: Ident,
1339 /// The plugin-specific authentication (hash) string literal.
1340 auth_string: Literal,
1341 /// Source location and node identity.
1342 meta: Meta,
1343 },
1344 /// `IDENTIFIED WITH <plugin> BY '<password>'`.
1345 PluginByPassword {
1346 /// The authentication-plugin name.
1347 plugin: Ident,
1348 /// The cleartext password literal.
1349 password: Literal,
1350 /// Source location and node identity.
1351 meta: Meta,
1352 },
1353 /// `IDENTIFIED WITH <plugin> BY RANDOM PASSWORD`.
1354 PluginByRandomPassword {
1355 /// The authentication-plugin name.
1356 plugin: Ident,
1357 /// Source location and node identity.
1358 meta: Meta,
1359 },
1360}
1361
1362/// `ALTER USER [IF EXISTS] …` — the MySQL account-modification statement.
1363///
1364/// Two shapes share the `[IF EXISTS]` guard: the [`Modify`](AlterUser::Modify) list form
1365/// (re-authenticate / re-configure a comma list of accounts) and the
1366/// [`DefaultRole`](AlterUser::DefaultRole) single-account `DEFAULT ROLE` reset. The
1367/// multi-factor factor-registration forms (`ADD`/`MODIFY`/`DROP FACTOR`, `… REGISTRATION`)
1368/// are a deferred multi-factor-authentication family (see [`UserSpec`]).
1369#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1370#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1371#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1372pub enum AlterUser {
1373 /// `ALTER USER [IF EXISTS] <user> [<auth>] [REPLACE '…'] [RETAIN CURRENT PASSWORD |
1374 /// DISCARD OLD PASSWORD] [, …] [REQUIRE …] [WITH …] [<password/lock option> …]
1375 /// [COMMENT | ATTRIBUTE '…']`.
1376 Modify {
1377 /// Whether the `IF EXISTS` guard was written.
1378 if_exists: bool,
1379 /// The per-account modifications, in source order (always non-empty).
1380 users: ThinVec<AlterUserSpec>,
1381 /// The `REQUIRE …` TLS requirement; `None` when omitted.
1382 require: Option<TlsRequirement>,
1383 /// The `WITH <resource> …` resource limits, in source order; empty when no `WITH`.
1384 resource_options: ThinVec<ResourceLimit>,
1385 /// The password / account-lock options, in source order; empty when none.
1386 password_lock_options: ThinVec<PasswordLockOption>,
1387 /// The `COMMENT '…'` / `ATTRIBUTE '…'` account attribute; `None` when neither.
1388 attribute: Option<UserAttribute>,
1389 /// Source location and node identity.
1390 meta: Meta,
1391 },
1392 /// `ALTER USER [IF EXISTS] <user> DEFAULT ROLE {ALL | NONE | <role> [, …]}`.
1393 DefaultRole {
1394 /// Whether the `IF EXISTS` guard was written.
1395 if_exists: bool,
1396 /// The account whose default roles are reset.
1397 user: AccountName,
1398 /// The default-role target — `ALL`, `NONE`, or an explicit role list.
1399 roles: DefaultRoleTarget,
1400 /// Source location and node identity.
1401 meta: Meta,
1402 },
1403}
1404
1405/// One per-account element of an [`AlterUser::Modify`] list: an account, its optional new
1406/// authentication, and the password-rotation flags that attach to it.
1407#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1408#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1409#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1410pub struct AlterUserSpec {
1411 /// The account being altered.
1412 pub account: AccountName,
1413 /// The new primary-factor authentication; `None` for a bare account (e.g. a lone
1414 /// `DISCARD OLD PASSWORD` or a re-configuration with no re-authentication).
1415 pub auth: Option<AuthOption>,
1416 /// The `REPLACE '<current password>'` verification string; `None` when not written.
1417 pub replace: Option<Literal>,
1418 /// Whether `RETAIN CURRENT PASSWORD` was written (keep the old password as a secondary).
1419 pub retain_current_password: bool,
1420 /// Whether `DISCARD OLD PASSWORD` was written (drop the retained secondary password).
1421 pub discard_old_password: bool,
1422 /// Source location and node identity.
1423 pub meta: Meta,
1424}
1425
1426/// The target of an `ALTER USER … DEFAULT ROLE` clause.
1427#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1428#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1429#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1430pub enum DefaultRoleTarget {
1431 /// `DEFAULT ROLE ALL` — every granted role becomes a default.
1432 All {
1433 /// Source location and node identity.
1434 meta: Meta,
1435 },
1436 /// `DEFAULT ROLE NONE` — clear the default roles.
1437 None {
1438 /// Source location and node identity.
1439 meta: Meta,
1440 },
1441 /// `DEFAULT ROLE <role> [, …]` — an explicit default-role list (always non-empty).
1442 Roles {
1443 /// The default roles, in source order.
1444 roles: ThinVec<AccountName>,
1445 /// Source location and node identity.
1446 meta: Meta,
1447 },
1448}
1449
1450/// A MySQL account/role-name-list DDL statement whose whole grammar is `<verb> [<if-guard>]
1451/// <name> [, …]`: `DROP USER`, `CREATE ROLE`, or `DROP ROLE`.
1452///
1453/// The three share one spine — a verb, an existence guard, and a comma list of
1454/// [`AccountName`]s — so they ride one node with the verb carried as data ([`kind`](Self::kind)),
1455/// the same "sub-command identity as data" precedent the SHOW / table-maintenance families use.
1456/// The richer `CREATE USER` / `ALTER USER` statements keep their own nodes.
1457#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1458#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1459#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1460pub struct UserRoleList {
1461 /// Which verb this is; also fixes the [`if_guard`](Self::if_guard) spelling
1462 /// (`IF EXISTS` for the drops, `IF NOT EXISTS` for `CREATE ROLE`).
1463 pub kind: UserRoleListKind,
1464 /// Whether the existence guard was written (`IF EXISTS` / `IF NOT EXISTS` per `kind`).
1465 pub if_guard: bool,
1466 /// The account/role names, in source order (always non-empty).
1467 pub names: ThinVec<AccountName>,
1468 /// Source location and node identity.
1469 pub meta: Meta,
1470}
1471
1472/// Which account/role-list verb a [`UserRoleList`] carries.
1473#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1474#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1475#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1476pub enum UserRoleListKind {
1477 /// `DROP USER [IF EXISTS] <user> [, …]`.
1478 DropUser,
1479 /// `CREATE ROLE [IF NOT EXISTS] <role> [, …]`.
1480 CreateRole,
1481 /// `DROP ROLE [IF EXISTS] <role> [, …]`.
1482 DropRole,
1483}
1484
1485/// A `REQUIRE …` TLS requirement on a `CREATE`/`ALTER USER`.
1486#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1487#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1488#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1489pub enum TlsRequirement {
1490 /// `REQUIRE NONE` — no TLS required.
1491 None {
1492 /// Source location and node identity.
1493 meta: Meta,
1494 },
1495 /// `REQUIRE SSL` — any TLS connection.
1496 Ssl {
1497 /// Source location and node identity.
1498 meta: Meta,
1499 },
1500 /// `REQUIRE X509` — a valid client certificate.
1501 X509 {
1502 /// Source location and node identity.
1503 meta: Meta,
1504 },
1505 /// `REQUIRE <option> [AND <option> …]` — one or more certificate-attribute requirements
1506 /// (`SUBJECT`/`ISSUER`/`CIPHER`), always non-empty.
1507 Options {
1508 /// The certificate-attribute requirements, in source order.
1509 options: ThinVec<TlsOption>,
1510 /// Source location and node identity.
1511 meta: Meta,
1512 },
1513}
1514
1515/// One certificate-attribute requirement inside a [`TlsRequirement::Options`] list.
1516#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1517#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1518#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1519pub enum TlsOption {
1520 /// `SUBJECT '<subject>'`.
1521 Subject {
1522 /// The required certificate subject string literal.
1523 value: Literal,
1524 /// Source location and node identity.
1525 meta: Meta,
1526 },
1527 /// `ISSUER '<issuer>'`.
1528 Issuer {
1529 /// The required certificate issuer string literal.
1530 value: Literal,
1531 /// Source location and node identity.
1532 meta: Meta,
1533 },
1534 /// `CIPHER '<cipher>'`.
1535 Cipher {
1536 /// The required cipher string literal.
1537 value: Literal,
1538 /// Source location and node identity.
1539 meta: Meta,
1540 },
1541}
1542
1543/// One `WITH <resource>`-list resource limit on a `CREATE`/`ALTER USER`. Each value is an
1544/// unsigned-integer [`Literal`].
1545#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1546#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1547#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1548pub enum ResourceLimit {
1549 /// `MAX_QUERIES_PER_HOUR <n>`.
1550 MaxQueriesPerHour {
1551 /// The limit value.
1552 value: Literal,
1553 /// Source location and node identity.
1554 meta: Meta,
1555 },
1556 /// `MAX_UPDATES_PER_HOUR <n>`.
1557 MaxUpdatesPerHour {
1558 /// The limit value.
1559 value: Literal,
1560 /// Source location and node identity.
1561 meta: Meta,
1562 },
1563 /// `MAX_CONNECTIONS_PER_HOUR <n>`.
1564 MaxConnectionsPerHour {
1565 /// The limit value.
1566 value: Literal,
1567 /// Source location and node identity.
1568 meta: Meta,
1569 },
1570 /// `MAX_USER_CONNECTIONS <n>`.
1571 MaxUserConnections {
1572 /// The limit value.
1573 value: Literal,
1574 /// Source location and node identity.
1575 meta: Meta,
1576 },
1577}
1578
1579/// One password-management / account-lock option on a `CREATE`/`ALTER USER`. Numeric bodies
1580/// are unsigned-integer [`Literal`]s.
1581#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1582#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1583#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1584pub enum PasswordLockOption {
1585 /// `ACCOUNT LOCK`.
1586 AccountLock {
1587 /// Source location and node identity.
1588 meta: Meta,
1589 },
1590 /// `ACCOUNT UNLOCK`.
1591 AccountUnlock {
1592 /// Source location and node identity.
1593 meta: Meta,
1594 },
1595 /// `PASSWORD EXPIRE` — expire the password immediately.
1596 PasswordExpire {
1597 /// Source location and node identity.
1598 meta: Meta,
1599 },
1600 /// `PASSWORD EXPIRE DEFAULT` — use the global `default_password_lifetime`.
1601 PasswordExpireDefault {
1602 /// Source location and node identity.
1603 meta: Meta,
1604 },
1605 /// `PASSWORD EXPIRE NEVER`.
1606 PasswordExpireNever {
1607 /// Source location and node identity.
1608 meta: Meta,
1609 },
1610 /// `PASSWORD EXPIRE INTERVAL <n> DAY`.
1611 PasswordExpireInterval {
1612 /// The interval, in days.
1613 days: Literal,
1614 /// Source location and node identity.
1615 meta: Meta,
1616 },
1617 /// `PASSWORD HISTORY <n>` — remember the last `n` passwords.
1618 PasswordHistory {
1619 /// The number of remembered passwords.
1620 count: Literal,
1621 /// Source location and node identity.
1622 meta: Meta,
1623 },
1624 /// `PASSWORD HISTORY DEFAULT`.
1625 PasswordHistoryDefault {
1626 /// Source location and node identity.
1627 meta: Meta,
1628 },
1629 /// `PASSWORD REUSE INTERVAL <n> DAY`.
1630 PasswordReuseInterval {
1631 /// The reuse-blocking interval, in days.
1632 days: Literal,
1633 /// Source location and node identity.
1634 meta: Meta,
1635 },
1636 /// `PASSWORD REUSE INTERVAL DEFAULT`.
1637 PasswordReuseIntervalDefault {
1638 /// Source location and node identity.
1639 meta: Meta,
1640 },
1641 /// `PASSWORD REQUIRE CURRENT` — a password change must verify the current password.
1642 PasswordRequireCurrent {
1643 /// Source location and node identity.
1644 meta: Meta,
1645 },
1646 /// `PASSWORD REQUIRE CURRENT DEFAULT`.
1647 PasswordRequireCurrentDefault {
1648 /// Source location and node identity.
1649 meta: Meta,
1650 },
1651 /// `PASSWORD REQUIRE CURRENT OPTIONAL`.
1652 PasswordRequireCurrentOptional {
1653 /// Source location and node identity.
1654 meta: Meta,
1655 },
1656 /// `FAILED_LOGIN_ATTEMPTS <n>`.
1657 FailedLoginAttempts {
1658 /// The failed-login threshold.
1659 count: Literal,
1660 /// Source location and node identity.
1661 meta: Meta,
1662 },
1663 /// `PASSWORD_LOCK_TIME <n>` — lock duration in days after `FAILED_LOGIN_ATTEMPTS`.
1664 PasswordLockTime {
1665 /// The lock duration, in days.
1666 days: Literal,
1667 /// Source location and node identity.
1668 meta: Meta,
1669 },
1670 /// `PASSWORD_LOCK_TIME UNBOUNDED` — lock until manually unlocked.
1671 PasswordLockTimeUnbounded {
1672 /// Source location and node identity.
1673 meta: Meta,
1674 },
1675}
1676
1677/// A `CREATE`/`ALTER USER` account attribute: `COMMENT '…'` or `ATTRIBUTE '<json>'`
1678/// (mutually exclusive in the grammar).
1679#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1680#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1681#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1682pub enum UserAttribute {
1683 /// `COMMENT '<text>'`.
1684 Comment {
1685 /// The comment string literal.
1686 comment: Literal,
1687 /// Source location and node identity.
1688 meta: Meta,
1689 },
1690 /// `ATTRIBUTE '<json>'` — a JSON object of user attributes.
1691 Attribute {
1692 /// The JSON attribute string literal.
1693 attribute: Literal,
1694 /// Source location and node identity.
1695 meta: Meta,
1696 },
1697}