Skip to main content

tursotui_sql/
quoting.rs

1//! SQL identifier and literal quoting/escaping.
2
3/// Wrap `name` in double-quotes, doubling any internal `"`.
4///
5/// ```
6/// assert_eq!(tursotui_sql::quoting::quote_identifier("col"), r#""col""#);
7/// assert_eq!(tursotui_sql::quoting::quote_identifier(r#"a"b"#), r#""a""b""#);
8/// ```
9pub fn quote_identifier(name: &str) -> String {
10    let mut out = String::with_capacity(name.len() + 2);
11    out.push('"');
12    for c in name.chars() {
13        if c == '"' {
14            out.push('"');
15        }
16        out.push(c);
17    }
18    out.push('"');
19    out
20}
21
22/// Wrap `value` in single-quotes, doubling any internal `'`.
23///
24/// ```
25/// assert_eq!(tursotui_sql::quoting::quote_literal("hello"), "'hello'");
26/// assert_eq!(tursotui_sql::quoting::quote_literal("it's"), "'it''s'");
27/// ```
28pub fn quote_literal(value: &str) -> String {
29    let mut out = String::with_capacity(value.len() + 2);
30    out.push('\'');
31    for c in value.chars() {
32        if c == '\'' {
33            out.push('\'');
34        }
35        out.push(c);
36    }
37    out.push('\'');
38    out
39}
40
41/// Format an `Option<&str>` as a SQL literal: `None` → `"NULL"`, `Some(v)` →
42/// `quote_literal(v)`.
43pub fn format_value(opt: Option<&str>) -> String {
44    match opt {
45        None => "NULL".to_owned(),
46        Some(v) => quote_literal(v),
47    }
48}
49
50#[cfg(test)]
51mod tests {
52    use super::*;
53
54    #[test]
55    fn quote_identifier_simple() {
56        assert_eq!(quote_identifier("col"), r#""col""#);
57    }
58
59    #[test]
60    fn quote_identifier_with_quotes() {
61        assert_eq!(quote_identifier(r#"a"b"#), r#""a""b""#);
62    }
63
64    #[test]
65    fn quote_literal_simple() {
66        assert_eq!(quote_literal("hello"), "'hello'");
67    }
68
69    #[test]
70    fn quote_literal_with_quotes() {
71        assert_eq!(quote_literal("it's"), "'it''s'");
72    }
73
74    #[test]
75    fn format_value_none() {
76        assert_eq!(format_value(None), "NULL");
77    }
78
79    #[test]
80    fn format_value_some() {
81        assert_eq!(format_value(Some("hello")), "'hello'");
82    }
83
84    #[test]
85    fn format_value_some_with_quotes() {
86        assert_eq!(format_value(Some("it's")), "'it''s'");
87    }
88}