dinoco_engine/databases/postgresql/
dialect.rs1use crate::{AdapterDialect, ColumnDefinition, ColumnType, DinocoValue};
2
3pub struct PostgresDialect;
4
5impl AdapterDialect for PostgresDialect {
6 fn bind_param(&self, index: usize) -> String {
7 format!("${}", index)
8 }
9
10 fn cast_numeric_for_division(&self, expr: &str) -> String {
11 format!("CAST({expr} AS DOUBLE PRECISION)")
12 }
13
14 fn bind_value(&self, index: usize, value: &DinocoValue) -> String {
15 match value {
16 DinocoValue::Enum(type_name, _) => {
17 format!("{}::{}", self.bind_param(index), self.identifier(type_name))
18 }
19 _ => self.bind_param(index),
20 }
21 }
22
23 fn identifier(&self, v: &str) -> String {
24 let escaped = v.replace('"', "\"\"");
25
26 format!("\"{}\"", escaped)
27 }
28
29 fn literal_string(&self, v: &str) -> String {
30 let escaped = v.replace('\'', "''");
31 format!("'{}'", escaped)
32 }
33
34 fn supports_native_enums(&self) -> bool {
35 true
36 }
37
38 fn supports_insert_returning(&self) -> bool {
39 true
40 }
41
42 fn column_type(&self, col: &ColumnDefinition, is_primary: bool, auto_increment: bool) -> String {
43 let mut base_type = match &col.col_type {
44 ColumnType::Integer => "BIGINT".to_string(),
45 ColumnType::Float => "DOUBLE PRECISION".to_string(),
46 ColumnType::Text => "TEXT".to_string(),
47 ColumnType::Boolean => "BOOLEAN".to_string(),
48 ColumnType::Json => "JSONB".to_string(),
49 ColumnType::DateTime => "TIMESTAMP".to_string(),
50 ColumnType::Date => "DATE".to_string(),
51 ColumnType::Bytes => "BYTEA".to_string(),
52
53 ColumnType::Enum(name) => self.identifier(name),
54 ColumnType::EnumInline(_) => "TEXT".into(),
55 };
56
57 if auto_increment {
58 base_type.push_str(" GENERATED ALWAYS AS IDENTITY");
59 }
60
61 if is_primary {
62 base_type.push_str(" PRIMARY KEY");
63 }
64
65 base_type
66 }
67}