Skip to main content

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}