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}