mirror of
https://github.com/aljazceru/turso.git
synced 2026-01-31 05:44:25 +01:00
adjust edge-cases
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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}");
|
||||
|
||||
@@ -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: _,
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
Reference in New Issue
Block a user