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