Skip to content

Commit

Permalink
fix(cubesql): Fix LIKE behavior with startsWith, endsWith
Browse files Browse the repository at this point in the history
  • Loading branch information
MazterQyou committed Dec 14, 2023
1 parent a8cd98a commit f0719cd
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 3 deletions.
66 changes: 66 additions & 0 deletions rust/cubesql/cubesql/src/compile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4875,6 +4875,39 @@ ORDER BY \"COUNT(count)\" DESC"
// LIKE
(
"customer_gender LIKE 'female'".to_string(),
Some(vec![V1LoadRequestQueryFilterItem {
member: Some("KibanaSampleDataEcommerce.customer_gender".to_string()),
operator: Some("equals".to_string()),
values: Some(vec!["female".to_string()]),
or: None,
and: None,
}]),
None,
),
(
"customer_gender LIKE 'female%'".to_string(),
Some(vec![V1LoadRequestQueryFilterItem {
member: Some("KibanaSampleDataEcommerce.customer_gender".to_string()),
operator: Some("startsWith".to_string()),
values: Some(vec!["female".to_string()]),
or: None,
and: None,
}]),
None,
),
(
"customer_gender LIKE '%female'".to_string(),
Some(vec![V1LoadRequestQueryFilterItem {
member: Some("KibanaSampleDataEcommerce.customer_gender".to_string()),
operator: Some("endsWith".to_string()),
values: Some(vec!["female".to_string()]),
or: None,
and: None,
}]),
None,
),
(
"customer_gender LIKE '%female%'".to_string(),
Some(vec![V1LoadRequestQueryFilterItem {
member: Some("KibanaSampleDataEcommerce.customer_gender".to_string()),
operator: Some("contains".to_string()),
Expand All @@ -4886,6 +4919,39 @@ ORDER BY \"COUNT(count)\" DESC"
),
(
"customer_gender NOT LIKE 'male'".to_string(),
Some(vec![V1LoadRequestQueryFilterItem {
member: Some("KibanaSampleDataEcommerce.customer_gender".to_string()),
operator: Some("notEquals".to_string()),
values: Some(vec!["male".to_string()]),
or: None,
and: None,
}]),
None,
),
(
"customer_gender NOT LIKE 'male%'".to_string(),
Some(vec![V1LoadRequestQueryFilterItem {
member: Some("KibanaSampleDataEcommerce.customer_gender".to_string()),
operator: Some("notStartsWith".to_string()),
values: Some(vec!["male".to_string()]),
or: None,
and: None,
}]),
None,
),
(
"customer_gender NOT LIKE '%male'".to_string(),
Some(vec![V1LoadRequestQueryFilterItem {
member: Some("KibanaSampleDataEcommerce.customer_gender".to_string()),
operator: Some("notEndsWith".to_string()),
values: Some(vec!["male".to_string()]),
or: None,
and: None,
}]),
None,
),
(
"customer_gender NOT LIKE '%male%'".to_string(),
Some(vec![V1LoadRequestQueryFilterItem {
member: Some("KibanaSampleDataEcommerce.customer_gender".to_string()),
operator: Some("notContains".to_string()),
Expand Down
61 changes: 58 additions & 3 deletions rust/cubesql/cubesql/src/compile/rewrite/rules/filters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,6 @@ impl RewriteRules for FilterRules {
),
self.transform_granularity_to_interval("?granularity", "?interval"),
),
// TODO define zero
rewrite(
"filter-str-pos-to-like",
filter_replacer(
Expand All @@ -959,14 +958,22 @@ impl RewriteRules for FilterRules {
vec![column_expr("?column"), literal_expr("?value")],
),
">",
literal_expr("?zero"),
literal_int(0),
),
"?alias_to_cube",
"?members",
"?filter_aliases",
),
filter_replacer(
binary_expr(column_expr("?column"), "LIKE", literal_expr("?value")),
binary_expr(
column_expr("?column"),
"LIKE",
binary_expr(
binary_expr(literal_string("%"), "||", literal_expr("?value")),
"||",
literal_string("%"),
),
),
"?alias_to_cube",
"?members",
"?filter_aliases",
Expand Down Expand Up @@ -2795,6 +2802,33 @@ impl FilterRules {
},
};

let op = match literal {
ScalarValue::Utf8(Some(value)) => match op {
"contains" => {
let starts_with_pcnt = value.starts_with("%");
let ends_with_pcnt = value.ends_with("%");
match (starts_with_pcnt, ends_with_pcnt) {
(false, false) => "equals",
(false, true) => "startsWith",
(true, false) => "endsWith",
(true, true) => "contains",
}
}
"notContains" => {
let starts_with_pcnt = value.starts_with("%");
let ends_with_pcnt = value.ends_with("%");
match (starts_with_pcnt, ends_with_pcnt) {
(false, false) => "notEquals",
(false, true) => "notStartsWith",
(true, false) => "notEndsWith",
(true, true) => "notContains",
}
}
_ => op,
},
_ => op,
};

let value = match literal {
ScalarValue::Utf8(Some(value)) => {
if op == "startsWith"
Expand All @@ -2813,6 +2847,27 @@ impl FilterRules {
} else {
value.to_string()
}
} else if op == "startsWith" || op == "notStartsWith" {
if value.ends_with("%") {
let without_wildcard =
value[..value.len() - 1].to_string();
if without_wildcard.contains("%") {
continue;
}
without_wildcard
} else {
value.to_string()
}
} else if op == "endsWith" || op == "notEndsWith" {
if value.starts_with("%") {
let without_wildcard = value[1..].to_string();
if without_wildcard.contains("%") {
continue;
}
without_wildcard
} else {
value.to_string()
}
} else {
value.to_string()
}
Expand Down

0 comments on commit f0719cd

Please sign in to comment.