sqlx_mysql/types/
text.rs

1use crate::{MySql, MySqlTypeInfo, MySqlValueRef};
2use sqlx_core::decode::Decode;
3use sqlx_core::encode::{Encode, IsNull};
4use sqlx_core::error::BoxDynError;
5use sqlx_core::types::{Text, Type};
6use std::fmt::Display;
7use std::str::FromStr;
8
9impl<T> Type<MySql> for Text<T> {
10    fn type_info() -> MySqlTypeInfo {
11        <String as Type<MySql>>::type_info()
12    }
13
14    fn compatible(ty: &MySqlTypeInfo) -> bool {
15        <String as Type<MySql>>::compatible(ty)
16    }
17}
18
19impl<'q, T> Encode<'q, MySql> for Text<T>
20where
21    T: Display,
22{
23    fn encode_by_ref(&self, buf: &mut Vec<u8>) -> Result<IsNull, BoxDynError> {
24        // We can't really do the trick like with Postgres where we reserve the space for the
25        // length up-front and then overwrite it later, because MySQL appears to enforce that
26        // length-encoded integers use the smallest encoding for the value:
27        // https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_basic_dt_integers.html#sect_protocol_basic_dt_int_le
28        //
29        // So we'd have to reserve space for the max-width encoding, format into the buffer,
30        // then figure out how many bytes our length-encoded integer needs to be and move the
31        // value bytes down to use up the empty space.
32        //
33        // Copying from a completely separate buffer instead is easier. It may or may not be faster
34        // or slower depending on a ton of different variables, but I don't currently have the time
35        // to implement both approaches and compare their performance.
36        Encode::<MySql>::encode(self.0.to_string(), buf)
37    }
38}
39
40impl<'r, T> Decode<'r, MySql> for Text<T>
41where
42    T: FromStr,
43    BoxDynError: From<<T as FromStr>::Err>,
44{
45    fn decode(value: MySqlValueRef<'r>) -> Result<Self, BoxDynError> {
46        let s: &str = Decode::<MySql>::decode(value)?;
47        Ok(Self(s.parse()?))
48    }
49}