diff --git a/Cargo.lock b/Cargo.lock index 9838d600f..7a027407a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1841,10 +1841,12 @@ dependencies = [ "ryu", "sorted-vec", "strum", + "strum_macros", "tempfile", "test-log", "thiserror 1.0.69", "tracing", + "uncased", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 774de264a..31794d093 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,8 @@ limbo_series = { path = "extensions/series", version = "0.0.20" } limbo_sqlite3_parser = { path = "vendored/sqlite3-parser", version = "0.0.20" } limbo_time = { path = "extensions/time", version = "0.0.20" } limbo_uuid = { path = "extensions/uuid", version = "0.0.20" } +strum = { version = "0.26", features = ["derive"] } +strum_macros = "0.26" [profile.release] debug = "line-tables-only" diff --git a/core/Cargo.toml b/core/Cargo.toml index 485f94b12..27807f3dd 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -69,11 +69,13 @@ limbo_ipaddr = { workspace = true, optional = true, features = ["static"] } limbo_completion = { workspace = true, optional = true, features = ["static"] } limbo_ext_tests = { workspace = true, optional = true, features = ["static"] } miette = "7.6.0" -strum = "0.26" +strum = { workspace = true } parking_lot = "0.12.3" crossbeam-skiplist = "0.1.3" tracing = "0.1.41" ryu = "1.0.19" +uncased = "0.9.10" +strum_macros = {workspace = true } bitflags = "2.9.0" [build-dependencies] diff --git a/core/translate/collate.rs b/core/translate/collate.rs new file mode 100644 index 000000000..bd6d1be4f --- /dev/null +++ b/core/translate/collate.rs @@ -0,0 +1,42 @@ +use std::cmp::Ordering; + +// TODO: in the future allow user to define collation sequences +// Will have to meddle with ffi for this +#[derive(Debug, Eq, PartialEq, strum_macros::Display, Default)] +#[strum(ascii_case_insensitive)] +/// **Pre defined collation sequences**\ +/// Collating functions only matter when comparing string values. +/// Numeric values are always compared numerically, and BLOBs are always compared byte-by-byte using memcmp(). +pub enum CollationSeq { + /// Standard String compare + #[default] + Binary, + /// Ascii case insensitive + NoCase, + /// Same as Binary but with trimmed whitespace + Rtrim, +} + +impl CollationSeq { + fn compare_strings(&self, lhs: &str, rhs: &str) -> Ordering { + match self { + CollationSeq::Binary => Self::binary_cmp(lhs, rhs), + CollationSeq::NoCase => Self::nocase_cmp(lhs, rhs), + CollationSeq::Rtrim => Self::rtrim_cmp(lhs, rhs), + } + } + + fn binary_cmp(lhs: &str, rhs: &str) -> Ordering { + lhs.cmp(rhs) + } + + fn nocase_cmp(lhs: &str, rhs: &str) -> Ordering { + let nocase_lhs = uncased::UncasedStr::new(lhs); + let nocase_rhs = uncased::UncasedStr::new(rhs); + nocase_lhs.cmp(nocase_rhs) + } + + fn rtrim_cmp(lhs: &str, rhs: &str) -> Ordering { + lhs.trim().cmp(rhs.trim()) + } +} diff --git a/core/translate/mod.rs b/core/translate/mod.rs index fa0b6d343..073df226c 100644 --- a/core/translate/mod.rs +++ b/core/translate/mod.rs @@ -8,6 +8,7 @@ //! will read rows from the database and filter them according to a WHERE clause. pub(crate) mod aggregation; +pub(crate) mod collate; pub(crate) mod delete; pub(crate) mod emitter; pub(crate) mod expr; diff --git a/vendored/sqlite3-parser/Cargo.toml b/vendored/sqlite3-parser/Cargo.toml index fc0f1bf8e..4701cdeba 100644 --- a/vendored/sqlite3-parser/Cargo.toml +++ b/vendored/sqlite3-parser/Cargo.toml @@ -32,8 +32,8 @@ bitflags = "2.0" uncased = "0.9.10" indexmap = "2.0" miette = "7.4.0" -strum = { version = "0.26", features = ["derive"] } -strum_macros = "0.26" +strum = { workspace = true } +strum_macros = {workspace = true } [dev-dependencies] env_logger = { version = "0.11", default-features = false }