use stoolap::Database;
#[test]
fn test_binary_collation() {
let db = Database::open("memory://collate_binary").expect("Failed to create database");
db.execute(
"CREATE TABLE collate_test (
id INTEGER,
text_value TEXT
)",
(),
)
.expect("Failed to create table");
db.execute(
"INSERT INTO collate_test (id, text_value) VALUES
(1, 'Apple'),
(2, 'apple'),
(3, 'APPLE'),
(4, 'Banana'),
(5, 'banana'),
(6, 'BANANA')",
(),
)
.expect("Failed to insert data");
let result = db
.query(
"SELECT id, text_value
FROM collate_test
WHERE COLLATE(text_value, 'BINARY') = 'Apple'
ORDER BY id",
(),
)
.expect("Failed to query with BINARY collation");
let mut count = 0;
for row in result {
let row = row.expect("Failed to get row");
let id: i64 = row.get(0).unwrap();
let value: String = row.get(1).unwrap();
assert_eq!(id, 1, "Expected id=1");
assert_eq!(value, "Apple", "Expected 'Apple'");
count += 1;
}
assert_eq!(count, 1, "Expected 1 row from BINARY collation");
}
#[test]
fn test_nocase_collation() {
let db = Database::open("memory://collate_nocase").expect("Failed to create database");
db.execute(
"CREATE TABLE collate_test (
id INTEGER,
text_value TEXT
)",
(),
)
.expect("Failed to create table");
db.execute(
"INSERT INTO collate_test (id, text_value) VALUES
(1, 'Apple'),
(2, 'apple'),
(3, 'APPLE'),
(4, 'Banana'),
(5, 'banana'),
(6, 'BANANA')",
(),
)
.expect("Failed to insert data");
let result = db
.query(
"SELECT id, text_value
FROM collate_test
WHERE COLLATE(text_value, 'NOCASE') = COLLATE('apple', 'NOCASE')
ORDER BY id",
(),
)
.expect("Failed to query with NOCASE collation");
let mut count = 0;
for row in result {
let row = row.expect("Failed to get row");
let id: i64 = row.get(0).unwrap();
assert!((1..=3).contains(&id), "Unexpected id: {}", id);
count += 1;
}
assert_eq!(count, 3, "Expected 3 rows from NOCASE collation");
}
#[test]
fn test_noaccent_collation() {
let db = Database::open("memory://collate_noaccent").expect("Failed to create database");
db.execute(
"CREATE TABLE collate_test (
id INTEGER,
text_value TEXT
)",
(),
)
.expect("Failed to create table");
db.execute(
"INSERT INTO collate_test (id, text_value) VALUES
(1, 'Cafe'),
(2, 'cafe'),
(3, 'CAFE')",
(),
)
.expect("Failed to insert data");
let result = db
.query(
"SELECT id, text_value
FROM collate_test
WHERE COLLATE(LOWER(text_value), 'NOACCENT') = COLLATE('cafe', 'NOACCENT')
ORDER BY id",
(),
)
.expect("Failed to query with NOACCENT collation");
let mut count = 0;
for row in result {
let row = row.expect("Failed to get row");
let id: i64 = row.get(0).unwrap();
assert!((1..=3).contains(&id), "Unexpected id: {}", id);
count += 1;
}
assert_eq!(count, 3, "Expected 3 rows from NOACCENT collation");
}
#[test]
fn test_ordering_with_collate() {
let db = Database::open("memory://collate_order").expect("Failed to create database");
db.execute(
"CREATE TABLE collate_test (
id INTEGER,
text_value TEXT
)",
(),
)
.expect("Failed to create table");
db.execute(
"INSERT INTO collate_test (id, text_value) VALUES
(1, 'Apple'),
(2, 'apple'),
(3, 'APPLE'),
(4, 'Banana'),
(5, 'banana'),
(6, 'BANANA')",
(),
)
.expect("Failed to insert data");
let result = db
.query(
"SELECT id, text_value
FROM collate_test
ORDER BY COLLATE(text_value, 'NOCASE')
LIMIT 6",
(),
)
.expect("Failed to query with ORDER BY COLLATE");
let mut apple_count = 0;
let mut banana_count = 0;
for row in result {
let row = row.expect("Failed to get row");
let value: String = row.get(1).unwrap();
let lower_value = value.to_lowercase();
if lower_value == "apple" {
apple_count += 1;
} else if lower_value == "banana" {
banana_count += 1;
}
}
assert_eq!(apple_count, 3, "Expected 3 'Apple' entries");
assert_eq!(banana_count, 3, "Expected 3 'Banana' entries");
}
#[test]
fn test_collate_null_handling() {
let db = Database::open("memory://collate_null").expect("Failed to create database");
db.execute(
"CREATE TABLE collate_test (
id INTEGER,
text_value TEXT
)",
(),
)
.expect("Failed to create table");
db.execute(
"INSERT INTO collate_test (id, text_value) VALUES (1, NULL)",
(),
)
.expect("Failed to insert NULL");
let result = db
.query(
"SELECT COLLATE(text_value, 'BINARY')
FROM collate_test
WHERE id = 1",
(),
)
.expect("Failed to query NULL value");
let mut count = 0;
for _row in result {
count += 1;
}
assert_eq!(count, 1, "Should return 1 row for NULL value");
}
#[test]
fn test_case_insensitive_comparison() {
let db = Database::open("memory://collate_ci").expect("Failed to create database");
db.execute(
"CREATE TABLE users (
id INTEGER,
username TEXT
)",
(),
)
.expect("Failed to create table");
db.execute(
"INSERT INTO users (id, username) VALUES
(1, 'JohnDoe'),
(2, 'johndoe'),
(3, 'JOHNDOE'),
(4, 'JaneDoe')",
(),
)
.expect("Failed to insert data");
let count: i64 = db
.query_one(
"SELECT COUNT(*) FROM users
WHERE COLLATE(username, 'NOCASE') = COLLATE('johndoe', 'NOCASE')",
(),
)
.expect("Failed to query");
assert_eq!(count, 3, "Expected 3 matching usernames (case-insensitive)");
}
#[test]
fn test_collate_practical_usage() {
let db = Database::open("memory://collate_practical").expect("Failed to create database");
db.execute(
"CREATE TABLE products (
id INTEGER,
category TEXT,
price FLOAT
)",
(),
)
.expect("Failed to create table");
db.execute(
"INSERT INTO products (id, category, price) VALUES
(1, 'Electronics', 100.0),
(2, 'electronics', 200.0),
(3, 'ELECTRONICS', 150.0),
(4, 'Furniture', 300.0)",
(),
)
.expect("Failed to insert data");
let total: f64 = db
.query_one(
"SELECT SUM(price)
FROM products
WHERE COLLATE(category, 'NOCASE') = COLLATE('electronics', 'NOCASE')",
(),
)
.expect("Failed to query with COLLATE filter");
assert!(
(total - 450.0).abs() < 0.01,
"Expected Electronics total 450, got {}",
total
);
}