sqlx_core/mysql/protocol/statement/
row.rs1use bytes::{Buf, Bytes};
2
3use crate::error::Error;
4use crate::io::{BufExt, Decode};
5use crate::mysql::io::MySqlBufExt;
6use crate::mysql::protocol::text::ColumnType;
7use crate::mysql::protocol::Row;
8use crate::mysql::MySqlColumn;
9
10#[derive(Debug)]
14pub(crate) struct BinaryRow(pub(crate) Row);
15
16impl<'de> Decode<'de, &'de [MySqlColumn]> for BinaryRow {
17 fn decode_with(mut buf: Bytes, columns: &'de [MySqlColumn]) -> Result<Self, Error> {
18 let header = buf.get_u8();
19 if header != 0 {
20 return Err(err_protocol!(
21 "exepcted 0x00 (ROW) but found 0x{:02x}",
22 header
23 ));
24 }
25
26 let storage = buf.clone();
27 let offset = buf.len();
28
29 let null_bitmap_len = (columns.len() + 9) / 8;
30 let null_bitmap = buf.get_bytes(null_bitmap_len);
31
32 let mut values = Vec::with_capacity(columns.len());
33
34 for (column_idx, column) in columns.iter().enumerate() {
35 let column_null_idx = column_idx + 2;
37 let is_null =
38 null_bitmap[column_null_idx / 8] & (1 << (column_null_idx % 8) as u8) != 0;
39
40 if is_null {
41 values.push(None);
42 continue;
43 }
44
45 let type_info = &column.type_info;
47
48 let size: usize = match type_info.r#type {
49 ColumnType::String
50 | ColumnType::VarChar
51 | ColumnType::VarString
52 | ColumnType::Enum
53 | ColumnType::Set
54 | ColumnType::LongBlob
55 | ColumnType::MediumBlob
56 | ColumnType::Blob
57 | ColumnType::TinyBlob
58 | ColumnType::Geometry
59 | ColumnType::Bit
60 | ColumnType::Decimal
61 | ColumnType::Json
62 | ColumnType::NewDecimal => buf.get_uint_lenenc() as usize,
63
64 ColumnType::LongLong => 8,
65 ColumnType::Long | ColumnType::Int24 => 4,
66 ColumnType::Short | ColumnType::Year => 2,
67 ColumnType::Tiny => 1,
68 ColumnType::Float => 4,
69 ColumnType::Double => 8,
70
71 ColumnType::Time
72 | ColumnType::Timestamp
73 | ColumnType::Date
74 | ColumnType::Datetime => {
75 buf[0] as usize + 1
77 }
78
79 ColumnType::Null => unreachable!(),
81 };
82
83 let offset = offset - buf.len();
84
85 values.push(Some(offset..(offset + size)));
86
87 buf.advance(size);
88 }
89
90 Ok(BinaryRow(Row { values, storage }))
91 }
92}