Skip to content

Commit

Permalink
Fix deep-equality as per specification of eqg
Browse files Browse the repository at this point in the history
  • Loading branch information
jpschorr committed Jan 7, 2025
1 parent 748c93d commit 321dc80
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 8 deletions.
35 changes: 30 additions & 5 deletions extension/partiql-extension-ion/src/boxed_ion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,12 @@ impl<'a, const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq
{
fn eq(&self, rhs: &Self) -> Value {
let wrap = IonEqualityValue::<'a, { NULLS_EQUAL }, { NAN_EQUAL }, _>;
wrap(&self.0.doc).eq(&wrap(&rhs.0.doc))
NullableEq::eq(&wrap(&self.0.doc), &wrap(&rhs.0.doc))
}
#[inline(always)]
fn eqg(&self, rhs: &Self) -> Value {
let wrap = IonEqualityValue::<'_, true, { NAN_EQUAL }, _>;
NullableEq::eq(&wrap(self.0), &wrap(rhs.0))
}
}

Expand Down Expand Up @@ -574,6 +579,11 @@ impl<'a, const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq
_ => Value::Boolean(false),
}
}
#[inline(always)]
fn eqg(&self, rhs: &Self) -> Value {
let wrap = IonEqualityValue::<'_, true, { NAN_EQUAL }, _>;
NullableEq::eq(&wrap(self.0), &wrap(rhs.0))
}
}

impl<'a, const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq
Expand Down Expand Up @@ -622,6 +632,11 @@ impl<'a, const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq

Value::Boolean(result)
}
#[inline(always)]
fn eqg(&self, rhs: &Self) -> Value {
let wrap = IonEqualityValue::<'_, true, { NAN_EQUAL }, _>;
NullableEq::eq(&wrap(self.0), &wrap(rhs.0))
}
}

impl<'a, const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq
Expand All @@ -632,9 +647,14 @@ impl<'a, const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq
let (l, r) = (self.0, other.0);
let l = l.iter().map(wrap);
let r = r.iter().map(wrap);
let res = l.zip(r).all(|(l, r)| l == r);
let res = l.zip(r).all(|(l, r)| l.eqg(&r) == Value::Boolean(true));
Value::Boolean(res)
}
#[inline(always)]
fn eqg(&self, rhs: &Self) -> Value {
let wrap = IonEqualityValue::<'_, true, { NAN_EQUAL }, _>;
NullableEq::eq(&wrap(self.0), &wrap(rhs.0))
}
}

impl<'a, const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq
Expand All @@ -645,11 +665,16 @@ impl<'a, const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq
let (l, r) = (self.0, other.0);
let l = l.iter().map(|(s, elt)| (s, wrap(elt)));
let r = r.iter().map(|(s, elt)| (s, wrap(elt)));
let res = l.zip(r).all(|((ls, lelt), (rs, relt))| {
ls == rs && NullableEq::eq(&lelt, &relt) == Value::Boolean(true)
});
let res = l
.zip(r)
.all(|((ls, lelt), (rs, relt))| ls == rs && lelt.eqg(&relt) == Value::Boolean(true));
Value::Boolean(res)
}
#[inline(always)]
fn eqg(&self, rhs: &Self) -> Value {
let wrap = IonEqualityValue::<'_, true, { NAN_EQUAL }, _>;
NullableEq::eq(&wrap(self.0), &wrap(rhs.0))
}
}

/*
Expand Down
8 changes: 7 additions & 1 deletion partiql-value/src/bag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,18 @@ impl<const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq

for (v1, v2) in li.zip(ri) {
let wrap = EqualityValue::<{ NULLS_EQUAL }, { NAN_EQUAL }, Value>;
if NullableEq::eq(&wrap(v1), &wrap(v2)) != Value::Boolean(true) {
if NullableEq::eqg(&wrap(v1), &wrap(v2)) != Value::Boolean(true) {
return Value::Boolean(false);
}
}
Value::Boolean(true)
}

#[inline(always)]
fn eqg(&self, rhs: &Self) -> Value {
let wrap = EqualityValue::<'_, true, { NAN_EQUAL }, _>;
NullableEq::eq(&wrap(self.0), &wrap(rhs.0))
}
}

impl PartialOrd for Bag {
Expand Down
20 changes: 20 additions & 0 deletions partiql-value/src/comparison.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,20 @@ pub trait NullableEq {
_ => Value::Missing,
}
}

/// `PartiQL's `eqg` is used to compare the internals of Lists, Bags, and Tuples.
///
/// > The eqg, unlike the =, returns true when a NULL is compared to a NULL or a MISSING
/// > to a MISSING
fn eqg(&self, rhs: &Self) -> Value;

fn neqg(&self, rhs: &Self) -> Value {
let eqg_result = NullableEq::eqg(self, rhs);
match eqg_result {
Value::Boolean(_) | Value::Null => !eqg_result,
_ => Value::Missing,
}
}
}

/// A wrapper on [`T`] that specifies if missing and null values should be equal.
Expand Down Expand Up @@ -101,6 +115,12 @@ impl<const GROUP_NULLS: bool, const NAN_EQUAL: bool> NullableEq
(_, _) => Value::from(self.0 == rhs.0),
}
}

#[inline(always)]
fn eqg(&self, rhs: &Self) -> Value {
let wrap = EqualityValue::<'_, true, { NAN_EQUAL }, _>;
NullableEq::eq(&wrap(self.0), &wrap(rhs.0))
}
}

// `Value` comparison with Missing and Null propagation
Expand Down
8 changes: 7 additions & 1 deletion partiql-value/src/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,18 @@ impl<const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq
}
for (v1, v2) in self.0.iter().zip(other.0.iter()) {
let wrap = EqualityValue::<{ NULLS_EQUAL }, { NAN_EQUAL }, Value>;
if NullableEq::eq(&wrap(v1), &wrap(v2)) != Value::Boolean(true) {
if NullableEq::eqg(&wrap(v1), &wrap(v2)) != Value::Boolean(true) {
return Value::Boolean(false);
}
}
Value::Boolean(true)
}

#[inline(always)]
fn eqg(&self, rhs: &Self) -> Value {
let wrap = EqualityValue::<'_, true, { NAN_EQUAL }, _>;
NullableEq::eq(&wrap(self.0), &wrap(rhs.0))
}
}

impl PartialOrd for List {
Expand Down
8 changes: 7 additions & 1 deletion partiql-value/src/tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,12 +231,18 @@ impl<const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq
return Value::Boolean(false);
}
let wrap = EqualityValue::<{ NULLS_EQUAL }, { NAN_EQUAL }, Value>;
if NullableEq::eq(&wrap(lv), &wrap(rv)) != Value::Boolean(true) {
if NullableEq::eqg(&wrap(lv), &wrap(rv)) != Value::Boolean(true) {
return Value::Boolean(false);
}
}
Value::Boolean(true)
}

#[inline(always)]
fn eqg(&self, rhs: &Self) -> Value {
let wrap = EqualityValue::<'_, true, { NAN_EQUAL }, _>;
NullableEq::eq(&wrap(self.0), &wrap(rhs.0))
}
}

impl PartialOrd for Tuple {
Expand Down
6 changes: 6 additions & 0 deletions partiql-value/src/variant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,12 @@ impl<const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq
let res = lty == rty && lty.value_eq_param(l, r, NULLS_EQUAL, NAN_EQUAL);
Value::Boolean(res)
}

#[inline(always)]
fn eqg(&self, rhs: &Self) -> Value {
let wrap = EqualityValue::<'_, true, { NAN_EQUAL }, _>;
NullableEq::eq(&wrap(self.0), &wrap(rhs.0))
}
}

#[cfg(feature = "serde")]
Expand Down

0 comments on commit 321dc80

Please sign in to comment.