diff --git a/partiql-logical/src/lib.rs b/partiql-logical/src/lib.rs index c8deaab0..c99046d2 100644 --- a/partiql-logical/src/lib.rs +++ b/partiql-logical/src/lib.rs @@ -56,11 +56,11 @@ use partiql_common::catalog::ObjectId; /// assert_eq!(3, p.operators().len()); /// assert_eq!(2, p.flows().len()); /// ``` -use partiql_value::BindingsName; use rust_decimal::Decimal as RustDecimal; use std::collections::HashMap; use std::fmt::{Debug, Display, Formatter}; +use partiql_value::BindingsName; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -464,7 +464,6 @@ pub enum Lit { Bag(Vec), List(Vec), } - // TODO we should replace this enum with some identifier that can be looked up in a symtab/funcregistry? /// Represents logical plan's unary operators. #[derive(Debug, Clone, Eq, PartialEq)] diff --git a/partiql-value/src/bindings.rs b/partiql-value/src/bindings.rs index ede44318..3f6b6e37 100644 --- a/partiql-value/src/bindings.rs +++ b/partiql-value/src/bindings.rs @@ -3,6 +3,7 @@ use crate::{PairsIntoIter, PairsIter, Value}; use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::iter::Once; +use unicase::UniCase; #[derive(Clone, Hash, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -11,6 +12,38 @@ pub enum BindingsName<'s> { CaseInsensitive(Cow<'s, str>), } +impl<'s> BindingsName<'s> { + pub fn matcher(&'s self) -> BindingsMatcher<'s> { + BindingsMatcher::from(self) + } +} + +#[derive(Clone, Hash, Debug, Eq, PartialEq)] +pub enum BindingsMatcher<'s> { + CaseSensitive(&'s str), + CaseInsensitive(UniCase<&'s str>), +} + +impl<'s> BindingsMatcher<'s> { + pub fn matches(&'s self, candidate: &str) -> bool { + match self { + BindingsMatcher::CaseSensitive(target) => *target == candidate, + BindingsMatcher::CaseInsensitive(target) => *target == UniCase::new(candidate), + } + } +} + +impl<'s> From<&'s BindingsName<'s>> for BindingsMatcher<'s> { + fn from(name: &'s BindingsName<'_>) -> Self { + match name { + BindingsName::CaseSensitive(s) => BindingsMatcher::CaseSensitive(s.as_ref()), + BindingsName::CaseInsensitive(s) => { + BindingsMatcher::CaseInsensitive(UniCase::new(s.as_ref())) + } + } + } +} + #[derive(Debug, Clone)] pub enum BindingIter<'a> { Tuple(PairsIter<'a>), diff --git a/partiql-value/src/tuple.rs b/partiql-value/src/tuple.rs index 9559eb10..337784be 100644 --- a/partiql-value/src/tuple.rs +++ b/partiql-value/src/tuple.rs @@ -7,8 +7,6 @@ use std::hash::{Hash, Hasher}; use std::iter::{zip, Zip}; use std::vec; -use unicase::UniCase; - use crate::sort::NullSortedValue; use crate::{BindingsName, EqualityValue, NullableEq, Value}; #[cfg(feature = "serde")] @@ -79,15 +77,8 @@ impl Tuple { #[inline(always)] fn find_value(&self, attr: &BindingsName<'_>) -> Option { - match attr { - BindingsName::CaseSensitive(s) => { - self.attrs.iter().position(|a| a.as_str() == s.as_ref()) - } - BindingsName::CaseInsensitive(s) => { - let target = UniCase::new(&s); - self.attrs.iter().position(|a| target == UniCase::new(a)) - } - } + let matcher = attr.matcher(); + self.attrs.iter().position(|a| matcher.matches(a)) } #[inline]