rbdc_mysql/
value.rs

1use crate::protocol::text::ColumnType;
2use crate::result_set::MySqlTypeInfo;
3use rbdc::Error;
4use std::borrow::Cow;
5use std::str::from_utf8;
6use std::sync::Arc;
7use crate::options::MySqlConnectOptions;
8
9#[derive(Debug, Clone, Copy,Eq,PartialEq)]
10#[repr(u8)]
11pub enum MySqlValueFormat {
12    Text,
13    Binary,
14}
15
16/// Implementation of [`Value`] for MySQL.
17#[derive(Clone)]
18pub struct MySqlValue {
19    pub(crate) value: Option<Vec<u8>>,
20    pub(crate) type_info: MySqlTypeInfo,
21    pub(crate) format: MySqlValueFormat,
22    pub(crate) option: Arc<MySqlConnectOptions>,
23}
24
25/// Implementation of [`ValueRef`] for MySQL.
26#[derive(Clone)]
27pub struct MySqlValueRef<'r> {
28    pub(crate) value: Option<&'r [u8]>,
29    pub(crate) type_info: MySqlTypeInfo,
30    pub(crate) format: MySqlValueFormat,
31}
32
33impl MySqlValue {
34    pub fn format(&self) -> MySqlValueFormat {
35        self.format
36    }
37
38    pub fn as_bytes(&self) -> Result<&[u8], Error> {
39        match &self.value {
40            Some(v) => Ok(v),
41            None => Err(Error::protocol("UnexpectedNull")),
42        }
43    }
44
45    pub fn as_str(&self) -> Result<&str, Error> {
46        Ok(from_utf8(self.as_bytes()?)?)
47    }
48}
49
50impl<'r> MySqlValueRef<'r> {
51    pub(crate) fn format(&self) -> MySqlValueFormat {
52        self.format
53    }
54
55    pub(crate) fn as_bytes(&self) -> Result<&'r [u8], Error> {
56        match &self.value {
57            Some(v) => Ok(v),
58            None => Err(Error::protocol("UnexpectedNull")),
59        }
60    }
61
62    pub(crate) fn as_str(&self) -> Result<&'r str, Error> {
63        Ok(from_utf8(self.as_bytes()?)?)
64    }
65}
66
67impl MySqlValue {
68    fn as_ref(&self) -> MySqlValueRef<'_> {
69        MySqlValueRef {
70            value: self.value.as_deref(),
71            type_info: self.type_info.clone(),
72            format: self.format,
73        }
74    }
75
76    pub fn type_info(&self) -> Cow<'_, MySqlTypeInfo> {
77        Cow::Borrowed(&self.type_info)
78    }
79
80    pub fn is_null(&self) -> bool {
81        is_null(self.value.as_deref(), &self.type_info)
82    }
83}
84
85fn is_null(value: Option<&[u8]>, ty: &MySqlTypeInfo) -> bool {
86    if let Some(value) = value {
87        // zero dates and date times should be treated the same as NULL
88        if matches!(
89            ty.r#type,
90            ColumnType::Date | ColumnType::Timestamp | ColumnType::Datetime
91        ) && value.get(0) == Some(&0)
92        {
93            return true;
94        }
95    }
96
97    value.is_none()
98}