uqa_sql/expr/scalar_helpers/
quoting.rs1use uqa_core::{
10 memory::{Produced, ProductionControl, ProductionString},
11 ValueRetentionError,
12};
13
14pub(crate) fn append_sql_literal(output: &mut String, value: &str, standard_strings: bool) {
16 output.push('\'');
17 for character in value.chars() {
18 if character == '\'' || (character == '\\' && !standard_strings) {
19 output.push(character);
20 }
21 output.push(character);
22 }
23 output.push('\'');
24}
25
26pub fn quote_ident(ident: &str) -> String {
28 quote_ident_with_control(ident, &ProductionControl::uncontrolled())
29 .expect("ordinary identifier quoting")
30 .into_uncontrolled()
31 .expect("ordinary quoted identifier")
32}
33
34pub(crate) fn quote_ident_with_control(
35 ident: &str,
36 control: &ProductionControl<'_>,
37) -> Result<Produced<String>, ValueRetentionError> {
38 control.check()?;
39 let mut safe = !ident.is_empty();
40 for (index, character) in ident.chars().enumerate() {
41 control.check()?;
42 safe &= character.is_ascii_lowercase()
43 || character == '_'
44 || (index > 0 && character.is_ascii_digit());
45 }
46 if safe && !super::is_quoted_keyword(ident) {
47 return control.copy_text(ident);
48 }
49 let mut output = ProductionString::new(*control);
50 output.push('"')?;
51 for character in ident.chars() {
52 if character == '"' {
53 output.push('"')?;
54 }
55 output.push(character)?;
56 }
57 output.push('"')?;
58 output.finish()
59}
60
61pub(in crate::expr) fn quote_literal_with_control(
63 text: &str,
64 control: &ProductionControl<'_>,
65) -> Result<Produced<String>, ValueRetentionError> {
66 control.check()?;
67 let mut escape = false;
68 for character in text.chars() {
69 control.check()?;
70 escape |= character == '\\';
71 }
72 let mut output = ProductionString::new(*control);
73 if escape {
74 output.push('E')?;
75 }
76 output.push('\'')?;
77 for character in text.chars() {
78 if matches!(character, '\'' | '\\') {
79 output.push(character)?;
80 }
81 output.push(character)?;
82 }
83 output.push('\'')?;
84 output.finish()
85}