diff --git a/extension/partiql-extension-ion-functions/Cargo.toml b/extension/partiql-extension-ion-functions/Cargo.toml index bbb04fc1..0641c0ba 100644 --- a/extension/partiql-extension-ion-functions/Cargo.toml +++ b/extension/partiql-extension-ion-functions/Cargo.toml @@ -31,7 +31,7 @@ itertools = "0.13" unicase = "2.7" rust_decimal = { version = "1.36.0", default-features = false, features = ["std"] } ion-rs_old = { version = "0.18", package = "ion-rs" } -ion-rs = { version = "1.0.0-rc.10", features = ["experimental"] } +ion-rs = { version = "1.0.0-rc.11", features = ["experimental"] } time = { version = "0.3", features = ["macros"] } once_cell = "1" regex = "1.10" diff --git a/extension/partiql-extension-ion/src/boxed_ion.rs b/extension/partiql-extension-ion/src/boxed_ion.rs index 4ed715f8..90af798d 100644 --- a/extension/partiql-extension-ion/src/boxed_ion.rs +++ b/extension/partiql-extension-ion/src/boxed_ion.rs @@ -3,8 +3,6 @@ use ion_rs::{ AnyEncoding, Element, ElementReader, IonResult, IonType, OwnedSequenceIterator, Reader, Sequence, Struct, }; -use ion_rs_old::IonReader; -use itertools::Itertools; use partiql_value::boxed_variant::{ BoxedVariant, BoxedVariantResult, BoxedVariantType, BoxedVariantTypeTag, BoxedVariantValueIntoIterator, DynBoxedVariant, @@ -21,6 +19,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::any::Any; use std::borrow::Cow; use std::cell::RefCell; +use std::error::Error; use std::fmt::{Debug, Display, Formatter}; use std::hash::{Hash, Hasher}; use std::ops::DerefMut; @@ -127,9 +126,8 @@ impl IonContext { } } -pub type IonContextPtr = Rc>; +type IonContextPtr = Rc>; -// TODO [EMBDOC] does this serialization work? #[derive(Clone)] pub struct BoxedIon { ctx: IonContextPtr, @@ -142,7 +140,7 @@ impl Serialize for BoxedIon { where S: Serializer, { - todo!() + todo!("Serialize for BoxedIon") } } @@ -152,7 +150,7 @@ impl<'de> Deserialize<'de> for BoxedIon { where D: Deserializer<'de>, { - todo!() + todo!("Deserialize for BoxedIon") } } @@ -175,14 +173,16 @@ impl BoxedVariant for BoxedIon { fn into_dyn_iter(self: Box) -> BoxedVariantResult { let iter = self.try_into_iter()?; - Ok(Box::new(iter.map(|d| Box::new(d) as Box)) - as BoxedVariantValueIntoIterator) + Ok(Box::new(iter.map(|res| { + res.map(|d| Box::new(d) as Box) + .map_err(|e| Box::new(e) as Box) + })) as BoxedVariantValueIntoIterator) } fn category(&self) -> DatumCategoryRef<'_> { match &self.doc { BoxedIonValue::Stream() => DatumCategoryRef::Sequence(DatumSeqRef::Dynamic(self)), - BoxedIonValue::Sequence(seq) => DatumCategoryRef::Sequence(DatumSeqRef::Dynamic(self)), + BoxedIonValue::Sequence(_seq) => DatumCategoryRef::Sequence(DatumSeqRef::Dynamic(self)), BoxedIonValue::Value(elt) => { if elt.is_null() { DatumCategoryRef::Null @@ -202,7 +202,7 @@ impl BoxedVariant for BoxedIon { fn into_category(self: Box) -> DatumCategoryOwned { match &self.doc { BoxedIonValue::Stream() => DatumCategoryOwned::Sequence(DatumSeqOwned::Dynamic(self)), - BoxedIonValue::Sequence(seq) => { + BoxedIonValue::Sequence(_seq) => { DatumCategoryOwned::Sequence(DatumSeqOwned::Dynamic(self)) } BoxedIonValue::Value(elt) => { @@ -240,19 +240,13 @@ impl<'a, const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq let wrap = IonEqualityValue::<'_, true, { NAN_EQUAL }, _>; NullableEq::eq(&wrap(self.0), &wrap(rhs.0)) } - - #[inline(always)] - fn eqg(&self, rhs: &Self) -> Value { - let wrap = IonEqualityValue::<'_, true, { NAN_EQUAL }, _>; - NullableEq::eq(&wrap(self.0), &wrap(rhs.0)) - } } impl DatumLower for BoxedIon { fn into_lower(self) -> DatumLowerResult { let Self { ctx, doc } = self; let pval = match doc { - BoxedIonValue::Stream() => todo!("into_lower stream"), + BoxedIonValue::Stream() => todo!("DatumLower::into_lower for BoxedIonValue::Stream"), BoxedIonValue::Sequence(seq) => seq.into_partiql_value()?, BoxedIonValue::Value(elt) => elt.into_partiql_value()?, }; @@ -292,12 +286,12 @@ impl SequenceDatum for BoxedIon { fn len(&self) -> usize { match &self.doc { BoxedIonValue::Stream() => { - todo!() + todo!("SequenceDatum::len for BoxedIonValue::Stream") } BoxedIonValue::Sequence(seq) => seq.len(), BoxedIonValue::Value(elt) => match elt.expect_sequence() { - Ok(seq) => seq.len(), // TODO - Err(e) => todo!(), + Ok(seq) => seq.len(), + Err(_) => 0, }, } } @@ -307,20 +301,24 @@ impl<'a> RefSequenceView<'a, Value> for BoxedIon { fn get_val(&self, k: i64) -> Option> { match &self.doc { BoxedIonValue::Stream() => { - todo!() + todo!("RefSequenceView::get_val for BoxedIonValue::Stream") } BoxedIonValue::Sequence(seq) => seq .get(k as usize) - .map(|elt| Cow::Owned(self.child_value(elt.clone()))), // TODO remove clone + .map(|elt| Cow::Owned(self.child_value(elt.clone()))), // TODO find a way to remove clone BoxedIonValue::Value(elt) => match elt.expect_sequence() { Ok(seq) => seq .iter() .nth(k as usize) - .map(|elt| Cow::Owned(self.child_value(elt.clone()))), // TODO remove clone - Err(e) => todo!(), + .map(|elt| Cow::Owned(self.child_value(elt.clone()))), // TODO find a way to remove clone + Err(_) => None, }, } } + + fn into_iter(self) -> Box> + 'a> { + todo!() + } } impl OwnedSequenceView for BoxedIon { @@ -328,7 +326,7 @@ impl OwnedSequenceView for BoxedIon { let Self { doc, ctx } = self; match doc { BoxedIonValue::Stream() => { - todo!() + todo!("OwnedSequenceView::take_val for BoxedIonValue::Stream") } BoxedIonValue::Sequence(seq) => seq .into_iter() @@ -339,7 +337,7 @@ impl OwnedSequenceView for BoxedIon { .into_iter() .nth(k as usize) .map(|elt| Self::new_value(elt, ctx)), - Err(e) => todo!(), + Err(_) => None, }, } } @@ -349,7 +347,12 @@ impl OwnedSequenceView for BoxedIon { } fn into_iter_boxed(self: Box) -> Box> { - todo!() + Box::new( + self.into_dyn_iter() + .expect("BoxedIon::into_iter_boxed") + .map(|r| r.expect("BoxedIon::into_iter_boxed")) + .map(|v| Value::from(Variant::from(v))), + ) } } @@ -357,14 +360,12 @@ impl TupleDatum for BoxedIon { fn len(&self) -> usize { match &self.doc { BoxedIonValue::Stream() => { - todo!() - } - BoxedIonValue::Sequence(seq) => { - todo!() + todo!("TupleDatum::len for BoxedIonValue::Stream") } + BoxedIonValue::Sequence(_seq) => 0, BoxedIonValue::Value(elt) => match elt.expect_struct() { Ok(strct) => strct.len(), - Err(e) => todo!(), + Err(_) => 0, }, } } @@ -376,11 +377,9 @@ impl<'a> RefTupleView<'a, Value> for BoxedIon { let Self { doc, ctx } = self; match doc { BoxedIonValue::Stream() => { - todo!() - } - BoxedIonValue::Sequence(seq) => { - todo!() + todo!("RefTupleView::get_val for BoxedIonValue::Stream") } + BoxedIonValue::Sequence(_seq) => None, BoxedIonValue::Value(elt) => match elt.expect_struct() { Ok(strct) => { for (k, elt) in strct { @@ -392,27 +391,21 @@ impl<'a> RefTupleView<'a, Value> for BoxedIon { } None } - Err(e) => todo!(), + Err(_) => None, }, } } } impl OwnedTupleView for BoxedIon { - fn take_val(self, k: &BindingsName<'_>) -> Option { - todo!() - } - - fn take_val_boxed(self: Box, target_key: &BindingsName<'_>) -> Option { + fn take_val(self, target_key: &BindingsName<'_>) -> Option { let matcher = target_key.matcher(); - let Self { doc, ctx } = *self; + let Self { doc, ctx } = self; match doc { BoxedIonValue::Stream() => { - todo!() - } - BoxedIonValue::Sequence(seq) => { - todo!() + todo!("OwnedTupleView::take_val for BoxedIonValue::Stream") } + BoxedIonValue::Sequence(_) => None, BoxedIonValue::Value(elt) => match elt.try_into_struct() { Ok(strct) => { for (k, elt) in strct { @@ -424,10 +417,14 @@ impl OwnedTupleView for BoxedIon { } None } - Err(e) => todo!(), + Err(_) => None, }, } } + + fn take_val_boxed(self: Box, target_key: &BindingsName<'_>) -> Option { + OwnedTupleView::take_val(*self, target_key) + } } impl Debug for BoxedIon { @@ -447,13 +444,13 @@ impl BoxedIon { Value::from(Variant::from(self)) } - pub fn new(doc: impl Into, ctx: IonContextPtr) -> Self { + fn new(doc: impl Into, ctx: IonContextPtr) -> Self { Self { ctx, doc: doc.into(), } } - pub fn new_value(doc: impl Into, ctx: IonContextPtr) -> Value { + fn new_value(doc: impl Into, ctx: IonContextPtr) -> Value { Self::new(doc, ctx).into_value() } @@ -471,7 +468,7 @@ impl BoxedIon { pub fn parse(data: Vec, expected: BoxedIonStreamType) -> IonResult { let mut ctx = IonContext::new_ptr(data)?; let doc = Self::init_doc(&mut ctx, expected); - Ok(Self::new(doc, ctx)) + Ok(Self::new(doc?, ctx)) } pub fn parse_unknown(data: Vec) -> IonResult { @@ -485,7 +482,7 @@ impl BoxedIon { Self::parse(data, BoxedIonStreamType::Stream) } - fn init_doc(ctx: &mut IonContextPtr, expected: BoxedIonStreamType) -> BoxedIonValue { + fn init_doc(ctx: &mut IonContextPtr, expected: BoxedIonStreamType) -> IonResult { let reader = &mut ctx.borrow_mut().reader; let expected = match expected { BoxedIonStreamType::Unknown => { @@ -497,14 +494,13 @@ impl BoxedIon { } other => other, }; - match expected { + Ok(match expected { BoxedIonStreamType::Unknown => { unreachable!() } BoxedIonStreamType::Stream => BoxedIonValue::Stream(), BoxedIonStreamType::SingleTLV => { - let elt = reader.next().expect("ion value"); // TODO [EMBDOC] - let elt = elt.expect("ion element"); // TODO [EMBDOC] + let elt = reader.next().expect("ion value")?; if reader.peek().is_some() { // TODO error on stream instead of TLV? } @@ -514,7 +510,7 @@ impl BoxedIon { Ok(seq) => BoxedIonValue::Sequence(seq), } } - } + }) } fn try_into_iter(self) -> Result { @@ -524,7 +520,6 @@ impl BoxedIon { BoxedIonValue::Stream() => BoxedIonIterType::Stream(), BoxedIonValue::Value(elt) => match elt.try_into_sequence() { Err(err) => { - // TODO [EMBDOC] // We could error? But generally PartiQL coerces to a singleton collection... //Err(BoxedIonError::NotASequence { elt }), BoxedIonIterType::Sequence(Sequence::new([err.original_value()]).into_iter()) @@ -557,13 +552,18 @@ impl Hash for BoxedIonValue { fn hash(&self, state: &mut H) { match self { BoxedIonValue::Stream() => { - todo!("stream not hashable? ") + todo!("Hash::hash for BoxedIonValue::Stream") } BoxedIonValue::Value(val) => { let sha = ion_rs::ion_hash::sha256(val).expect("ion hash"); state.write(&sha); } - BoxedIonValue::Sequence(seq) => todo!("ion seq hash"), + BoxedIonValue::Sequence(seq) => { + for elt in seq { + let sha = ion_rs::ion_hash::sha256(elt).expect("ion hash"); + state.write(&sha); + } + } } } } @@ -687,22 +687,6 @@ impl<'a, const NULLS_EQUAL: bool, const NAN_EQUAL: bool> NullableEq } } -/* - -impl PartialEq for BoxedIonValue { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (BoxedIonValue::Value(l), BoxedIonValue::Value(r)) => l == r, - (BoxedIonValue::Sequence(l), BoxedIonValue::Sequence(r)) => l == r, - _ => false, - } - } -} - -impl Eq for BoxedIonValue {} - - */ - impl From for BoxedIonValue { fn from(value: Element) -> Self { BoxedIonValue::Value(value) @@ -717,10 +701,9 @@ impl From for BoxedIonValue { impl Clone for BoxedIonValue { fn clone(&self) -> Self { - // TODO [EMBDOC] match self { BoxedIonValue::Stream() => { - todo!("stream not cloneable? ") + todo!("Clone::clone for BoxedIonValue::Stream") } BoxedIonValue::Value(val) => BoxedIonValue::Value(val.clone()), BoxedIonValue::Sequence(seq) => BoxedIonValue::Sequence(seq.clone()), @@ -730,10 +713,9 @@ impl Clone for BoxedIonValue { impl Display for BoxedIonValue { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - // TODO [EMBDOC] match self { BoxedIonValue::Stream() => { - todo!("stream not displayable? ") + todo!("Display::fmt for BoxedIonValue::Stream") } BoxedIonValue::Value(val) => std::fmt::Display::fmt(val, f), BoxedIonValue::Sequence(seq) => std::fmt::Debug::fmt(&seq, f), @@ -778,18 +760,14 @@ struct BoxedIonIterator { } impl Iterator for BoxedIonIterator { - type Item = BoxedIon; + type Item = IonResult; fn next(&mut self) -> Option { let elt = match self.inner.borrow_mut().deref_mut() { - BoxedIonIterType::Stream() => { - let elt = self.ctx.borrow_mut().deref_mut().reader.next(); - // TODO [EMBDOC] - elt.transpose().expect("ion not error") - } - BoxedIonIterType::Sequence(seq) => seq.next(), + BoxedIonIterType::Stream() => self.ctx.borrow_mut().deref_mut().reader.next(), + BoxedIonIterType::Sequence(seq) => Ok(seq.next()).transpose(), }; - elt.map(|elt| BoxedIon::new(BoxedIonValue::Value(elt), self.ctx.clone())) + elt.map(|res| res.map(|elt| BoxedIon::new(BoxedIonValue::Value(elt), self.ctx.clone()))) } } @@ -799,8 +777,8 @@ mod tests { fn flatten_dump(doc: BoxedIon) { if doc.is_sequence() { - for c in doc.try_into_iter().expect("TODO [EMBDOC]") { - flatten_dump(c) + for c in doc.try_into_iter().expect("boxed ion iterate") { + flatten_dump(c.expect("boxed ion element")) } } else { println!("{:?}", doc); diff --git a/extension/partiql-extension-ion/src/util.rs b/extension/partiql-extension-ion/src/util.rs index 5f0c76b0..c9b3e18d 100644 --- a/extension/partiql-extension-ion/src/util.rs +++ b/extension/partiql-extension-ion/src/util.rs @@ -8,6 +8,7 @@ use std::str::FromStr; pub enum PartiqlValueTarget { Atom(Value), List(Vec), + #[allow(dead_code)] Bag(Vec), Struct(Vec<(String, T)>), } diff --git a/partiql-eval/src/eval/eval_expr_wrapper.rs b/partiql-eval/src/eval/eval_expr_wrapper.rs index d75c2b99..3c6f0b8c 100644 --- a/partiql-eval/src/eval/eval_expr_wrapper.rs +++ b/partiql-eval/src/eval/eval_expr_wrapper.rs @@ -59,7 +59,7 @@ impl TypeSatisfier for Static { }, (StaticCategory::Sequence(shape), DatumCategoryRef::Sequence(seq)) => match shape { PartiqlShape::Dynamic | PartiqlShape::Undefined => true, - shape => seq.into_iter().all(|v| shape.satisfies(v)), + shape => seq.into_iter().all(|v| shape.satisfies(&v)), }, (StaticCategory::Tuple(), DatumCategoryRef::Tuple(_)) => { true // TODO when Static typing knows how to type a tuple diff --git a/partiql-eval/src/plan.rs b/partiql-eval/src/plan.rs index aab47a60..fe908535 100644 --- a/partiql-eval/src/plan.rs +++ b/partiql-eval/src/plan.rs @@ -796,7 +796,7 @@ fn plan_lit(lit: &Lit) -> Result { Lit::Double(f) => Value::from(*f), Lit::Bool(b) => Value::from(*b), Lit::String(s) => Value::from(s.as_ref()), - Lit::BoxDocument(contents, _typ) => { + Lit::Variant(contents, _typ) => { let ion_typ = BoxedIonType::default().to_dyn_type_tag(); let variant = Variant::new(contents.clone(), ion_typ) .map_err(|e| PlanningError::IllegalState(e.to_string())); diff --git a/partiql-logical-planner/src/lower.rs b/partiql-logical-planner/src/lower.rs index 19ee65a2..55d46ae2 100644 --- a/partiql-logical-planner/src/lower.rs +++ b/partiql-logical-planner/src/lower.rs @@ -1923,9 +1923,9 @@ fn lit_to_lit(lit: &Lit) -> Result { Lit::FloatLit(f) => logical::Lit::Double(OrderedFloat::from(*f as f64)), Lit::DoubleLit(f) => logical::Lit::Double(OrderedFloat::from(*f)), Lit::BoolLit(b) => logical::Lit::Bool(*b), - Lit::EmbeddedDocLit(s, _) => { - // TODO [EMBDOC] fix type - logical::Lit::BoxDocument(s.clone().into_bytes(), "Ion".to_string()) + Lit::EmbeddedDocLit(s, _typ) => { + // TODO fix type for boxed variants + logical::Lit::Variant(s.clone().into_bytes(), "Ion".to_string()) } Lit::CharStringLit(s) => logical::Lit::String(s.clone()), Lit::NationalCharStringLit(s) => logical::Lit::String(s.clone()), diff --git a/partiql-logical-planner/src/typer.rs b/partiql-logical-planner/src/typer.rs index 3ebb15a3..f3d868cd 100644 --- a/partiql-logical-planner/src/typer.rs +++ b/partiql-logical-planner/src/typer.rs @@ -346,7 +346,7 @@ impl<'c> PlanTyper<'c> { Lit::Double(_) => type_float64!(self.bld), Lit::Bool(_) => type_bool!(self.bld), Lit::String(_) => type_string!(self.bld), - Lit::BoxDocument(_, _) => type_dynamic!(self.bld), // TODO + Lit::Variant(_, _) => type_dynamic!(self.bld), // TODO Lit::Struct(_) => type_struct!(self.bld), Lit::Bag(_) => type_bag!(self.bld), Lit::List(_) => type_array!(self.bld), diff --git a/partiql-logical/src/lib.rs b/partiql-logical/src/lib.rs index c99046d2..2dcc614c 100644 --- a/partiql-logical/src/lib.rs +++ b/partiql-logical/src/lib.rs @@ -459,7 +459,7 @@ pub enum Lit { Double(OrderedFloat), Bool(bool), String(String), - BoxDocument(Vec, String), // (bytes, type-name as string) TODO replace with strongly typed box name. + Variant(Vec, String), // (bytes, type-name as string) TODO replace with strongly typed box name. Struct(Vec<(String, Lit)>), Bag(Vec), List(Vec), diff --git a/partiql-value/src/boxed_variant.rs b/partiql-value/src/boxed_variant.rs index 0c6a307b..ebd4559a 100644 --- a/partiql-value/src/boxed_variant.rs +++ b/partiql-value/src/boxed_variant.rs @@ -14,7 +14,8 @@ use std::fmt::{Debug, Display}; pub type BoxedVariantError = Box; pub type BoxedVariantResult = Result; -pub type BoxedVariantValueIntoIterator = Box>; +pub type BoxedVariantValueIntoIterator = + Box>>; pub type BoxedVariantValueIter<'a> = Box>>; diff --git a/partiql-value/src/datum.rs b/partiql-value/src/datum.rs index e6a3735b..92d9196b 100644 --- a/partiql-value/src/datum.rs +++ b/partiql-value/src/datum.rs @@ -5,9 +5,7 @@ use std::borrow::Cow; use std::error::Error; use std::fmt::Debug; -use std::vec; -// TODO [EMBDOC] pub type DatumIterator = dyn Iterator; pub type DatumLowerError = Box; pub type DatumLowerResult = Result; @@ -221,12 +219,12 @@ pub trait SequenceDatum { pub trait RefSequenceView<'a, DV: DatumValue>: SequenceDatum + Debug { fn get_val(&self, k: i64) -> Option>; + fn into_iter(self) -> Box> + 'a>; } pub trait OwnedSequenceView>: SequenceDatum + Debug { fn take_val(self, k: i64) -> Option; fn take_val_boxed(self: Box, k: i64) -> Option; - fn into_iter_boxed(self: Box) -> Box>; } @@ -252,12 +250,18 @@ impl<'a> RefSequenceView<'a, Value> for DatumSeqRef<'a> { fn get_val(&self, k: i64) -> Option> { match self { DatumSeqRef::List(l) => List::get(l, k).map(Cow::Borrowed), - DatumSeqRef::Bag(_) => { - todo!("TODO [EMBDOC]: Bag::get") - } + DatumSeqRef::Bag(_) => None, DatumSeqRef::Dynamic(boxed) => boxed.get_val(k), } } + + fn into_iter(self) -> Box> + 'a> { + match self { + DatumSeqRef::List(l) => Box::new(l.iter().map(Cow::Borrowed)), + DatumSeqRef::Bag(b) => Box::new(b.iter().map(Cow::Borrowed)), + DatumSeqRef::Dynamic(boxed) => boxed.into_iter(), + } + } } impl SequenceDatum for DatumSeqOwned { @@ -270,7 +274,11 @@ impl SequenceDatum for DatumSeqOwned { } fn len(&self) -> usize { - todo!() + match self { + DatumSeqOwned::List(l) => l.len(), + DatumSeqOwned::Bag(b) => b.len(), + DatumSeqOwned::Dynamic(boxed) => boxed.len(), + } } } @@ -278,7 +286,7 @@ impl OwnedSequenceView for DatumSeqOwned { fn take_val(self, k: i64) -> Option { match self { DatumSeqOwned::List(l) => l.take_val(k), - DatumSeqOwned::Bag(_) => todo!("TODO [EMBDOC]: Bag::get"), + DatumSeqOwned::Bag(_) => None, DatumSeqOwned::Dynamic(boxed) => boxed.take_val_boxed(k), } } @@ -288,21 +296,23 @@ impl OwnedSequenceView for DatumSeqOwned { } fn into_iter_boxed(self: Box) -> Box> { - todo!() + match *self { + DatumSeqOwned::List(l) => Box::new(l.into_iter()), + DatumSeqOwned::Bag(b) => Box::new(b.into_iter()), + DatumSeqOwned::Dynamic(boxed) => boxed.into_iter_boxed(), + } } } impl<'a> IntoIterator for DatumSeqRef<'a> { - type Item = &'a Value; + type Item = Cow<'a, Value>; type IntoIter = DatumSeqRefIterator<'a>; fn into_iter(self) -> Self::IntoIter { match self { DatumSeqRef::List(l) => DatumSeqRefIterator::List(l.into_iter()), DatumSeqRef::Bag(b) => DatumSeqRefIterator::Bag(b.into_iter()), - DatumSeqRef::Dynamic(_) => { - todo!() - } + DatumSeqRef::Dynamic(d) => DatumSeqRefIterator::Dynamic(d.into_iter()), } } } @@ -310,16 +320,26 @@ impl<'a> IntoIterator for DatumSeqRef<'a> { pub enum DatumSeqRefIterator<'a> { List(ListIter<'a>), Bag(BagIter<'a>), - Dynamic(Box + 'a>), + Dynamic(Box>>), +} + +impl<'a> IntoIterator for &'a dyn RefSequenceView<'a, Value> { + type Item = Cow<'a, Value>; + type IntoIter = Box>>; + + #[inline] + fn into_iter(self) -> Self::IntoIter { + todo!("into_iter for &'a dyn RefSequenceView<'a, Value>") + } } impl<'a> Iterator for DatumSeqRefIterator<'a> { - type Item = &'a Value; + type Item = Cow<'a, Value>; fn next(&mut self) -> Option { match self { - DatumSeqRefIterator::List(l) => l.next(), - DatumSeqRefIterator::Bag(b) => b.next(), + DatumSeqRefIterator::List(l) => l.next().map(Cow::Borrowed), + DatumSeqRefIterator::Bag(b) => b.next().map(Cow::Borrowed), DatumSeqRefIterator::Dynamic(d) => d.next(), } } @@ -333,9 +353,7 @@ impl IntoIterator for DatumSeqOwned { match self { DatumSeqOwned::List(l) => DatumSeqOwnedIterator::List(l.into_iter()), DatumSeqOwned::Bag(b) => DatumSeqOwnedIterator::Bag(b.into_iter()), - DatumSeqOwned::Dynamic(_) => { - todo!() - } + DatumSeqOwned::Dynamic(d) => DatumSeqOwnedIterator::Dynamic(d.into_iter_boxed()), } } } @@ -357,20 +375,3 @@ impl Iterator for DatumSeqOwnedIterator { } } } - -// TODO remove -pub struct DynIntoIterator(vec::IntoIter); - -impl Iterator for DynIntoIterator { - type Item = Value; - - #[inline] - fn next(&mut self) -> Option { - self.0.next() - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.0.size_hint() - } -} diff --git a/partiql-value/src/value.rs b/partiql-value/src/value.rs index 5f60e525..3730debe 100644 --- a/partiql-value/src/value.rs +++ b/partiql-value/src/value.rs @@ -39,7 +39,6 @@ pub enum Value { Bag(Box), Tuple(Box), Variant(Box), - // TODO: add other supported PartiQL values -- sexp } impl Value { diff --git a/partiql-value/src/value/iter.rs b/partiql-value/src/value/iter.rs index 8eede279..ded7bd23 100644 --- a/partiql-value/src/value/iter.rs +++ b/partiql-value/src/value/iter.rs @@ -2,13 +2,10 @@ use crate::{ BagIntoIterator, BagIter, ListIntoIterator, ListIter, Value, VariantIntoIterator, VariantIter, }; -// TODO [EMBDOC] iterate - -#[derive(Debug, Clone)] pub enum ValueIter<'a> { List(ListIter<'a>), Bag(BagIter<'a>), - Embedded(VariantIter<'a>), + Variant(VariantIter<'a>), Single(Option<&'a Value>), } @@ -20,16 +17,8 @@ impl<'a> Iterator for ValueIter<'a> { match self { ValueIter::List(list) => list.next(), ValueIter::Bag(bag) => bag.next(), - ValueIter::Embedded(doc) => { - todo!() - // TODO [EMBDOC] don't just unwrap errors to MISSING; report in strict mode? - /* - doc.next().map(|res| { - &res.map(|doc| Value::EmbeddedDoc(doc)) - .unwrap_or(Value::Missing) - }) - - */ + ValueIter::Variant(_doc) => { + todo!("next for ValueIter::Variant") } ValueIter::Single(v) => v.take(), } @@ -40,9 +29,8 @@ impl<'a> Iterator for ValueIter<'a> { match self { ValueIter::List(list) => list.size_hint(), ValueIter::Bag(bag) => bag.size_hint(), - ValueIter::Embedded(doc) => { - todo!() - //doc.size_hint(), + ValueIter::Variant(_doc) => { + todo!("size_hint for ValueIter::Variant") } ValueIter::Single(_) => (1, Some(1)), } @@ -58,7 +46,7 @@ impl IntoIterator for Value { match self { Value::List(list) => ValueIntoIterator::List(list.into_iter()), Value::Bag(bag) => ValueIntoIterator::Bag(bag.into_iter()), - Value::Variant(doc) => ValueIntoIterator::Embedded(doc.into_iter()), + Value::Variant(doc) => ValueIntoIterator::Variant(doc.into_iter()), other => ValueIntoIterator::Single(Some(other)), } } @@ -67,7 +55,7 @@ impl IntoIterator for Value { pub enum ValueIntoIterator { List(ListIntoIterator), Bag(BagIntoIterator), - Embedded(VariantIntoIterator), + Variant(VariantIntoIterator), Single(Option), } @@ -79,7 +67,9 @@ impl Iterator for ValueIntoIterator { match self { ValueIntoIterator::List(list) => list.next(), ValueIntoIterator::Bag(bag) => bag.next(), - ValueIntoIterator::Embedded(doc) => doc.next().map(|d| Value::Variant(Box::new(d))), + ValueIntoIterator::Variant(doc) => doc + .next() + .map(|d| Value::Variant(Box::new(d.expect("Variant iteration")))), ValueIntoIterator::Single(v) => v.take(), } } @@ -89,7 +79,7 @@ impl Iterator for ValueIntoIterator { match self { ValueIntoIterator::List(list) => list.size_hint(), ValueIntoIterator::Bag(bag) => bag.size_hint(), - ValueIntoIterator::Embedded(doc) => doc.size_hint(), + ValueIntoIterator::Variant(doc) => doc.size_hint(), ValueIntoIterator::Single(_) => (1, Some(1)), } } diff --git a/partiql-value/src/variant.rs b/partiql-value/src/variant.rs index a4a70b7c..73d17223 100644 --- a/partiql-value/src/variant.rs +++ b/partiql-value/src/variant.rs @@ -9,19 +9,20 @@ use crate::datum::{ use crate::{Comparable, EqualityValue, NullSortedValue, NullableEq, Value}; use delegate::delegate; -use partiql_common::pretty::{pretty_surrounded_doc, PrettyDoc, ToPretty}; +use partiql_common::pretty::{pretty_surrounded_doc, PrettyDoc}; use pretty::{DocAllocator, DocBuilder}; #[cfg(feature = "serde")] use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::borrow::Cow; use std::cmp::Ordering; -use std::fmt::{Debug, Formatter, Write}; -use std::hash::{Hash, Hasher}; +use std::fmt::Debug; +use std::hash::Hash; use thiserror::Error; -#[derive(Clone)] +#[derive(Clone, Debug)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Variant { variant: DynBoxedVariant, } @@ -36,12 +37,6 @@ impl Variant { } } -impl std::fmt::Debug for Variant { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - f.write_str(&self.to_pretty_string(80).expect("pretty")) - } -} - impl From for Variant where T: BoxedVariant + 'static, @@ -120,25 +115,15 @@ impl Unparsed { } } +#[allow(dead_code)] pub struct VariantIter<'a>(BoxedVariantValueIter<'a>); -impl Debug for VariantIter<'_> { - fn fmt(&self, _f: &mut Formatter<'_>) -> std::fmt::Result { - todo!() - } -} - -impl Clone for VariantIter<'_> { - fn clone(&self) -> Self { - todo!() - } -} impl IntoIterator for Variant { - type Item = Variant; + type Item = BoxedVariantResult; type IntoIter = VariantIntoIterator; fn into_iter(self) -> VariantIntoIterator { - let iter = self.variant.into_dyn_iter().expect("TODO [EMBDOC]"); + let iter = self.variant.into_dyn_iter().expect("into_dyn_iter"); VariantIntoIterator(iter) } } @@ -146,11 +131,11 @@ impl IntoIterator for Variant { pub struct VariantIntoIterator(BoxedVariantValueIntoIterator); impl Iterator for VariantIntoIterator { - type Item = Variant; + type Item = BoxedVariantResult; #[inline] fn next(&mut self) -> Option { - self.0.next().map(Variant::from) + self.0.next().map(|res| res.map(Variant::from)) } #[inline] @@ -172,12 +157,6 @@ impl Datum for Variant { } } -impl Hash for Variant { - fn hash(&self, _state: &mut H) { - todo!() - } -} - impl PartialOrd for Variant { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) @@ -202,6 +181,13 @@ impl PartialEq for Variant { impl Eq for Variant {} +impl Hash for Variant { + fn hash(&self, state: &mut H) { + self.variant.type_tag().name().hash(state); + self.variant.hash(state); + } +} + impl NullableEq for EqualityValue<'_, NULLS_EQUAL, NAN_EQUAL, Variant> { @@ -223,26 +209,6 @@ impl NullableEq } } -#[cfg(feature = "serde")] -impl Serialize for Variant { - fn serialize(&self, _serializer: S) -> Result - where - S: Serializer, - { - todo!() - } -} - -#[cfg(feature = "serde")] -impl<'de> Deserialize<'de> for Variant { - fn deserialize(_deserializer: D) -> Result - where - D: Deserializer<'de>, - { - todo!() - } -} - impl PrettyDoc for Variant { fn pretty_doc<'b, D, A>(&'b self, arena: &'b D) -> DocBuilder<'b, D, A> where @@ -250,8 +216,6 @@ impl PrettyDoc for Variant { D::Doc: Clone, A: Clone, { - // TODO [EMBDOC] write out type tag? - // TODO [EMBDOC] handle backticks more generally. let doc = self.variant.pretty_doc(arena); let ty = self.variant.type_tag().name();