1use crate::PostgresValue;
4use drizzle_core::{SQLParam, error::DrizzleError};
5use std::borrow::Cow;
6#[cfg(feature = "uuid")]
7use uuid::Uuid;
8
9#[cfg(feature = "chrono")]
10use chrono::{DateTime, Duration, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime, Utc};
11
12#[cfg(feature = "rust_decimal")]
13use rust_decimal::Decimal;
14
15#[cfg(feature = "ipnet")]
16use ipnet::IpNet;
17
18#[cfg(feature = "geo-types")]
19use geo_types::{LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon};
20
21#[cfg(feature = "bitvec")]
22use bitvec::prelude::*;
23
24#[derive(Debug, Clone, PartialEq)]
26pub enum OwnedPostgresValue {
27 Smallint(i16),
29 Integer(i32),
31 Bigint(i64),
33 Real(f32),
35 DoublePrecision(f64),
37 Text(String),
39 Bytea(Vec<u8>),
41 Boolean(bool),
43 #[cfg(feature = "uuid")]
45 Uuid(Uuid),
46 #[cfg(feature = "serde")]
48 Json(serde_json::Value),
49
50 #[cfg(feature = "chrono")]
53 Date(NaiveDate),
54 #[cfg(feature = "chrono")]
56 Time(NaiveTime),
57 #[cfg(feature = "chrono")]
59 Timestamp(NaiveDateTime),
60 #[cfg(feature = "chrono")]
62 TimestampTz(DateTime<FixedOffset>),
63 #[cfg(feature = "chrono")]
65 Interval(Duration),
66
67 #[cfg(feature = "rust_decimal")]
70 Decimal(Decimal),
71
72 #[cfg(feature = "ipnet")]
75 Inet(IpNet),
76 #[cfg(feature = "ipnet")]
78 Cidr(IpNet),
79 #[cfg(feature = "ipnet")]
81 MacAddr([u8; 6]),
82 #[cfg(feature = "ipnet")]
84 MacAddr8([u8; 8]),
85
86 #[cfg(feature = "geo-types")]
89 Point(Point<f64>),
90 #[cfg(feature = "geo-types")]
92 LineString(LineString<f64>),
93 #[cfg(feature = "geo-types")]
95 Polygon(Polygon<f64>),
96 #[cfg(feature = "geo-types")]
98 MultiPoint(MultiPoint<f64>),
99 #[cfg(feature = "geo-types")]
101 MultiLineString(MultiLineString<f64>),
102 #[cfg(feature = "geo-types")]
104 MultiPolygon(MultiPolygon<f64>),
105
106 #[cfg(feature = "bitvec")]
109 BitVec(BitVec),
110
111 Array(Vec<OwnedPostgresValue>),
114
115 Null,
117}
118
119impl SQLParam for OwnedPostgresValue {}
120
121impl Default for OwnedPostgresValue {
122 fn default() -> Self {
123 OwnedPostgresValue::Null
124 }
125}
126
127impl std::fmt::Display for OwnedPostgresValue {
128 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
129 let value = match self {
130 OwnedPostgresValue::Smallint(i) => i.to_string(),
131 OwnedPostgresValue::Integer(i) => i.to_string(),
132 OwnedPostgresValue::Bigint(i) => i.to_string(),
133 OwnedPostgresValue::Real(r) => r.to_string(),
134 OwnedPostgresValue::DoublePrecision(r) => r.to_string(),
135 OwnedPostgresValue::Text(s) => s.clone(),
136 OwnedPostgresValue::Bytea(b) => format!(
137 "\\x{}",
138 b.iter().map(|b| format!("{:02x}", b)).collect::<String>()
139 ),
140 OwnedPostgresValue::Boolean(b) => b.to_string(),
141 #[cfg(feature = "uuid")]
142 OwnedPostgresValue::Uuid(uuid) => uuid.to_string(),
143 #[cfg(feature = "serde")]
144 OwnedPostgresValue::Json(json) => json.to_string(),
145
146 #[cfg(feature = "chrono")]
148 OwnedPostgresValue::Date(date) => date.format("%Y-%m-%d").to_string(),
149 #[cfg(feature = "chrono")]
150 OwnedPostgresValue::Time(time) => time.format("%H:%M:%S%.f").to_string(),
151 #[cfg(feature = "chrono")]
152 OwnedPostgresValue::Timestamp(ts) => ts.format("%Y-%m-%d %H:%M:%S%.f").to_string(),
153 #[cfg(feature = "chrono")]
154 OwnedPostgresValue::TimestampTz(ts) => {
155 ts.format("%Y-%m-%d %H:%M:%S%.f %:z").to_string()
156 }
157 #[cfg(feature = "chrono")]
158 OwnedPostgresValue::Interval(dur) => format!("{} seconds", dur.num_seconds()),
159
160 #[cfg(feature = "rust_decimal")]
162 OwnedPostgresValue::Decimal(dec) => dec.to_string(),
163
164 #[cfg(feature = "ipnet")]
166 OwnedPostgresValue::Inet(net) => net.to_string(),
167 #[cfg(feature = "ipnet")]
168 OwnedPostgresValue::Cidr(net) => net.to_string(),
169 #[cfg(feature = "ipnet")]
170 OwnedPostgresValue::MacAddr(mac) => format!(
171 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
172 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
173 ),
174 #[cfg(feature = "ipnet")]
175 OwnedPostgresValue::MacAddr8(mac) => format!(
176 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
177 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], mac[6], mac[7]
178 ),
179
180 #[cfg(feature = "geo-types")]
182 OwnedPostgresValue::Point(point) => format!("({},{})", point.x(), point.y()),
183 #[cfg(feature = "geo-types")]
184 OwnedPostgresValue::LineString(line) => {
185 let coords: Vec<String> = line
186 .coords()
187 .map(|coord| format!("({},{})", coord.x, coord.y))
188 .collect();
189 format!("[{}]", coords.join(","))
190 }
191 #[cfg(feature = "geo-types")]
192 OwnedPostgresValue::Polygon(poly) => format!(
193 "POLYGON({})",
194 poly.exterior()
195 .coords()
196 .map(|c| format!("({},{})", c.x, c.y))
197 .collect::<Vec<_>>()
198 .join(",")
199 ),
200 #[cfg(feature = "geo-types")]
201 OwnedPostgresValue::MultiPoint(mp) => format!(
202 "MULTIPOINT({})",
203 mp.iter()
204 .map(|p| format!("({},{})", p.x(), p.y()))
205 .collect::<Vec<_>>()
206 .join(",")
207 ),
208 #[cfg(feature = "geo-types")]
209 OwnedPostgresValue::MultiLineString(mls) => format!(
210 "MULTILINESTRING({})",
211 mls.iter()
212 .map(|ls| format!(
213 "[{}]",
214 ls.coords()
215 .map(|c| format!("({},{})", c.x, c.y))
216 .collect::<Vec<_>>()
217 .join(",")
218 ))
219 .collect::<Vec<_>>()
220 .join(",")
221 ),
222 #[cfg(feature = "geo-types")]
223 OwnedPostgresValue::MultiPolygon(mp) => format!(
224 "MULTIPOLYGON({})",
225 mp.iter()
226 .map(|p| format!(
227 "POLYGON({})",
228 p.exterior()
229 .coords()
230 .map(|c| format!("({},{})", c.x, c.y))
231 .collect::<Vec<_>>()
232 .join(",")
233 ))
234 .collect::<Vec<_>>()
235 .join(",")
236 ),
237
238 #[cfg(feature = "bitvec")]
240 OwnedPostgresValue::BitVec(bv) => bv
241 .iter()
242 .map(|b| if *b { '1' } else { '0' })
243 .collect::<String>(),
244
245 OwnedPostgresValue::Array(arr) => {
247 let elements: Vec<String> = arr.iter().map(|v| v.to_string()).collect();
248 format!("{{{}}}", elements.join(","))
249 }
250
251 OwnedPostgresValue::Null => String::new(),
252 };
253 write!(f, "{value}")
254 }
255}
256
257impl<'a> From<PostgresValue<'a>> for OwnedPostgresValue {
259 fn from(value: PostgresValue<'a>) -> Self {
260 match value {
261 PostgresValue::Smallint(i) => OwnedPostgresValue::Smallint(i),
262 PostgresValue::Integer(i) => OwnedPostgresValue::Integer(i),
263 PostgresValue::Bigint(i) => OwnedPostgresValue::Bigint(i),
264 PostgresValue::Real(r) => OwnedPostgresValue::Real(r),
265 PostgresValue::DoublePrecision(r) => OwnedPostgresValue::DoublePrecision(r),
266 PostgresValue::Text(cow) => OwnedPostgresValue::Text(cow.into_owned()),
267 PostgresValue::Bytea(cow) => OwnedPostgresValue::Bytea(cow.into_owned()),
268 PostgresValue::Boolean(b) => OwnedPostgresValue::Boolean(b),
269 #[cfg(feature = "uuid")]
270 PostgresValue::Uuid(uuid) => OwnedPostgresValue::Uuid(uuid),
271 #[cfg(feature = "serde")]
272 PostgresValue::Json(json) => OwnedPostgresValue::Json(json),
273 PostgresValue::Enum(enum_val) => {
274 OwnedPostgresValue::Text(enum_val.variant_name().to_string())
275 }
276 PostgresValue::Null => OwnedPostgresValue::Null,
277 #[cfg(feature = "chrono")]
278 PostgresValue::Date(date) => OwnedPostgresValue::Date(date),
279 #[cfg(feature = "chrono")]
280 PostgresValue::Time(time) => OwnedPostgresValue::Time(time),
281 #[cfg(feature = "chrono")]
282 PostgresValue::Timestamp(ts) => OwnedPostgresValue::Timestamp(ts),
283 #[cfg(feature = "chrono")]
284 PostgresValue::TimestampTz(ts) => OwnedPostgresValue::TimestampTz(ts),
285 #[cfg(feature = "chrono")]
286 PostgresValue::Interval(dur) => OwnedPostgresValue::Interval(dur),
287 #[cfg(feature = "rust_decimal")]
288 PostgresValue::Decimal(dec) => OwnedPostgresValue::Decimal(dec),
289 #[cfg(feature = "ipnet")]
290 PostgresValue::Inet(net) => OwnedPostgresValue::Inet(net),
291 #[cfg(feature = "ipnet")]
292 PostgresValue::Cidr(net) => OwnedPostgresValue::Cidr(net),
293 #[cfg(feature = "ipnet")]
294 PostgresValue::MacAddr(mac) => OwnedPostgresValue::MacAddr(mac),
295 #[cfg(feature = "ipnet")]
296 PostgresValue::MacAddr8(mac) => OwnedPostgresValue::MacAddr8(mac),
297 #[cfg(feature = "geo-types")]
298 PostgresValue::Point(point) => OwnedPostgresValue::Point(point),
299 #[cfg(feature = "geo-types")]
300 PostgresValue::LineString(line) => OwnedPostgresValue::LineString(line),
301 #[cfg(feature = "geo-types")]
302 PostgresValue::Polygon(poly) => OwnedPostgresValue::Polygon(poly),
303 #[cfg(feature = "geo-types")]
304 PostgresValue::MultiPoint(mp) => OwnedPostgresValue::MultiPoint(mp),
305 #[cfg(feature = "geo-types")]
306 PostgresValue::MultiLineString(mls) => OwnedPostgresValue::MultiLineString(mls),
307 #[cfg(feature = "geo-types")]
308 PostgresValue::MultiPolygon(mp) => OwnedPostgresValue::MultiPolygon(mp),
309 #[cfg(feature = "bitvec")]
310 PostgresValue::BitVec(bv) => OwnedPostgresValue::BitVec(bv),
311 PostgresValue::Array(arr) => {
312 let owned_arr = arr
313 .into_iter()
314 .map(|v| OwnedPostgresValue::from(v))
315 .collect();
316 OwnedPostgresValue::Array(owned_arr)
317 }
318 }
319 }
320}
321
322impl<'a> From<OwnedPostgresValue> for PostgresValue<'a> {
324 fn from(value: OwnedPostgresValue) -> Self {
325 match value {
326 OwnedPostgresValue::Smallint(i) => PostgresValue::Smallint(i),
327 OwnedPostgresValue::Integer(i) => PostgresValue::Integer(i),
328 OwnedPostgresValue::Bigint(i) => PostgresValue::Bigint(i),
329 OwnedPostgresValue::Real(r) => PostgresValue::Real(r),
330 OwnedPostgresValue::DoublePrecision(r) => PostgresValue::DoublePrecision(r),
331 OwnedPostgresValue::Text(s) => PostgresValue::Text(Cow::Owned(s)),
332 OwnedPostgresValue::Bytea(b) => PostgresValue::Bytea(Cow::Owned(b)),
333 OwnedPostgresValue::Boolean(b) => PostgresValue::Boolean(b),
334 #[cfg(feature = "uuid")]
335 OwnedPostgresValue::Uuid(uuid) => PostgresValue::Uuid(uuid),
336 #[cfg(feature = "serde")]
337 OwnedPostgresValue::Json(json) => PostgresValue::Json(json),
338
339 #[cfg(feature = "chrono")]
341 OwnedPostgresValue::Date(date) => PostgresValue::Date(date),
342 #[cfg(feature = "chrono")]
343 OwnedPostgresValue::Time(time) => PostgresValue::Time(time),
344 #[cfg(feature = "chrono")]
345 OwnedPostgresValue::Timestamp(ts) => PostgresValue::Timestamp(ts),
346 #[cfg(feature = "chrono")]
347 OwnedPostgresValue::TimestampTz(ts) => PostgresValue::TimestampTz(ts),
348 #[cfg(feature = "chrono")]
349 OwnedPostgresValue::Interval(dur) => PostgresValue::Interval(dur),
350 #[cfg(feature = "rust_decimal")]
351 OwnedPostgresValue::Decimal(dec) => PostgresValue::Decimal(dec),
352 #[cfg(feature = "ipnet")]
353 OwnedPostgresValue::Inet(net) => PostgresValue::Inet(net),
354 #[cfg(feature = "ipnet")]
355 OwnedPostgresValue::Cidr(net) => PostgresValue::Cidr(net),
356 #[cfg(feature = "ipnet")]
357 OwnedPostgresValue::MacAddr(mac) => PostgresValue::MacAddr(mac),
358 #[cfg(feature = "ipnet")]
359 OwnedPostgresValue::MacAddr8(mac) => PostgresValue::MacAddr8(mac),
360 #[cfg(feature = "geo-types")]
361 OwnedPostgresValue::Point(point) => PostgresValue::Point(point),
362 #[cfg(feature = "geo-types")]
363 OwnedPostgresValue::LineString(line) => PostgresValue::LineString(line),
364 #[cfg(feature = "geo-types")]
365 OwnedPostgresValue::Polygon(poly) => PostgresValue::Polygon(poly),
366 #[cfg(feature = "geo-types")]
367 OwnedPostgresValue::MultiPoint(mp) => PostgresValue::MultiPoint(mp),
368 #[cfg(feature = "geo-types")]
369 OwnedPostgresValue::MultiLineString(mls) => PostgresValue::MultiLineString(mls),
370 #[cfg(feature = "geo-types")]
371 OwnedPostgresValue::MultiPolygon(mp) => PostgresValue::MultiPolygon(mp),
372 #[cfg(feature = "bitvec")]
373 OwnedPostgresValue::BitVec(bv) => PostgresValue::BitVec(bv),
374 OwnedPostgresValue::Array(arr) => {
375 let postgres_arr = arr.into_iter().map(|v| PostgresValue::from(v)).collect();
376 PostgresValue::Array(postgres_arr)
377 }
378
379 OwnedPostgresValue::Null => PostgresValue::Null,
380 }
381 }
382}
383
384impl From<i16> for OwnedPostgresValue {
386 fn from(value: i16) -> Self {
387 OwnedPostgresValue::Smallint(value)
388 }
389}
390
391impl From<i32> for OwnedPostgresValue {
392 fn from(value: i32) -> Self {
393 OwnedPostgresValue::Integer(value)
394 }
395}
396
397impl From<i64> for OwnedPostgresValue {
398 fn from(value: i64) -> Self {
399 OwnedPostgresValue::Bigint(value)
400 }
401}
402
403impl From<f32> for OwnedPostgresValue {
404 fn from(value: f32) -> Self {
405 OwnedPostgresValue::Real(value)
406 }
407}
408
409impl From<f64> for OwnedPostgresValue {
410 fn from(value: f64) -> Self {
411 OwnedPostgresValue::DoublePrecision(value)
412 }
413}
414
415impl From<String> for OwnedPostgresValue {
416 fn from(value: String) -> Self {
417 OwnedPostgresValue::Text(value)
418 }
419}
420
421impl From<Vec<u8>> for OwnedPostgresValue {
422 fn from(value: Vec<u8>) -> Self {
423 OwnedPostgresValue::Bytea(value)
424 }
425}
426
427impl From<bool> for OwnedPostgresValue {
428 fn from(value: bool) -> Self {
429 OwnedPostgresValue::Boolean(value)
430 }
431}
432
433#[cfg(feature = "uuid")]
434impl From<Uuid> for OwnedPostgresValue {
435 fn from(value: Uuid) -> Self {
436 OwnedPostgresValue::Uuid(value)
437 }
438}
439
440#[cfg(feature = "serde")]
441impl From<serde_json::Value> for OwnedPostgresValue {
442 fn from(value: serde_json::Value) -> Self {
443 OwnedPostgresValue::Json(value)
444 }
445}
446
447impl TryFrom<OwnedPostgresValue> for i16 {
449 type Error = DrizzleError;
450
451 fn try_from(value: OwnedPostgresValue) -> Result<Self, Self::Error> {
452 match value {
453 OwnedPostgresValue::Smallint(i) => Ok(i),
454 OwnedPostgresValue::Integer(i) => Ok(i.try_into()?),
455 OwnedPostgresValue::Bigint(i) => Ok(i.try_into()?),
456 _ => Err(DrizzleError::ConversionError(
457 format!("Cannot convert {:?} to i16", value).into(),
458 )),
459 }
460 }
461}
462
463impl TryFrom<OwnedPostgresValue> for i32 {
464 type Error = DrizzleError;
465
466 fn try_from(value: OwnedPostgresValue) -> Result<Self, Self::Error> {
467 match value {
468 OwnedPostgresValue::Smallint(i) => Ok(i.into()),
469 OwnedPostgresValue::Integer(i) => Ok(i),
470 OwnedPostgresValue::Bigint(i) => Ok(i.try_into()?),
471 _ => Err(DrizzleError::ConversionError(
472 format!("Cannot convert {:?} to i32", value).into(),
473 )),
474 }
475 }
476}
477
478impl TryFrom<OwnedPostgresValue> for i64 {
479 type Error = DrizzleError;
480
481 fn try_from(value: OwnedPostgresValue) -> Result<Self, Self::Error> {
482 match value {
483 OwnedPostgresValue::Smallint(i) => Ok(i.into()),
484 OwnedPostgresValue::Integer(i) => Ok(i.into()),
485 OwnedPostgresValue::Bigint(i) => Ok(i),
486 _ => Err(DrizzleError::ConversionError(
487 format!("Cannot convert {:?} to i64", value).into(),
488 )),
489 }
490 }
491}
492
493impl TryFrom<OwnedPostgresValue> for f32 {
494 type Error = DrizzleError;
495
496 fn try_from(value: OwnedPostgresValue) -> Result<Self, Self::Error> {
497 match value {
498 OwnedPostgresValue::Real(r) => Ok(r),
499 OwnedPostgresValue::DoublePrecision(r) => Ok(r as f32),
500 OwnedPostgresValue::Smallint(i) => Ok(i as f32),
501 OwnedPostgresValue::Integer(i) => Ok(i as f32),
502 OwnedPostgresValue::Bigint(i) => Ok(i as f32),
503 _ => Err(DrizzleError::ConversionError(
504 format!("Cannot convert {:?} to f32", value).into(),
505 )),
506 }
507 }
508}
509
510impl TryFrom<OwnedPostgresValue> for f64 {
511 type Error = DrizzleError;
512
513 fn try_from(value: OwnedPostgresValue) -> Result<Self, Self::Error> {
514 match value {
515 OwnedPostgresValue::Real(r) => Ok(r as f64),
516 OwnedPostgresValue::DoublePrecision(r) => Ok(r),
517 OwnedPostgresValue::Smallint(i) => Ok(i as f64),
518 OwnedPostgresValue::Integer(i) => Ok(i as f64),
519 OwnedPostgresValue::Bigint(i) => Ok(i as f64),
520 _ => Err(DrizzleError::ConversionError(
521 format!("Cannot convert {:?} to f64", value).into(),
522 )),
523 }
524 }
525}
526
527impl TryFrom<OwnedPostgresValue> for String {
528 type Error = DrizzleError;
529
530 fn try_from(value: OwnedPostgresValue) -> Result<Self, Self::Error> {
531 match value {
532 OwnedPostgresValue::Text(s) => Ok(s),
533 _ => Err(DrizzleError::ConversionError(
534 format!("Cannot convert {:?} to String", value).into(),
535 )),
536 }
537 }
538}
539
540impl TryFrom<OwnedPostgresValue> for Vec<u8> {
541 type Error = DrizzleError;
542
543 fn try_from(value: OwnedPostgresValue) -> Result<Self, Self::Error> {
544 match value {
545 OwnedPostgresValue::Bytea(b) => Ok(b),
546 _ => Err(DrizzleError::ConversionError(
547 format!("Cannot convert {:?} to Vec<u8>", value).into(),
548 )),
549 }
550 }
551}
552
553impl TryFrom<OwnedPostgresValue> for bool {
554 type Error = DrizzleError;
555
556 fn try_from(value: OwnedPostgresValue) -> Result<Self, Self::Error> {
557 match value {
558 OwnedPostgresValue::Boolean(b) => Ok(b),
559 _ => Err(DrizzleError::ConversionError(
560 format!("Cannot convert {:?} to bool", value).into(),
561 )),
562 }
563 }
564}
565
566#[cfg(feature = "uuid")]
567impl TryFrom<OwnedPostgresValue> for Uuid {
568 type Error = DrizzleError;
569
570 fn try_from(value: OwnedPostgresValue) -> Result<Self, Self::Error> {
571 match value {
572 OwnedPostgresValue::Uuid(uuid) => Ok(uuid),
573 OwnedPostgresValue::Text(s) => Ok(Uuid::parse_str(&s)?),
574 _ => Err(DrizzleError::ConversionError(
575 format!("Cannot convert {:?} to UUID", value).into(),
576 )),
577 }
578 }
579}
580
581#[cfg(feature = "serde")]
582impl TryFrom<OwnedPostgresValue> for serde_json::Value {
583 type Error = DrizzleError;
584
585 fn try_from(value: OwnedPostgresValue) -> Result<Self, Self::Error> {
586 match value {
587 OwnedPostgresValue::Json(json) => Ok(json),
588 OwnedPostgresValue::Text(s) => serde_json::from_str(&s).map_err(|e| {
589 DrizzleError::ConversionError(format!("Failed to parse JSON: {}", e).into())
590 }),
591 _ => Err(DrizzleError::ConversionError(
592 format!("Cannot convert {:?} to JSON", value).into(),
593 )),
594 }
595 }
596}