Skip to main content

sqlx_xugu/types/
str.rs

1use crate::arguments::XuguArgumentValue;
2use crate::protocol::text::{ColumnFlags, ColumnType};
3use crate::{Xugu, XuguTypeInfo, XuguValueRef};
4
5use sqlx_core::decode::Decode;
6use sqlx_core::encode::{Encode, IsNull};
7use sqlx_core::error::BoxDynError;
8use sqlx_core::types::Type;
9use sqlx_core::value::ValueRef;
10use std::borrow::Cow;
11
12impl Type<Xugu> for str {
13    fn type_info() -> XuguTypeInfo {
14        XuguTypeInfo {
15            r#type: ColumnType::CHAR,
16            flags: ColumnFlags::empty(),
17        }
18    }
19
20    fn compatible(ty: &XuguTypeInfo) -> bool {
21        matches!(
22            ty.r#type,
23            ColumnType::BLOB
24                | ColumnType::BLOB_I
25                | ColumnType::BLOB_M
26                | ColumnType::BLOB_OM
27                | ColumnType::BLOB_S
28                | ColumnType::CLOB
29                | ColumnType::BINARY
30                | ColumnType::NUMERIC
31                | ColumnType::TINYINT
32                | ColumnType::SMALLINT
33                | ColumnType::INTEGER
34                | ColumnType::BIGINT
35                | ColumnType::BOOLEAN
36                | ColumnType::CHAR
37                | ColumnType::NCHAR
38                | ColumnType::GUID
39                | ColumnType::ROWID
40                | ColumnType::ROWVERSION
41                | ColumnType::ARRAY
42                | ColumnType::VECTOR
43                | ColumnType::HALFVEC
44                | ColumnType::SPARSEVEC
45
46                // 几何类型 按字符串编解码
47                | ColumnType::POINT
48                | ColumnType::LSEG
49                | ColumnType::PATH
50                | ColumnType::BOX
51                | ColumnType::POLYGON
52                | ColumnType::LINE
53                | ColumnType::CIRCLE
54                | ColumnType::GEOMETRY
55                | ColumnType::GEOGRAPHY
56                | ColumnType::BOX2D
57                | ColumnType::BOX3D
58                | ColumnType::SPHEROID
59                | ColumnType::RASTER
60        )
61    }
62}
63
64impl<'q> Encode<'q, Xugu> for &'q str {
65    fn encode_by_ref(&self, args: &mut Vec<XuguArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
66        if self.is_empty() {
67            args.push(XuguArgumentValue::Str(Cow::Borrowed("\0")));
68        } else {
69            args.push(XuguArgumentValue::Str(Cow::Borrowed(*self)));
70        }
71
72        Ok(IsNull::No)
73    }
74}
75
76impl<'q> Decode<'q, Xugu> for &'q str {
77    fn decode(value: XuguValueRef<'q>) -> Result<Self, BoxDynError> {
78        value.as_str().map(map_empty)
79    }
80}
81
82impl Type<Xugu> for Box<str> {
83    fn type_info() -> XuguTypeInfo {
84        <&str as Type<Xugu>>::type_info()
85    }
86
87    fn compatible(ty: &XuguTypeInfo) -> bool {
88        <&str as Type<Xugu>>::compatible(ty)
89    }
90}
91
92impl Encode<'_, Xugu> for Box<str> {
93    fn encode(self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
94        if self.is_empty() {
95            args.push(XuguArgumentValue::Str(Cow::Borrowed("\0")));
96        } else {
97            args.push(XuguArgumentValue::Str(Cow::Owned(self.into_string())));
98        }
99
100        Ok(IsNull::No)
101    }
102
103    fn encode_by_ref(&self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
104        if self.is_empty() {
105            args.push(XuguArgumentValue::Str(Cow::Borrowed("\0")));
106        } else {
107            args.push(XuguArgumentValue::Str(Cow::Owned(
108                self.clone().into_string(),
109            )));
110        }
111
112        Ok(IsNull::No)
113    }
114}
115
116impl<'r> Decode<'r, Xugu> for Box<str> {
117    fn decode(value: XuguValueRef<'r>) -> Result<Self, BoxDynError> {
118        let ty = value.type_info().r#type;
119        if matches!(
120            ty,
121            ColumnType::TINYINT | ColumnType::SMALLINT | ColumnType::INTEGER | ColumnType::BIGINT
122        ) {
123            let num = <i64 as Decode<Xugu>>::decode(value)?;
124            return Ok(Box::from(num.to_string()));
125        }
126
127        value.as_str().map(map_empty).map(Box::from)
128    }
129}
130
131impl Type<Xugu> for String {
132    fn type_info() -> XuguTypeInfo {
133        <str as Type<Xugu>>::type_info()
134    }
135
136    fn compatible(ty: &XuguTypeInfo) -> bool {
137        <str as Type<Xugu>>::compatible(ty)
138    }
139}
140
141impl Encode<'_, Xugu> for String {
142    fn encode(self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
143        if self.is_empty() {
144            args.push(XuguArgumentValue::Str(Cow::Borrowed("\0")));
145        } else {
146            args.push(XuguArgumentValue::Str(Cow::Owned(self)));
147        }
148
149        Ok(IsNull::No)
150    }
151
152    fn encode_by_ref(&self, args: &mut Vec<XuguArgumentValue<'_>>) -> Result<IsNull, BoxDynError> {
153        if self.is_empty() {
154            args.push(XuguArgumentValue::Str(Cow::Borrowed("\0")));
155        } else {
156            args.push(XuguArgumentValue::Str(Cow::Owned(self.clone())));
157        }
158
159        Ok(IsNull::No)
160    }
161}
162
163impl Decode<'_, Xugu> for String {
164    fn decode(value: XuguValueRef<'_>) -> Result<Self, BoxDynError> {
165        let ty = value.type_info().r#type;
166        if matches!(
167            ty,
168            ColumnType::TINYINT | ColumnType::SMALLINT | ColumnType::INTEGER | ColumnType::BIGINT
169        ) {
170            let num = <i64 as Decode<Xugu>>::decode(value)?;
171            return Ok(num.to_string());
172        }
173
174        value.as_str().map(map_empty).map(ToOwned::to_owned)
175    }
176}
177
178impl Type<Xugu> for Cow<'_, str> {
179    fn type_info() -> XuguTypeInfo {
180        <&str as Type<Xugu>>::type_info()
181    }
182
183    fn compatible(ty: &XuguTypeInfo) -> bool {
184        <&str as Type<Xugu>>::compatible(ty)
185    }
186}
187
188impl<'q> Encode<'q, Xugu> for Cow<'q, str> {
189    fn encode(self, args: &mut Vec<XuguArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
190        if self.is_empty() {
191            args.push(XuguArgumentValue::Str(Cow::Borrowed("\0")));
192        } else {
193            args.push(XuguArgumentValue::Str(self));
194        }
195
196        Ok(IsNull::No)
197    }
198
199    fn encode_by_ref(&self, args: &mut Vec<XuguArgumentValue<'q>>) -> Result<IsNull, BoxDynError> {
200        if self.is_empty() {
201            args.push(XuguArgumentValue::Str(Cow::Borrowed("\0")));
202        } else {
203            args.push(XuguArgumentValue::Str(self.clone()));
204        }
205
206        Ok(IsNull::No)
207    }
208}
209
210impl<'r> Decode<'r, Xugu> for Cow<'r, str> {
211    fn decode(value: XuguValueRef<'r>) -> Result<Self, BoxDynError> {
212        let ty = value.type_info().r#type;
213        if matches!(
214            ty,
215            ColumnType::TINYINT | ColumnType::SMALLINT | ColumnType::INTEGER | ColumnType::BIGINT
216        ) {
217            let num = <i64 as Decode<Xugu>>::decode(value)?;
218            return Ok(Cow::Owned(num.to_string()));
219        }
220
221        value.as_str().map(map_empty).map(Cow::Borrowed)
222    }
223}
224
225// 处理空字符串
226fn map_empty(s: &str) -> &str {
227    if s == "\0" {
228        return "";
229    }
230    s
231}