use std::{borrow::Cow, cmp::Ordering};
use super::grouping::compare_sql_values;
use super::SortKey;
fn apply_collation<'a>(
val: &'a vibesql_types::SqlValue,
collation: Option<&String>,
) -> Cow<'a, vibesql_types::SqlValue> {
if let Some(coll) = collation {
if coll.eq_ignore_ascii_case("nocase") {
match val {
vibesql_types::SqlValue::Varchar(s) => Cow::Owned(
vibesql_types::SqlValue::Varchar(arcstr::ArcStr::from(s.to_uppercase())),
),
vibesql_types::SqlValue::Character(s) => Cow::Owned(
vibesql_types::SqlValue::Character(arcstr::ArcStr::from(s.to_uppercase())),
),
other => Cow::Borrowed(other),
}
} else if coll.eq_ignore_ascii_case("rtrim") {
match val {
vibesql_types::SqlValue::Varchar(s) => {
Cow::Owned(vibesql_types::SqlValue::Varchar(arcstr::ArcStr::from(s.trim_end())))
}
vibesql_types::SqlValue::Character(s) => Cow::Owned(
vibesql_types::SqlValue::Character(arcstr::ArcStr::from(s.trim_end())),
),
other => Cow::Borrowed(other),
}
} else {
Cow::Borrowed(val)
}
} else {
Cow::Borrowed(val)
}
}
pub(super) fn compare_rows_by_sort_keys(keys_a: &[SortKey], keys_b: &[SortKey]) -> Ordering {
for ((val_a, dir, nulls_order, collation), (val_b, _, _, _)) in keys_a.iter().zip(keys_b.iter())
{
let nulls_first = match nulls_order {
Some(vibesql_ast::NullsOrder::First) => true,
Some(vibesql_ast::NullsOrder::Last) => false,
None => matches!(dir, vibesql_ast::OrderDirection::Asc),
};
let cmp = match (val_a.is_null(), val_b.is_null()) {
(true, true) => Ordering::Equal,
(true, false) => {
if nulls_first {
return Ordering::Less; } else {
return Ordering::Greater; }
}
(false, true) => {
if nulls_first {
return Ordering::Greater; } else {
return Ordering::Less; }
}
(false, false) => {
let cmp_val_a = apply_collation(val_a, collation.as_ref());
let cmp_val_b = apply_collation(val_b, collation.as_ref());
match dir {
vibesql_ast::OrderDirection::Asc => compare_sql_values(&cmp_val_a, &cmp_val_b),
vibesql_ast::OrderDirection::Desc => {
compare_sql_values(&cmp_val_a, &cmp_val_b).reverse()
}
}
}
};
if cmp != Ordering::Equal {
return cmp;
}
}
Ordering::Equal
}