waypoint_core/dialect/
postgres.rs1use super::{DatabaseDialect, DialectKind};
4
5pub struct PostgresDialect;
7
8impl DatabaseDialect for PostgresDialect {
9 fn kind(&self) -> DialectKind {
10 DialectKind::Postgres
11 }
12
13 fn quote_ident(&self, name: &str) -> String {
14 format!("\"{}\"", name.replace('"', "\"\""))
15 }
16
17 fn history_table_ddl(&self, schema: &str, table: &str) -> String {
18 let fq = self.qualified_table(schema, table);
19 let success_idx = self.quote_ident(&format!("{}_s_idx", table));
20 let version_idx = self.quote_ident(&format!("{}_v_idx", table));
21 format!(
22 r#"
23CREATE TABLE IF NOT EXISTS {fq} (
24 installed_rank INTEGER PRIMARY KEY,
25 version VARCHAR(50),
26 description VARCHAR(200) NOT NULL,
27 type VARCHAR(20) NOT NULL,
28 script VARCHAR(1000) NOT NULL,
29 checksum INTEGER,
30 installed_by VARCHAR(100) NOT NULL,
31 installed_on TIMESTAMPTZ NOT NULL DEFAULT now(),
32 execution_time INTEGER NOT NULL,
33 success BOOLEAN NOT NULL,
34 reversal_sql TEXT
35);
36
37CREATE INDEX IF NOT EXISTS {success_idx} ON {fq} (success);
38CREATE INDEX IF NOT EXISTS {version_idx} ON {fq} (version);
39"#
40 )
41 }
42
43 fn supports_transactional_ddl(&self) -> bool {
44 true
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 #[test]
53 fn quotes_identifier_with_double_quotes() {
54 let d = PostgresDialect;
55 assert_eq!(d.quote_ident("users"), r#""users""#);
56 assert_eq!(d.quote_ident(r#"my"table"#), r#""my""table""#);
57 }
58
59 #[test]
60 fn history_ddl_contains_required_columns() {
61 let d = PostgresDialect;
62 let ddl = d.history_table_ddl("public", "waypoint_schema_history");
63 for col in [
64 "installed_rank",
65 "version",
66 "description",
67 "type",
68 "script",
69 "checksum",
70 "installed_by",
71 "installed_on",
72 "execution_time",
73 "success",
74 "reversal_sql",
75 ] {
76 assert!(ddl.contains(col), "DDL missing column {}", col);
77 }
78 assert!(ddl.contains("TIMESTAMPTZ"));
79 }
80
81 #[test]
82 fn supports_transactional_ddl() {
83 assert!(PostgresDialect.supports_transactional_ddl());
84 }
85}