1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, Utc};
use postgres::types::Type;
use rust_decimal::Decimal;
use serde_json::Value;
use std::collections::HashMap;
use uuid::Uuid;

#[derive(Copy, Clone, Debug)]
pub enum PostgresTypeSystem {
    Bool(bool),
    Float4(bool),
    Float8(bool),
    Numeric(bool),
    Int2(bool),
    Int4(bool),
    Int8(bool),
    Float4Array(bool),
    Float8Array(bool),
    NumericArray(bool),
    BoolArray(bool),
    Int2Array(bool),
    Int4Array(bool),
    Int8Array(bool),
    VarcharArray(bool),
    TextArray(bool),
    Date(bool),
    Char(bool),
    BpChar(bool),
    VarChar(bool),
    Text(bool),
    ByteA(bool),
    Time(bool),
    Timestamp(bool),
    TimestampTz(bool),
    UUID(bool),
    JSON(bool),
    JSONB(bool),
    Enum(bool),
    HSTORE(bool),
    Name(bool),
}

impl_typesystem! {
    system = PostgresTypeSystem,
    mappings = {
        { Int2 => i16 }
        { Int4 => i32 }
        { Int8 => i64 }
        { Float4 => f32 }
        { Float8 => f64 }
        { Numeric => Decimal }
        { BoolArray => Vec<bool> }
        { Int2Array => Vec<i16> }
        { Int4Array => Vec<i32> }
        { Int8Array => Vec<i64> }
        { Float4Array => Vec<f32> }
        { Float8Array => Vec<f64> }
        { NumericArray => Vec<Decimal> }
        { VarcharArray | TextArray => Vec<String>}
        { Bool => bool }
        { Char => i8 }
        { Text | BpChar | VarChar | Enum | Name => &'r str }        { ByteA => Vec<u8> }
        { Time => NaiveTime }
        { Timestamp => NaiveDateTime }
        { TimestampTz => DateTime<Utc> }
        { Date => NaiveDate }
        { UUID => Uuid }
        { JSON | JSONB => Value }
        { HSTORE => HashMap<String, Option<String>> }
    }
}

impl<'a> From<&'a Type> for PostgresTypeSystem {
    fn from(ty: &'a Type) -> PostgresTypeSystem {
        use PostgresTypeSystem::*;
        match ty.name() {
            "int2" => Int2(true),
            "int4" => Int4(true),
            "int8" => Int8(true),
            "float4" => Float4(true),
            "float8" => Float8(true),
            "numeric" => Numeric(true),
            "_bool" => BoolArray(true),
            "_int2" => Int2Array(true),
            "_int4" => Int4Array(true),
            "_int8" => Int8Array(true),
            "_float4" => Float4Array(true),
            "_float8" => Float8Array(true),
            "_numeric" => NumericArray(true),
            "_varchar" => VarcharArray(true),
            "_text" => TextArray(true),
            "bool" => Bool(true),
            "char" => Char(true),
            "text" | "citext" | "ltree" | "lquery" | "ltxtquery" | "name" => Text(true),
            "bpchar" => BpChar(true),
            "varchar" => VarChar(true),
            "bytea" => ByteA(true),
            "time" => Time(true),
            "timestamp" => Timestamp(true),
            "timestamptz" => TimestampTz(true),
            "date" => Date(true),
            "uuid" => UUID(true),
            "json" => JSON(true),
            "jsonb" => JSONB(true),
            "hstore" => HSTORE(true),
            _ => match ty.kind() {
                postgres::types::Kind::Enum(_) => Enum(true),
                _ => unimplemented!("{}", ty.name()),
            },
        }
    }
}

pub struct PostgresTypePairs<'a>(pub &'a Type, pub &'a PostgresTypeSystem);

// Link (postgres::Type, connectorx::PostgresTypes) back to the one defiend by the postgres crate.
impl<'a> From<PostgresTypePairs<'a>> for Type {
    fn from(ty: PostgresTypePairs) -> Type {
        use PostgresTypeSystem::*;
        match ty.1 {
            Enum(_) => Type::TEXT,
            HSTORE(_) => Type::TEXT, // hstore is not supported in binary protocol (since no corresponding inner TYPE)
            _ => ty.0.clone(),
        }
    }
}