1mod conversions;
4mod drivers;
5mod insert;
6mod owned;
7
8pub use insert::*;
9pub use owned::*;
10
11use drizzle_core::{error::DrizzleError, sql::SQL, traits::SQLParam};
12
13#[cfg(feature = "uuid")]
14use uuid::Uuid;
15
16#[cfg(feature = "chrono")]
17use chrono::{DateTime, Duration, FixedOffset, NaiveDate, NaiveDateTime, NaiveTime};
18
19#[cfg(feature = "cidr")]
20use cidr::{IpCidr, IpInet};
21
22#[cfg(feature = "geo-types")]
23use geo_types::{LineString, Point, Rect};
24
25#[cfg(feature = "bit-vec")]
26use bit_vec::BitVec;
27
28use std::borrow::Cow;
29
30use crate::{PostgresEnum, traits::FromPostgresValue};
31
32#[derive(Debug, Clone, PartialEq, Default)]
58pub enum PostgresValue<'a> {
59 Smallint(i16),
61 Integer(i32),
63 Bigint(i64),
65 Real(f32),
67 DoublePrecision(f64),
69 Text(Cow<'a, str>),
71 Bytea(Cow<'a, [u8]>),
73 Boolean(bool),
75 #[cfg(feature = "uuid")]
77 Uuid(Uuid),
78 #[cfg(feature = "serde")]
80 Json(serde_json::Value),
81 #[cfg(feature = "serde")]
83 Jsonb(serde_json::Value),
84 Enum(Box<dyn PostgresEnum>),
86
87 #[cfg(feature = "chrono")]
90 Date(NaiveDate),
91 #[cfg(feature = "chrono")]
93 Time(NaiveTime),
94 #[cfg(feature = "chrono")]
96 Timestamp(NaiveDateTime),
97 #[cfg(feature = "chrono")]
99 TimestampTz(DateTime<FixedOffset>),
100 #[cfg(feature = "chrono")]
102 Interval(Duration),
103
104 #[cfg(feature = "cidr")]
107 Inet(IpInet),
108 #[cfg(feature = "cidr")]
110 Cidr(IpCidr),
111 #[cfg(feature = "cidr")]
113 MacAddr([u8; 6]),
114 #[cfg(feature = "cidr")]
116 MacAddr8([u8; 8]),
117
118 #[cfg(feature = "geo-types")]
121 Point(Point<f64>),
122 #[cfg(feature = "geo-types")]
124 LineString(LineString<f64>),
125 #[cfg(feature = "geo-types")]
127 Rect(Rect<f64>),
128
129 #[cfg(feature = "bit-vec")]
132 BitVec(BitVec),
133
134 Array(Vec<PostgresValue<'a>>),
137
138 #[default]
140 Null,
141}
142
143impl<'a> std::fmt::Display for PostgresValue<'a> {
144 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145 let value = match self {
146 PostgresValue::Smallint(i) => i.to_string(),
147 PostgresValue::Integer(i) => i.to_string(),
148 PostgresValue::Bigint(i) => i.to_string(),
149 PostgresValue::Real(r) => r.to_string(),
150 PostgresValue::DoublePrecision(r) => r.to_string(),
151 PostgresValue::Text(cow) => cow.to_string(),
152 PostgresValue::Bytea(cow) => format!(
153 "\\x{}",
154 cow.iter().map(|b| format!("{:02x}", b)).collect::<String>()
155 ),
156 PostgresValue::Boolean(b) => b.to_string(),
157 #[cfg(feature = "uuid")]
158 PostgresValue::Uuid(uuid) => uuid.to_string(),
159 #[cfg(feature = "serde")]
160 PostgresValue::Json(json) => json.to_string(),
161 #[cfg(feature = "serde")]
162 PostgresValue::Jsonb(json) => json.to_string(),
163 PostgresValue::Enum(enum_val) => enum_val.variant_name().to_string(),
164
165 #[cfg(feature = "chrono")]
167 PostgresValue::Date(date) => date.format("%Y-%m-%d").to_string(),
168 #[cfg(feature = "chrono")]
169 PostgresValue::Time(time) => time.format("%H:%M:%S%.f").to_string(),
170 #[cfg(feature = "chrono")]
171 PostgresValue::Timestamp(ts) => ts.format("%Y-%m-%d %H:%M:%S%.f").to_string(),
172 #[cfg(feature = "chrono")]
173 PostgresValue::TimestampTz(ts) => ts.format("%Y-%m-%d %H:%M:%S%.f %:z").to_string(),
174 #[cfg(feature = "chrono")]
175 PostgresValue::Interval(dur) => format!("{} seconds", dur.num_seconds()),
176
177 #[cfg(feature = "cidr")]
179 PostgresValue::Inet(net) => net.to_string(),
180 #[cfg(feature = "cidr")]
181 PostgresValue::Cidr(net) => net.to_string(),
182 #[cfg(feature = "cidr")]
183 PostgresValue::MacAddr(mac) => format!(
184 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
185 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
186 ),
187 #[cfg(feature = "cidr")]
188 PostgresValue::MacAddr8(mac) => format!(
189 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
190 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], mac[6], mac[7]
191 ),
192
193 #[cfg(feature = "geo-types")]
195 PostgresValue::Point(point) => format!("({},{})", point.x(), point.y()),
196 #[cfg(feature = "geo-types")]
197 PostgresValue::LineString(line) => {
198 let coords: Vec<String> = line
199 .coords()
200 .map(|coord| format!("({},{})", coord.x, coord.y))
201 .collect();
202 format!("[{}]", coords.join(","))
203 }
204 #[cfg(feature = "geo-types")]
205 PostgresValue::Rect(rect) => {
206 format!(
207 "(({},{}),({},{}))",
208 rect.min().x,
209 rect.min().y,
210 rect.max().x,
211 rect.max().y
212 )
213 }
214
215 #[cfg(feature = "bit-vec")]
217 PostgresValue::BitVec(bv) => bv
218 .iter()
219 .map(|b| if b { '1' } else { '0' })
220 .collect::<String>(),
221
222 PostgresValue::Array(arr) => {
224 let elements: Vec<String> = arr.iter().map(|v| v.to_string()).collect();
225 format!("{{{}}}", elements.join(","))
226 }
227
228 PostgresValue::Null => String::new(),
229 };
230 write!(f, "{value}")
231 }
232}
233
234impl<'a> PostgresValue<'a> {
235 #[inline]
237 pub const fn is_null(&self) -> bool {
238 matches!(self, PostgresValue::Null)
239 }
240
241 #[inline]
243 pub const fn as_bool(&self) -> Option<bool> {
244 match self {
245 PostgresValue::Boolean(value) => Some(*value),
246 _ => None,
247 }
248 }
249
250 #[inline]
252 pub const fn as_i16(&self) -> Option<i16> {
253 match self {
254 PostgresValue::Smallint(value) => Some(*value),
255 _ => None,
256 }
257 }
258
259 #[inline]
261 pub const fn as_i32(&self) -> Option<i32> {
262 match self {
263 PostgresValue::Integer(value) => Some(*value),
264 _ => None,
265 }
266 }
267
268 #[inline]
270 pub const fn as_i64(&self) -> Option<i64> {
271 match self {
272 PostgresValue::Bigint(value) => Some(*value),
273 _ => None,
274 }
275 }
276
277 #[inline]
279 pub const fn as_f32(&self) -> Option<f32> {
280 match self {
281 PostgresValue::Real(value) => Some(*value),
282 _ => None,
283 }
284 }
285
286 #[inline]
288 pub const fn as_f64(&self) -> Option<f64> {
289 match self {
290 PostgresValue::DoublePrecision(value) => Some(*value),
291 _ => None,
292 }
293 }
294
295 #[inline]
297 pub fn as_str(&self) -> Option<&str> {
298 match self {
299 PostgresValue::Text(value) => Some(value.as_ref()),
300 _ => None,
301 }
302 }
303
304 #[inline]
306 pub fn as_bytes(&self) -> Option<&[u8]> {
307 match self {
308 PostgresValue::Bytea(value) => Some(value.as_ref()),
309 _ => None,
310 }
311 }
312
313 #[inline]
315 #[cfg(feature = "uuid")]
316 pub fn as_uuid(&self) -> Option<Uuid> {
317 match self {
318 PostgresValue::Uuid(value) => Some(*value),
319 _ => None,
320 }
321 }
322
323 #[inline]
325 #[cfg(feature = "serde")]
326 pub fn as_json(&self) -> Option<&serde_json::Value> {
327 match self {
328 PostgresValue::Json(value) => Some(value),
329 _ => None,
330 }
331 }
332
333 #[inline]
335 #[cfg(feature = "serde")]
336 pub fn as_jsonb(&self) -> Option<&serde_json::Value> {
337 match self {
338 PostgresValue::Jsonb(value) => Some(value),
339 _ => None,
340 }
341 }
342
343 #[inline]
345 pub fn as_enum(&self) -> Option<&dyn PostgresEnum> {
346 match self {
347 PostgresValue::Enum(value) => Some(value.as_ref()),
348 _ => None,
349 }
350 }
351
352 #[inline]
354 #[cfg(feature = "chrono")]
355 pub fn as_date(&self) -> Option<&NaiveDate> {
356 match self {
357 PostgresValue::Date(value) => Some(value),
358 _ => None,
359 }
360 }
361
362 #[inline]
364 #[cfg(feature = "chrono")]
365 pub fn as_time(&self) -> Option<&NaiveTime> {
366 match self {
367 PostgresValue::Time(value) => Some(value),
368 _ => None,
369 }
370 }
371
372 #[inline]
374 #[cfg(feature = "chrono")]
375 pub fn as_timestamp(&self) -> Option<&NaiveDateTime> {
376 match self {
377 PostgresValue::Timestamp(value) => Some(value),
378 _ => None,
379 }
380 }
381
382 #[inline]
384 #[cfg(feature = "chrono")]
385 pub fn as_timestamp_tz(&self) -> Option<&DateTime<FixedOffset>> {
386 match self {
387 PostgresValue::TimestampTz(value) => Some(value),
388 _ => None,
389 }
390 }
391
392 #[inline]
394 #[cfg(feature = "chrono")]
395 pub fn as_interval(&self) -> Option<&Duration> {
396 match self {
397 PostgresValue::Interval(value) => Some(value),
398 _ => None,
399 }
400 }
401
402 #[inline]
404 #[cfg(feature = "cidr")]
405 pub fn as_inet(&self) -> Option<&IpInet> {
406 match self {
407 PostgresValue::Inet(value) => Some(value),
408 _ => None,
409 }
410 }
411
412 #[inline]
414 #[cfg(feature = "cidr")]
415 pub fn as_cidr(&self) -> Option<&IpCidr> {
416 match self {
417 PostgresValue::Cidr(value) => Some(value),
418 _ => None,
419 }
420 }
421
422 #[inline]
424 #[cfg(feature = "cidr")]
425 pub const fn as_macaddr(&self) -> Option<[u8; 6]> {
426 match self {
427 PostgresValue::MacAddr(value) => Some(*value),
428 _ => None,
429 }
430 }
431
432 #[inline]
434 #[cfg(feature = "cidr")]
435 pub const fn as_macaddr8(&self) -> Option<[u8; 8]> {
436 match self {
437 PostgresValue::MacAddr8(value) => Some(*value),
438 _ => None,
439 }
440 }
441
442 #[inline]
444 #[cfg(feature = "geo-types")]
445 pub fn as_point(&self) -> Option<&Point<f64>> {
446 match self {
447 PostgresValue::Point(value) => Some(value),
448 _ => None,
449 }
450 }
451
452 #[inline]
454 #[cfg(feature = "geo-types")]
455 pub fn as_line_string(&self) -> Option<&LineString<f64>> {
456 match self {
457 PostgresValue::LineString(value) => Some(value),
458 _ => None,
459 }
460 }
461
462 #[inline]
464 #[cfg(feature = "geo-types")]
465 pub fn as_rect(&self) -> Option<&Rect<f64>> {
466 match self {
467 PostgresValue::Rect(value) => Some(value),
468 _ => None,
469 }
470 }
471
472 #[inline]
474 #[cfg(feature = "bit-vec")]
475 pub fn as_bitvec(&self) -> Option<&BitVec> {
476 match self {
477 PostgresValue::BitVec(value) => Some(value),
478 _ => None,
479 }
480 }
481
482 #[inline]
484 pub fn as_array(&self) -> Option<&[PostgresValue<'a>]> {
485 match self {
486 PostgresValue::Array(values) => Some(values),
487 _ => None,
488 }
489 }
490
491 #[inline]
493 pub fn into_owned(self) -> OwnedPostgresValue {
494 self.into()
495 }
496
497 pub fn convert<T: FromPostgresValue>(self) -> Result<T, DrizzleError> {
499 match self {
500 PostgresValue::Boolean(value) => T::from_postgres_bool(value),
501 PostgresValue::Smallint(value) => T::from_postgres_i16(value),
502 PostgresValue::Integer(value) => T::from_postgres_i32(value),
503 PostgresValue::Bigint(value) => T::from_postgres_i64(value),
504 PostgresValue::Real(value) => T::from_postgres_f32(value),
505 PostgresValue::DoublePrecision(value) => T::from_postgres_f64(value),
506 PostgresValue::Text(value) => T::from_postgres_text(&value),
507 PostgresValue::Bytea(value) => T::from_postgres_bytes(&value),
508 #[cfg(feature = "uuid")]
509 PostgresValue::Uuid(value) => T::from_postgres_uuid(value),
510 #[cfg(feature = "serde")]
511 PostgresValue::Json(value) => T::from_postgres_json(value),
512 #[cfg(feature = "serde")]
513 PostgresValue::Jsonb(value) => T::from_postgres_jsonb(value),
514 PostgresValue::Enum(value) => T::from_postgres_text(value.variant_name()),
515 #[cfg(feature = "chrono")]
516 PostgresValue::Date(value) => T::from_postgres_date(value),
517 #[cfg(feature = "chrono")]
518 PostgresValue::Time(value) => T::from_postgres_time(value),
519 #[cfg(feature = "chrono")]
520 PostgresValue::Timestamp(value) => T::from_postgres_timestamp(value),
521 #[cfg(feature = "chrono")]
522 PostgresValue::TimestampTz(value) => T::from_postgres_timestamptz(value),
523 #[cfg(feature = "chrono")]
524 PostgresValue::Interval(value) => T::from_postgres_interval(value),
525 #[cfg(feature = "cidr")]
526 PostgresValue::Inet(value) => T::from_postgres_inet(value),
527 #[cfg(feature = "cidr")]
528 PostgresValue::Cidr(value) => T::from_postgres_cidr(value),
529 #[cfg(feature = "cidr")]
530 PostgresValue::MacAddr(value) => T::from_postgres_macaddr(value),
531 #[cfg(feature = "cidr")]
532 PostgresValue::MacAddr8(value) => T::from_postgres_macaddr8(value),
533 #[cfg(feature = "geo-types")]
534 PostgresValue::Point(value) => T::from_postgres_point(value),
535 #[cfg(feature = "geo-types")]
536 PostgresValue::LineString(value) => T::from_postgres_linestring(value),
537 #[cfg(feature = "geo-types")]
538 PostgresValue::Rect(value) => T::from_postgres_rect(value),
539 #[cfg(feature = "bit-vec")]
540 PostgresValue::BitVec(value) => T::from_postgres_bitvec(value),
541 PostgresValue::Array(value) => T::from_postgres_array(value),
542 PostgresValue::Null => T::from_postgres_null(),
543 }
544 }
545
546 pub fn convert_ref<T: FromPostgresValue>(&self) -> Result<T, DrizzleError> {
548 match self {
549 PostgresValue::Boolean(value) => T::from_postgres_bool(*value),
550 PostgresValue::Smallint(value) => T::from_postgres_i16(*value),
551 PostgresValue::Integer(value) => T::from_postgres_i32(*value),
552 PostgresValue::Bigint(value) => T::from_postgres_i64(*value),
553 PostgresValue::Real(value) => T::from_postgres_f32(*value),
554 PostgresValue::DoublePrecision(value) => T::from_postgres_f64(*value),
555 PostgresValue::Text(value) => T::from_postgres_text(value),
556 PostgresValue::Bytea(value) => T::from_postgres_bytes(value),
557 #[cfg(feature = "uuid")]
558 PostgresValue::Uuid(value) => T::from_postgres_uuid(*value),
559 #[cfg(feature = "serde")]
560 PostgresValue::Json(value) => T::from_postgres_json(value.clone()),
561 #[cfg(feature = "serde")]
562 PostgresValue::Jsonb(value) => T::from_postgres_jsonb(value.clone()),
563 PostgresValue::Enum(value) => T::from_postgres_text(value.variant_name()),
564 #[cfg(feature = "chrono")]
565 PostgresValue::Date(value) => T::from_postgres_date(*value),
566 #[cfg(feature = "chrono")]
567 PostgresValue::Time(value) => T::from_postgres_time(*value),
568 #[cfg(feature = "chrono")]
569 PostgresValue::Timestamp(value) => T::from_postgres_timestamp(*value),
570 #[cfg(feature = "chrono")]
571 PostgresValue::TimestampTz(value) => T::from_postgres_timestamptz(*value),
572 #[cfg(feature = "chrono")]
573 PostgresValue::Interval(value) => T::from_postgres_interval(*value),
574 #[cfg(feature = "cidr")]
575 PostgresValue::Inet(value) => T::from_postgres_inet(*value),
576 #[cfg(feature = "cidr")]
577 PostgresValue::Cidr(value) => T::from_postgres_cidr(*value),
578 #[cfg(feature = "cidr")]
579 PostgresValue::MacAddr(value) => T::from_postgres_macaddr(*value),
580 #[cfg(feature = "cidr")]
581 PostgresValue::MacAddr8(value) => T::from_postgres_macaddr8(*value),
582 #[cfg(feature = "geo-types")]
583 PostgresValue::Point(value) => T::from_postgres_point(*value),
584 #[cfg(feature = "geo-types")]
585 PostgresValue::LineString(value) => T::from_postgres_linestring(value.clone()),
586 #[cfg(feature = "geo-types")]
587 PostgresValue::Rect(value) => T::from_postgres_rect(*value),
588 #[cfg(feature = "bit-vec")]
589 PostgresValue::BitVec(value) => T::from_postgres_bitvec(value.clone()),
590 PostgresValue::Array(value) => T::from_postgres_array(value.clone()),
591 PostgresValue::Null => T::from_postgres_null(),
592 }
593 }
594}
595
596impl<'a> SQLParam for PostgresValue<'a> {
598 const DIALECT: drizzle_core::dialect::Dialect = drizzle_core::dialect::Dialect::PostgreSQL;
599}
600
601impl<'a> From<PostgresValue<'a>> for SQL<'a, PostgresValue<'a>> {
602 fn from(value: PostgresValue<'a>) -> Self {
603 SQL::param(value)
604 }
605}
606
607impl<'a> From<PostgresValue<'a>> for Cow<'a, PostgresValue<'a>> {
609 fn from(value: PostgresValue<'a>) -> Self {
610 Cow::Owned(value)
611 }
612}
613
614impl<'a> From<&'a PostgresValue<'a>> for Cow<'a, PostgresValue<'a>> {
615 fn from(value: &'a PostgresValue<'a>) -> Self {
616 Cow::Borrowed(value)
617 }
618}