use crate::velesql::{Condition, Parser};
#[test]
fn test_like_percent_only() {
let q = Parser::parse("SELECT * FROM docs WHERE name LIKE '%'")
.expect("percent-only pattern should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.column, "name");
assert_eq!(like.pattern, "%");
assert!(!like.case_insensitive);
}
#[test]
fn test_like_underscore_only() {
let q = Parser::parse("SELECT * FROM docs WHERE code LIKE '_'")
.expect("underscore-only pattern should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.pattern, "_");
}
#[test]
fn test_like_multiple_underscores() {
let q = Parser::parse("SELECT * FROM docs WHERE code LIKE '___'")
.expect("triple underscore pattern should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.pattern, "___");
}
#[test]
fn test_like_percent_at_start() {
let q = Parser::parse("SELECT * FROM docs WHERE name LIKE '%suffix'")
.expect("suffix pattern should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.pattern, "%suffix");
}
#[test]
fn test_like_percent_at_end() {
let q = Parser::parse("SELECT * FROM docs WHERE name LIKE 'prefix%'")
.expect("prefix pattern should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.pattern, "prefix%");
}
#[test]
fn test_like_percent_both_ends() {
let q = Parser::parse("SELECT * FROM docs WHERE name LIKE '%middle%'")
.expect("contains pattern should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.pattern, "%middle%");
}
#[test]
fn test_like_mixed_wildcards() {
let q = Parser::parse("SELECT * FROM docs WHERE code LIKE 'A_%_B%'")
.expect("mixed wildcard pattern should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.pattern, "A_%_B%");
}
#[test]
fn test_like_no_wildcards() {
let q = Parser::parse("SELECT * FROM docs WHERE name LIKE 'exact'")
.expect("exact-match LIKE should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.pattern, "exact");
}
#[test]
fn test_like_empty_pattern() {
let q = Parser::parse("SELECT * FROM docs WHERE name LIKE ''")
.expect("empty LIKE pattern should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.pattern, "");
}
#[test]
fn test_like_pattern_with_spaces() {
let q = Parser::parse("SELECT * FROM docs WHERE title LIKE 'hello world%'")
.expect("pattern with spaces should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.pattern, "hello world%");
}
#[test]
fn test_like_pattern_with_numbers() {
let q = Parser::parse("SELECT * FROM docs WHERE sku LIKE 'SKU-2024-%'")
.expect("pattern with numbers should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.pattern, "SKU-2024-%");
}
#[test]
fn test_like_pattern_with_unicode() {
let q = Parser::parse("SELECT * FROM docs WHERE name LIKE '\u{65E5}\u{672C}%'")
.expect("unicode pattern should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.pattern, "\u{65E5}\u{672C}%");
}
#[test]
fn test_like_pattern_with_escaped_quote() {
let q = Parser::parse("SELECT * FROM docs WHERE name LIKE 'O''Brien%'")
.expect("escaped-quote pattern should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.pattern, "O'Brien%");
}
#[test]
fn test_ilike_percent_only() {
let q = Parser::parse("SELECT * FROM docs WHERE name ILIKE '%'")
.expect("ILIKE percent-only should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.pattern, "%");
assert!(like.case_insensitive);
}
#[test]
fn test_ilike_mixed_case_pattern() {
let q = Parser::parse("SELECT * FROM docs WHERE name ILIKE 'JoHn%'")
.expect("ILIKE mixed-case pattern should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.pattern, "JoHn%");
assert!(like.case_insensitive);
}
#[test]
fn test_ilike_with_underscore() {
let q = Parser::parse("SELECT * FROM docs WHERE code ILIKE 'a_c'")
.expect("ILIKE underscore should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.pattern, "a_c");
assert!(like.case_insensitive);
}
#[test]
fn test_ilike_empty_pattern() {
let q = Parser::parse("SELECT * FROM docs WHERE name ILIKE ''")
.expect("ILIKE empty pattern should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.pattern, "");
assert!(like.case_insensitive);
}
#[test]
fn test_like_and_comparison() {
let q = Parser::parse("SELECT * FROM docs WHERE name LIKE '%test%' AND active = true")
.expect("LIKE + AND should parse");
let Condition::And(left, right) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected And condition");
};
assert!(
matches!(*left, Condition::Like(_)),
"Left branch should be Like, got: {left:?}"
);
assert!(
matches!(*right, Condition::Comparison(_)),
"Right branch should be Comparison, got: {right:?}"
);
}
#[test]
fn test_like_or_like() {
let q = Parser::parse("SELECT * FROM docs WHERE name LIKE '%a%' OR name LIKE '%b%'")
.expect("LIKE OR LIKE should parse");
let Condition::Or(left, right) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Or condition");
};
let Condition::Like(left_like) = *left else {
panic!("Left branch should be Like");
};
assert_eq!(left_like.pattern, "%a%");
let Condition::Like(right_like) = *right else {
panic!("Right branch should be Like");
};
assert_eq!(right_like.pattern, "%b%");
}
#[test]
fn test_like_and_vector_near() {
let sql = "SELECT * FROM docs WHERE vector NEAR $v AND title LIKE '%AI%' LIMIT 10";
let q = Parser::parse(sql).expect("LIKE + vector NEAR should parse");
let Condition::And(left, right) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected And condition");
};
assert!(
matches!(*left, Condition::VectorSearch(_)),
"Left should be VectorSearch, got: {left:?}"
);
let Condition::Like(like) = *right else {
panic!("Right should be Like, got: {right:?}");
};
assert_eq!(like.pattern, "%AI%");
assert_eq!(q.select.limit, Some(10));
}
#[test]
fn test_not_like() {
let q = Parser::parse("SELECT * FROM docs WHERE NOT (name LIKE '%spam%')")
.expect("NOT LIKE should parse");
let Condition::Not(inner) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Not condition");
};
let Condition::Group(grouped) = *inner else {
panic!("Expected Group inside Not, got: {inner:?}");
};
let Condition::Like(like) = *grouped else {
panic!("Expected Like inside Group, got: {grouped:?}");
};
assert_eq!(like.pattern, "%spam%");
}
#[test]
fn test_ilike_and_comparison_with_limit() {
let sql = "SELECT * FROM docs WHERE title ILIKE '%db%' AND price > 50 LIMIT 10";
let q = Parser::parse(sql).expect("ILIKE + AND + comparison should parse");
let Condition::And(left, right) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected And condition");
};
let Condition::Like(like) = *left else {
panic!("Left should be Like (ILIKE), got: {left:?}");
};
assert!(like.case_insensitive);
assert_eq!(like.pattern, "%db%");
assert!(
matches!(*right, Condition::Comparison(_)),
"Right should be Comparison, got: {right:?}"
);
assert_eq!(q.select.limit, Some(10));
}
#[test]
fn test_like_ast_fields() {
let q =
Parser::parse("SELECT * FROM docs WHERE name LIKE '%test%'").expect("should parse LIKE");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.column, "name");
assert_eq!(like.pattern, "%test%");
assert!(!like.case_insensitive, "LIKE must be case-sensitive");
}
#[test]
fn test_ilike_ast_fields() {
let q =
Parser::parse("SELECT * FROM docs WHERE title ILIKE 'Hello%'").expect("should parse ILIKE");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.column, "title");
assert_eq!(like.pattern, "Hello%");
assert!(like.case_insensitive, "ILIKE must be case-insensitive");
}
#[test]
fn test_like_nested_column() {
let q = Parser::parse("SELECT * FROM docs WHERE payload.title LIKE '%test%'")
.expect("nested column LIKE should parse");
let Condition::Like(like) = q.select.where_clause.expect("should have WHERE") else {
panic!("Expected Like condition");
};
assert_eq!(like.column, "payload.title");
assert_eq!(like.pattern, "%test%");
}
#[test]
fn test_reject_like_integer_pattern() {
let query = "SELECT * FROM docs WHERE name LIKE 123";
assert!(
Parser::parse(query).is_err(),
"LIKE with integer pattern should fail: {query}"
);
}
#[test]
fn test_reject_like_parameter_pattern() {
let query = "SELECT * FROM docs WHERE name LIKE $pattern";
assert!(
Parser::parse(query).is_err(),
"LIKE with parameter pattern should fail: {query}"
);
}
#[test]
fn test_reject_like_missing_column() {
let query = "SELECT * FROM docs WHERE LIKE '%test%'";
assert!(
Parser::parse(query).is_err(),
"LIKE without column should fail: {query}"
);
}