adjust edge-cases

This commit is contained in:
Nikita Sivukhin
2025-09-26 11:34:27 +04:00
parent 12b89fd2f1
commit ae24d637a8
5 changed files with 16 additions and 16 deletions

View File

@@ -1826,7 +1826,7 @@ pub fn translate_expr(
ast::Expr::Id(id) => {
// Treat double-quoted identifiers as string literals (SQLite compatibility)
program.emit_insn(Insn::String8 {
value: sanitize_double_quoted_string(id.as_str()),
value: id.as_str().to_string(),
dest: target_register,
});
Ok(target_register)
@@ -3008,12 +3008,6 @@ pub fn sanitize_string(input: &str) -> String {
inner.replace("''", "'")
}
/// Sanitizes a double-quoted string literal by removing double quotes at front and back
/// and unescaping double quotes
pub fn sanitize_double_quoted_string(input: &str) -> String {
input[1..input.len() - 1].replace("\"\"", "\"").to_string()
}
/// Returns the components of a binary expression
/// e.g. t.x = 5 -> Some((t.x, =, 5))
pub fn as_binary_components(
@@ -3473,7 +3467,7 @@ pub fn bind_and_rewrite_expr<'a>(
// Single quotes are handled as literals earlier, unquoted identifiers must resolve to columns
if id.quoted_with('"') {
// Convert failed double-quoted identifier to string literal
*expr = Expr::Literal(ast::Literal::String(id.as_str().to_string()));
*expr = Expr::Literal(ast::Literal::String(id.as_literal()));
return Ok(WalkControl::Continue);
} else {
// Unquoted identifiers must resolve to columns - no fallback

View File

@@ -149,10 +149,8 @@ pub fn translate_insert(
match expr.as_mut() {
Expr::Id(name) => {
if name.quoted_with('"') {
*expr = Expr::Literal(ast::Literal::String(
name.as_literal().to_string(),
))
.into();
*expr =
Expr::Literal(ast::Literal::String(name.as_literal())).into();
} else {
// an INSERT INTO ... VALUES (...) cannot reference columns
crate::bail_parse_error!("no such column: {name}");

View File

@@ -422,7 +422,7 @@ fn collect_autoindexes(
fn create_table_body_to_str(tbl_name: &ast::QualifiedName, body: &ast::CreateTableBody) -> String {
let mut sql = String::new();
sql.push_str(format!("CREATE TABLE {} {}", tbl_name.name.as_str(), body).as_str());
sql.push_str(format!("CREATE TABLE {} {}", tbl_name.name.as_quoted(), body).as_str());
match body {
ast::CreateTableBody::ColumnsAndConstraints {
columns: _,

View File

@@ -5365,7 +5365,7 @@ pub fn op_function(
let column = columns
.iter_mut()
.find(|column| {
column.col_name == ast::Name::exact(original_rename_from.to_string())
column.col_name.as_str() == original_rename_from.as_str()
})
.expect("column being renamed should be present");

View File

@@ -924,6 +924,8 @@ impl<'de> serde::Deserialize<'de> for Name {
}
impl Name {
/// Create name which will have exactly the value of given string
/// (e.g. if s = "\"str\"" - the name value will contain quotes and translation to SQL will give us """str""")
pub fn exact(s: String) -> Self {
let value_is_lowercase = s.chars().all(|x| x.is_lowercase());
Self {
@@ -933,9 +935,11 @@ impl Name {
value_is_lowercase,
}
}
/// Parse name from the bytes (e.g. handle quoting and handle escaped quotes)
pub fn from_bytes(s: &[u8]) -> Self {
Self::from_str(unsafe { std::str::from_utf8_unchecked(s) })
}
/// Parse name from the string (e.g. handle quoting and handle escaped quotes)
pub fn from_str(s: impl AsRef<str>) -> Self {
let s = s.as_ref();
let bytes = s.as_bytes();
@@ -969,6 +973,8 @@ impl Name {
}
}
/// Return string value of the name alredy converted to the lowercase
/// This value can be safely compared with other values without any normalization logic
pub fn as_str(&self) -> &str {
if self.value_is_lowercase {
return &self.value;
@@ -979,10 +985,12 @@ impl Name {
self.lowercase.get().unwrap()
}
pub fn as_literal(&self) -> &str {
&self.value
/// Convert value to the string literal (e.g. single-quoted string with escaped single quotes)
pub fn as_literal(&self) -> String {
format!("'{}'", self.value.replace("'", "''"))
}
/// Convert value to the name string (e.g. double-quoted string with escaped double quotes)
pub fn as_quoted(&self) -> String {
let value = self.value.as_bytes();
if !value.is_empty() && value.iter().all(|x| x.is_ascii_alphanumeric()) {