Skip to main content

dinoco_engine/databases/sqlite/
dialect.rs

1use crate::{AdapterDialect, ColumnDefinition, ColumnType};
2
3pub struct SqliteDialect;
4
5impl AdapterDialect for SqliteDialect {
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 REAL)")
12    }
13
14    fn identifier(&self, v: &str) -> String {
15        let escaped = v.replace('"', "\"\"");
16        format!("\"{}\"", escaped)
17    }
18
19    fn literal_string(&self, v: &str) -> String {
20        let escaped = v.replace('\'', "''");
21        format!("'{}'", escaped)
22    }
23
24    fn column_type(&self, col: &ColumnDefinition, is_primary: bool, auto_increment: bool) -> String {
25        if is_primary && auto_increment {
26            return "INTEGER PRIMARY KEY AUTOINCREMENT".to_string();
27        }
28
29        let mut base_type = match &col.col_type {
30            ColumnType::Integer => "INTEGER".to_string(),
31            ColumnType::Float => "REAL".to_string(),
32            ColumnType::Text => "TEXT".to_string(),
33            ColumnType::Boolean => "BOOLEAN".to_string(),
34            ColumnType::Json => "TEXT".to_string(),
35            ColumnType::DateTime => "DATETIME".to_string(),
36            ColumnType::Date => "DATE".to_string(),
37            ColumnType::Bytes => "BLOB".to_string(),
38            ColumnType::Enum(_) => "TEXT".to_string(),
39            ColumnType::EnumInline(values) => {
40                let check_values = values.iter().map(|v| self.literal_string(v)).collect::<Vec<_>>().join(", ");
41
42                format!("TEXT CHECK ({} IN ({}))", col.name, check_values)
43            }
44        };
45
46        if is_primary {
47            base_type.push_str(" PRIMARY KEY");
48        }
49
50        base_type
51    }
52
53    fn supports_insert_returning(&self) -> bool {
54        true
55    }
56}