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    ParameterKind, 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, a parameter, or a
412/// DuckDB 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/// PostgreSQL also admits a positional parameter such as `$1` as a `var_value`.
420///
421/// DuckDB additionally admits a bracketed list value ([`List`](Self::List)) —
422/// `SET allowed_paths = ['a', 'b']`, `SET allowed_directories = []` — reusing the same
423/// `[…]` collection-literal syntax DuckDB accepts in expression position (gated by the
424/// same [`ExpressionSyntax::collection_literals`](crate::dialect::ExpressionSyntax), the
425/// one dialect for which `[` opens a list rather than a quoted identifier). Its elements
426/// are again this restricted value grammar (so nesting is expressible), *not* a general
427/// [`Expr`]: DuckDB's parser accepts richer element expressions but rejects
428/// them at bind, past this validator's parse-level contract.
429#[derive(Clone, Debug, PartialEq, Eq, Hash)]
430#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
431#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
432pub enum SetParameterValue {
433    /// A literal value (a number or string).
434    Literal {
435        /// The literal value; see [`Literal`].
436        literal: Literal,
437        /// Source location and node identity.
438        meta: Meta,
439    },
440    /// A bareword name value (`on`/`off`/`iso`/…).
441    Name {
442        /// Name referenced by this syntax.
443        name: Ident,
444        /// Source location and node identity.
445        meta: Meta,
446    },
447    /// A prepared-statement parameter accepted by the active dialect's parameter
448    /// syntax, such as PostgreSQL's positional `$1`.
449    Parameter {
450        /// Placeholder identity and spelling.
451        kind: ParameterKind,
452        /// Source location and node identity.
453        meta: Meta,
454    },
455    /// A DuckDB bracketed list value (`['a', 'b']`, `[]`). Empty when the list was
456    /// `[]`; the elements are the same restricted value grammar, so a nested list is
457    /// representable.
458    List {
459        /// Values in source order.
460        values: ThinVec<SetParameterValue>,
461        /// Source location and node identity.
462        meta: Meta,
463    },
464}
465
466/// The operand of a single-valued special `SET` (`TIME ZONE`, `ROLE`, `SESSION
467/// AUTHORIZATION`): an explicit value or a reset-sentinel keyword.
468///
469/// Which sentinel is admissible is a per-form rule the parser enforces — `LOCAL`
470/// and `DEFAULT` for `TIME ZONE`, `NONE` for `ROLE`, `DEFAULT` for `SESSION
471/// AUTHORIZATION`. One shape keeps the near-identical forms uniform; a
472/// sentinel a given form never accepts simply never appears for it.
473#[derive(Clone, Debug, PartialEq, Eq, Hash)]
474#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
475#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
476pub enum SpecialSetValue {
477    /// `DEFAULT` — reset the parameter to its default value.
478    Default {
479        /// Source location and node identity.
480        meta: Meta,
481    },
482    /// `LOCAL` — the `SET TIME ZONE LOCAL` reset sentinel.
483    Local {
484        /// Source location and node identity.
485        meta: Meta,
486    },
487    /// `NONE` — the `SET ROLE NONE` reset sentinel.
488    None {
489        /// Source location and node identity.
490        meta: Meta,
491    },
492    /// An explicit value.
493    Value {
494        /// Value supplied by this syntax.
495        value: SetParameterValue,
496        /// Source location and node identity.
497        meta: Meta,
498    },
499}
500
501#[derive(Clone, Debug, PartialEq, Eq, Hash)]
502#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
503#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
504/// The SQL constraints target forms represented by the AST.
505pub enum ConstraintsTarget {
506    /// `SET CONSTRAINTS ALL …` — every deferrable constraint.
507    All {
508        /// Source location and node identity.
509        meta: Meta,
510    },
511    /// `SET CONSTRAINTS <name>, … …` — the named constraints.
512    Names {
513        /// Names in source order.
514        names: ThinVec<ObjectName>,
515        /// Source location and node identity.
516        meta: Meta,
517    },
518}
519
520#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
521#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
522#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
523/// The SQL constraint check time forms represented by the AST.
524pub enum ConstraintCheckTime {
525    /// `DEFERRED` — check the constraints at transaction commit.
526    Deferred,
527    /// `IMMEDIATE` — check the constraints at the end of each statement.
528    Immediate,
529}
530
531/// The operand of `SET NAMES` (MySQL): a client character set with an optional
532/// collation, or `DEFAULT`.
533#[derive(Clone, Debug, PartialEq, Eq, Hash)]
534#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
535#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
536pub enum SetNamesValue {
537    /// `DEFAULT`: the server's configured character set.
538    Default {
539        /// Source location and node identity.
540        meta: Meta,
541    },
542    /// `<charset> [COLLATE <collation>]`.
543    Charset {
544        /// The client character set value.
545        charset: SetParameterValue,
546        /// Optional collation for this syntax.
547        collation: Option<Ident>,
548        /// Source location and node identity.
549        meta: Meta,
550    },
551}
552
553#[derive(Clone, Debug, PartialEq, Eq, Hash)]
554#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
555#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
556/// The SQL config parameter forms represented by the AST.
557pub enum ConfigParameter {
558    /// `ALL` — every configuration parameter (`SHOW ALL` / `RESET ALL`).
559    All {
560        /// Source location and node identity.
561        meta: Meta,
562    },
563    /// A single named parameter.
564    Named {
565        /// Name referenced by this syntax.
566        name: ObjectName,
567        /// Source location and node identity.
568        meta: Meta,
569    },
570}
571
572/// A PostgreSQL `ALTER SYSTEM { SET <name> {= | TO} <value> | RESET <name> | RESET ALL }`
573/// statement (`AlterSystemStmt`), gated by
574/// [`StatementDdlGates::alter_system`](crate::dialect::StatementDdlGates::alter_system).
575///
576/// `ALTER SYSTEM` writes and clears the *server-wide* persisted configuration (PostgreSQL's
577/// `postgresql.auto.conf`), not a session parameter — but its grammar is a thin wrapper over
578/// the very `generic_set` / `generic_reset` productions the session `SET` / `RESET` use, so
579/// the setting-name / value axis is shared verbatim rather than re-minted. The `SET` form is a
580/// dotted `var_name` plus the `=` / `TO` separator ([`SetAssignment`]) and a `var_list`-or-
581/// `DEFAULT` value ([`SetValue`]); the `RESET` form is the `var_name`-or-`ALL` target
582/// ([`ConfigParameter`]).
583///
584/// Unlike the session `SET`, `ALTER SYSTEM SET` admits no `SESSION` / `LOCAL` scope (a scope
585/// keyword is a reject) and no `SET FROM CURRENT` form — the wrapper is exactly
586/// `generic_set` / `generic_reset`, measured against `pg_query`.
587#[derive(Clone, Debug, PartialEq, Eq, Hash)]
588#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
589#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
590pub struct AlterSystem {
591    /// The change applied to the server-wide configuration — a `SET` assignment or a `RESET`.
592    pub action: AlterSystemAction,
593    /// Source location and node identity.
594    pub meta: Meta,
595}
596
597/// The change an [`AlterSystem`] applies — PostgreSQL's `generic_set` / `generic_reset`.
598#[derive(Clone, Debug, PartialEq, Eq, Hash)]
599#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
600#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
601pub enum AlterSystemAction {
602    /// `SET <name> {= | TO} { <value>[, …] | DEFAULT }` — persist a new server-wide value for
603    /// the named parameter (PostgreSQL's `generic_set`). Reuses the session-`SET` value axis:
604    /// [`name`](Self::Set::name) is the dotted `var_name`, [`assignment`](Self::Set::assignment)
605    /// records the `=` / `TO` spelling, and [`value`](Self::Set::value) is the shared
606    /// [`SetValue`] (a value list or `DEFAULT`).
607    Set {
608        /// The configuration parameter name — a dotted `var_name` (`work_mem`, `myapp.foo`).
609        name: ObjectName,
610        /// Which of the exact-synonym `=` / `TO` separators the source wrote (a fidelity tag).
611        assignment: SetAssignment,
612        /// The new value — a value list or `DEFAULT`; see [`SetValue`].
613        value: SetValue,
614        /// Source location and node identity.
615        meta: Meta,
616    },
617    /// `RESET { <name> | ALL }` — clear the persisted server-wide setting(s), restoring the
618    /// compiled-in / `postgresql.conf` default (PostgreSQL's `generic_reset`). The target is
619    /// the shared [`ConfigParameter`] (`ALL` or a named parameter).
620    Reset {
621        /// The parameter(s) to reset (`ALL` or a named parameter); see [`ConfigParameter`].
622        target: ConfigParameter,
623        /// Source location and node identity.
624        meta: Meta,
625    },
626}
627
628/// An access-control (DCL) statement: `GRANT` or `REVOKE`.
629///
630/// Covers both branches of the SQL access-control grammar. A *privilege* grant
631/// names privileges on a database object ([`Grant`](Self::Grant) /
632/// [`Revoke`](Self::Revoke)); a *role-membership* grant confers membership in one
633/// role on another ([`GrantRole`](Self::GrantRole) /
634/// [`RevokeRole`](Self::RevokeRole)). The two share a leading comma list that only
635/// `ON` (privilege grant) versus a bare `TO`/`FROM` (role grant) disambiguates —
636/// exactly as PostgreSQL's grammar reuses one `privilege_list` production for both,
637/// which is why `GRANT SELECT TO alice` is a role grant whose granted "role" merely
638/// happens to be spelled like a privilege keyword.
639#[derive(Clone, Debug, PartialEq, Eq, Hash)]
640#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
641#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
642pub enum AccessControlStatement<X: Extension = NoExt> {
643    /// `ALTER ROLE <name> RENAME TO <new_name>`.
644    AlterRoleRename {
645        /// Existing role name.
646        name: Ident,
647        /// New role name.
648        new_name: Ident,
649        /// Source location and node identity.
650        meta: Meta,
651    },
652    /// A `GRANT <privileges> ON <object> TO <grantees>` statement.
653    Grant {
654        /// The privileges granted/revoked; see [`Privileges`].
655        privileges: Privileges,
656        /// The object the privileges apply to; see [`GrantObject`].
657        object: GrantObject<X>,
658        /// grantees in source order.
659        grantees: ThinVec<Grantee>,
660        /// Whether the with grant option form was present in the source.
661        with_grant_option: bool,
662        /// Optional granted by for this syntax.
663        granted_by: Option<RoleSpec>,
664        /// Source location and node identity.
665        meta: Meta,
666    },
667    /// `REVOKE [GRANT OPTION FOR] <privileges> ON <object> FROM <grantees> [GRANTED BY
668    /// <grantor>] [CASCADE | RESTRICT]`.
669    ///
670    /// `behavior` carries the trailing `<drop behavior>` that governs whether
671    /// dependent grants are revoked too; `GRANT` has no such clause, so it lives only
672    /// on the two `REVOKE` variants.
673    Revoke {
674        /// Whether the grant option for form was present in the source.
675        grant_option_for: bool,
676        /// The privileges granted/revoked; see [`Privileges`].
677        privileges: Privileges,
678        /// The object the privileges apply to; see [`GrantObject`].
679        object: GrantObject<X>,
680        /// grantees in source order.
681        grantees: ThinVec<Grantee>,
682        /// Optional granted by for this syntax.
683        granted_by: Option<RoleSpec>,
684        /// Optional behavior for this syntax.
685        behavior: Option<DropBehavior>,
686        /// Source location and node identity.
687        meta: Meta,
688    },
689    /// A `GRANT <role> TO <grantees>` role-membership statement.
690    GrantRole {
691        /// roles in source order.
692        roles: ThinVec<Ident>,
693        /// grantees in source order.
694        grantees: ThinVec<Grantee>,
695        /// Whether the with admin option form was present in the source.
696        with_admin_option: bool,
697        /// Optional granted by for this syntax.
698        granted_by: Option<RoleSpec>,
699        /// Source location and node identity.
700        meta: Meta,
701    },
702    /// `REVOKE [ADMIN OPTION FOR] <roles> FROM <grantees> [GRANTED BY <grantor>]
703    /// [CASCADE | RESTRICT]`.
704    RevokeRole {
705        /// Whether the admin option for form was present in the source.
706        admin_option_for: bool,
707        /// roles in source order.
708        roles: ThinVec<Ident>,
709        /// grantees in source order.
710        grantees: ThinVec<Grantee>,
711        /// Optional granted by for this syntax.
712        granted_by: Option<RoleSpec>,
713        /// Optional behavior for this syntax.
714        behavior: Option<DropBehavior>,
715        /// Source location and node identity.
716        meta: Meta,
717    },
718    // --- MySQL account-based access control ------------------------------------------------
719    //
720    // The MySQL `GRANT`/`REVOKE` grammar, gated by
721    // [`AccessControlSyntax::access_control_account_grants`](crate::dialect::AccessControlSyntax).
722    // It forks from the standard/PostgreSQL forms above on two axes that admit no shared node —
723    // the object is a `priv_level` ([`PrivilegeLevelObject`], with `*`/`*.*`/`db.*` wildcards) rather
724    // than a typed object with a name list, and every grantee/role is an [`AccountName`]
725    // (`user@host` / `CURRENT_USER`) rather than a [`RoleSpec`]. The privilege list itself reuses
726    // the shared [`Privileges`] axis. MySQL has no `GRANTED BY`, no `CASCADE`/`RESTRICT`, and no
727    // `{GRANT | ADMIN} OPTION FOR` prefix (all engine-measured `ER_PARSE_ERROR` on 8.4.10); it
728    // adds `PROXY` grants, the `AS <user> [WITH ROLE …]` grantor context, and the
729    // `[IF EXISTS] … [IGNORE UNKNOWN USER]` `REVOKE` guards.
730    /// `GRANT <priv> ON [TABLE | FUNCTION | PROCEDURE] <priv_level> TO <user> [, …]
731    /// [WITH GRANT OPTION] [AS <user> [WITH ROLE …]]` — a MySQL object-privilege grant.
732    AccountGrantPrivilege {
733        /// The privileges granted; see [`Privileges`].
734        privileges: Privileges,
735        /// The `priv_level` object the privileges apply to; see [`PrivilegeLevelObject`].
736        object: PrivilegeLevelObject,
737        /// The grantee accounts, in source order (always non-empty).
738        grantees: ThinVec<AccountName>,
739        /// Whether the `WITH GRANT OPTION` trailer was written.
740        with_grant_option: bool,
741        /// The `AS <user> [WITH ROLE …]` grantor context; `None` when omitted. Boxed — it is a
742        /// rare, wide clause (ADR-0007), kept off the common privilege-grant path.
743        grant_as: Option<Box<GrantAs>>,
744        /// Source location and node identity.
745        meta: Meta,
746    },
747    /// `GRANT PROXY ON <user> TO <user> [, …] [WITH GRANT OPTION]` — a MySQL proxy grant.
748    AccountGrantProxy {
749        /// The proxied account (`ON <user>`).
750        proxy: AccountName,
751        /// The grantee accounts, in source order (always non-empty).
752        grantees: ThinVec<AccountName>,
753        /// Whether the `WITH GRANT OPTION` trailer was written.
754        with_grant_option: bool,
755        /// Source location and node identity.
756        meta: Meta,
757    },
758    /// `GRANT <role> [, …] TO <user> [, …] [WITH ADMIN OPTION]` — a MySQL role-membership grant.
759    AccountGrantRole {
760        /// The granted roles, in source order (always non-empty).
761        roles: ThinVec<AccountName>,
762        /// The grantee accounts, in source order (always non-empty).
763        grantees: ThinVec<AccountName>,
764        /// Whether the `WITH ADMIN OPTION` trailer was written.
765        with_admin_option: bool,
766        /// Source location and node identity.
767        meta: Meta,
768    },
769    /// `REVOKE [IF EXISTS] <priv> ON [TABLE | FUNCTION | PROCEDURE] <priv_level> FROM <user> [, …]
770    /// [IGNORE UNKNOWN USER]` — a MySQL object-privilege revoke.
771    AccountRevokePrivilege {
772        /// Whether the `IF EXISTS` guard was written.
773        if_exists: bool,
774        /// The privileges revoked; see [`Privileges`].
775        privileges: Privileges,
776        /// The `priv_level` object; see [`PrivilegeLevelObject`].
777        object: PrivilegeLevelObject,
778        /// The grantee accounts, in source order (always non-empty).
779        grantees: ThinVec<AccountName>,
780        /// Whether the `IGNORE UNKNOWN USER` trailer was written.
781        ignore_unknown_user: bool,
782        /// Source location and node identity.
783        meta: Meta,
784    },
785    /// `REVOKE [IF EXISTS] ALL [PRIVILEGES], GRANT OPTION FROM <user> [, …] [IGNORE UNKNOWN USER]`
786    /// — the MySQL "revoke everything" form, which takes no `ON` object.
787    AccountRevokeAll {
788        /// Whether the `IF EXISTS` guard was written.
789        if_exists: bool,
790        /// Whether the optional `PRIVILEGES` noise word followed `ALL` (fidelity only; the
791        /// canonical render emits `ALL PRIVILEGES, GRANT OPTION`).
792        privileges_keyword: bool,
793        /// The grantee accounts, in source order (always non-empty).
794        grantees: ThinVec<AccountName>,
795        /// Whether the `IGNORE UNKNOWN USER` trailer was written.
796        ignore_unknown_user: bool,
797        /// Source location and node identity.
798        meta: Meta,
799    },
800    /// `REVOKE [IF EXISTS] PROXY ON <user> FROM <user> [, …] [IGNORE UNKNOWN USER]` — a MySQL
801    /// proxy revoke.
802    AccountRevokeProxy {
803        /// Whether the `IF EXISTS` guard was written.
804        if_exists: bool,
805        /// The proxied account (`ON <user>`).
806        proxy: AccountName,
807        /// The grantee accounts, in source order (always non-empty).
808        grantees: ThinVec<AccountName>,
809        /// Whether the `IGNORE UNKNOWN USER` trailer was written.
810        ignore_unknown_user: bool,
811        /// Source location and node identity.
812        meta: Meta,
813    },
814    /// `REVOKE [IF EXISTS] <role> [, …] FROM <user> [, …] [IGNORE UNKNOWN USER]` — a MySQL
815    /// role-membership revoke.
816    AccountRevokeRole {
817        /// Whether the `IF EXISTS` guard was written.
818        if_exists: bool,
819        /// The revoked roles, in source order (always non-empty).
820        roles: ThinVec<AccountName>,
821        /// The grantee accounts, in source order (always non-empty).
822        grantees: ThinVec<AccountName>,
823        /// Whether the `IGNORE UNKNOWN USER` trailer was written.
824        ignore_unknown_user: bool,
825        /// Source location and node identity.
826        meta: Meta,
827    },
828}
829
830/// A MySQL grant object: an object-type keyword and a `priv_level`.
831///
832/// `GRANT … ON [TABLE | FUNCTION | PROCEDURE] <priv_level>` — the optional object-type keyword
833/// defaults to `TABLE`, and the `priv_level` is one of the four spellings in [`PrivilegeLevel`].
834#[derive(Clone, Debug, PartialEq, Eq, Hash)]
835#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
836#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
837pub struct PrivilegeLevelObject {
838    /// The `TABLE`/`FUNCTION`/`PROCEDURE` object type (`TABLE` is the default).
839    pub object_type: PrivilegeObjectType,
840    /// The privilege level (`*`, `*.*`, `db.*`, or a named object).
841    pub level: PrivilegeLevel,
842    /// Source location and node identity.
843    pub meta: Meta,
844}
845
846/// The object-type keyword of a MySQL grant object (`opt_acl_type`).
847#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
848#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
849#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
850pub enum PrivilegeObjectType {
851    /// `TABLE` — the default object type. [`explicit`](Self::Table::explicit) records whether the
852    /// redundant `TABLE` keyword was written so a source-fidelity render replays it.
853    Table {
854        /// Whether the redundant `TABLE` object-type keyword was written.
855        explicit: bool,
856    },
857    /// `FUNCTION`.
858    Function,
859    /// `PROCEDURE`.
860    Procedure,
861}
862
863/// A MySQL `priv_level` — the object a privilege grant/revoke targets.
864#[derive(Clone, Debug, PartialEq, Eq, Hash)]
865#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
866#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
867pub enum PrivilegeLevel {
868    /// `*.*` — global (every database).
869    Global {
870        /// Source location and node identity.
871        meta: Meta,
872    },
873    /// `*` — every object in the default database.
874    CurrentDatabase {
875        /// Source location and node identity.
876        meta: Meta,
877    },
878    /// `<db>.*` — every object in a named database.
879    Database {
880        /// The database name.
881        database: Ident,
882        /// Source location and node identity.
883        meta: Meta,
884    },
885    /// `<obj>` / `<db>.<obj>` — a specific named object.
886    Object {
887        /// The object name (one or two parts).
888        name: ObjectName,
889        /// Source location and node identity.
890        meta: Meta,
891    },
892}
893
894/// A MySQL `AS <user> [WITH ROLE …]` grantor-context clause on a privilege grant.
895#[derive(Clone, Debug, PartialEq, Eq, Hash)]
896#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
897#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
898pub struct GrantAs {
899    /// The grantor account (`AS <user>`).
900    pub user: AccountName,
901    /// The `WITH ROLE …` role restriction; `None` for a bare `AS <user>`.
902    pub with_role: Option<WithRoleSpec>,
903    /// Source location and node identity.
904    pub meta: Meta,
905}
906
907/// The `WITH ROLE …` restriction of a MySQL [`GrantAs`] clause.
908#[derive(Clone, Debug, PartialEq, Eq, Hash)]
909#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
910#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
911pub enum WithRoleSpec {
912    /// `WITH ROLE <role> [, …]` — an explicit role list (always non-empty).
913    Roles {
914        /// The roles, in source order.
915        roles: ThinVec<AccountName>,
916        /// Source location and node identity.
917        meta: Meta,
918    },
919    /// `WITH ROLE ALL [EXCEPT <role> [, …]]` — all roles, minus an optional exception list
920    /// (empty [`except`](Self::All::except) is a bare `WITH ROLE ALL`).
921    All {
922        /// The `EXCEPT` exception roles, in source order; empty when no `EXCEPT` was written.
923        except: ThinVec<AccountName>,
924        /// Source location and node identity.
925        meta: Meta,
926    },
927    /// `WITH ROLE NONE`.
928    None {
929        /// Source location and node identity.
930        meta: Meta,
931    },
932    /// `WITH ROLE DEFAULT`.
933    Default {
934        /// Source location and node identity.
935        meta: Meta,
936    },
937}
938
939#[derive(Clone, Debug, PartialEq, Eq, Hash)]
940#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
941#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
942/// The SQL privileges forms represented by the AST.
943pub enum Privileges {
944    /// `ALL [PRIVILEGES]`. The optional `PRIVILEGES` noise word is exact-synonym
945    /// sugar; [`privileges_keyword`](Self::All::privileges_keyword) records whether it
946    /// was written so a source-fidelity render replays it (the canonical render emits
947    /// `ALL PRIVILEGES`).
948    All {
949        /// Whether the optional `PRIVILEGES` keyword was written (`ALL PRIVILEGES` vs a
950        /// bare `ALL`). Fidelity only; the canonical render emits `PRIVILEGES`.
951        privileges_keyword: bool,
952        /// Source location and node identity.
953        meta: Meta,
954    },
955    /// An explicit privilege list (`SELECT, UPDATE (a, b), …`).
956    List {
957        /// privileges in source order.
958        privileges: ThinVec<Privilege>,
959        /// Source location and node identity.
960        meta: Meta,
961    },
962}
963
964/// One privilege in a `GRANT`/`REVOKE` list, optionally column-scoped.
965///
966/// A built-in privilege word carries a structured [`PrivilegeKind`]; any other
967/// identifier rides [`Other`](Self::Other). PostgreSQL accepts an arbitrary
968/// identifier in privilege position and only rejects an unknown name at execution,
969/// so the [`Other`](Self::Other) escape keeps parse-time acceptance aligned and
970/// captures dialect/extension privileges the built-in set does not name.
971#[derive(Clone, Debug, PartialEq, Eq, Hash)]
972#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
973#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
974pub enum Privilege {
975    /// A built-in privilege keyword, e.g. `SELECT` or `UPDATE (a, b)`.
976    Known {
977        /// Which built-in privilege; see [`PrivilegeKind`].
978        kind: PrivilegeKind,
979        /// Column-level scope (`SELECT (a, b)`); empty for a table-wide privilege.
980        columns: ThinVec<Ident>,
981        /// Source location and node identity.
982        meta: Meta,
983    },
984    /// A privilege named by an arbitrary identifier (a dialect/extension privilege).
985    Other {
986        /// Name referenced by this syntax.
987        name: Ident,
988        /// Column-level scope; empty for a table-wide privilege.
989        columns: ThinVec<Ident>,
990        /// Source location and node identity.
991        meta: Meta,
992    },
993}
994
995/// A built-in privilege keyword.
996///
997/// A closed set of the SQL-standard table privileges (SQL:2016 §12.3) and the
998/// common non-table privileges. Privileges outside this set ride
999/// [`Privilege::Other`], so the enum stays a `Copy` classifier.
1000#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1001#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1002#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1003pub enum PrivilegeKind {
1004    /// `SELECT` — read rows from the object.
1005    Select,
1006    /// `INSERT` — add rows to the object.
1007    Insert,
1008    /// `UPDATE` — modify rows in the object.
1009    Update,
1010    /// `DELETE` — remove rows from the object.
1011    Delete,
1012    /// `TRUNCATE` — empty the table.
1013    Truncate,
1014    /// `REFERENCES` — create foreign keys referencing the object.
1015    References,
1016    /// `TRIGGER` — create triggers on the object.
1017    Trigger,
1018    /// `USAGE` — use a schema, sequence, type, or language.
1019    Usage,
1020    /// `EXECUTE` — call a function or procedure.
1021    Execute,
1022    /// `CREATE` — create objects within the database/schema.
1023    Create,
1024    /// `CONNECT` — connect to the database.
1025    Connect,
1026    /// `TEMPORARY`. The `TEMP` alias is preserved separately as [`Temp`](Self::Temp).
1027    Temporary,
1028    /// `TEMP`, the shorthand alias for `TEMPORARY`, kept distinct so it round-trips.
1029    Temp,
1030    /// `MAINTAIN` — run maintenance commands (`VACUUM`/`ANALYZE`/…, PostgreSQL 17+).
1031    Maintain,
1032    // --- MySQL static privileges ---------------------------------------------------------
1033    //
1034    // The MySQL `role_or_privilege` static-privilege keywords not already named above, each a
1035    // fixed keyword phrase the render reproduces verbatim. Recognized only by the MySQL
1036    // account-grant grammar
1037    // ([`AccessControlSyntax::access_control_account_grants`](crate::dialect::AccessControlSyntax)),
1038    // so the PostgreSQL privilege parser never yields them; MySQL dynamic privileges
1039    // (`BACKUP_ADMIN`, …) and role names ride [`Privilege::Other`] instead. `SELECT`/`INSERT`/
1040    // `UPDATE`/`DELETE`/`REFERENCES`/`USAGE`/`EXECUTE`/`CREATE`/`TRIGGER` reuse the shared
1041    // variants above.
1042    /// `INDEX`.
1043    Index,
1044    /// `ALTER`.
1045    Alter,
1046    /// `DROP`.
1047    Drop,
1048    /// `RELOAD`.
1049    Reload,
1050    /// `SHUTDOWN`.
1051    Shutdown,
1052    /// `PROCESS`.
1053    Process,
1054    /// `FILE`.
1055    File,
1056    /// `SUPER` (deprecated in MySQL, still grammar-valid).
1057    Super,
1058    /// `EVENT`.
1059    Event,
1060    /// `GRANT OPTION` — spelled as a privilege in a `REVOKE`/`GRANT` list (distinct from the
1061    /// `WITH GRANT OPTION` trailer).
1062    GrantOption,
1063    /// `SHOW DATABASES`.
1064    ShowDatabases,
1065    /// `CREATE TEMPORARY TABLES`.
1066    CreateTemporaryTables,
1067    /// `LOCK TABLES`.
1068    LockTables,
1069    /// `REPLICATION SLAVE`.
1070    ReplicationSlave,
1071    /// `REPLICATION CLIENT`.
1072    ReplicationClient,
1073    /// `CREATE VIEW`.
1074    CreateView,
1075    /// `SHOW VIEW`.
1076    ShowView,
1077    /// `CREATE ROUTINE`.
1078    CreateRoutine,
1079    /// `ALTER ROUTINE`.
1080    AlterRoutine,
1081    /// `CREATE USER`.
1082    CreateUser,
1083    /// `CREATE TABLESPACE`.
1084    CreateTablespace,
1085    /// `CREATE ROLE`.
1086    CreateRole,
1087    /// `DROP ROLE`.
1088    DropRole,
1089}
1090
1091/// The object a privilege applies to.
1092///
1093/// `TABLE` is the default object type, so [`Table`](Self::Table) records whether the
1094/// redundant keyword was written; every other object type names its keyword
1095/// explicitly.
1096#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1097#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1098#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1099pub enum GrantObject<X: Extension = NoExt> {
1100    /// A table (or the default object type when the `TABLE` keyword is omitted).
1101    Table {
1102        /// Whether the redundant `TABLE` object-type keyword was written.
1103        explicit: bool,
1104        /// Names in source order.
1105        names: ThinVec<ObjectName>,
1106        /// Source location and node identity.
1107        meta: Meta,
1108    },
1109    /// An object type whose target is a plain name list (`SEQUENCE <name> [, ...]`,
1110    /// `DATABASE …`, `SCHEMA …`, `DOMAIN …`, `TYPE …`, `LANGUAGE …`, `TABLESPACE …`,
1111    /// `FOREIGN DATA WRAPPER …`, `FOREIGN SERVER …`).
1112    Named {
1113        /// Which named object type; see [`NamedObjectKind`].
1114        kind: NamedObjectKind,
1115        /// Names in source order.
1116        names: ThinVec<ObjectName>,
1117        /// Source location and node identity.
1118        meta: Meta,
1119    },
1120    /// Routine targets (`FUNCTION`/`PROCEDURE`/`ROUTINE <name>(<sig>)`).
1121    Routines {
1122        /// Which routine kind; see [`RoutineObjectKind`].
1123        kind: RoutineObjectKind,
1124        /// routines in source order.
1125        routines: ThinVec<RoutineSignature<X>>,
1126        /// Source location and node identity.
1127        meta: Meta,
1128    },
1129    /// `ALL {TABLES | SEQUENCES | FUNCTIONS | PROCEDURES | ROUTINES} IN SCHEMA <name> [, ...]`.
1130    AllInSchema {
1131        /// Which object class is granted schema-wide; see [`SchemaObjectKind`].
1132        kind: SchemaObjectKind,
1133        /// schemas in source order.
1134        schemas: ThinVec<ObjectName>,
1135        /// Source location and node identity.
1136        meta: Meta,
1137    },
1138}
1139
1140#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1141#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1142#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1143/// The SQL named object kind forms represented by the AST.
1144pub enum NamedObjectKind {
1145    /// `SEQUENCE` object.
1146    Sequence,
1147    /// `DATABASE` object.
1148    Database,
1149    /// `SCHEMA` object.
1150    Schema,
1151    /// `DOMAIN` object.
1152    Domain,
1153    /// `TYPE` object.
1154    Type,
1155    /// `LANGUAGE` object.
1156    Language,
1157    /// `TABLESPACE` object.
1158    Tablespace,
1159    /// `FOREIGN DATA WRAPPER` object.
1160    ForeignDataWrapper,
1161    /// `FOREIGN SERVER` object.
1162    ForeignServer,
1163}
1164
1165#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1166#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1167#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1168/// The SQL routine object kind forms represented by the AST.
1169pub enum RoutineObjectKind {
1170    /// `FUNCTION`.
1171    Function,
1172    /// `PROCEDURE`.
1173    Procedure,
1174    /// `ROUTINE` — a function or procedure.
1175    Routine,
1176}
1177
1178#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1179#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1180#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1181/// The SQL schema object kind forms represented by the AST.
1182pub enum SchemaObjectKind {
1183    /// `ALL TABLES IN SCHEMA`.
1184    Tables,
1185    /// `ALL SEQUENCES IN SCHEMA`.
1186    Sequences,
1187    /// `ALL FUNCTIONS IN SCHEMA`.
1188    Functions,
1189    /// `ALL PROCEDURES IN SCHEMA`.
1190    Procedures,
1191    /// `ALL ROUTINES IN SCHEMA`.
1192    Routines,
1193}
1194
1195/// A routine reference in a `FUNCTION`/`PROCEDURE`/`ROUTINE` grant: a name with an
1196/// optional argument-type signature.
1197///
1198/// `arg_types` is `None` when no parenthesized list was written (`FUNCTION foo`) and
1199/// `Some` — possibly empty — when it was (`FUNCTION foo()` / `FUNCTION foo(int, text)`),
1200/// preserving the distinction. Argument names and modes (`IN`/`OUT`/`VARIADIC`) are
1201/// out of scope; only the type list is modelled.
1202#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1203#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1204#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1205pub struct RoutineSignature<X: Extension = NoExt> {
1206    /// Name referenced by this syntax.
1207    pub name: ObjectName,
1208    /// Optional arg types for this syntax.
1209    pub arg_types: Option<ThinVec<DataType<X>>>,
1210    /// Source location and node identity.
1211    pub meta: Meta,
1212}
1213
1214/// A `GRANT`/`REVOKE` grantee: a role specification, optionally with the legacy
1215/// `GROUP` keyword prefix (`GROUP <role>`).
1216#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1217#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1218#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1219pub struct Grantee {
1220    /// Whether the PostgreSQL-legacy `GROUP` keyword preceded the role.
1221    pub group: bool,
1222    /// The role specification; see [`RoleSpec`].
1223    pub spec: RoleSpec,
1224    /// Source location and node identity.
1225    pub meta: Meta,
1226}
1227
1228/// A role specification: a named role, `PUBLIC`, or a session-role pseudo-role.
1229///
1230/// Shared by grantees and the `GRANTED BY` grantor.
1231#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1232#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1233#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1234pub enum RoleSpec {
1235    /// `PUBLIC` — the implicit role every role belongs to.
1236    Public {
1237        /// Source location and node identity.
1238        meta: Meta,
1239    },
1240    /// `CURRENT_ROLE` — the current role.
1241    CurrentRole {
1242        /// Source location and node identity.
1243        meta: Meta,
1244    },
1245    /// `CURRENT_USER` — the current user.
1246    CurrentUser {
1247        /// Source location and node identity.
1248        meta: Meta,
1249    },
1250    /// `SESSION_USER` — the session user.
1251    SessionUser {
1252        /// Source location and node identity.
1253        meta: Meta,
1254    },
1255    /// A named role.
1256    Name {
1257        /// Name referenced by this syntax.
1258        name: Ident,
1259        /// Source location and node identity.
1260        meta: Meta,
1261    },
1262}
1263
1264// --- User / role administration DDL (MySQL) --------------------------------------------
1265//
1266// `CREATE`/`ALTER`/`DROP USER` and `CREATE`/`DROP ROLE` — the MySQL account-management
1267// family, gated by
1268// [`AccessControlSyntax::user_role_management`](crate::dialect::AccessControlSyntax). Every
1269// account reference rides the shared [`AccountName`] axis; the authentication, TLS, resource,
1270// and password/lock option lists below are shared by `CREATE USER` and `ALTER USER`.
1271
1272/// `CREATE USER [IF NOT EXISTS] <user> [<auth>] [, …] [DEFAULT ROLE <role> [, …]]
1273/// [REQUIRE <tls>] [WITH <resource> …] [<password/lock option> …]
1274/// [COMMENT | ATTRIBUTE '<string>']` — the MySQL account-creation statement.
1275///
1276/// The `<user> [<auth>]` elements are a comma list of [`UserSpec`]s. The trailing clauses are
1277/// each written at most once (MySQL's grammar has them as single optional tails, not a
1278/// repeatable option bag), except the resource-limit and password/lock lists, which are
1279/// whitespace-separated repeatable runs.
1280#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1281#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1282#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1283pub struct CreateUser {
1284    /// Whether the `IF NOT EXISTS` guard was written.
1285    pub if_not_exists: bool,
1286    /// The `<user> [<auth>]` account list, in source order (always non-empty).
1287    pub users: ThinVec<UserSpec>,
1288    /// The `DEFAULT ROLE <role> [, …]` roles, in source order; empty when the clause was not
1289    /// written (MySQL rejects an empty `DEFAULT ROLE`, so empty is unambiguously "absent").
1290    pub default_roles: ThinVec<AccountName>,
1291    /// The `REQUIRE …` TLS requirement; `None` when the clause was omitted.
1292    pub require: Option<TlsRequirement>,
1293    /// The `WITH <resource> …` resource limits, in source order; empty when no `WITH` was
1294    /// written.
1295    pub resource_options: ThinVec<ResourceLimit>,
1296    /// The password / account-lock options, in source order; empty when none were written.
1297    pub password_lock_options: ThinVec<PasswordLockOption>,
1298    /// The `COMMENT '…'` / `ATTRIBUTE '…'` account attribute; `None` when neither was written
1299    /// (the two are mutually exclusive in the grammar).
1300    pub attribute: Option<UserAttribute>,
1301    /// Source location and node identity.
1302    pub meta: Meta,
1303}
1304
1305/// One `<user> [<auth>]` element of a [`CreateUser`] list: an account name and its optional
1306/// primary-factor authentication.
1307///
1308/// The multi-factor `AND IDENTIFIED …` tail, the `INITIAL AUTHENTICATION` clause, and the
1309/// `ALTER USER` factor-registration surface are a separate MySQL multi-factor-authentication
1310/// family, deferred from this measured single-factor axis; this spec extends additively when
1311/// that family lands.
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 struct UserSpec {
1316    /// The account being created.
1317    pub account: AccountName,
1318    /// The primary-factor authentication (`IDENTIFIED BY …` / `IDENTIFIED WITH …`); `None`
1319    /// for a bare account with no authentication clause.
1320    pub auth: Option<AuthOption>,
1321    /// Source location and node identity.
1322    pub meta: Meta,
1323}
1324
1325/// A primary-factor authentication clause: `IDENTIFIED BY …` / `IDENTIFIED WITH <plugin> …`.
1326///
1327/// The password and auth-string bodies are [`Literal`]s so the exact source spelling
1328/// round-trips from the span (and redacts to `?` under the redacted render). The plugin name
1329/// is a MySQL `ident_or_text`, folded to an [`Ident`] whose quote style round-trips.
1330#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1331#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1332#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1333pub enum AuthOption {
1334    /// `IDENTIFIED BY '<password>'`.
1335    Password {
1336        /// The cleartext password literal.
1337        password: Literal,
1338        /// Source location and node identity.
1339        meta: Meta,
1340    },
1341    /// `IDENTIFIED BY RANDOM PASSWORD` — the server generates and returns a random password.
1342    RandomPassword {
1343        /// Source location and node identity.
1344        meta: Meta,
1345    },
1346    /// `IDENTIFIED WITH <plugin>`.
1347    Plugin {
1348        /// The authentication-plugin name.
1349        plugin: Ident,
1350        /// Source location and node identity.
1351        meta: Meta,
1352    },
1353    /// `IDENTIFIED WITH <plugin> AS '<auth string>'` — a pre-hashed authentication string.
1354    PluginAs {
1355        /// The authentication-plugin name.
1356        plugin: Ident,
1357        /// The plugin-specific authentication (hash) string literal.
1358        auth_string: Literal,
1359        /// Source location and node identity.
1360        meta: Meta,
1361    },
1362    /// `IDENTIFIED WITH <plugin> BY '<password>'`.
1363    PluginByPassword {
1364        /// The authentication-plugin name.
1365        plugin: Ident,
1366        /// The cleartext password literal.
1367        password: Literal,
1368        /// Source location and node identity.
1369        meta: Meta,
1370    },
1371    /// `IDENTIFIED WITH <plugin> BY RANDOM PASSWORD`.
1372    PluginByRandomPassword {
1373        /// The authentication-plugin name.
1374        plugin: Ident,
1375        /// Source location and node identity.
1376        meta: Meta,
1377    },
1378}
1379
1380/// `ALTER USER [IF EXISTS] …` — the MySQL account-modification statement.
1381///
1382/// Two shapes share the `[IF EXISTS]` guard: the [`Modify`](AlterUser::Modify) list form
1383/// (re-authenticate / re-configure a comma list of accounts) and the
1384/// [`DefaultRole`](AlterUser::DefaultRole) single-account `DEFAULT ROLE` reset. The
1385/// multi-factor factor-registration forms (`ADD`/`MODIFY`/`DROP FACTOR`, `… REGISTRATION`)
1386/// are a deferred multi-factor-authentication family (see [`UserSpec`]).
1387#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1388#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1389#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1390pub enum AlterUser {
1391    /// `ALTER USER [IF EXISTS] <user> [<auth>] [REPLACE '…'] [RETAIN CURRENT PASSWORD |
1392    /// DISCARD OLD PASSWORD] [, …] [REQUIRE …] [WITH …] [<password/lock option> …]
1393    /// [COMMENT | ATTRIBUTE '…']`.
1394    Modify {
1395        /// Whether the `IF EXISTS` guard was written.
1396        if_exists: bool,
1397        /// The per-account modifications, in source order (always non-empty).
1398        users: ThinVec<AlterUserSpec>,
1399        /// The `REQUIRE …` TLS requirement; `None` when omitted.
1400        require: Option<TlsRequirement>,
1401        /// The `WITH <resource> …` resource limits, in source order; empty when no `WITH`.
1402        resource_options: ThinVec<ResourceLimit>,
1403        /// The password / account-lock options, in source order; empty when none.
1404        password_lock_options: ThinVec<PasswordLockOption>,
1405        /// The `COMMENT '…'` / `ATTRIBUTE '…'` account attribute; `None` when neither.
1406        attribute: Option<UserAttribute>,
1407        /// Source location and node identity.
1408        meta: Meta,
1409    },
1410    /// `ALTER USER [IF EXISTS] <user> DEFAULT ROLE {ALL | NONE | <role> [, …]}`.
1411    DefaultRole {
1412        /// Whether the `IF EXISTS` guard was written.
1413        if_exists: bool,
1414        /// The account whose default roles are reset.
1415        user: AccountName,
1416        /// The default-role target — `ALL`, `NONE`, or an explicit role list.
1417        roles: DefaultRoleTarget,
1418        /// Source location and node identity.
1419        meta: Meta,
1420    },
1421}
1422
1423/// One per-account element of an [`AlterUser::Modify`] list: an account, its optional new
1424/// authentication, and the password-rotation flags that attach to it.
1425#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1426#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1427#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1428pub struct AlterUserSpec {
1429    /// The account being altered.
1430    pub account: AccountName,
1431    /// The new primary-factor authentication; `None` for a bare account (e.g. a lone
1432    /// `DISCARD OLD PASSWORD` or a re-configuration with no re-authentication).
1433    pub auth: Option<AuthOption>,
1434    /// The `REPLACE '<current password>'` verification string; `None` when not written.
1435    pub replace: Option<Literal>,
1436    /// Whether `RETAIN CURRENT PASSWORD` was written (keep the old password as a secondary).
1437    pub retain_current_password: bool,
1438    /// Whether `DISCARD OLD PASSWORD` was written (drop the retained secondary password).
1439    pub discard_old_password: bool,
1440    /// Source location and node identity.
1441    pub meta: Meta,
1442}
1443
1444/// The target of an `ALTER USER … DEFAULT ROLE` clause.
1445#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1446#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1447#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1448pub enum DefaultRoleTarget {
1449    /// `DEFAULT ROLE ALL` — every granted role becomes a default.
1450    All {
1451        /// Source location and node identity.
1452        meta: Meta,
1453    },
1454    /// `DEFAULT ROLE NONE` — clear the default roles.
1455    None {
1456        /// Source location and node identity.
1457        meta: Meta,
1458    },
1459    /// `DEFAULT ROLE <role> [, …]` — an explicit default-role list (always non-empty).
1460    Roles {
1461        /// The default roles, in source order.
1462        roles: ThinVec<AccountName>,
1463        /// Source location and node identity.
1464        meta: Meta,
1465    },
1466}
1467
1468/// A MySQL account/role-name-list DDL statement whose whole grammar is `<verb> [<if-guard>]
1469/// <name> [, …]`: `DROP USER`, `CREATE ROLE`, or `DROP ROLE`.
1470///
1471/// The three share one spine — a verb, an existence guard, and a comma list of
1472/// [`AccountName`]s — so they ride one node with the verb carried as data ([`kind`](Self::kind)),
1473/// the same "sub-command identity as data" precedent the SHOW / table-maintenance families use.
1474/// The richer `CREATE USER` / `ALTER USER` statements keep their own nodes.
1475#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1476#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1477#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1478pub struct UserRoleList {
1479    /// Which verb this is; also fixes the [`if_guard`](Self::if_guard) spelling
1480    /// (`IF EXISTS` for the drops, `IF NOT EXISTS` for `CREATE ROLE`).
1481    pub kind: UserRoleListKind,
1482    /// Whether the existence guard was written (`IF EXISTS` / `IF NOT EXISTS` per `kind`).
1483    pub if_guard: bool,
1484    /// The account/role names, in source order (always non-empty).
1485    pub names: ThinVec<AccountName>,
1486    /// Source location and node identity.
1487    pub meta: Meta,
1488}
1489
1490/// Which account/role-list verb a [`UserRoleList`] carries.
1491#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1492#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1493#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1494pub enum UserRoleListKind {
1495    /// `DROP USER [IF EXISTS] <user> [, …]`.
1496    DropUser,
1497    /// `CREATE ROLE [IF NOT EXISTS] <role> [, …]`.
1498    CreateRole,
1499    /// `DROP ROLE [IF EXISTS] <role> [, …]`.
1500    DropRole,
1501}
1502
1503/// A `REQUIRE …` TLS requirement on a `CREATE`/`ALTER USER`.
1504#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1505#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1506#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1507pub enum TlsRequirement {
1508    /// `REQUIRE NONE` — no TLS required.
1509    None {
1510        /// Source location and node identity.
1511        meta: Meta,
1512    },
1513    /// `REQUIRE SSL` — any TLS connection.
1514    Ssl {
1515        /// Source location and node identity.
1516        meta: Meta,
1517    },
1518    /// `REQUIRE X509` — a valid client certificate.
1519    X509 {
1520        /// Source location and node identity.
1521        meta: Meta,
1522    },
1523    /// `REQUIRE <option> [AND <option> …]` — one or more certificate-attribute requirements
1524    /// (`SUBJECT`/`ISSUER`/`CIPHER`), always non-empty.
1525    Options {
1526        /// The certificate-attribute requirements, in source order.
1527        options: ThinVec<TlsOption>,
1528        /// Source location and node identity.
1529        meta: Meta,
1530    },
1531}
1532
1533/// One certificate-attribute requirement inside a [`TlsRequirement::Options`] list.
1534#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1535#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1536#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1537pub enum TlsOption {
1538    /// `SUBJECT '<subject>'`.
1539    Subject {
1540        /// The required certificate subject string literal.
1541        value: Literal,
1542        /// Source location and node identity.
1543        meta: Meta,
1544    },
1545    /// `ISSUER '<issuer>'`.
1546    Issuer {
1547        /// The required certificate issuer string literal.
1548        value: Literal,
1549        /// Source location and node identity.
1550        meta: Meta,
1551    },
1552    /// `CIPHER '<cipher>'`.
1553    Cipher {
1554        /// The required cipher string literal.
1555        value: Literal,
1556        /// Source location and node identity.
1557        meta: Meta,
1558    },
1559}
1560
1561/// One `WITH <resource>`-list resource limit on a `CREATE`/`ALTER USER`. Each value is an
1562/// unsigned-integer [`Literal`].
1563#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1564#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1565#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1566pub enum ResourceLimit {
1567    /// `MAX_QUERIES_PER_HOUR <n>`.
1568    MaxQueriesPerHour {
1569        /// The limit value.
1570        value: Literal,
1571        /// Source location and node identity.
1572        meta: Meta,
1573    },
1574    /// `MAX_UPDATES_PER_HOUR <n>`.
1575    MaxUpdatesPerHour {
1576        /// The limit value.
1577        value: Literal,
1578        /// Source location and node identity.
1579        meta: Meta,
1580    },
1581    /// `MAX_CONNECTIONS_PER_HOUR <n>`.
1582    MaxConnectionsPerHour {
1583        /// The limit value.
1584        value: Literal,
1585        /// Source location and node identity.
1586        meta: Meta,
1587    },
1588    /// `MAX_USER_CONNECTIONS <n>`.
1589    MaxUserConnections {
1590        /// The limit value.
1591        value: Literal,
1592        /// Source location and node identity.
1593        meta: Meta,
1594    },
1595}
1596
1597/// One password-management / account-lock option on a `CREATE`/`ALTER USER`. Numeric bodies
1598/// are unsigned-integer [`Literal`]s.
1599#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1600#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1601#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1602pub enum PasswordLockOption {
1603    /// `ACCOUNT LOCK`.
1604    AccountLock {
1605        /// Source location and node identity.
1606        meta: Meta,
1607    },
1608    /// `ACCOUNT UNLOCK`.
1609    AccountUnlock {
1610        /// Source location and node identity.
1611        meta: Meta,
1612    },
1613    /// `PASSWORD EXPIRE` — expire the password immediately.
1614    PasswordExpire {
1615        /// Source location and node identity.
1616        meta: Meta,
1617    },
1618    /// `PASSWORD EXPIRE DEFAULT` — use the global `default_password_lifetime`.
1619    PasswordExpireDefault {
1620        /// Source location and node identity.
1621        meta: Meta,
1622    },
1623    /// `PASSWORD EXPIRE NEVER`.
1624    PasswordExpireNever {
1625        /// Source location and node identity.
1626        meta: Meta,
1627    },
1628    /// `PASSWORD EXPIRE INTERVAL <n> DAY`.
1629    PasswordExpireInterval {
1630        /// The interval, in days.
1631        days: Literal,
1632        /// Source location and node identity.
1633        meta: Meta,
1634    },
1635    /// `PASSWORD HISTORY <n>` — remember the last `n` passwords.
1636    PasswordHistory {
1637        /// The number of remembered passwords.
1638        count: Literal,
1639        /// Source location and node identity.
1640        meta: Meta,
1641    },
1642    /// `PASSWORD HISTORY DEFAULT`.
1643    PasswordHistoryDefault {
1644        /// Source location and node identity.
1645        meta: Meta,
1646    },
1647    /// `PASSWORD REUSE INTERVAL <n> DAY`.
1648    PasswordReuseInterval {
1649        /// The reuse-blocking interval, in days.
1650        days: Literal,
1651        /// Source location and node identity.
1652        meta: Meta,
1653    },
1654    /// `PASSWORD REUSE INTERVAL DEFAULT`.
1655    PasswordReuseIntervalDefault {
1656        /// Source location and node identity.
1657        meta: Meta,
1658    },
1659    /// `PASSWORD REQUIRE CURRENT` — a password change must verify the current password.
1660    PasswordRequireCurrent {
1661        /// Source location and node identity.
1662        meta: Meta,
1663    },
1664    /// `PASSWORD REQUIRE CURRENT DEFAULT`.
1665    PasswordRequireCurrentDefault {
1666        /// Source location and node identity.
1667        meta: Meta,
1668    },
1669    /// `PASSWORD REQUIRE CURRENT OPTIONAL`.
1670    PasswordRequireCurrentOptional {
1671        /// Source location and node identity.
1672        meta: Meta,
1673    },
1674    /// `FAILED_LOGIN_ATTEMPTS <n>`.
1675    FailedLoginAttempts {
1676        /// The failed-login threshold.
1677        count: Literal,
1678        /// Source location and node identity.
1679        meta: Meta,
1680    },
1681    /// `PASSWORD_LOCK_TIME <n>` — lock duration in days after `FAILED_LOGIN_ATTEMPTS`.
1682    PasswordLockTime {
1683        /// The lock duration, in days.
1684        days: Literal,
1685        /// Source location and node identity.
1686        meta: Meta,
1687    },
1688    /// `PASSWORD_LOCK_TIME UNBOUNDED` — lock until manually unlocked.
1689    PasswordLockTimeUnbounded {
1690        /// Source location and node identity.
1691        meta: Meta,
1692    },
1693}
1694
1695/// A `CREATE`/`ALTER USER` account attribute: `COMMENT '…'` or `ATTRIBUTE '<json>'`
1696/// (mutually exclusive in the grammar).
1697#[derive(Clone, Debug, PartialEq, Eq, Hash)]
1698#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
1699#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
1700pub enum UserAttribute {
1701    /// `COMMENT '<text>'`.
1702    Comment {
1703        /// The comment string literal.
1704        comment: Literal,
1705        /// Source location and node identity.
1706        meta: Meta,
1707    },
1708    /// `ATTRIBUTE '<json>'` — a JSON object of user attributes.
1709    Attribute {
1710        /// The JSON attribute string literal.
1711        attribute: Literal,
1712        /// Source location and node identity.
1713        meta: Meta,
1714    },
1715}