mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-01 14:24:23 +01:00
handle single, double and unquoted strings in values clause
This commit is contained in:
@@ -2715,11 +2715,6 @@ pub fn sanitize_double_quoted_string(input: &str) -> String {
|
||||
input[1..input.len() - 1].replace("\"\"", "\"").to_string()
|
||||
}
|
||||
|
||||
/// Checks if an identifier represents a double-quoted string that should get fallback behavior
|
||||
pub fn is_double_quoted_identifier(id_str: &str) -> bool {
|
||||
id_str.len() >= 2 && id_str.starts_with('"') && id_str.ends_with('"')
|
||||
}
|
||||
|
||||
/// Returns the components of a binary expression
|
||||
/// e.g. t.x = 5 -> Some((t.x, =, 5))
|
||||
pub fn as_binary_components(
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use turso_sqlite3_parser::ast::{
|
||||
DistinctNames, Expr, InsertBody, OneSelect, QualifiedName, ResolveType, ResultColumn, With,
|
||||
self, DistinctNames, Expr, InsertBody, OneSelect, QualifiedName, ResolveType, ResultColumn,
|
||||
With,
|
||||
};
|
||||
|
||||
use crate::error::{SQLITE_CONSTRAINT_NOTNULL, SQLITE_CONSTRAINT_PRIMARYKEY};
|
||||
@@ -111,6 +112,14 @@ pub fn translate_insert(
|
||||
}
|
||||
let mut param_idx = 1;
|
||||
for expr in values_expr.iter_mut().flat_map(|v| v.iter_mut()) {
|
||||
if let Expr::Id(name) = expr {
|
||||
if name.is_double_quoted() {
|
||||
*expr = Expr::Literal(ast::Literal::String(format!("{name}")));
|
||||
} else {
|
||||
// an INSERT INTO ... VALUES (...) cannot reference columns
|
||||
crate::bail_parse_error!("no such column: {name}");
|
||||
}
|
||||
}
|
||||
rewrite_expr(expr, &mut param_idx)?;
|
||||
}
|
||||
values = values_expr.pop();
|
||||
|
||||
@@ -14,9 +14,8 @@ use crate::{
|
||||
parameters::PARAM_PREFIX,
|
||||
schema::{Index, IndexColumn, Schema, Table},
|
||||
translate::{
|
||||
expr::is_double_quoted_identifier, expr::walk_expr_mut,
|
||||
optimizer::access_method::AccessMethodParams, optimizer::constraints::TableConstraints,
|
||||
plan::Scan, plan::TerminationKey,
|
||||
expr::walk_expr_mut, optimizer::access_method::AccessMethodParams,
|
||||
optimizer::constraints::TableConstraints, plan::Scan, plan::TerminationKey,
|
||||
},
|
||||
types::SeekOp,
|
||||
LimboError, Result,
|
||||
@@ -701,7 +700,7 @@ impl Optimizable for ast::Expr {
|
||||
Expr::FunctionCallStar { .. } => false,
|
||||
Expr::Id(id) => {
|
||||
// If we got here with an id, this has to be double-quotes identifier
|
||||
assert!(is_double_quoted_identifier(id.as_str()));
|
||||
assert!(id.is_double_quoted());
|
||||
true
|
||||
}
|
||||
Expr::Column { .. } => false,
|
||||
|
||||
@@ -205,7 +205,7 @@ pub fn bind_column_references(
|
||||
}
|
||||
// SQLite behavior: Only double-quoted identifiers get fallback to string literals
|
||||
// Single quotes are handled as literals earlier, unquoted identifiers must resolve to columns
|
||||
if crate::translate::expr::is_double_quoted_identifier(id.as_str()) {
|
||||
if id.is_double_quoted() {
|
||||
// Convert failed double-quoted identifier to string literal
|
||||
*expr = Expr::Literal(Literal::String(id.as_str().to_string()));
|
||||
Ok(())
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env tclsh
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
source $testdir/sqlite3/tester.tcl
|
||||
|
||||
do_execsql_test_on_specific_db {:memory:} basic-insert {
|
||||
create table temp (t1 integer, primary key (t1));
|
||||
@@ -582,3 +583,15 @@ do_execsql_test_on_specific_db {:memory:} returning-null-values {
|
||||
CREATE TABLE test (id INTEGER, name TEXT, value INTEGER);
|
||||
INSERT INTO test (id, name, value) VALUES (1, NULL, NULL) RETURNING id, name, value;
|
||||
} {1||}
|
||||
|
||||
do_catchsql_test unknown-identifier-in-values-clause {
|
||||
DROP TABLE IF EXISTS tt;
|
||||
CREATE TABLE tt (x);
|
||||
INSERT INTO tt VALUES(asdf);
|
||||
} {1 {no such column: asdf}}
|
||||
|
||||
do_catchsql_test unknown-backtick-identifier-in-values-clause {
|
||||
DROP TABLE IF EXISTS tt;
|
||||
CREATE TABLE tt (x);
|
||||
INSERT INTO tt VALUES(`asdf`);
|
||||
} {1 {no such column: `asdf`}}
|
||||
|
||||
@@ -1178,6 +1178,14 @@ impl Name {
|
||||
_ => Name::Ident(s.to_string()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if a name represents a double-quoted string that should get fallback behavior
|
||||
pub fn is_double_quoted(&self) -> bool {
|
||||
if let Self::Quoted(ident) = self {
|
||||
return ident.starts_with("\"");
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
struct QuotedIterator<'s>(Bytes<'s>, u8);
|
||||
|
||||
Reference in New Issue
Block a user