sqlx_core_guts/mysql/
value.rs1use crate::error::{BoxDynError, UnexpectedNullError};
2use crate::mysql::protocol::text::ColumnType;
3use crate::mysql::{MySql, MySqlTypeInfo};
4use crate::value::{Value, ValueRef};
5use bytes::Bytes;
6use std::borrow::Cow;
7use std::str::from_utf8;
8
9#[derive(Debug, Clone, Copy)]
10#[repr(u8)]
11pub enum MySqlValueFormat {
12 Text,
13 Binary,
14}
15
16#[derive(Clone)]
18pub struct MySqlValue {
19 value: Option<Bytes>,
20 type_info: MySqlTypeInfo,
21 format: MySqlValueFormat,
22}
23
24#[derive(Clone)]
26pub struct MySqlValueRef<'r> {
27 pub(crate) value: Option<&'r [u8]>,
28 pub(crate) row: Option<&'r Bytes>,
29 pub(crate) type_info: MySqlTypeInfo,
30 pub(crate) format: MySqlValueFormat,
31}
32
33impl<'r> MySqlValueRef<'r> {
34 pub(crate) fn format(&self) -> MySqlValueFormat {
35 self.format
36 }
37
38 pub(crate) fn as_bytes(&self) -> Result<&'r [u8], BoxDynError> {
39 match &self.value {
40 Some(v) => Ok(v),
41 None => Err(UnexpectedNullError.into()),
42 }
43 }
44
45 pub(crate) fn as_str(&self) -> Result<&'r str, BoxDynError> {
46 Ok(from_utf8(self.as_bytes()?)?)
47 }
48}
49
50impl Value for MySqlValue {
51 type Database = MySql;
52
53 fn as_ref(&self) -> MySqlValueRef<'_> {
54 MySqlValueRef {
55 value: self.value.as_deref(),
56 row: None,
57 type_info: self.type_info.clone(),
58 format: self.format,
59 }
60 }
61
62 fn type_info(&self) -> Cow<'_, MySqlTypeInfo> {
63 Cow::Borrowed(&self.type_info)
64 }
65
66 fn is_null(&self) -> bool {
67 is_null(self.value.as_deref(), &self.type_info)
68 }
69}
70
71impl<'r> ValueRef<'r> for MySqlValueRef<'r> {
72 type Database = MySql;
73
74 fn to_owned(&self) -> MySqlValue {
75 let value = match (self.row, self.value) {
76 (Some(row), Some(value)) => Some(row.slice_ref(value)),
77
78 (None, Some(value)) => Some(Bytes::copy_from_slice(value)),
79
80 _ => None,
81 };
82
83 MySqlValue {
84 value,
85 format: self.format,
86 type_info: self.type_info.clone(),
87 }
88 }
89
90 fn type_info(&self) -> Cow<'_, MySqlTypeInfo> {
91 Cow::Borrowed(&self.type_info)
92 }
93
94 #[inline]
95 fn is_null(&self) -> bool {
96 is_null(self.value.as_deref(), &self.type_info)
97 }
98}
99
100#[cfg(feature = "any")]
101impl<'r> From<MySqlValueRef<'r>> for crate::any::AnyValueRef<'r> {
102 #[inline]
103 fn from(value: MySqlValueRef<'r>) -> Self {
104 crate::any::AnyValueRef {
105 type_info: value.type_info.clone().into(),
106 kind: crate::any::value::AnyValueRefKind::MySql(value),
107 }
108 }
109}
110
111#[cfg(feature = "any")]
112impl From<MySqlValue> for crate::any::AnyValue {
113 #[inline]
114 fn from(value: MySqlValue) -> Self {
115 crate::any::AnyValue {
116 type_info: value.type_info.clone().into(),
117 kind: crate::any::value::AnyValueKind::MySql(value),
118 }
119 }
120}
121
122fn is_null(value: Option<&[u8]>, ty: &MySqlTypeInfo) -> bool {
123 if let Some(value) = value {
124 if matches!(
126 ty.r#type,
127 ColumnType::Date | ColumnType::Timestamp | ColumnType::Datetime
128 ) && value.get(0) == Some(&0)
129 {
130 return true;
131 }
132 }
133
134 value.is_none()
135}