sqlx_mysql/protocol/text/
column.rs1use std::str::from_utf8;
2
3use bitflags::bitflags;
4use bytes::{Buf, Bytes};
5
6use crate::error::Error;
7use crate::io::MySqlBufExt;
8use crate::io::ProtocolDecode;
9use crate::protocol::Capabilities;
10
11bitflags! {
14 #[cfg_attr(feature = "offline", derive(serde::Serialize, serde::Deserialize))]
15 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16 pub(crate) struct ColumnFlags: u16 {
17 const NOT_NULL = 1;
19
20 const PRIMARY_KEY = 2;
22
23 const UNIQUE_KEY = 4;
25
26 const MULTIPLE_KEY = 8;
28
29 const BLOB = 16;
31
32 const UNSIGNED = 32;
34
35 const ZEROFILL = 64;
37
38 const BINARY = 128;
40
41 const ENUM = 256;
43
44 const AUTO_INCREMENT = 512;
46
47 const TIMESTAMP = 1024;
49
50 const SET = 2048;
52
53 const NO_DEFAULT_VALUE = 4096;
55
56 const ON_UPDATE_NOW = 8192;
58
59 const NUM = 32768;
61 }
62}
63
64#[derive(Debug, Copy, Clone, PartialEq)]
67#[cfg_attr(feature = "offline", derive(serde::Serialize, serde::Deserialize))]
68#[repr(u8)]
69pub enum ColumnType {
70 Decimal = 0x00,
71 Tiny = 0x01,
72 Short = 0x02,
73 Long = 0x03,
74 Float = 0x04,
75 Double = 0x05,
76 Null = 0x06,
77 Timestamp = 0x07,
78 LongLong = 0x08,
79 Int24 = 0x09,
80 Date = 0x0a,
81 Time = 0x0b,
82 Datetime = 0x0c,
83 Year = 0x0d,
84 VarChar = 0x0f,
85 Bit = 0x10,
86 Json = 0xf5,
87 NewDecimal = 0xf6,
88 Enum = 0xf7,
89 Set = 0xf8,
90 TinyBlob = 0xf9,
91 MediumBlob = 0xfa,
92 LongBlob = 0xfb,
93 Blob = 0xfc,
94 VarString = 0xfd,
95 String = 0xfe,
96 Geometry = 0xff,
97}
98
99#[derive(Debug)]
104pub(crate) struct ColumnDefinition {
105 #[allow(unused)]
106 catalog: Bytes,
107 #[allow(unused)]
108 schema: Bytes,
109 #[allow(unused)]
110 table_alias: Bytes,
111 #[allow(unused)]
112 table: Bytes,
113 alias: Bytes,
114 name: Bytes,
115 #[allow(unused)]
116 pub(crate) collation: u16,
117 pub(crate) max_size: u32,
118 pub(crate) r#type: ColumnType,
119 pub(crate) flags: ColumnFlags,
120 #[allow(unused)]
121 decimals: u8,
122}
123
124impl ColumnDefinition {
125 pub(crate) fn name(&self) -> Result<&str, Error> {
129 from_utf8(&self.name).map_err(Error::protocol)
130 }
131
132 pub(crate) fn alias(&self) -> Result<&str, Error> {
133 from_utf8(&self.alias).map_err(Error::protocol)
134 }
135}
136
137impl ProtocolDecode<'_, Capabilities> for ColumnDefinition {
138 fn decode_with(mut buf: Bytes, _: Capabilities) -> Result<Self, Error> {
139 let catalog = buf.get_bytes_lenenc()?;
140 let schema = buf.get_bytes_lenenc()?;
141 let table_alias = buf.get_bytes_lenenc()?;
142 let table = buf.get_bytes_lenenc()?;
143 let alias = buf.get_bytes_lenenc()?;
144 let name = buf.get_bytes_lenenc()?;
145 let _next_len = buf.get_uint_lenenc(); let collation = buf.get_u16_le();
147 let max_size = buf.get_u32_le();
148 let type_id = buf.get_u8();
149 let flags = buf.get_u16_le();
150 let decimals = buf.get_u8();
151
152 Ok(Self {
153 catalog,
154 schema,
155 table_alias,
156 table,
157 alias,
158 name,
159 collation,
160 max_size,
161 r#type: ColumnType::try_from_u16(type_id)?,
162 flags: ColumnFlags::from_bits_truncate(flags),
163 decimals,
164 })
165 }
166}
167
168impl ColumnType {
169 pub(crate) fn name(self, flags: ColumnFlags, max_size: Option<u32>) -> &'static str {
170 let is_binary = flags.contains(ColumnFlags::BINARY);
171 let is_unsigned = flags.contains(ColumnFlags::UNSIGNED);
172 let is_enum = flags.contains(ColumnFlags::ENUM);
173
174 match self {
175 ColumnType::Tiny if max_size == Some(1) => "BOOLEAN",
176 ColumnType::Tiny if is_unsigned => "TINYINT UNSIGNED",
177 ColumnType::Short if is_unsigned => "SMALLINT UNSIGNED",
178 ColumnType::Long if is_unsigned => "INT UNSIGNED",
179 ColumnType::Int24 if is_unsigned => "MEDIUMINT UNSIGNED",
180 ColumnType::LongLong if is_unsigned => "BIGINT UNSIGNED",
181 ColumnType::Tiny => "TINYINT",
182 ColumnType::Short => "SMALLINT",
183 ColumnType::Long => "INT",
184 ColumnType::Int24 => "MEDIUMINT",
185 ColumnType::LongLong => "BIGINT",
186 ColumnType::Float => "FLOAT",
187 ColumnType::Double => "DOUBLE",
188 ColumnType::Null => "NULL",
189 ColumnType::Timestamp => "TIMESTAMP",
190 ColumnType::Date => "DATE",
191 ColumnType::Time => "TIME",
192 ColumnType::Datetime => "DATETIME",
193 ColumnType::Year => "YEAR",
194 ColumnType::Bit => "BIT",
195 ColumnType::Enum => "ENUM",
196 ColumnType::Set => "SET",
197 ColumnType::Decimal | ColumnType::NewDecimal => "DECIMAL",
198 ColumnType::Geometry => "GEOMETRY",
199 ColumnType::Json => "JSON",
200
201 ColumnType::String if is_binary => "BINARY",
202 ColumnType::String if is_enum => "ENUM",
203 ColumnType::VarChar | ColumnType::VarString if is_binary => "VARBINARY",
204
205 ColumnType::String => "CHAR",
206 ColumnType::VarChar | ColumnType::VarString => "VARCHAR",
207
208 ColumnType::TinyBlob if is_binary => "TINYBLOB",
209 ColumnType::TinyBlob => "TINYTEXT",
210
211 ColumnType::Blob if is_binary => "BLOB",
212 ColumnType::Blob => "TEXT",
213
214 ColumnType::MediumBlob if is_binary => "MEDIUMBLOB",
215 ColumnType::MediumBlob => "MEDIUMTEXT",
216
217 ColumnType::LongBlob if is_binary => "LONGBLOB",
218 ColumnType::LongBlob => "LONGTEXT",
219 }
220 }
221
222 pub(crate) fn try_from_u16(id: u8) -> Result<Self, Error> {
223 Ok(match id {
224 0x00 => ColumnType::Decimal,
225 0x01 => ColumnType::Tiny,
226 0x02 => ColumnType::Short,
227 0x03 => ColumnType::Long,
228 0x04 => ColumnType::Float,
229 0x05 => ColumnType::Double,
230 0x06 => ColumnType::Null,
231 0x07 => ColumnType::Timestamp,
232 0x08 => ColumnType::LongLong,
233 0x09 => ColumnType::Int24,
234 0x0a => ColumnType::Date,
235 0x0b => ColumnType::Time,
236 0x0c => ColumnType::Datetime,
237 0x0d => ColumnType::Year,
238 0x0f => ColumnType::VarChar,
240 0x10 => ColumnType::Bit,
241 0xf5 => ColumnType::Json,
245 0xf6 => ColumnType::NewDecimal,
246 0xf7 => ColumnType::Enum,
247 0xf8 => ColumnType::Set,
248 0xf9 => ColumnType::TinyBlob,
249 0xfa => ColumnType::MediumBlob,
250 0xfb => ColumnType::LongBlob,
251 0xfc => ColumnType::Blob,
252 0xfd => ColumnType::VarString,
253 0xfe => ColumnType::String,
254 0xff => ColumnType::Geometry,
255
256 _ => {
257 return Err(err_protocol!("unknown column type 0x{:02x}", id));
258 }
259 })
260 }
261}