1#![allow(missing_docs)]
9
10use std::fmt;
11
12use serde::{Deserialize, Serialize};
13
14#[cfg(feature = "pg")]
15use tokio_postgres as postgres;
16
17#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
19pub enum SqlTypeCustom {
20 #[cfg(feature = "pg")]
21 Pg(#[serde(with = "pgtypeser")] tokio_postgres::types::Type),
22}
23
24#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
26pub enum SqlValCustom {
27 #[cfg(feature = "pg")]
28 Pg {
29 #[serde(with = "pgtypeser")]
30 ty: postgres::types::Type,
31 data: Vec<u8>,
32 },
33}
34
35impl SqlValCustom {
36 pub fn as_valref(&self) -> SqlValRefCustom {
37 match self {
38 #[cfg(feature = "pg")]
39 SqlValCustom::Pg { ty, data } => SqlValRefCustom::PgBytes {
40 ty: ty.clone(),
41 data: data.as_ref(),
42 },
43 #[cfg(not(feature = "pg"))]
44 _ => panic!("SqlValCustom unsupported"),
45 }
46 }
47}
48
49impl fmt::Display for SqlValCustom {
50 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
51 match self {
52 #[cfg(feature = "pg")]
53 SqlValCustom::Pg { ty, .. } => f.write_str(&format!("<custom PG value of type {ty}>")),
54 #[cfg(not(feature = "pg"))]
55 _ => f.write_str("<unknown custom value>"),
56 }
57 }
58}
59
60#[cfg(feature = "pg")]
61impl postgres::types::ToSql for SqlValCustom {
62 fn to_sql(
63 &self,
64 wanted_ty: &postgres::types::Type,
65 out: &mut bytes::BytesMut,
66 ) -> std::result::Result<
67 postgres::types::IsNull,
68 Box<dyn std::error::Error + 'static + Sync + Send>,
69 > {
70 use bytes::BufMut;
71 match self {
72 SqlValCustom::Pg { ty, data } => {
73 if ty != wanted_ty {
74 return Err(Box::new(crate::Error::Internal(format!(
75 "postgres type mismatch. Wanted {wanted_ty} but have {ty}"
76 ))));
77 }
78 out.put(data.as_ref())
79 }
80 }
81 Ok(postgres::types::IsNull::No)
82 }
83
84 fn accepts(_: &postgres::types::Type) -> bool {
85 true
88 }
89 postgres::types::to_sql_checked!();
90}
91
92#[derive(Clone, Debug)]
94pub enum SqlValRefCustom<'a> {
95 #[cfg(feature = "pg")]
98 PgToSql {
99 ty: postgres::types::Type,
100 tosql: &'a (dyn postgres::types::ToSql + Sync),
101 },
102 #[cfg(feature = "pg")]
106 PgBytes {
107 ty: postgres::types::Type,
108 data: &'a [u8],
109 },
110 #[cfg(not(feature = "pg"))]
111 Phantom(std::marker::PhantomData<&'a ()>),
112}
113
114impl From<SqlValRefCustom<'_>> for SqlValCustom {
115 fn from(r: SqlValRefCustom) -> SqlValCustom {
116 match r {
117 #[cfg(feature = "pg")]
118 SqlValRefCustom::PgToSql { ty, tosql } => {
119 let mut b = bytes::BytesMut::new();
120 tosql.to_sql_checked(&ty, &mut b).unwrap();
122 SqlValCustom::Pg {
123 ty,
124 data: b.to_vec(),
125 }
126 }
127 #[cfg(feature = "pg")]
128 SqlValRefCustom::PgBytes { ty, data } => SqlValCustom::Pg {
129 ty,
130 data: data.into(),
131 },
132 #[cfg(not(feature = "pg"))]
133 SqlValRefCustom::Phantom(_) => {
134 panic!("phantom SqlValRefCustom should not be instantiated")
135 }
136 }
137 }
138}
139
140#[cfg(feature = "pg")]
141mod pgtypeser {
142 use serde::{Deserialize, Deserializer, Serialize, Serializer};
143 use tokio_postgres as postgres;
144
145 pub fn serialize<S>(ty: &postgres::types::Type, serializer: S) -> Result<S::Ok, S::Error>
146 where
147 S: Serializer,
148 {
149 let ty = SerializablePgType::from(ty.clone());
150 ty.serialize(serializer)
151 }
152
153 pub fn deserialize<'de, D>(deserializer: D) -> Result<postgres::types::Type, D::Error>
154 where
155 D: Deserializer<'de>,
156 {
157 Ok(SerializablePgType::deserialize(deserializer)?.into())
158 }
159
160 #[derive(Clone, Debug, Deserialize, Serialize)]
162 struct SerializablePgType {
163 name: String,
164 oid: u32,
165 kind: Box<SerializablePgKind>,
166 schema: String,
167 }
168 impl From<postgres::types::Type> for SerializablePgType {
169 fn from(ty: postgres::types::Type) -> Self {
170 Self {
171 name: ty.name().to_string(),
172 oid: ty.oid(),
173 kind: Box::new(ty.kind().clone().into()),
174 schema: ty.schema().to_string(),
175 }
176 }
177 }
178 impl From<SerializablePgType> for postgres::types::Type {
179 fn from(spt: SerializablePgType) -> postgres::types::Type {
180 postgres::types::Type::new(spt.name, spt.oid, (*spt.kind).into(), spt.schema)
181 }
182 }
183
184 #[derive(Clone, Debug, Deserialize, Serialize)]
185 enum SerializablePgKind {
186 Simple,
187 Enum(Vec<String>),
188 Pseudo,
189 Array(SerializablePgType),
190 Range(SerializablePgType),
191 Domain(SerializablePgType),
192 Composite(Vec<SerializablePgField>),
193 }
194 impl From<postgres::types::Kind> for SerializablePgKind {
195 fn from(k: postgres::types::Kind) -> Self {
196 use postgres::types::Kind::*;
197 match k {
198 Simple => Self::Simple,
199 Enum(v) => Self::Enum(v),
200 Pseudo => Self::Pseudo,
201 Array(ty) => Self::Array(ty.into()),
202 Range(ty) => Self::Range(ty.into()),
203 Domain(ty) => Self::Domain(ty.into()),
204 Composite(v) => Self::Composite(v.into_iter().map(|f| f.into()).collect()),
205 _ => panic!("Unhandled variant"),
207 }
208 }
209 }
210 impl From<SerializablePgKind> for postgres::types::Kind {
211 fn from(spk: SerializablePgKind) -> postgres::types::Kind {
212 use postgres::types::Kind::*;
213 match spk {
214 SerializablePgKind::Simple => Simple,
215 SerializablePgKind::Enum(v) => Enum(v),
216 SerializablePgKind::Pseudo => Pseudo,
217 SerializablePgKind::Array(ty) => Array(ty.into()),
218 SerializablePgKind::Range(ty) => Range(ty.into()),
219 SerializablePgKind::Domain(ty) => Domain(ty.into()),
220 SerializablePgKind::Composite(v) => {
221 Composite(v.into_iter().map(|f| f.into()).collect())
222 }
223 }
224 }
225 }
226
227 #[derive(Clone, Debug, Deserialize, Serialize)]
228 struct SerializablePgField {
229 name: String,
230 ty: SerializablePgType,
231 }
232 impl From<postgres::types::Field> for SerializablePgField {
233 fn from(f: postgres::types::Field) -> Self {
234 Self {
235 name: f.name().to_string(),
236 ty: f.type_().clone().into(),
237 }
238 }
239 }
240 impl From<SerializablePgField> for postgres::types::Field {
241 fn from(spf: SerializablePgField) -> postgres::types::Field {
242 postgres::types::Field::new(spf.name, spf.ty.into())
243 }
244 }
245}