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
use anyhow::Result;
use dbui_core::database::results::ResultSet;
use dbui_core::field_type::FieldType;
use dbui_core::Column;
use postgres::types;
use uuid::Uuid;
pub fn from_rows(id: Uuid, ctx: &str, sql: &str, rows: Vec<postgres::row::Row>, duration_ms: i32) -> Result<ResultSet> {
if rows.is_empty() {
Ok(ResultSet::new(
id,
ctx.to_string(),
Some(sql.to_string()),
vec![],
vec![],
duration_ms
))
} else {
let columns: Vec<Column> = rows[0]
.columns()
.iter()
.map(|col| Column::new(col.name().to_string(), from_type(col.type_())))
.collect();
let data: Vec<Vec<Option<String>>> = rows
.iter()
.map(|row| {
columns
.iter()
.enumerate()
.map(|(idx, col)| match crate::results::to_string::to_string(&row, idx, col.t()) {
Ok(x) => x,
Err(e) => Some(format!("Error: {}", e))
})
.collect::<Vec<Option<String>>>()
})
.collect();
Ok(ResultSet::new(
id,
ctx.to_string(),
Some(sql.to_string()),
columns,
data,
duration_ms
))
}
}
pub(crate) fn from_type(t: &types::Type) -> FieldType {
match t.kind() {
postgres::types::Kind::Simple => from_simple(t.name()),
postgres::types::Kind::Enum(v) => FieldType::Enum {
key: format!("{}: {:?}", t.name(), v)
},
postgres::types::Kind::Array(tx) => FieldType::List {
t: Box::new(from_type(tx))
},
postgres::types::Kind::Range(tx) => FieldType::Range {
t: Box::new(from_type(tx))
},
postgres::types::Kind::Domain(tx) => FieldType::Domain {
t: Box::new(from_type(tx))
},
postgres::types::Kind::Composite(fields) => FieldType::Object {
key: t.name().into(),
fields: fields.iter().map(|f| format!("{:?}", f)).collect()
},
_ => FieldType::Unknown { t: "UNHANDLED".into() }
}
}
fn from_simple(n: &str) -> FieldType {
match n {
"varchar" | "name" | "text" | "bpchar" => FieldType::String,
"bool" => FieldType::Boolean,
"char" => FieldType::Char,
"int2" => FieldType::I16,
"int4" => FieldType::I32,
"oid" => FieldType::U32,
"int8" => FieldType::I64,
"float4" => FieldType::F32,
"float8" => FieldType::F64,
"money" | "numeric" => FieldType::Numeric,
"date" => FieldType::Date,
"time" => FieldType::Time,
"timetz" | "time with time zone" => FieldType::TimeZoned,
"timestamp" => FieldType::Timestamp,
"timestamptz" | "timestamp with time zone" => FieldType::TimestampZoned,
"interval" => FieldType::Interval,
"uuid" => FieldType::Uuid,
"json" | "jsonb" => FieldType::Json,
"xml" => FieldType::Xml,
"hstore" => FieldType::StringMap,
"bytea" => FieldType::ByteArray,
"bit" | "varbit" => FieldType::BitArray,
"cidr" => FieldType::Cidr,
"inet" => FieldType::InetAddr,
"macaddr" => FieldType::MacAddr,
"box" => FieldType::Box,
"circle" => FieldType::Circle,
"path" => FieldType::Path,
"polygon" => FieldType::Polygon,
"point" => FieldType::Point,
"tsquery" => FieldType::TsQuery,
"tsvector" => FieldType::TsVector,
s => FieldType::Unknown { t: s.to_string() }
}
}