Skip to content

Commit

Permalink
Add PartiqlShape
Browse files Browse the repository at this point in the history
Refactors `partiql-types` by adding `PartiqlShape`; with this model, `PartiqlShape`
is one of `Dynamic` (ex. `Any`), `AnyOf`, `Static`, or `Undefined`. `nullability` is
 defined as part of `StaticType`.

The large diff is as a result of the `PartiqlType` refactoring.
  • Loading branch information
am357 committed Jun 19, 2024
1 parent dd40192 commit 654461b
Show file tree
Hide file tree
Showing 8 changed files with 402 additions and 254 deletions.
2 changes: 1 addition & 1 deletion partiql-catalog/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use crate::call_defs::CallDef;

use partiql_types::{PartiqlShape};
use partiql_types::PartiqlShape;
use partiql_value::Value;
use std::borrow::Cow;

Expand Down
79 changes: 43 additions & 36 deletions partiql-eval/src/eval/eval_expr_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::eval::expr::{BindError, EvalExpr};
use crate::eval::EvalContext;
use itertools::Itertools;

use partiql_types::{PartiqlShape, PartiqlType, TYPE_ANY};
use partiql_types::{PartiqlShape, StaticTypeVariant, TYPE_DYNAMIC};
use partiql_value::Value::{Missing, Null};
use partiql_value::{Tuple, Value};

Expand All @@ -19,35 +19,46 @@ use std::ops::ControlFlow;
// TODO replace with type system's subsumption once it is in place
#[inline]
pub(crate) fn subsumes(typ: &PartiqlShape, value: &Value) -> bool {
match (typ.ty(), value) {
match (typ, value) {
(_, Value::Null) => true,
(_, Value::Missing) => true,
(PartiqlType::Any, _) => true,
(PartiqlType::AnyOf(anyof), val) => anyof.types().any(|typ| subsumes(typ, val)),
(
PartiqlType::Int | PartiqlType::Int8 | PartiqlType::Int16 | PartiqlType::Int32 | PartiqlType::Int64,
Value::Integer(_),
) => true,
(PartiqlType::Bool, Value::Boolean(_)) => true,
(PartiqlType::Decimal | PartiqlType::DecimalP(_, _), Value::Decimal(_)) => true,
(PartiqlType::Float32 | PartiqlType::Float64, Value::Real(_)) => true,
(
PartiqlType::String | PartiqlType::StringFixed(_) | PartiqlType::StringVarying(_),
Value::String(_),
) => true,
(PartiqlType::Struct(_), Value::Tuple(_)) => true,
(PartiqlType::Bag(b_type), Value::Bag(b_values)) => {
let bag_element_type = b_type.element_type();
let mut b_values = b_values.iter();
b_values.all(|b_value| subsumes(bag_element_type, b_value))
}
(PartiqlType::DateTime, Value::DateTime(_)) => true,
(PartiqlShape::Dynamic, _) => true,
(PartiqlShape::AnyOf(anyof), val) => anyof.types().any(|typ| subsumes(typ, val)),
(PartiqlShape::Static(s), val) => match (s.ty(), val) {
(
StaticTypeVariant::Int
| StaticTypeVariant::Int8
| StaticTypeVariant::Int16
| StaticTypeVariant::Int32
| StaticTypeVariant::Int64,
Value::Integer(_),
) => true,
(StaticTypeVariant::Bool, Value::Boolean(_)) => true,
(StaticTypeVariant::Decimal | StaticTypeVariant::DecimalP(_, _), Value::Decimal(_)) => {
true
}
(StaticTypeVariant::Float32 | StaticTypeVariant::Float64, Value::Real(_)) => true,
(
StaticTypeVariant::String
| StaticTypeVariant::StringFixed(_)
| StaticTypeVariant::StringVarying(_),
Value::String(_),
) => true,
(StaticTypeVariant::Struct(_), Value::Tuple(_)) => true,
(StaticTypeVariant::Bag(b_type), Value::Bag(b_values)) => {
let bag_element_type = b_type.element_type();
let mut b_values = b_values.iter();
b_values.all(|b_value| subsumes(bag_element_type, b_value))
}
(StaticTypeVariant::DateTime, Value::DateTime(_)) => true,

(PartiqlType::Array(a_type), Value::List(l_values)) => {
let array_element_type = a_type.element_type();
let mut l_values = l_values.iter();
l_values.all(|l_value| subsumes(array_element_type, l_value))
}
(StaticTypeVariant::Array(a_type), Value::List(l_values)) => {
let array_element_type = a_type.element_type();
let mut l_values = l_values.iter();
l_values.all(|l_value| subsumes(array_element_type, l_value))
}
_ => false,
},
_ => false,
}
}
Expand Down Expand Up @@ -298,11 +309,7 @@ impl<const STRICT: bool, const N: usize, E: ExecuteEvalExpr<N>, ArgC: ArgChecker
ArgCheckControlFlow::ShortCircuit(v) => return ControlFlow::Break(v),
ArgCheckControlFlow::ErrorOrShortCircuit(v) => {
if STRICT {
let signature = self
.types
.iter()
.map(|typ| format!("{}", typ.ty()))
.join(",");
let signature = self.types.iter().map(|typ| format!("{}", typ)).join(",");
let before = (0..i).map(|_| "_");
let arg = "MISSING"; // TODO display actual argument?
let after = (i + 1..N).map(|_| "_");
Expand Down Expand Up @@ -414,7 +421,7 @@ impl UnaryValueExpr {
where
F: 'static + Fn(&Value) -> Value,
{
Self::create_typed::<STRICT, F>([TYPE_ANY; 1], args, f)
Self::create_typed::<STRICT, F>([TYPE_DYNAMIC; 1], args, f)
}

#[allow(dead_code)]
Expand Down Expand Up @@ -478,7 +485,7 @@ impl BinaryValueExpr {
where
F: 'static + Fn(&Value, &Value) -> Value,
{
Self::create_typed::<STRICT, F>([TYPE_ANY; 2], args, f)
Self::create_typed::<STRICT, F>([TYPE_DYNAMIC; 2], args, f)
}

#[allow(dead_code)]
Expand Down Expand Up @@ -542,7 +549,7 @@ impl TernaryValueExpr {
where
F: 'static + Fn(&Value, &Value, &Value) -> Value,
{
Self::create_typed::<STRICT, F>([TYPE_ANY; 3], args, f)
Self::create_typed::<STRICT, F>([TYPE_DYNAMIC; 3], args, f)
}

#[allow(dead_code)]
Expand Down Expand Up @@ -611,7 +618,7 @@ impl QuaternaryValueExpr {
where
F: 'static + Fn(&Value, &Value, &Value, &Value) -> Value,
{
Self::create_typed::<STRICT, F>([TYPE_ANY; 4], args, f)
Self::create_typed::<STRICT, F>([TYPE_DYNAMIC; 4], args, f)
}

#[allow(dead_code)]
Expand Down
22 changes: 13 additions & 9 deletions partiql-eval/src/eval/expr/coll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use crate::eval::expr::{BindError, BindEvalExpr, EvalExpr};

use itertools::{Itertools, Unique};

use partiql_types::{ArrayType, BagType, PartiqlShape, PartiqlType, TYPE_BOOL, TYPE_NUMERIC_TYPES};
use partiql_types::{
ArrayType, BagType, PartiqlShape, StaticTypeVariant, TYPE_BOOL, TYPE_NUMERIC_TYPES,
};
use partiql_value::Value::{Missing, Null};
use partiql_value::{BinaryAnd, BinaryOr, Value, ValueIter};

Expand Down Expand Up @@ -50,20 +52,22 @@ impl BindEvalExpr for EvalCollFn {
})
}
let boolean_elems = [PartiqlShape::any_of([
PartiqlShape::new(PartiqlType::Array(ArrayType::new(Box::new(TYPE_BOOL)))),
PartiqlShape::new(PartiqlType::Bag(BagType::new(Box::new(TYPE_BOOL)))),
PartiqlShape::new(StaticTypeVariant::Array(ArrayType::new(Box::new(
TYPE_BOOL,
)))),
PartiqlShape::new(StaticTypeVariant::Bag(BagType::new(Box::new(TYPE_BOOL)))),
])];
let numeric_elems = [PartiqlShape::any_of([
PartiqlShape::new(PartiqlType::Array(ArrayType::new(Box::new(
PartiqlShape::new(StaticTypeVariant::Array(ArrayType::new(Box::new(
PartiqlShape::any_of(TYPE_NUMERIC_TYPES),
)))),
PartiqlShape::new(StaticTypeVariant::Bag(BagType::new(Box::new(
PartiqlShape::any_of(TYPE_NUMERIC_TYPES),
)))),
PartiqlShape::new(PartiqlType::Bag(BagType::new(Box::new(PartiqlShape::any_of(
TYPE_NUMERIC_TYPES,
))))),
])];
let any_elems = [PartiqlShape::any_of([
PartiqlShape::new(PartiqlType::Array(ArrayType::new_any())),
PartiqlShape::new(PartiqlType::Bag(BagType::new_any())),
PartiqlShape::new(StaticTypeVariant::Array(ArrayType::new_any())),
PartiqlShape::new(StaticTypeVariant::Bag(BagType::new_any())),
])];

match *self {
Expand Down
21 changes: 11 additions & 10 deletions partiql-eval/src/eval/expr/operators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use crate::eval::expr::{BindError, BindEvalExpr, EvalExpr};
use crate::eval::EvalContext;

use partiql_types::{
ArrayType, BagType, PartiqlShape, StructType, PartiqlType, TYPE_ANY, TYPE_BOOL, TYPE_NUMERIC_TYPES,
ArrayType, BagType, PartiqlShape, StaticTypeVariant, StructType, TYPE_BOOL, TYPE_DYNAMIC,
TYPE_NUMERIC_TYPES,
};
use partiql_value::Value::{Boolean, Missing, Null};
use partiql_value::{BinaryAnd, EqualityValue, NullableEq, NullableOrd, Tuple, Value};
Expand Down Expand Up @@ -172,7 +173,7 @@ impl BindEvalExpr for EvalOpBinary {

macro_rules! equality {
($f:expr) => {
create!(EqCheck<STRICT>, [TYPE_ANY, TYPE_ANY], $f)
create!(EqCheck<STRICT>, [TYPE_DYNAMIC, TYPE_DYNAMIC], $f)
};
}

Expand Down Expand Up @@ -208,10 +209,10 @@ impl BindEvalExpr for EvalOpBinary {
create!(
InCheck<STRICT>,
[
TYPE_ANY,
TYPE_DYNAMIC,
PartiqlShape::any_of([
PartiqlShape::new(PartiqlType::Array(ArrayType::new_any())),
PartiqlShape::new(PartiqlType::Bag(BagType::new_any())),
PartiqlShape::new(StaticTypeVariant::Array(ArrayType::new_any())),
PartiqlShape::new(StaticTypeVariant::Bag(BagType::new_any())),
])
],
|lhs, rhs| {
Expand Down Expand Up @@ -249,7 +250,7 @@ impl BindEvalExpr for EvalOpBinary {
)
}
EvalOpBinary::Concat => {
create!(Check<STRICT>, [TYPE_ANY, TYPE_ANY], |lhs, rhs| {
create!(Check<STRICT>, [TYPE_DYNAMIC, TYPE_DYNAMIC], |lhs, rhs| {
// TODO non-naive concat (i.e., don't just use debug print for non-strings).
let lhs = if let Value::String(s) = lhs {
s.as_ref().clone()
Expand Down Expand Up @@ -277,7 +278,7 @@ impl BindEvalExpr for EvalBetweenExpr {
&self,
args: Vec<Box<dyn EvalExpr>>,
) -> Result<Box<dyn EvalExpr>, BindError> {
let types = [TYPE_ANY, TYPE_ANY, TYPE_ANY];
let types = [TYPE_DYNAMIC, TYPE_DYNAMIC, TYPE_DYNAMIC];
TernaryValueExpr::create_checked::<{ STRICT }, NullArgChecker, _>(
types,
args,
Expand Down Expand Up @@ -337,9 +338,9 @@ impl BindEvalExpr for EvalFnCardinality {
args: Vec<Box<dyn EvalExpr>>,
) -> Result<Box<dyn EvalExpr>, BindError> {
let collections = PartiqlShape::any_of([
PartiqlShape::new(PartiqlType::Array(ArrayType::new_any())),
PartiqlShape::new(PartiqlType::Bag(BagType::new_any())),
PartiqlShape::new(PartiqlType::Struct(StructType::new_any())),
PartiqlShape::new(StaticTypeVariant::Array(ArrayType::new_any())),
PartiqlShape::new(StaticTypeVariant::Bag(BagType::new_any())),
PartiqlShape::new(StaticTypeVariant::Struct(StructType::new_any())),
]);

UnaryValueExpr::create_typed::<{ STRICT }, _>([collections], args, |v| match v {
Expand Down
4 changes: 2 additions & 2 deletions partiql-logical-planner/src/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2000,7 +2000,7 @@ mod tests {
use partiql_catalog::{PartiqlCatalog, TypeEnvEntry};
use partiql_logical::BindingsOp::Project;
use partiql_logical::ValueExpr;
use partiql_types::any;
use partiql_types::dynamic;

#[test]
fn test_plan_non_existent_fns() {
Expand Down Expand Up @@ -2100,7 +2100,7 @@ mod tests {
expected_logical.add_flow_with_branch_num(project, sink, 0);

let mut catalog = PartiqlCatalog::default();
let _oid = catalog.add_type_entry(TypeEnvEntry::new("customers", &[], any!()));
let _oid = catalog.add_type_entry(TypeEnvEntry::new("customers", &[], dynamic!()));
let statement = "SELECT c.id AS my_id, customers.name AS my_name FROM customers AS c";
let parsed = partiql_parser::Parser::default()
.parse(statement)
Expand Down
Loading

0 comments on commit 654461b

Please sign in to comment.