Skip to content

Commit

Permalink
Introduce Datum, an interface to introspecting Values
Browse files Browse the repository at this point in the history
  • Loading branch information
jpschorr committed Dec 6, 2024
1 parent 27d90d1 commit 55a58e5
Show file tree
Hide file tree
Showing 7 changed files with 321 additions and 53 deletions.
3 changes: 2 additions & 1 deletion extension/partiql-extension-ion-functions/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ mod tests {
use partiql_eval::eval::BasicContext;
use partiql_eval::plan::EvaluationMode;
use partiql_parser::{Parsed, ParserResult};
use partiql_value::datum::Datum;
use partiql_value::{bag, tuple, DateTime, Value};

#[track_caller]
Expand Down Expand Up @@ -229,7 +230,7 @@ mod tests {
.unwrap_or_default();
let out = evaluate(&catalog, lowered, bindings);

assert!(out.is_bag());
assert!(out.is_sequence());
assert_eq!(&out, expected);
}

Expand Down
1 change: 1 addition & 0 deletions partiql-eval/src/eval/evaluable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use std::collections::hash_map::Entry;
use std::collections::HashSet;
use std::fmt::{Debug, Formatter};

use partiql_value::datum::Datum;
use std::rc::Rc;

#[macro_export]
Expand Down
1 change: 1 addition & 0 deletions partiql-eval/src/eval/expr/coll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use std::fmt::Debug;
use std::hash::Hash;

use crate::eval::eval_expr_wrapper::UnaryValueExpr;
use partiql_value::datum::Datum;
use std::ops::ControlFlow;

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
Expand Down
264 changes: 264 additions & 0 deletions partiql-value/src/datum.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
use crate::{Bag, BindingsName, List, Tuple, Value};
use std::borrow::Cow;
use std::error::Error;
// TODO [EMBDOC] pub type DatumIterator = dyn Iterator<Item = Value>;

pub type DatumLowerError = Box<dyn Error>;
pub type DatumLowerResult<T> = Result<T, DatumLowerError>;

pub trait Datum<D>
where
D: Datum<D>,
{
#[inline]
/// Returns true if and only if Value is to be interpreted as `NULL`
#[must_use]
fn is_null(&self) -> bool {
false
}

#[inline]
/// Returns true if and only if Value is to be interpreted as `MISSING`
#[must_use]
fn is_missing(&self) -> bool {
false
}

#[inline]
/// Returns true if and only if Value is null or missing
#[must_use]
fn is_absent(&self) -> bool {
self.is_null() || self.is_missing()
}

#[inline]
/// Returns true if and only if Value is an integer, real, or decimal
#[must_use]
fn is_number(&self) -> bool;

#[inline]
/// Returns true if Value is neither null nor missing
#[must_use]
fn is_present(&self) -> bool {
!self.is_absent()
}

#[must_use]
fn is_sequence(&self) -> bool;

#[must_use]
fn is_ordered(&self) -> bool;

// #[must_use]
// fn into_iter(self) -> I;

//fn lower(self) -> DatumLowerResult<D>;
}

pub trait DatumValue<D>: Clone + Datum<D>
where
D: Datum<D>,
{
fn into_lower(self) -> DatumLowerResult<D>;
}

pub trait DatumCategory<'a> {
fn category(&'a self) -> DatumCategoryRef<'a>;
fn into_category(self) -> DatumCategoryOwned;
}

#[derive(Debug)]
pub enum DatumCategoryRef<'a> {
Null,
Missing,
Tuple(DatumTupleRef<'a>),
Sequence(DatumSeqRef<'a>),
Scalar(DatumValueRef<'a>),
}

#[derive(Debug)]
pub enum DatumCategoryOwned {
Null,
Missing,
Tuple(DatumTupleOwned),
Sequence(DatumSeqOwned),
Scalar(DatumValueOwned),
}

#[derive(Debug)]
pub enum DatumTupleRef<'a> {
Tuple(&'a Tuple),
}

#[derive(Debug)]
pub enum DatumSeqRef<'a> {
List(&'a List),
Bag(&'a Bag),
}

#[derive(Debug)]
pub enum DatumValueRef<'a> {
Value(&'a Value),
}

#[derive(Debug)]
pub enum DatumTupleOwned {
Tuple(Box<Tuple>),
}

#[derive(Debug)]
pub enum DatumSeqOwned {
List(Box<List>),
Bag(Box<Bag>),
}

#[derive(Debug)]
pub enum DatumValueOwned {
Value(Value),
}

impl<'a> DatumCategory<'a> for Value {
fn category(&'a self) -> DatumCategoryRef<'a> {
match self {
Value::Null => DatumCategoryRef::Null,
Value::Missing => DatumCategoryRef::Missing,
Value::List(list) => DatumCategoryRef::Sequence(DatumSeqRef::List(list)),
Value::Bag(bag) => DatumCategoryRef::Sequence(DatumSeqRef::Bag(bag)),
Value::Tuple(tuple) => DatumCategoryRef::Tuple(DatumTupleRef::Tuple(tuple.as_ref())),
val => DatumCategoryRef::Scalar(DatumValueRef::Value(val)),
}
}

fn into_category(self) -> DatumCategoryOwned {
match self {
Value::Null => DatumCategoryOwned::Null,
Value::Missing => DatumCategoryOwned::Missing,
Value::List(list) => DatumCategoryOwned::Sequence(DatumSeqOwned::List(list)),
Value::Bag(bag) => DatumCategoryOwned::Sequence(DatumSeqOwned::Bag(bag)),
Value::Tuple(tuple) => DatumCategoryOwned::Tuple(DatumTupleOwned::Tuple(tuple)),
val => DatumCategoryOwned::Scalar(DatumValueOwned::Value(val)),
}
}
}

pub trait TupleDatum {
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
}

pub trait RefTupleView<'a, DV: DatumValue<DV>>: TupleDatum {
fn get_val(&self, k: &BindingsName<'_>) -> Option<Cow<'a, DV>>;
}

pub trait OwnedTupleView<D: Datum<D>>: TupleDatum {
fn take_val(self, k: &BindingsName<'_>) -> Option<D>;
fn take_val_boxed(self: Box<Self>, k: &BindingsName<'_>) -> Option<D>;
}

impl TupleDatum for DatumTupleRef<'_> {
fn len(&self) -> usize {
match self {
DatumTupleRef::Tuple(tuple) => tuple.len(),
}
}
}

impl<'a> RefTupleView<'a, Value> for DatumTupleRef<'a> {
fn get_val(&self, k: &BindingsName<'_>) -> Option<Cow<'a, Value>> {
match self {
DatumTupleRef::Tuple(tuple) => Tuple::get(tuple, k).map(Cow::Borrowed),
}
}
}

impl TupleDatum for DatumTupleOwned {
fn len(&self) -> usize {
match self {
DatumTupleOwned::Tuple(tuple) => tuple.len(),
}
}
}

impl OwnedTupleView<Value> for DatumTupleOwned {
fn take_val(self, k: &BindingsName<'_>) -> Option<Value> {
match self {
DatumTupleOwned::Tuple(tuple) => Tuple::take_val(*tuple, k),
}
}

fn take_val_boxed(self: Box<Self>, k: &BindingsName<'_>) -> Option<Value> {
(*self).take_val(k)
}
}

pub trait SequenceDatum {
fn is_ordered(&self) -> bool;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
}

pub trait RefSequenceView<'a, DV: DatumValue<DV>>: SequenceDatum {
fn get_val(&self, k: i64) -> Option<Cow<'a, DV>>;
}

pub trait OwnedSequenceView<D: Datum<D>>: SequenceDatum {
fn take_val(self, k: i64) -> Option<D>;
fn take_val_boxed(self: Box<Self>, k: i64) -> Option<D>;
}

impl SequenceDatum for DatumSeqRef<'_> {
fn is_ordered(&self) -> bool {
match self {
DatumSeqRef::List(_) => true,
DatumSeqRef::Bag(_) => false,
}
}

fn len(&self) -> usize {
match self {
DatumSeqRef::List(l) => l.len(),
DatumSeqRef::Bag(b) => b.len(),
}
}
}

impl<'a> RefSequenceView<'a, Value> for DatumSeqRef<'a> {
fn get_val(&self, k: i64) -> Option<Cow<'a, Value>> {
match self {
DatumSeqRef::List(l) => List::get(l, k).map(Cow::Borrowed),
DatumSeqRef::Bag(_) => {
todo!("TODO RefSequenceView: Bag::get")
}
}
}
}

impl SequenceDatum for DatumSeqOwned {
fn is_ordered(&self) -> bool {
match self {
DatumSeqOwned::List(_) => true,
DatumSeqOwned::Bag(_) => false,
}
}

fn len(&self) -> usize {
todo!()
}
}

impl OwnedSequenceView<Value> for DatumSeqOwned {
fn take_val(self, k: i64) -> Option<Value> {
match self {
DatumSeqOwned::List(l) => l.take_val(k),
DatumSeqOwned::Bag(_) => todo!("TODO OwnedSequenceView: Bag::get"),
}
}

fn take_val_boxed(self: Box<Self>, k: i64) -> Option<Value> {
self.take_val(k)
}
}
1 change: 1 addition & 0 deletions partiql-value/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ mod bag;
mod bindings;
pub mod comparison;
mod datetime;
pub mod datum;
mod list;
mod pretty;
mod sort;
Expand Down
Loading

0 comments on commit 55a58e5

Please sign in to comment.