zero_mysql/
constant.rs

1/// client charset and collation
2pub const UTF8MB4_GENERAL_CI: u8 = 45;
3
4/// the max packet (header+payload) size accepted by client
5pub const MAX_ALLOWED_PACKET: u32 = 0x0100_0000;
6
7#[repr(u8)]
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum CommandByte {
10    Quit = 0x01,
11    InitDb = 0x02,
12    Query = 0x03,
13    FieldList = 0x04,
14    CreateDb = 0x05,
15    DropDb = 0x06,
16    Refresh = 0x07,
17    Shutdown = 0x08,
18    Statistics = 0x09,
19    ProcessInfo = 0x0a,
20    Connect = 0x0b,
21    ProcessKill = 0x0c,
22    Debug = 0x0d,
23    Ping = 0x0e,
24    Time = 0x0f,
25    DelayedInsert = 0x10,
26    ChangeUser = 0x11,
27    BinlogDump = 0x12,
28    TableDump = 0x13,
29    ConnectOut = 0x14,
30    RegisterSlave = 0x15,
31    StmtPrepare = 0x16,
32    StmtExecute = 0x17,
33    StmtSendLongData = 0x18,
34    StmtClose = 0x19,
35    StmtReset = 0x1a,
36    SetOption = 0x1b,
37    StmtFetch = 0x1c,
38    Daemon = 0x1d,
39    BinlogDumpGtid = 0x1e,
40    ResetConnection = 0x1f,
41    /// MariaDB Extension
42    StmtBulkExecute = 0xfa,
43}
44
45bitflags::bitflags! {
46    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
47    pub struct CapabilityFlags: u32 {
48        /// Use the improved version of Old Password Authentication (deprecated, assumed set since 4.1.1)
49        const CLIENT_LONG_PASSWORD = 0x00000001;
50        /// Send found rows instead of affected rows
51        const CLIENT_FOUND_ROWS = 0x00000002;
52        /// Get all column flags
53        const CLIENT_LONG_FLAG = 0x00000004;
54        /// Database (schema) name can be specified on connect
55        const CLIENT_CONNECT_WITH_DB = 0x00000008;
56        /// Don't allow database.table.column (deprecated)
57        const CLIENT_NO_SCHEMA = 0x00000010;
58        /// Compression protocol supported
59        const CLIENT_COMPRESS = 0x00000020;
60        /// ODBC client (no special behavior since 3.22)
61        const CLIENT_ODBC = 0x00000040;
62        /// Can use LOAD DATA LOCAL
63        const CLIENT_LOCAL_FILES = 0x00000080;
64        /// Ignore spaces before '('
65        const CLIENT_IGNORE_SPACE = 0x00000100;
66        /// New 4.1 protocol
67        const CLIENT_PROTOCOL_41 = 0x00000200;
68        /// Interactive client (affects timeout)
69        const CLIENT_INTERACTIVE = 0x00000400;
70        /// Use SSL encryption for the session
71        const CLIENT_SSL = 0x00000800;
72        /// Client will not issue SIGPIPE (client-only, not sent to server)
73        const CLIENT_IGNORE_SIGPIPE = 0x00001000;
74        /// Client knows about transactions
75        const CLIENT_TRANSACTIONS = 0x00002000;
76        /// Old flag for 4.1 protocol (deprecated)
77        const CLIENT_RESERVED = 0x00004000;
78        /// Old flag for 4.1 authentication (deprecated)
79        const CLIENT_SECURE_CONNECTION = 0x00008000;
80        /// Enable multi-statement support
81        const CLIENT_MULTI_STATEMENTS = 0x00010000;
82        /// Enable multi-results
83        const CLIENT_MULTI_RESULTS = 0x00020000;
84        /// Multi-results in prepared statements
85        const CLIENT_PS_MULTI_RESULTS = 0x00040000;
86        /// Pluggable authentication
87        const CLIENT_PLUGIN_AUTH = 0x00080000;
88        /// Connection attributes
89        const CLIENT_CONNECT_ATTRS = 0x00100000;
90        /// Enable authentication response larger than 255 bytes
91        const CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA = 0x00200000;
92        /// Can handle expired passwords
93        const CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS = 0x00400000;
94        /// Track session state changes
95        const CLIENT_SESSION_TRACK = 0x00800000;
96        /// Use OK instead of EOF packet
97        const CLIENT_DEPRECATE_EOF = 0x01000000;
98        /// Optional metadata in resultsets
99        const CLIENT_OPTIONAL_RESULTSET_METADATA = 0x02000000;
100        /// Support zstd compression
101        const CLIENT_ZSTD_COMPRESSION_ALGORITHM = 0x04000000;
102        /// Query attributes support
103        const CLIENT_QUERY_ATTRIBUTES = 0x08000000;
104        /// Multi-factor authentication
105        const CLIENT_MULTI_FACTOR_AUTHENTICATION = 0x10000000;
106        /// Reserved for capability extension
107        const CLIENT_CAPABILITY_EXTENSION = 0x20000000;
108        /// Verify server certificate (deprecated, use --ssl-mode)
109        const CLIENT_SSL_VERIFY_SERVER_CERT = 0x40000000;
110        /// Remember options after failed connect (client-only, not sent to server)
111        const CLIENT_REMEMBER_OPTIONS = 0x80000000;
112    }
113}
114
115impl CapabilityFlags {
116    /// Check if the server is MySQL (as opposed to MariaDB)
117    ///
118    /// MariaDB unsets the CLIENT_LONG_PASSWORD flag to distinguish itself from MySQL.
119    #[inline]
120    pub fn is_mysql(&self) -> bool {
121        self.contains(CapabilityFlags::CLIENT_LONG_PASSWORD)
122    }
123    #[inline]
124    pub fn is_mariadb(&self) -> bool {
125        !self.is_mysql()
126    }
127}
128
129// Capabilities that are always enabled (required by zero-mysql)
130pub const CAPABILITIES_ALWAYS_ENABLED: CapabilityFlags = CapabilityFlags::CLIENT_LONG_PASSWORD
131    .union(CapabilityFlags::CLIENT_LONG_FLAG)
132    .union(CapabilityFlags::CLIENT_PROTOCOL_41)
133    .union(CapabilityFlags::CLIENT_TRANSACTIONS)
134    .union(CapabilityFlags::CLIENT_MULTI_STATEMENTS)
135    .union(CapabilityFlags::CLIENT_MULTI_RESULTS)
136    .union(CapabilityFlags::CLIENT_PS_MULTI_RESULTS) // prepared statement multi-resultset
137    .union(CapabilityFlags::CLIENT_SECURE_CONNECTION) // On? Off?
138    .union(CapabilityFlags::CLIENT_PLUGIN_AUTH)
139    .union(CapabilityFlags::CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA)
140    .union(CapabilityFlags::CLIENT_DEPRECATE_EOF);
141
142// Capabilities that are configurable by user
143pub const CAPABILITIES_CONFIGURABLE: CapabilityFlags = CapabilityFlags::CLIENT_FOUND_ROWS
144    .union(CapabilityFlags::CLIENT_COMPRESS)
145    .union(CapabilityFlags::CLIENT_LOCAL_FILES)
146    .union(CapabilityFlags::CLIENT_IGNORE_SPACE)
147    .union(CapabilityFlags::CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS);
148
149// Capabilities that are always disabled (deprecated, not implemented, or not applicable)
150pub const CAPABILITIES_ALWAYS_DISABLED: CapabilityFlags =
151    CapabilityFlags::CLIENT_CONNECT_WITH_DB // This is automatically set if opts.db is provided
152        .union(CapabilityFlags::CLIENT_OPTIONAL_RESULTSET_METADATA) // TODO
153        .union(CapabilityFlags::CLIENT_NO_SCHEMA)
154        .union(CapabilityFlags::CLIENT_ODBC)
155        .union(CapabilityFlags::CLIENT_INTERACTIVE)
156        .union(CapabilityFlags::CLIENT_IGNORE_SIGPIPE)
157        .union(CapabilityFlags::CLIENT_RESERVED)
158        .union(CapabilityFlags::CLIENT_QUERY_ATTRIBUTES)
159        .union(CapabilityFlags::CLIENT_ZSTD_COMPRESSION_ALGORITHM)
160        .union(CapabilityFlags::CLIENT_MULTI_FACTOR_AUTHENTICATION)
161        .union(CapabilityFlags::CLIENT_CAPABILITY_EXTENSION)
162        .union(CapabilityFlags::CLIENT_SSL) // set by opts.tls
163        .union(CapabilityFlags::CLIENT_SSL_VERIFY_SERVER_CERT)
164        .union(CapabilityFlags::CLIENT_REMEMBER_OPTIONS)
165        .union(CapabilityFlags::CLIENT_CONNECT_ATTRS) // TODO
166        .union(CapabilityFlags::CLIENT_SESSION_TRACK); // To support this flag, we need to update the parsing logic
167
168bitflags::bitflags! {
169    /// MariaDB Extension Capability Flags
170    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
171    pub struct MariadbCapabilityFlags: u32 {
172        // ─── Mariadb Extensions ──────────────────────────────────────
173        const MARIADB_CLIENT_PROGRESS = 1 << 0;
174        const MARIADB_CLIENT_COM_MULTI = 1 << 1; // TODO: COM_MULTI?
175        const MARIADB_CLIENT_STMT_BULK_OPERATIONS = 1 << 2;
176        const MARIADB_CLIENT_EXTENDED_METADATA = 1 << 3; // TODO: implement
177        const MARIADB_CLIENT_CACHE_METADATA = 1 << 4;
178        const MARIADB_CLIENT_BULK_UNIT_RESULTS = 1 << 5; // TODO: needs MariaDB 12.x, but most distributions are 10.x or 11.x now
179    }
180}
181
182pub const MARIADB_CAPABILITIES_ENABLED: MariadbCapabilityFlags =
183    MariadbCapabilityFlags::MARIADB_CLIENT_STMT_BULK_OPERATIONS
184        .union(MariadbCapabilityFlags::MARIADB_CLIENT_CACHE_METADATA);
185
186bitflags::bitflags! {
187    /// MySQL Server Status Flags
188    /// Note: 0x0004 does not exist in the protocol
189    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
190    pub struct ServerStatusFlags: u16 {
191        /// A transaction is active
192        const SERVER_STATUS_IN_TRANS = 0x0001;
193        /// Autocommit mode is enabled
194        const SERVER_STATUS_AUTOCOMMIT = 0x0002;
195        /// More results exist (for multi-statement or multi-resultset)
196        const SERVER_MORE_RESULTS_EXISTS = 0x0008;
197        /// Query did not use a good index
198        const SERVER_STATUS_NO_GOOD_INDEX_USED = 0x0010;
199        /// Query did not use any index
200        const SERVER_STATUS_NO_INDEX_USED = 0x0020;
201        /// Cursor exists (for prepared statements)
202        const SERVER_STATUS_CURSOR_EXISTS = 0x0040;
203        /// Last row was sent
204        const SERVER_STATUS_LAST_ROW_SENT = 0x0080;
205        /// Database was dropped
206        const SERVER_STATUS_DB_DROPPED = 0x0100;
207        /// No backslash escapes mode is enabled
208        const SERVER_STATUS_NO_BACKSLASH_ESCAPES = 0x0200;
209        /// Metadata changed (for prepared statements)
210        const SERVER_STATUS_METADATA_CHANGED = 0x0400;
211        /// Query was slow
212        const SERVER_QUERY_WAS_SLOW = 0x0800;
213        /// Prepared statement has output parameters
214        const SERVER_PS_OUT_PARAMS = 0x1000;
215        /// In a read-only transaction
216        const SERVER_STATUS_IN_TRANS_READONLY = 0x2000;
217        /// Session state has changed
218        const SERVER_SESSION_STATE_CHANGED = 0x4000;
219    }
220}
221
222bitflags::bitflags! {
223    /// MySQL Column Definition Flags
224    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
225    pub struct ColumnFlags: u16 {
226        /// Field can't be NULL
227        const NOT_NULL_FLAG = 0x0001;
228        /// Field is part of a primary key
229        const PRI_KEY_FLAG = 0x0002;
230        /// Field is part of a unique key
231        const UNIQUE_KEY_FLAG = 0x0004;
232        /// Field is part of a key
233        const MULTIPLE_KEY_FLAG = 0x0008;
234        /// Field is a blob
235        const BLOB_FLAG = 0x0010;
236        /// Field is unsigned
237        const UNSIGNED_FLAG = 0x0020;
238        /// Field is zerofill
239        const ZEROFILL_FLAG = 0x0040;
240        /// Field is binary
241        const BINARY_FLAG = 0x0080;
242        /// Field is an enum
243        const ENUM_FLAG = 0x0100;
244        /// Field is auto-increment
245        const AUTO_INCREMENT_FLAG = 0x0200;
246        /// Field is a timestamp
247        const TIMESTAMP_FLAG = 0x0400;
248        /// Field is a set
249        const SET_FLAG = 0x0800;
250        /// Field has no default value
251        const NO_DEFAULT_VALUE_FLAG = 0x1000;
252        /// Field is set to NOW on UPDATE
253        const ON_UPDATE_NOW_FLAG = 0x2000;
254        /// Field is part of some key (index)
255        const PART_KEY_FLAG = 0x4000;
256        /// Field is numeric
257        const NUM_FLAG = 0x8000;
258    }
259}
260
261#[expect(non_camel_case_types)]
262#[repr(u8)]
263#[derive(Debug, Clone, Copy, PartialEq, Eq)]
264pub enum ColumnType {
265    MYSQL_TYPE_DECIMAL = 0x00,
266    MYSQL_TYPE_TINY = 0x01,
267    MYSQL_TYPE_SHORT = 0x02,
268    MYSQL_TYPE_LONG = 0x03,
269    MYSQL_TYPE_FLOAT = 0x04,
270    MYSQL_TYPE_DOUBLE = 0x05,
271    MYSQL_TYPE_NULL = 0x06,
272    MYSQL_TYPE_TIMESTAMP = 0x07,
273    MYSQL_TYPE_LONGLONG = 0x08,
274    MYSQL_TYPE_INT24 = 0x09,
275    MYSQL_TYPE_DATE = 0x0a,
276    MYSQL_TYPE_TIME = 0x0b,
277    MYSQL_TYPE_DATETIME = 0x0c,
278    MYSQL_TYPE_YEAR = 0x0d,
279    MYSQL_TYPE_NEWDATE = 0x0e,
280    MYSQL_TYPE_VARCHAR = 0x0f,
281    MYSQL_TYPE_BIT = 0x10,
282    MYSQL_TYPE_TIMESTAMP2 = 0x11,
283    MYSQL_TYPE_DATETIME2 = 0x12,
284    MYSQL_TYPE_TIME2 = 0x13,
285    MYSQL_TYPE_TYPED_ARRAY = 0x14,
286    MYSQL_TYPE_JSON = 0xf5,
287    MYSQL_TYPE_NEWDECIMAL = 0xf6,
288    MYSQL_TYPE_ENUM = 0xf7,
289    MYSQL_TYPE_SET = 0xf8,
290    MYSQL_TYPE_TINY_BLOB = 0xf9,
291    MYSQL_TYPE_MEDIUM_BLOB = 0xfa,
292    MYSQL_TYPE_LONG_BLOB = 0xfb,
293    MYSQL_TYPE_BLOB = 0xfc,
294    MYSQL_TYPE_VAR_STRING = 0xfd,
295    MYSQL_TYPE_STRING = 0xfe,
296    MYSQL_TYPE_GEOMETRY = 0xff,
297}
298
299impl ColumnType {
300    pub fn from_u8(value: u8) -> Option<Self> {
301        match value {
302            0x00 => Some(Self::MYSQL_TYPE_DECIMAL),
303            0x01 => Some(Self::MYSQL_TYPE_TINY),
304            0x02 => Some(Self::MYSQL_TYPE_SHORT),
305            0x03 => Some(Self::MYSQL_TYPE_LONG),
306            0x04 => Some(Self::MYSQL_TYPE_FLOAT),
307            0x05 => Some(Self::MYSQL_TYPE_DOUBLE),
308            0x06 => Some(Self::MYSQL_TYPE_NULL),
309            0x07 => Some(Self::MYSQL_TYPE_TIMESTAMP),
310            0x08 => Some(Self::MYSQL_TYPE_LONGLONG),
311            0x09 => Some(Self::MYSQL_TYPE_INT24),
312            0x0a => Some(Self::MYSQL_TYPE_DATE),
313            0x0b => Some(Self::MYSQL_TYPE_TIME),
314            0x0c => Some(Self::MYSQL_TYPE_DATETIME),
315            0x0d => Some(Self::MYSQL_TYPE_YEAR),
316            0x0e => Some(Self::MYSQL_TYPE_NEWDATE),
317            0x0f => Some(Self::MYSQL_TYPE_VARCHAR),
318            0x10 => Some(Self::MYSQL_TYPE_BIT),
319            0x11 => Some(Self::MYSQL_TYPE_TIMESTAMP2),
320            0x12 => Some(Self::MYSQL_TYPE_DATETIME2),
321            0x13 => Some(Self::MYSQL_TYPE_TIME2),
322            0x14 => Some(Self::MYSQL_TYPE_TYPED_ARRAY),
323            0xf5 => Some(Self::MYSQL_TYPE_JSON),
324            0xf6 => Some(Self::MYSQL_TYPE_NEWDECIMAL),
325            0xf7 => Some(Self::MYSQL_TYPE_ENUM),
326            0xf8 => Some(Self::MYSQL_TYPE_SET),
327            0xf9 => Some(Self::MYSQL_TYPE_TINY_BLOB),
328            0xfa => Some(Self::MYSQL_TYPE_MEDIUM_BLOB),
329            0xfb => Some(Self::MYSQL_TYPE_LONG_BLOB),
330            0xfc => Some(Self::MYSQL_TYPE_BLOB),
331            0xfd => Some(Self::MYSQL_TYPE_VAR_STRING),
332            0xfe => Some(Self::MYSQL_TYPE_STRING),
333            0xff => Some(Self::MYSQL_TYPE_GEOMETRY),
334            _ => None,
335        }
336    }
337}