connectorx/transports/
postgres_arrow.rs1use crate::destinations::arrow::{
4 typesystem::{
5 ArrowTypeSystem, DateTimeWrapperMicro, NaiveDateTimeWrapperMicro, NaiveTimeWrapperMicro,
6 },
7 ArrowDestination, ArrowDestinationError,
8};
9use crate::sources::postgres::{
10 BinaryProtocol, CSVProtocol, CursorProtocol, PostgresSource, PostgresSourceError,
11 PostgresTypeSystem, SimpleProtocol,
12};
13use crate::typesystem::TypeConversion;
14use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, Utc};
15use cidr_02::IpInet;
16use num_traits::ToPrimitive;
17use pgvector::{Bit, HalfVector, SparseVector, Vector};
18use postgres::NoTls;
19use postgres_openssl::MakeTlsConnector;
20use rust_decimal::Decimal;
21use serde_json::Value;
22use std::marker::PhantomData;
23use thiserror::Error;
24use uuid::Uuid;
25
26#[derive(Error, Debug)]
27pub enum PostgresArrowTransportError {
28 #[error(transparent)]
29 Source(#[from] PostgresSourceError),
30
31 #[error(transparent)]
32 Destination(#[from] ArrowDestinationError),
33
34 #[error(transparent)]
35 ConnectorX(#[from] crate::errors::ConnectorXError),
36}
37
38pub struct PostgresArrowTransport<P, C>(PhantomData<P>, PhantomData<C>);
40
41macro_rules! impl_postgres_transport {
42 ($proto:ty, $tls:ty) => {
43 impl_transport!(
44 name = PostgresArrowTransport<$proto, $tls>,
45 error = PostgresArrowTransportError,
46 systems = PostgresTypeSystem => ArrowTypeSystem,
47 route = PostgresSource<$proto, $tls> => ArrowDestination,
48 mappings = {
49 { Float4[f32] => Float32[f32] | conversion auto }
50 { Float8[f64] => Float64[f64] | conversion auto }
51 { Numeric[Decimal] => Decimal[Decimal] | conversion auto }
52 { Int2[i16] => Int16[i16] | conversion auto }
53 { Int4[i32] => Int32[i32] | conversion auto }
54 { Int8[i64] => Int64[i64] | conversion auto }
55 { UInt4[u32] => UInt32[u32] | conversion auto }
56 { Bool[bool] => Boolean[bool] | conversion auto }
57 { Text[&'r str] => LargeUtf8[String] | conversion owned }
58 { BpChar[&'r str] => LargeUtf8[String] | conversion none }
59 { VarChar[&'r str] => LargeUtf8[String] | conversion none }
60 { Name[&'r str] => LargeUtf8[String] | conversion none }
61 { Enum[&'r str] => LargeUtf8[String] | conversion none }
62 { Timestamp[NaiveDateTime] => Date64Micro[NaiveDateTimeWrapperMicro] | conversion option }
63 { Date[NaiveDate] => Date32[NaiveDate] | conversion auto }
64 { Time[NaiveTime] => Time64Micro[NaiveTimeWrapperMicro] | conversion option }
65 { TimestampTz[DateTime<Utc>] => DateTimeTzMicro[DateTimeWrapperMicro] | conversion option }
66 { UUID[Uuid] => LargeUtf8[String] | conversion option }
67 { Char[&'r str] => LargeUtf8[String] | conversion none }
68 { ByteA[Vec<u8>] => LargeBinary[Vec<u8>] | conversion auto }
69 { JSON[Value] => LargeUtf8[String] | conversion option }
70 { JSONB[Value] => LargeUtf8[String] | conversion none }
71 { Inet[IpInet] => LargeUtf8[String] | conversion none }
72 { Range[&'r str] => LargeUtf8[String] | conversion none }
73 { TsVector[&'r str] => LargeUtf8[String] | conversion none }
74 { BoolArray[Vec<Option<bool>>] => BoolArray[Vec<Option<bool>>] | conversion auto }
75 { VarcharArray[Vec<Option<String>>] => Utf8Array[Vec<Option<String>>] | conversion auto }
76 { TextArray[Vec<Option<String>>] => Utf8Array[Vec<Option<String>>] | conversion none }
77 { Int2Array[Vec<Option<i16>>] => Int16Array[Vec<Option<i16>>] | conversion auto }
78 { Int4Array[Vec<Option<i32>>] => Int32Array[Vec<Option<i32>>] | conversion auto }
79 { Int8Array[Vec<Option<i64>>] => Int64Array[Vec<Option<i64>>] | conversion auto }
80 { Float4Array[Vec<Option<f32>>] => Float32Array[Vec<Option<f32>>] | conversion auto }
81 { Float8Array[Vec<Option<f64>>] => Float64Array[Vec<Option<f64>>] | conversion auto }
82 { NumericArray[Vec<Option<Decimal>>] => DecimalArray[Vec<Option<Decimal>>] | conversion auto }
83 { Vector[Vector] => Float32Array[Vec<Option<f32>>] | conversion option }
84 { HalfVec[HalfVector] => Float32Array[Vec<Option<f32>>] | conversion option }
85 { Bit[Bit] => LargeBinary[Vec<u8>] | conversion option }
86 { SparseVec[SparseVector] => Float32Array[Vec<Option<f32>>] | conversion option }
87 }
88 );
89 }
90}
91
92impl_postgres_transport!(BinaryProtocol, NoTls);
93impl_postgres_transport!(BinaryProtocol, MakeTlsConnector);
94impl_postgres_transport!(CSVProtocol, NoTls);
95impl_postgres_transport!(CSVProtocol, MakeTlsConnector);
96impl_postgres_transport!(CursorProtocol, NoTls);
97impl_postgres_transport!(CursorProtocol, MakeTlsConnector);
98impl_postgres_transport!(SimpleProtocol, NoTls);
99impl_postgres_transport!(SimpleProtocol, MakeTlsConnector);
100
101impl<P, C> TypeConversion<IpInet, String> for PostgresArrowTransport<P, C> {
102 fn convert(val: IpInet) -> String {
103 val.to_string()
104 }
105}
106
107impl<P, C> TypeConversion<Option<IpInet>, Option<String>> for PostgresArrowTransport<P, C> {
108 fn convert(val: Option<IpInet>) -> Option<String> {
109 val.map(|val| val.to_string())
110 }
111}
112
113impl<P, C> TypeConversion<NaiveTime, NaiveTimeWrapperMicro> for PostgresArrowTransport<P, C> {
114 fn convert(val: NaiveTime) -> NaiveTimeWrapperMicro {
115 NaiveTimeWrapperMicro(val)
116 }
117}
118
119impl<P, C> TypeConversion<NaiveDateTime, NaiveDateTimeWrapperMicro>
120 for PostgresArrowTransport<P, C>
121{
122 fn convert(val: NaiveDateTime) -> NaiveDateTimeWrapperMicro {
123 NaiveDateTimeWrapperMicro(val)
124 }
125}
126
127impl<P, C> TypeConversion<DateTime<Utc>, DateTimeWrapperMicro> for PostgresArrowTransport<P, C> {
128 fn convert(val: DateTime<Utc>) -> DateTimeWrapperMicro {
129 DateTimeWrapperMicro(val)
130 }
131}
132
133impl<P, C> TypeConversion<Uuid, String> for PostgresArrowTransport<P, C> {
134 fn convert(val: Uuid) -> String {
135 val.to_string()
136 }
137}
138
139impl<P, C> TypeConversion<Decimal, f64> for PostgresArrowTransport<P, C> {
140 fn convert(val: Decimal) -> f64 {
141 val.to_f64()
142 .unwrap_or_else(|| panic!("cannot convert decimal {:?} to float64", val))
143 }
144}
145
146impl<P, C> TypeConversion<Value, String> for PostgresArrowTransport<P, C> {
147 fn convert(val: Value) -> String {
148 val.to_string()
149 }
150}
151
152impl<P, C> TypeConversion<Vector, Vec<Option<f32>>> for PostgresArrowTransport<P, C> {
153 fn convert(val: Vector) -> Vec<Option<f32>> {
154 val.to_vec().into_iter().map(Some).collect()
155 }
156}
157
158impl<P, C> TypeConversion<HalfVector, Vec<Option<f32>>> for PostgresArrowTransport<P, C> {
159 fn convert(val: HalfVector) -> Vec<Option<f32>> {
160 val.to_vec().into_iter().map(|v| Some(v.to_f32())).collect()
161 }
162}
163
164impl<P, C> TypeConversion<Bit, Vec<u8>> for PostgresArrowTransport<P, C> {
165 fn convert(val: Bit) -> Vec<u8> {
166 val.as_bytes().into()
167 }
168}
169
170impl<P, C> TypeConversion<SparseVector, Vec<Option<f32>>> for PostgresArrowTransport<P, C> {
171 fn convert(val: SparseVector) -> Vec<Option<f32>> {
172 val.to_vec().into_iter().map(Some).collect()
173 }
174}