1use keelson_core::{Dialect, SqlWriter};
2
3#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
9pub struct Psql;
10
11impl Dialect for Psql {
12 fn write_arg(&self, w: &mut SqlWriter<'_>, position: usize) {
13 w.push_str("$");
14 w.push_str(&position.to_string());
15 }
16
17 fn write_quoted(&self, w: &mut SqlWriter<'_>, s: &str) {
26 w.push_str("\"");
27 if s.contains('"') {
28 w.push_str(&s.replace('"', "\"\""));
29 } else {
30 w.push_str(s);
31 }
32 w.push_str("\"");
33 }
34}
35
36#[cfg(test)]
37mod tests {
38 use super::*;
39 use keelson_core::{Value, build, expr};
40
41 #[test]
42 fn placeholders_are_dollar_numbered_and_identifiers_are_double_quoted() {
43 let e = expr::Expr::join((expr::quote(("users", "id")), expr::arg(1i32)));
44 let (sql, args) = build(&Psql, &e).unwrap();
45 assert_eq!(sql, r#""users"."id" $1"#);
46 assert_eq!(args, vec![Value::I32(1)]);
47 }
48
49 #[test]
50 fn an_embedded_quote_is_doubled() {
51 let (sql, _) = build(&Psql, &expr::quote(r#"we"ird"#)).unwrap();
52 assert_eq!(sql, r#""we""ird""#);
53 }
54
55 #[test]
56 fn named_arguments_are_refused() {
57 assert!(matches!(
58 build(&Psql, &expr::named("x")),
59 Err(keelson_core::Error::NoNamedArgs)
60 ));
61 }
62}