cufflink_pgcodec/
render.rs1use crate::row_json::{column_to_json, column_to_json_v2};
4use cufflink_types::db::{Column, DbError, DbResponse, RowMap};
5use serde_json::Value;
6use tokio_postgres::Row;
7
8pub fn legacy_rows(rows: &[Row]) -> Vec<Value> {
11 rows.iter()
12 .map(|row| {
13 Value::Object(
14 row.columns()
15 .iter()
16 .enumerate()
17 .map(|(i, column)| {
18 (
19 column.name().to_string(),
20 column_to_json(row, i, column.type_()),
21 )
22 })
23 .collect(),
24 )
25 })
26 .collect()
27}
28
29pub fn rows_v2(columns: &[tokio_postgres::Column], rows: &[Row]) -> Result<DbResponse, DbError> {
32 let rows = rows
33 .iter()
34 .map(|row| {
35 columns
36 .iter()
37 .enumerate()
38 .map(|(i, column)| {
39 column_to_json_v2(row, i, column.type_())
40 .map(|value| (column.name().to_string(), value))
41 })
42 .collect::<Result<RowMap, DbError>>()
43 })
44 .collect::<Result<Vec<_>, _>>()?;
45 Ok(DbResponse::Rows {
46 rows,
47 columns: columns_v2(columns),
48 })
49}
50
51pub struct ColumnOrder(Vec<(String, usize)>);
55
56impl ColumnOrder {
57 pub fn of(columns: &[tokio_postgres::Column]) -> Self {
58 let last: std::collections::BTreeMap<&str, usize> = columns
59 .iter()
60 .enumerate()
61 .map(|(i, column)| (column.name(), i))
62 .collect();
63 Self(
64 last.into_iter()
65 .map(|(name, i)| (Value::from(name).to_string(), i))
66 .collect(),
67 )
68 }
69
70 pub fn legacy_row(&self, row: &Row, out: &mut String) {
73 self.write(out, |i| column_to_json(row, i, row.columns()[i].type_()));
74 }
75
76 pub fn row_v2(&self, row: &Row, out: &mut String) -> Result<(), DbError> {
79 let mut values = row
80 .columns()
81 .iter()
82 .enumerate()
83 .map(|(i, column)| column_to_json_v2(row, i, column.type_()).map(Some))
84 .collect::<Result<Vec<Option<Value>>, DbError>>()?;
85 self.write(out, |i| values[i].take().unwrap_or(Value::Null));
86 Ok(())
87 }
88
89 fn write(&self, out: &mut String, mut value: impl FnMut(usize) -> Value) {
90 out.push('{');
91 for (n, (key, i)) in self.0.iter().enumerate() {
92 if n > 0 {
93 out.push(',');
94 }
95 out.push_str(key);
96 out.push(':');
97 out.push_str(&value(*i).to_string());
98 }
99 out.push('}');
100 }
101}
102
103pub fn columns_v2(columns: &[tokio_postgres::Column]) -> Vec<Column> {
105 columns
106 .iter()
107 .map(|column| Column {
108 name: column.name().to_string(),
109 type_name: column.type_().name().to_string(),
110 })
111 .collect()
112}