Skip to main content

squonk_ast/ast/
replication.rs

1// SPDX-License-Identifier: MIT
2// Copyright (c) 2026 Moderately AI Inc.
3
4//! MySQL replication-administration statement AST nodes.
5//!
6//! The five measured MySQL replication-control families, gated as one cohesive unit by
7//! [`UtilitySyntax::replication_statements`](crate::dialect::UtilitySyntax):
8//!
9//! - `CHANGE REPLICATION SOURCE TO <option-list> [FOR CHANNEL '<ch>']` — configure the
10//!   asynchronous-replication source connection (`sql_yacc.yy` `change_replication_stmt`,
11//!   `source_defs`).
12//! - `CHANGE REPLICATION FILTER <rule-list> [FOR CHANNEL '<ch>']` — set the replication
13//!   filtering rules (`filter_defs`).
14//! - `START REPLICA [<threads>] [UNTIL <cond>] [<connection>] [FOR CHANNEL '<ch>']` and
15//!   `STOP REPLICA [<threads>] [FOR CHANNEL '<ch>']` — the replica-thread lifecycle
16//!   (`start_replica_stmt` / `stop_replica_stmt`).
17//! - `START GROUP_REPLICATION [<option-list>]` / `STOP GROUP_REPLICATION` — the Group
18//!   Replication plugin lifecycle (`group_replication`).
19//!
20//! MySQL 8.4 removed the legacy `MASTER`/`SLAVE` spellings (`CHANGE MASTER TO`, `START
21//! SLAVE`, the `MASTER_*` option names), so only the `REPLICATION`/`REPLICA`/`SOURCE_*`
22//! grammar is modelled here — each is an `ER_PARSE_ERROR` on mysql:8.4.10 and never parsed.
23//! No operand is an expression, so the whole family is non-generic (no extension parameter).
24
25use super::{AccountName, Ident, Literal, ObjectName};
26use crate::vocab::Meta;
27use thin_vec::ThinVec;
28
29/// A MySQL replication-administration statement — the boxed payload of
30/// [`Statement::Replication`](crate::ast::Statement::Replication).
31///
32/// Six verbs across the five measured families ride one enum because they are one dialect
33/// unit reached through the replication-specific leading-keyword sequences. `START`/`STOP
34/// GROUP_REPLICATION` are two variants (the two verbs carry different tails — only `START`
35/// takes options) of the single `GROUP REPLICATION` family.
36#[derive(Clone, Debug, PartialEq, Eq, Hash)]
37#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
38#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
39pub enum ReplicationStatement {
40    /// `CHANGE REPLICATION SOURCE TO <option-list> [FOR CHANNEL '<ch>']`.
41    ///
42    /// The option list is non-empty (a bare `CHANGE REPLICATION SOURCE TO` is
43    /// `ER_PARSE_ERROR` on mysql:8.4.10) and comma-separated; each element is a
44    /// [`ChangeReplicationSourceOption`]. `FOR CHANNEL` is a trailing suffix, not a list
45    /// member — an option after the channel (`… FOR CHANNEL 'c', SOURCE_PORT = 1`) rejects.
46    ChangeSource {
47        /// The `<name> = <value>` options in source order; always non-empty.
48        options: ThinVec<ChangeReplicationSourceOption>,
49        /// The optional `FOR CHANNEL '<name>'` replication-channel name.
50        channel: Option<Literal>,
51        /// Source location and node identity.
52        meta: Meta,
53    },
54    /// `CHANGE REPLICATION FILTER <rule-list> [FOR CHANNEL '<ch>']`.
55    ///
56    /// The rule list is non-empty and comma-separated; each element is a
57    /// [`ReplicationFilterRule`].
58    ChangeFilter {
59        /// The filter rules in source order; always non-empty.
60        rules: ThinVec<ReplicationFilterRule>,
61        /// The optional `FOR CHANNEL '<name>'` replication-channel name.
62        channel: Option<Literal>,
63        /// Source location and node identity.
64        meta: Meta,
65    },
66    /// `START REPLICA [<thread-list>] [UNTIL <cond-list>] [USER='u'] [PASSWORD='p']
67    /// [DEFAULT_AUTH='a'] [PLUGIN_DIR='d'] [FOR CHANNEL '<ch>']`.
68    ///
69    /// The connection options are four independent fixed-order optionals (MySQL's
70    /// `opt_user_option` … `opt_plugin_dir_option`, space-separated — *not* a comma list,
71    /// unlike [`StartGroupReplication`](Self::StartGroupReplication)). Each may appear alone
72    /// (`START REPLICA PASSWORD = 'p'` is grammar-valid on mysql:8.4.10).
73    StartReplica {
74        /// The `SQL_THREAD`/`IO_THREAD` thread-type list (`opt_replica_thread_option_list`);
75        /// empty when none was written (start both threads).
76        threads: ThinVec<ReplicaThreadOption>,
77        /// The `UNTIL <cond-list>` stop condition (`opt_replica_until`); empty when no
78        /// `UNTIL` was written. See [`ReplicaUntilCondition`].
79        until: ThinVec<ReplicaUntilCondition>,
80        /// The `USER = '<u>'` connection user; `None` when absent.
81        user: Option<Literal>,
82        /// The `PASSWORD = '<p>'` connection password; `None` when absent.
83        password: Option<Literal>,
84        /// The `DEFAULT_AUTH = '<a>'` authentication plugin; `None` when absent.
85        default_auth: Option<Literal>,
86        /// The `PLUGIN_DIR = '<d>'` plugin directory; `None` when absent.
87        plugin_dir: Option<Literal>,
88        /// The optional `FOR CHANNEL '<name>'` replication-channel name.
89        channel: Option<Literal>,
90        /// Source location and node identity.
91        meta: Meta,
92    },
93    /// `STOP REPLICA [<thread-list>] [FOR CHANNEL '<ch>']`.
94    ///
95    /// Unlike [`StartReplica`](Self::StartReplica), `STOP REPLICA` takes no `UNTIL` or
96    /// connection tail — `STOP REPLICA UNTIL …` / `STOP REPLICA USER = …` is `ER_PARSE_ERROR`
97    /// on mysql:8.4.10.
98    StopReplica {
99        /// The `SQL_THREAD`/`IO_THREAD` thread-type list; empty when none was written.
100        threads: ThinVec<ReplicaThreadOption>,
101        /// The optional `FOR CHANNEL '<name>'` replication-channel name.
102        channel: Option<Literal>,
103        /// Source location and node identity.
104        meta: Meta,
105    },
106    /// `START GROUP_REPLICATION [<option-list>]`.
107    ///
108    /// The options are `USER`/`PASSWORD`/`DEFAULT_AUTH` in any order, *comma-separated*
109    /// (`group_replication_start_options` — the distinguishing difference from
110    /// [`StartReplica`](Self::StartReplica)'s space-separated fixed-order tail), so they ride
111    /// an ordered list. Empty when none was written.
112    StartGroupReplication {
113        /// The connection options in source order; empty when none was written.
114        options: ThinVec<GroupReplicationOption>,
115        /// Source location and node identity.
116        meta: Meta,
117    },
118    /// `STOP GROUP_REPLICATION` — takes no options (`STOP GROUP_REPLICATION USER = …` is
119    /// `ER_PARSE_ERROR` on mysql:8.4.10).
120    StopGroupReplication {
121        /// Source location and node identity.
122        meta: Meta,
123    },
124}
125
126/// One `<name> = <value>` option of `CHANGE REPLICATION SOURCE TO` (`sql_yacc.yy`
127/// `source_def` / `source_file_def`).
128///
129/// The [`name`](Self::name) is a closed, measured keyword set ([`SourceOption`]); the
130/// [`value`](Self::value) carries the option's argument in one of the measured value shapes
131/// ([`ChangeReplicationSourceOptionValue`]). The name→shape correspondence is fixed per
132/// option and enforced by the parser (which reads the value shape the name dictates) rather
133/// than the type — the [`CopyOption`](crate::ast::CopyOption) name/value idiom for a wide
134/// flat option grammar.
135#[derive(Clone, Debug, PartialEq, Eq, Hash)]
136#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
137#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
138pub struct ChangeReplicationSourceOption {
139    /// The option name; see [`SourceOption`].
140    pub name: SourceOption,
141    /// The option value; see [`ChangeReplicationSourceOptionValue`].
142    pub value: ChangeReplicationSourceOptionValue,
143    /// Source location and node identity.
144    pub meta: Meta,
145}
146
147/// The closed set of `CHANGE REPLICATION SOURCE TO` option names admitted by mysql:8.4.10.
148///
149/// A surface tag (no `meta`; the span rides the enclosing [`ChangeReplicationSourceOption`]).
150/// The set is the 8.4 grammar's `source_def`/`source_file_def` alternatives, engine-narrowed:
151/// the deprecated `MASTER_*` names were removed (each `ER_PARSE_ERROR`), and the compression
152/// option is the *plural* `SOURCE_COMPRESSION_ALGORITHMS` — the singular
153/// `SOURCE_COMPRESSION_ALGORITHM` (the yacc token's bare name) is `ER_PARSE_ERROR` on
154/// mysql:8.4.10, so only the plural keyword is admitted.
155#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
156#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
157#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
158pub enum SourceOption {
159    /// `SOURCE_BIND` — the network interface to bind to.
160    SourceBind,
161    /// `SOURCE_HOST` — the source server host name.
162    SourceHost,
163    /// `SOURCE_USER` — the replication account user name.
164    SourceUser,
165    /// `SOURCE_PASSWORD` — the replication account password.
166    SourcePassword,
167    /// `SOURCE_PORT` — the source server TCP port.
168    SourcePort,
169    /// `SOURCE_CONNECT_RETRY` — seconds between reconnection attempts.
170    SourceConnectRetry,
171    /// `SOURCE_RETRY_COUNT` — the reconnection-attempt cap.
172    SourceRetryCount,
173    /// `SOURCE_DELAY` — the replication delay in seconds.
174    SourceDelay,
175    /// `SOURCE_HEARTBEAT_PERIOD` — the heartbeat interval (a fractional number of seconds).
176    SourceHeartbeatPeriod,
177    /// `SOURCE_LOG_FILE` — the source binary-log file name to read from.
178    SourceLogFile,
179    /// `SOURCE_LOG_POS` — the source binary-log position to read from.
180    SourceLogPos,
181    /// `SOURCE_AUTO_POSITION` — enable GTID auto-positioning (`0`/`1`).
182    SourceAutoPosition,
183    /// `RELAY_LOG_FILE` — the relay-log file name to resume from.
184    RelayLogFile,
185    /// `RELAY_LOG_POS` — the relay-log position to resume from.
186    RelayLogPos,
187    /// `SOURCE_SSL` — enable an encrypted connection (`0`/`1`).
188    SourceSsl,
189    /// `SOURCE_SSL_CA` — the certificate-authority file.
190    SourceSslCa,
191    /// `SOURCE_SSL_CAPATH` — the certificate-authority directory.
192    SourceSslCapath,
193    /// `SOURCE_SSL_CERT` — the client public-key certificate file.
194    SourceSslCert,
195    /// `SOURCE_SSL_CIPHER` — the permitted cipher list.
196    SourceSslCipher,
197    /// `SOURCE_SSL_KEY` — the client private-key file.
198    SourceSslKey,
199    /// `SOURCE_SSL_VERIFY_SERVER_CERT` — verify the source certificate (`0`/`1`).
200    SourceSslVerifyServerCert,
201    /// `SOURCE_SSL_CRL` — the certificate-revocation-list file.
202    SourceSslCrl,
203    /// `SOURCE_SSL_CRLPATH` — the certificate-revocation-list directory.
204    SourceSslCrlpath,
205    /// `SOURCE_TLS_VERSION` — the permitted TLS-protocol list.
206    SourceTlsVersion,
207    /// `SOURCE_TLS_CIPHERSUITES` — the permitted TLSv1.3 ciphersuite list (string, or `NULL`).
208    SourceTlsCiphersuites,
209    /// `SOURCE_PUBLIC_KEY_PATH` — the RSA public-key file for password exchange.
210    SourcePublicKeyPath,
211    /// `GET_SOURCE_PUBLIC_KEY` — request the RSA public key from the source (`0`/`1`).
212    GetSourcePublicKey,
213    /// `NETWORK_NAMESPACE` — the network namespace.
214    NetworkNamespace,
215    /// `IGNORE_SERVER_IDS` — the parenthesized server-id ignore list.
216    IgnoreServerIds,
217    /// `SOURCE_COMPRESSION_ALGORITHMS` — the permitted connection-compression algorithms.
218    SourceCompressionAlgorithms,
219    /// `SOURCE_ZSTD_COMPRESSION_LEVEL` — the zstd compression level.
220    SourceZstdCompressionLevel,
221    /// `PRIVILEGE_CHECKS_USER` — the account whose privileges gate applied transactions (an
222    /// account, or `NULL`).
223    PrivilegeChecksUser,
224    /// `REQUIRE_ROW_FORMAT` — require row-based events (`0`/`1`).
225    RequireRowFormat,
226    /// `REQUIRE_TABLE_PRIMARY_KEY_CHECK` — the primary-key-check policy
227    /// (`ON`/`OFF`/`STREAM`/`GENERATE`).
228    RequireTablePrimaryKeyCheck,
229    /// `SOURCE_CONNECTION_AUTO_FAILOVER` — enable asynchronous connection failover (`0`/`1`).
230    SourceConnectionAutoFailover,
231    /// `ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS` — the anonymous-transaction GTID policy
232    /// (`OFF`/`LOCAL`/`'<uuid>'`).
233    AssignGtidsToAnonymousTransactions,
234    /// `GTID_ONLY` — replicate using only GTIDs, storing no file/position (`0`/`1`).
235    GtidOnly,
236}
237
238impl SourceOption {
239    /// The exact keyword spelling this option renders as — the single source of truth
240    /// shared by the renderer and the parser's option table.
241    pub fn keyword(self) -> &'static str {
242        match self {
243            Self::SourceBind => "SOURCE_BIND",
244            Self::SourceHost => "SOURCE_HOST",
245            Self::SourceUser => "SOURCE_USER",
246            Self::SourcePassword => "SOURCE_PASSWORD",
247            Self::SourcePort => "SOURCE_PORT",
248            Self::SourceConnectRetry => "SOURCE_CONNECT_RETRY",
249            Self::SourceRetryCount => "SOURCE_RETRY_COUNT",
250            Self::SourceDelay => "SOURCE_DELAY",
251            Self::SourceHeartbeatPeriod => "SOURCE_HEARTBEAT_PERIOD",
252            Self::SourceLogFile => "SOURCE_LOG_FILE",
253            Self::SourceLogPos => "SOURCE_LOG_POS",
254            Self::SourceAutoPosition => "SOURCE_AUTO_POSITION",
255            Self::RelayLogFile => "RELAY_LOG_FILE",
256            Self::RelayLogPos => "RELAY_LOG_POS",
257            Self::SourceSsl => "SOURCE_SSL",
258            Self::SourceSslCa => "SOURCE_SSL_CA",
259            Self::SourceSslCapath => "SOURCE_SSL_CAPATH",
260            Self::SourceSslCert => "SOURCE_SSL_CERT",
261            Self::SourceSslCipher => "SOURCE_SSL_CIPHER",
262            Self::SourceSslKey => "SOURCE_SSL_KEY",
263            Self::SourceSslVerifyServerCert => "SOURCE_SSL_VERIFY_SERVER_CERT",
264            Self::SourceSslCrl => "SOURCE_SSL_CRL",
265            Self::SourceSslCrlpath => "SOURCE_SSL_CRLPATH",
266            Self::SourceTlsVersion => "SOURCE_TLS_VERSION",
267            Self::SourceTlsCiphersuites => "SOURCE_TLS_CIPHERSUITES",
268            Self::SourcePublicKeyPath => "SOURCE_PUBLIC_KEY_PATH",
269            Self::GetSourcePublicKey => "GET_SOURCE_PUBLIC_KEY",
270            Self::NetworkNamespace => "NETWORK_NAMESPACE",
271            Self::IgnoreServerIds => "IGNORE_SERVER_IDS",
272            Self::SourceCompressionAlgorithms => "SOURCE_COMPRESSION_ALGORITHMS",
273            Self::SourceZstdCompressionLevel => "SOURCE_ZSTD_COMPRESSION_LEVEL",
274            Self::PrivilegeChecksUser => "PRIVILEGE_CHECKS_USER",
275            Self::RequireRowFormat => "REQUIRE_ROW_FORMAT",
276            Self::RequireTablePrimaryKeyCheck => "REQUIRE_TABLE_PRIMARY_KEY_CHECK",
277            Self::SourceConnectionAutoFailover => "SOURCE_CONNECTION_AUTO_FAILOVER",
278            Self::AssignGtidsToAnonymousTransactions => "ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS",
279            Self::GtidOnly => "GTID_ONLY",
280        }
281    }
282}
283
284/// The value of a [`ChangeReplicationSourceOption`] — the measured argument shapes of
285/// mysql:8.4.10's `source_def` grammar.
286///
287/// Most options take a [`String`](Self::String) or [`Number`](Self::Number); the remaining
288/// five carry the exotic shapes the grammar defines for specific options.
289#[derive(Clone, Debug, PartialEq, Eq, Hash)]
290#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
291#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
292pub enum ChangeReplicationSourceOptionValue {
293    /// A string-literal value (`SOURCE_HOST = 'h'`, `SOURCE_LOG_FILE = 'f'`). The spelling
294    /// round-trips from the [`Literal`] span.
295    String {
296        /// The string value.
297        value: Literal,
298        /// Source location and node identity.
299        meta: Meta,
300    },
301    /// A numeric-literal value (`SOURCE_PORT = 3306`, `SOURCE_HEARTBEAT_PERIOD = 1.5`,
302    /// the `0`/`1` boolean-ish flags). Integer and fractional spellings ride one shape;
303    /// the [`Literal`] classifies its own kind and round-trips from its span.
304    Number {
305        /// The numeric value.
306        value: Literal,
307        /// Source location and node identity.
308        meta: Meta,
309    },
310    /// `SOURCE_TLS_CIPHERSUITES`'s `<string> | NULL` value: `Some` for a string,
311    /// `None` for the bare `NULL` (`source_tls_ciphersuites_def`).
312    NullableString {
313        /// The string value; `None` for `NULL`.
314        value: Option<Literal>,
315        /// Source location and node identity.
316        meta: Meta,
317    },
318    /// `PRIVILEGE_CHECKS_USER`'s `<user> | NULL` value: `Some` for a named account,
319    /// `None` for the bare `NULL` (`privilege_check_def`).
320    User {
321        /// The account; `None` for `NULL`.
322        account: Option<AccountName>,
323        /// Source location and node identity.
324        meta: Meta,
325    },
326    /// `IGNORE_SERVER_IDS`'s parenthesized server-id list (`ignore_server_id_list`). Empty
327    /// for the `()` reset form.
328    ServerIds {
329        /// The server ids in source order; empty for `()`.
330        ids: ThinVec<Literal>,
331        /// Source location and node identity.
332        meta: Meta,
333    },
334    /// `REQUIRE_TABLE_PRIMARY_KEY_CHECK`'s `ON | OFF | STREAM | GENERATE` keyword value
335    /// (`table_primary_key_check_def`).
336    PrimaryKeyCheck {
337        /// The primary-key-check policy.
338        check: RequirePrimaryKeyCheck,
339        /// Source location and node identity.
340        meta: Meta,
341    },
342    /// `ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS`'s `OFF | LOCAL | '<uuid>'` value
343    /// (`assign_gtids_to_anonymous_transactions_def`). The `uuid` literal is present only
344    /// when [`kind`](Self::AssignGtids::kind) is [`Uuid`](AssignGtidsKind::Uuid).
345    AssignGtids {
346        /// Which of the three forms was written.
347        kind: AssignGtidsKind,
348        /// The UUID string, present only for [`Uuid`](AssignGtidsKind::Uuid).
349        uuid: Option<Literal>,
350        /// Source location and node identity.
351        meta: Meta,
352    },
353}
354
355/// The `REQUIRE_TABLE_PRIMARY_KEY_CHECK` policy keyword. A surface tag (no `meta`).
356#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
357#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
358#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
359pub enum RequirePrimaryKeyCheck {
360    /// `ON` — require a primary key on replicated tables.
361    On,
362    /// `OFF` — do not require a primary key.
363    Off,
364    /// `STREAM` — take the source's setting from the replication stream.
365    Stream,
366    /// `GENERATE` — generate a hidden primary key where the source table lacks one.
367    Generate,
368}
369
370/// Which `ASSIGN_GTIDS_TO_ANONYMOUS_TRANSACTIONS` form was written. A surface tag (no
371/// `meta`); the [`Uuid`](Self::Uuid) form's string rides
372/// [`ChangeReplicationSourceOptionValue::AssignGtids::uuid`].
373#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
374#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
375#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
376pub enum AssignGtidsKind {
377    /// `OFF` — do not assign GTIDs to anonymous transactions.
378    Off,
379    /// `LOCAL` — assign GTIDs using the replica's own UUID.
380    Local,
381    /// `'<uuid>'` — assign GTIDs using the given UUID string.
382    Uuid,
383}
384
385/// One rule of `CHANGE REPLICATION FILTER` (`sql_yacc.yy` `filter_def`).
386///
387/// Each rule's parenthesized argument list may be empty (the `()` reset form, engine-valid
388/// on mysql:8.4.10). The table forms require *schema-qualified* names (`db.t` — a bare `t`
389/// is `ER_PARSE_ERROR`), so they carry [`ObjectName`]s; the wild forms take string patterns;
390/// `REPLICATE_REWRITE_DB` takes `(from, to)` database pairs.
391#[derive(Clone, Debug, PartialEq, Eq, Hash)]
392#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
393#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
394pub enum ReplicationFilterRule {
395    /// `REPLICATE_DO_DB = (<db>, …)` — replicate only the listed databases.
396    DoDb {
397        /// The database names; empty for the `()` reset form.
398        databases: ThinVec<Ident>,
399        /// Source location and node identity.
400        meta: Meta,
401    },
402    /// `REPLICATE_IGNORE_DB = (<db>, …)` — ignore the listed databases.
403    IgnoreDb {
404        /// The database names; empty for the `()` reset form.
405        databases: ThinVec<Ident>,
406        /// Source location and node identity.
407        meta: Meta,
408    },
409    /// `REPLICATE_DO_TABLE = (<db.t>, …)` — replicate only the listed (schema-qualified)
410    /// tables.
411    DoTable {
412        /// The schema-qualified table names; empty for the `()` reset form.
413        tables: ThinVec<ObjectName>,
414        /// Source location and node identity.
415        meta: Meta,
416    },
417    /// `REPLICATE_IGNORE_TABLE = (<db.t>, …)` — ignore the listed (schema-qualified) tables.
418    IgnoreTable {
419        /// The schema-qualified table names; empty for the `()` reset form.
420        tables: ThinVec<ObjectName>,
421        /// Source location and node identity.
422        meta: Meta,
423    },
424    /// `REPLICATE_WILD_DO_TABLE = ('<pattern>', …)` — replicate tables matching the wildcard
425    /// patterns.
426    WildDoTable {
427        /// The wildcard pattern strings; empty for the `()` reset form.
428        patterns: ThinVec<Literal>,
429        /// Source location and node identity.
430        meta: Meta,
431    },
432    /// `REPLICATE_WILD_IGNORE_TABLE = ('<pattern>', …)` — ignore tables matching the wildcard
433    /// patterns.
434    WildIgnoreTable {
435        /// The wildcard pattern strings; empty for the `()` reset form.
436        patterns: ThinVec<Literal>,
437        /// Source location and node identity.
438        meta: Meta,
439    },
440    /// `REPLICATE_REWRITE_DB = ((<from>, <to>), …)` — rewrite database names. Each pair is
441    /// doubly parenthesized (`filter_db_pair_list`); a single-paren `(a, b)` is
442    /// `ER_PARSE_ERROR`.
443    RewriteDb {
444        /// The `(from, to)` rewrite pairs; empty for the `()` reset form.
445        pairs: ThinVec<RewriteDbPair>,
446        /// Source location and node identity.
447        meta: Meta,
448    },
449}
450
451/// One `(<from>, <to>)` database-rewrite pair of a
452/// [`ReplicationFilterRule::RewriteDb`] rule.
453#[derive(Clone, Debug, PartialEq, Eq, Hash)]
454#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
455#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
456pub struct RewriteDbPair {
457    /// The source database name.
458    pub from: Ident,
459    /// The rewritten database name.
460    pub to: Ident,
461    /// Source location and node identity.
462    pub meta: Meta,
463}
464
465/// A replica-thread selector on `START`/`STOP REPLICA` (`sql_yacc.yy`
466/// `replica_thread_option`).
467#[derive(Clone, Debug, PartialEq, Eq, Hash)]
468#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
469#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
470pub enum ReplicaThreadOption {
471    /// `SQL_THREAD` — the applier thread.
472    Sql {
473        /// Source location and node identity.
474        meta: Meta,
475    },
476    /// The I/O (receiver) thread. `IO_THREAD` and `RELAY_THREAD` are exact synonyms (both the
477    /// yacc `RELAY_THREAD` token); an [`IoThreadKeyword`] surface tag records which was
478    /// written so it round-trips.
479    Io {
480        /// Which of the `IO_THREAD` / `RELAY_THREAD` spellings was written.
481        keyword: IoThreadKeyword,
482        /// Source location and node identity.
483        meta: Meta,
484    },
485}
486
487/// Which of the interchangeable `IO_THREAD` / `RELAY_THREAD` spellings names the receiver
488/// thread. A surface tag (no `meta`); the two are exact synonyms.
489#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
490#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
491#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
492pub enum IoThreadKeyword {
493    /// `IO_THREAD` — the documented spelling.
494    Io,
495    /// `RELAY_THREAD` — the synonym.
496    Relay,
497}
498
499/// One condition of a `START REPLICA … UNTIL <cond-list>` clause (`sql_yacc.yy`
500/// `replica_until`).
501///
502/// The grammar admits any single condition as the head of the list, but only the
503/// file/position coordinates (`SOURCE_LOG_FILE`/`SOURCE_LOG_POS`/`RELAY_LOG_FILE`/
504/// `RELAY_LOG_POS`, the `source_file_def` alternatives) may follow a comma — the parser
505/// enforces that a GTID/gaps condition appears only as the first element. Which combinations
506/// are *coherent* (a file needs its position, GTIDs and coordinates are mutually exclusive)
507/// is a semantic check (`ER_BAD_REPLICA_UNTIL_COND` = 1277, grammar-positive), left to a
508/// binding pass.
509#[derive(Clone, Debug, PartialEq, Eq, Hash)]
510#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
511#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
512pub enum ReplicaUntilCondition {
513    /// `SOURCE_LOG_FILE = '<f>'` — stop at the given source binary-log file.
514    SourceLogFile {
515        /// The source binary-log file name.
516        value: Literal,
517        /// Source location and node identity.
518        meta: Meta,
519    },
520    /// `SOURCE_LOG_POS = <n>` — stop at the given source binary-log position.
521    SourceLogPos {
522        /// The source binary-log position.
523        value: Literal,
524        /// Source location and node identity.
525        meta: Meta,
526    },
527    /// `RELAY_LOG_FILE = '<f>'` — stop at the given relay-log file.
528    RelayLogFile {
529        /// The relay-log file name.
530        value: Literal,
531        /// Source location and node identity.
532        meta: Meta,
533    },
534    /// `RELAY_LOG_POS = <n>` — stop at the given relay-log position.
535    RelayLogPos {
536        /// The relay-log position.
537        value: Literal,
538        /// Source location and node identity.
539        meta: Meta,
540    },
541    /// `SQL_BEFORE_GTIDS = '<gtid-set>'` — stop before applying the given GTIDs.
542    SqlBeforeGtids {
543        /// The GTID set.
544        value: Literal,
545        /// Source location and node identity.
546        meta: Meta,
547    },
548    /// `SQL_AFTER_GTIDS = '<gtid-set>'` — stop after applying the given GTIDs.
549    SqlAfterGtids {
550        /// The GTID set.
551        value: Literal,
552        /// Source location and node identity.
553        meta: Meta,
554    },
555    /// `SQL_AFTER_MTS_GAPS` — stop once the multi-threaded applier has filled its gaps.
556    SqlAfterMtsGaps {
557        /// Source location and node identity.
558        meta: Meta,
559    },
560}
561
562/// One option of `START GROUP_REPLICATION` (`sql_yacc.yy`
563/// `group_replication_start_option`). The options are comma-separated and order-preserving.
564#[derive(Clone, Debug, PartialEq, Eq, Hash)]
565#[cfg_attr(feature = "serde-serialize", derive(serde::Serialize))]
566#[cfg_attr(feature = "serde-deserialize", derive(serde::Deserialize))]
567pub enum GroupReplicationOption {
568    /// `USER = '<u>'` — the distributed-recovery account user.
569    User {
570        /// The user name.
571        value: Literal,
572        /// Source location and node identity.
573        meta: Meta,
574    },
575    /// `PASSWORD = '<p>'` — the distributed-recovery account password.
576    Password {
577        /// The password.
578        value: Literal,
579        /// Source location and node identity.
580        meta: Meta,
581    },
582    /// `DEFAULT_AUTH = '<a>'` — the distributed-recovery authentication plugin.
583    DefaultAuth {
584        /// The authentication plugin name.
585        value: Literal,
586        /// Source location and node identity.
587        meta: Meta,
588    },
589}