diff --git a/lib/src/fnc/array.rs b/lib/src/fnc/array.rs index e13134d8..c9716a97 100644 --- a/lib/src/fnc/array.rs +++ b/lib/src/fnc/array.rs @@ -1,5 +1,6 @@ use crate::err::Error; use crate::sql::array::Combine; +use crate::sql::array::Complement; use crate::sql::array::Concat; use crate::sql::array::Difference; use crate::sql::array::Intersect; @@ -7,16 +8,23 @@ use crate::sql::array::Union; use crate::sql::array::Uniq; use crate::sql::value::Value; -pub fn concat(arrays: (Value, Value)) -> Result { +pub fn combine(arrays: (Value, Value)) -> Result { Ok(match arrays { - (Value::Array(v), Value::Array(w)) => v.concat(w).into(), + (Value::Array(v), Value::Array(w)) => v.combine(w).into(), _ => Value::None, }) } -pub fn combine(arrays: (Value, Value)) -> Result { +pub fn complement(arrays: (Value, Value)) -> Result { Ok(match arrays { - (Value::Array(v), Value::Array(w)) => v.combine(w).into(), + (Value::Array(v), Value::Array(w)) => v.complement(w).into(), + _ => Value::None, + }) +} + +pub fn concat(arrays: (Value, Value)) -> Result { + Ok(match arrays { + (Value::Array(v), Value::Array(w)) => v.concat(w).into(), _ => Value::None, }) } diff --git a/lib/src/fnc/mod.rs b/lib/src/fnc/mod.rs index 7bef3654..55f3ea53 100644 --- a/lib/src/fnc/mod.rs +++ b/lib/src/fnc/mod.rs @@ -60,6 +60,7 @@ pub fn synchronous(ctx: &Context<'_>, name: &str, args: Vec) -> Result array::combine, + "array::complement" => array::complement, "array::concat" => array::concat, "array::difference" => array::difference, "array::distinct" => array::distinct, diff --git a/lib/src/sql/array.rs b/lib/src/sql/array.rs index 073c7dd3..720986d5 100644 --- a/lib/src/sql/array.rs +++ b/lib/src/sql/array.rs @@ -251,6 +251,24 @@ impl Combine for Array { // ------------------------------ +pub trait Complement { + fn complement(self, other: T) -> T; +} + +impl Complement for Array { + fn complement(self, other: Self) -> Array { + let mut out = Array::new(); + for v in self.into_iter() { + if other.contains(&v) { + out.push(v) + } + } + out + } +} + +// ------------------------------ + pub trait Concat { fn concat(self, other: T) -> T; } @@ -269,14 +287,13 @@ pub trait Difference { } impl Difference for Array { - fn difference(self, other: Array) -> Array { + fn difference(self, mut other: Array) -> Array { let mut out = Array::new(); - let mut other: Vec<_> = other.into_iter().collect(); - for a in self.into_iter() { - if let Some(pos) = other.iter().position(|b| a == *b) { + for v in self.into_iter() { + if let Some(pos) = other.iter().position(|w| v == *w) { other.remove(pos); } else { - out.push(a); + out.push(v); } } out.append(&mut other); @@ -291,13 +308,12 @@ pub trait Intersect { } impl Intersect for Array { - fn intersect(self, other: Self) -> Self { + fn intersect(self, mut other: Self) -> Self { let mut out = Self::new(); - let mut other: Vec<_> = other.into_iter().collect(); - for a in self.0.into_iter() { - if let Some(pos) = other.iter().position(|b| a == *b) { - out.push(a); + for v in self.0.into_iter() { + if let Some(pos) = other.iter().position(|w| v == *w) { other.remove(pos); + out.push(v); } } out diff --git a/lib/src/sql/function.rs b/lib/src/sql/function.rs index d59f71e4..543723c4 100644 --- a/lib/src/sql/function.rs +++ b/lib/src/sql/function.rs @@ -231,6 +231,7 @@ fn function_names(i: &str) -> IResult<&str, &str> { fn function_array(i: &str) -> IResult<&str, &str> { alt(( tag("array::combine"), + tag("array::complement"), tag("array::concat"), tag("array::difference"), tag("array::distinct"), diff --git a/lib/src/sql/operator.rs b/lib/src/sql/operator.rs index b3a2fbb5..b68b784e 100644 --- a/lib/src/sql/operator.rs +++ b/lib/src/sql/operator.rs @@ -48,8 +48,9 @@ pub enum Operator { AllInside, // ⊆ AnyInside, // ⊂ NoneInside, // ⊄ - Outside, // ∈ - Intersects, // ∩ + // + Outside, + Intersects, } impl Default for Operator {