From b0f4dd49d533459aaac4f039308c4d46b9114414 Mon Sep 17 00:00:00 2001 From: TcMits Date: Wed, 3 Sep 2025 12:01:52 +0700 Subject: [PATCH 1/2] use match_ignore_ascii_case macro --- core/lib.rs | 31 +++++++++++++++++-------------- core/translate/logical.rs | 11 ++++++++--- core/translate/optimizer/mod.rs | 18 +++++++++++------- core/translate/planner.rs | 26 ++++++++++++++------------ core/vdbe/execute.rs | 21 ++++++++++----------- 5 files changed, 60 insertions(+), 47 deletions(-) diff --git a/core/lib.rs b/core/lib.rs index fac579257..e6f58b71c 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -63,6 +63,7 @@ pub use io::{ }; use parking_lot::RwLock; use schema::Schema; +use turso_macros::match_ignore_ascii_case; use std::{ borrow::Cow, cell::{Cell, RefCell, UnsafeCell}, @@ -1911,21 +1912,23 @@ impl Connection { // Check if this is a qualified name (database.table) or unqualified if let Some(db_name) = &qualified_name.db_name { let db_name_normalized = normalize_ident(db_name.as_str()); - - if db_name_normalized.eq_ignore_ascii_case("main") { - Ok(0) - } else if db_name_normalized.eq_ignore_ascii_case("temp") { - Ok(1) - } else { - // Look up attached database - if let Some((idx, _attached_db)) = self.get_attached_database(&db_name_normalized) { - Ok(idx) - } else { - Err(LimboError::InvalidArgument(format!( - "no such database: {db_name_normalized}" - ))) + let name_bytes = db_name_normalized.as_bytes(); + match_ignore_ascii_case!(match name_bytes { + b"main" => Ok(0), + b"temp" => Ok(1), + _ => { + // Look up attached database + if let Some((idx, _attached_db)) = + self.get_attached_database(&db_name_normalized) + { + Ok(idx) + } else { + Err(LimboError::InvalidArgument(format!( + "no such database: {db_name_normalized}" + ))) + } } - } + }) } else { // Unqualified table name - use main database Ok(0) diff --git a/core/translate/logical.rs b/core/translate/logical.rs index 9c970f800..cd4e089e8 100644 --- a/core/translate/logical.rs +++ b/core/translate/logical.rs @@ -1368,9 +1368,14 @@ impl<'a> LogicalPlanBuilder<'a> { fn build_literal(lit: &ast::Literal) -> Result { match lit { ast::Literal::Null => Ok(Value::Null), - ast::Literal::Keyword(k) if k.eq_ignore_ascii_case("true") => Ok(Value::Integer(1)), // SQLite uses int for bool - ast::Literal::Keyword(k) if k.eq_ignore_ascii_case("false") => Ok(Value::Integer(0)), // SQLite uses int for bool - ast::Literal::Keyword(k) => Ok(Value::Text(k.clone().into())), + ast::Literal::Keyword(k) => { + let k_bytes = k.as_bytes(); + match_ignore_ascii_case!(match k_bytes { + b"true" => Ok(Value::Integer(1)), // SQLite uses int for bool + b"false" => Ok(Value::Integer(0)), // SQLite uses int for bool + _ => Ok(Value::Text(k.clone().into())), + }) + } ast::Literal::Numeric(s) => { if let Ok(i) = s.parse::() { Ok(Value::Integer(i)) diff --git a/core/translate/optimizer/mod.rs b/core/translate/optimizer/mod.rs index 49b88c402..ec9237f00 100644 --- a/core/translate/optimizer/mod.rs +++ b/core/translate/optimizer/mod.rs @@ -8,6 +8,7 @@ use join::{compute_best_join_order, BestJoinOrderResult}; use lift_common_subexpressions::lift_common_subexpressions_from_binary_or_terms; use order::{compute_order_target, plan_satisfies_order_target, EliminatesSortBy}; use turso_ext::{ConstraintInfo, ConstraintUsage}; +use turso_macros::match_ignore_ascii_case; use turso_parser::ast::{self, Expr, SortOrder}; use crate::{ @@ -1405,13 +1406,16 @@ pub fn rewrite_expr(top_level_expr: &mut ast::Expr, param_idx: &mut usize) -> Re match expr { ast::Expr::Id(id) => { // Convert "true" and "false" to 1 and 0 - if id.as_str().eq_ignore_ascii_case("true") { - *expr = ast::Expr::Literal(ast::Literal::Numeric(1.to_string())); - return Ok(()); - } - if id.as_str().eq_ignore_ascii_case("false") { - *expr = ast::Expr::Literal(ast::Literal::Numeric(0.to_string())); - } + let id_bytes = id.as_str().as_bytes(); + match_ignore_ascii_case!(match id_bytes { + b"true" => { + *expr = ast::Expr::Literal(ast::Literal::Numeric("1".to_owned())); + } + b"false" => { + *expr = ast::Expr::Literal(ast::Literal::Numeric("0".to_owned())); + } + _ => {} + }) } ast::Expr::Variable(var) => { if var.is_empty() { diff --git a/core/translate/planner.rs b/core/translate/planner.rs index 522256a25..9e9a6e0de 100644 --- a/core/translate/planner.rs +++ b/core/translate/planner.rs @@ -19,6 +19,7 @@ use crate::{ vdbe::{builder::TableRefIdCounter, BranchOffset}, Result, }; +use turso_macros::match_ignore_ascii_case; use turso_parser::ast::Literal::Null; use turso_parser::ast::{ self, As, Expr, FromClause, JoinType, Limit, Literal, Materialized, QualifiedName, @@ -114,11 +115,13 @@ pub fn bind_column_references( Expr::Id(id) => { // true and false are special constants that are effectively aliases for 1 and 0 // and not identifiers of columns - if id.as_str().eq_ignore_ascii_case("true") - || id.as_str().eq_ignore_ascii_case("false") - { - return Ok(()); - } + let id_bytes = id.as_str().as_bytes(); + match_ignore_ascii_case!(match id_bytes { + b"true" | b"false" => { + return Ok(()); + } + _ => {} + }); let normalized_id = normalize_ident(id.as_str()); if !referenced_tables.joined_tables().is_empty() { @@ -1127,13 +1130,12 @@ pub fn parse_limit(limit: &Limit) -> Result<(Option, Option)> { crate::bail_parse_error!("Invalid LIMIT clause"); } } else if let Expr::Id(id) = limit.expr.as_ref() { - if id.as_str().eq_ignore_ascii_case("true") { - Ok((Some(1), offset_val)) - } else if id.as_str().eq_ignore_ascii_case("false") { - Ok((Some(0), offset_val)) - } else { - crate::bail_parse_error!("Invalid LIMIT clause"); - } + let id_bytes = id.as_str().as_bytes(); + match_ignore_ascii_case!(match id_bytes { + b"true" => Ok((Some(1), offset_val)), + b"false" => Ok((Some(0), offset_val)), + _ => crate::bail_parse_error!("Invalid LIMIT clause"), + }) } else { crate::bail_parse_error!("Invalid LIMIT clause"); } diff --git a/core/vdbe/execute.rs b/core/vdbe/execute.rs index 851e67089..ec7ab3408 100644 --- a/core/vdbe/execute.rs +++ b/core/vdbe/execute.rs @@ -1763,25 +1763,24 @@ pub fn op_type_check( } let col_affinity = col.affinity(); let ty_str = &col.ty_str; + let ty_bytes = ty_str.as_bytes(); let applied = apply_affinity_char(reg, col_affinity); let value_type = reg.get_value().value_type(); - match value_type { - ValueType::Integer - if ty_str.eq_ignore_ascii_case("INTEGER") - || ty_str.eq_ignore_ascii_case("INT") => {} - ValueType::Float if ty_str.eq_ignore_ascii_case("REAL") => {} - ValueType::Blob if ty_str.eq_ignore_ascii_case("BLOB") => {} - ValueType::Text if ty_str.eq_ignore_ascii_case("TEXT") => {} - _ if ty_str.eq_ignore_ascii_case("ANY") => {} - v => bail_constraint_error!( + match_ignore_ascii_case!(match ty_bytes { + b"INTEGER" | b"INT" if value_type == ValueType::Integer => {} + b"REAL" if value_type == ValueType::Float => {} + b"BLOB" if value_type == ValueType::Blob => {} + b"TEXT" if value_type == ValueType::Text => {} + b"ANY" => {} + _ => bail_constraint_error!( "cannot store {} value in {} column {}.{} ({})", - v, + value_type, ty_str, &table_reference.name, col.name.as_deref().unwrap_or(""), SQLITE_CONSTRAINT ), - }; + }); Ok(()) })?; From b6fca2718f4a2945d4f59bffc124782b0623e84b Mon Sep 17 00:00:00 2001 From: TcMits Date: Wed, 3 Sep 2025 13:41:23 +0700 Subject: [PATCH 2/2] fmt --- core/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/lib.rs b/core/lib.rs index e6f58b71c..373e89c81 100644 --- a/core/lib.rs +++ b/core/lib.rs @@ -63,7 +63,6 @@ pub use io::{ }; use parking_lot::RwLock; use schema::Schema; -use turso_macros::match_ignore_ascii_case; use std::{ borrow::Cow, cell::{Cell, RefCell, UnsafeCell}, @@ -91,6 +90,7 @@ pub use storage::{ }; use tracing::{instrument, Level}; use translate::select::prepare_select_plan; +use turso_macros::match_ignore_ascii_case; use turso_parser::{ast, ast::Cmd, parser::Parser}; use types::IOResult; pub use types::RefValue;