use crate::atomic;
use crate::atomic::AtomicCompare;
use crate::context;
use crate::error;
pub(crate) fn general_comparison<O>(
a_atoms: impl Iterator<Item = error::Result<atomic::Atomic>>,
b_atoms: impl Iterator<Item = error::Result<atomic::Atomic>>,
context: &context::DynamicContext,
_op: O,
) -> error::Result<bool>
where
O: AtomicCompare,
{
let b_atoms = b_atoms.collect::<Result<Vec<_>, _>>()?;
let collation = context.static_context().default_collation()?;
let implicit_timezone = context.implicit_timezone();
for a in a_atoms {
let a = a?;
for b in b_atoms.iter() {
let (a, b) = cast(a.clone(), b.clone(), context.static_context())?;
if O::atomic_compare(
a,
b,
|a: &str, b: &str| collation.compare(a, b),
implicit_timezone,
)? {
return Ok(true);
}
}
}
Ok(false)
}
fn cast(
a: atomic::Atomic,
b: atomic::Atomic,
context: &context::StaticContext,
) -> error::Result<(atomic::Atomic, atomic::Atomic)> {
Ok(match (&a, &b) {
(atomic::Atomic::Untyped(_), atomic::Atomic::Untyped(_)) => {
let a = a.cast_to_string();
let b = b.cast_to_string();
(a, b)
}
(atomic::Atomic::Untyped(_), _) => {
let a = if b.is_numeric() {
a.cast_to_double()?
} else {
a.cast_to_schema_type_of(&b, context)?
};
(a, b)
}
(_, atomic::Atomic::Untyped(_)) => {
let b = if a.is_numeric() {
b.cast_to_double()?
} else {
b.cast_to_schema_type_of(&a, context)?
};
(a, b)
} _ => (a, b),
})
}