tank_postgres/
sql_writer.rs

1use std::fmt::Write;
2use tank_core::{Context, SqlWriter, Value, future::Either, separated_by};
3
4pub struct PostgresSqlWriter {}
5
6impl SqlWriter for PostgresSqlWriter {
7    fn as_dyn(&self) -> &dyn SqlWriter {
8        self
9    }
10
11    fn write_column_type(&self, context: &mut Context, buff: &mut String, value: &Value) {
12        match value {
13            Value::Boolean(..) => buff.push_str("BOOLEAN"),
14            Value::Int8(..) => buff.push_str("SMALLINT"),
15            Value::Int16(..) => buff.push_str("SMALLINT"),
16            Value::Int32(..) => buff.push_str("INTEGER"),
17            Value::Int64(..) => buff.push_str("BIGINT"),
18            Value::Int128(..) => buff.push_str("NUMERIC(38)"),
19            Value::UInt8(..) => buff.push_str("SMALLINT"),
20            Value::UInt16(..) => buff.push_str("INTEGER"),
21            Value::UInt32(..) => buff.push_str("BIGINT"),
22            Value::UInt64(..) => buff.push_str("NUMERIC(19)"),
23            Value::UInt128(..) => buff.push_str("NUMERIC(38)"),
24            Value::Float32(..) => buff.push_str("FLOAT4"),
25            Value::Float64(..) => buff.push_str("FLOAT8"),
26            Value::Decimal(.., precision, scale) => {
27                buff.push_str("NUMERIC");
28                if (precision, scale) != (&0, &0) {
29                    let _ = write!(buff, "({},{})", precision, scale);
30                }
31            }
32            Value::Char(..) => buff.push_str("CHARACTER(1)"),
33            Value::Varchar(..) => buff.push_str("TEXT"),
34            Value::Blob(..) => buff.push_str("BYTEA"),
35            Value::Date(..) => buff.push_str("DATE"),
36            Value::Time(..) => buff.push_str("TIME"),
37            Value::Timestamp(..) => buff.push_str("TIMESTAMP"),
38            Value::TimestampWithTimezone(..) => buff.push_str("TIMESTAMP WITH TIME ZONE"),
39            Value::Interval(..) => buff.push_str("INTERVAL"),
40            Value::Uuid(..) => buff.push_str("UUID"),
41            Value::Array(.., inner, size) => {
42                self.write_column_type(context, buff, inner);
43                let _ = write!(buff, "[{}]", size);
44            }
45            Value::List(.., inner) => {
46                self.write_column_type(context, buff, inner);
47                buff.push_str("[]");
48            }
49            _ => log::error!(
50                "Unexpected tank::Value, variant {:?} is not supported",
51                value
52            ),
53        };
54    }
55
56    fn write_value_blob(&self, _context: &mut Context, buff: &mut String, value: &[u8]) {
57        buff.push_str("'\\x");
58        for b in value {
59            let _ = write!(buff, "{:X}", b);
60        }
61        buff.push('\'');
62    }
63
64    fn write_value_list<'a>(
65        &self,
66        context: &mut Context,
67        buff: &mut String,
68        value: Either<&Box<[Value]>, &Vec<Value>>,
69        ty: &Value,
70    ) {
71        buff.push_str("ARRAY[");
72        separated_by(
73            buff,
74            match value {
75                Either::Left(v) => v.iter(),
76                Either::Right(v) => v.iter(),
77            },
78            |buff, v| {
79                self.write_value(context, buff, v);
80            },
81            ",",
82        );
83        buff.push_str("]::");
84        self.write_column_type(context, buff, ty);
85    }
86
87    fn write_expression_operand_question_mark(&self, context: &mut Context, buff: &mut String) {
88        context.counter += 1;
89        let _ = write!(buff, "${}", context.counter);
90    }
91}