#![deny(rust_2018_idioms)]
#![deny(clippy::all)]
#![warn(clippy::pedantic)]
#[cfg(test)]
mod tests {
use partiql_catalog::context::SystemContext;
use partiql_catalog::{Catalog, PartiqlCatalog};
use partiql_eval::env::basic::MapBindings;
use partiql_eval::error::EvalErr;
use partiql_eval::eval::BasicContext;
use partiql_eval::plan::EvaluationMode;
use partiql_logical::{LogicalPlan, ProjectValue, VarRefType};
use partiql_value::{bag, tuple, Bag, BindingsName, DateTime, Value};
use std::any::Any;
#[track_caller]
#[inline]
pub(crate) fn evaluate(
catalog: &dyn Catalog,
logical: partiql_logical::LogicalPlan<partiql_logical::BindingsOp>,
bindings: MapBindings<Value>,
ctx_vals: &[(String, &(dyn Any))],
) -> Result<Value, EvalErr> {
let mut planner =
partiql_eval::plan::EvaluatorPlanner::new(EvaluationMode::Strict, catalog);
let mut plan = planner.compile(&logical).expect("Expect no plan error");
let sys = SystemContext {
now: DateTime::from_system_now_utc(),
};
let mut ctx = BasicContext::new(bindings, sys);
for (k, v) in ctx_vals {
ctx.user.insert(k.as_str().into(), *v);
}
plan.execute_mut(&ctx).map(|out| out.result)
}
#[test]
fn locals_in_subqueries() {
let mut sub_query = partiql_logical::LogicalPlan::new();
let scan_op_id =
sub_query.add_operator(partiql_logical::BindingsOp::Scan(partiql_logical::Scan {
expr: partiql_logical::ValueExpr::Lit(Box::new(Value::Bag(Box::new(Bag::from(
vec![tuple![("a", "b")].into()],
))))),
as_key: "foo".into(),
at_key: None,
}));
let project_value_op_id = sub_query.add_operator(
partiql_logical::BindingsOp::ProjectValue(partiql_logical::ProjectValue {
expr: partiql_logical::ValueExpr::VarRef(
BindingsName::CaseSensitive("foo".into()),
VarRefType::Local,
),
}),
);
sub_query.add_flow(scan_op_id, project_value_op_id);
let sink_op_id = sub_query.add_operator(partiql_logical::BindingsOp::Sink);
sub_query.add_flow(project_value_op_id, sink_op_id);
let mut plan = LogicalPlan::new();
let scan_op_id =
plan.add_operator(partiql_logical::BindingsOp::Scan(partiql_logical::Scan {
expr: partiql_logical::ValueExpr::SubQueryExpr(partiql_logical::SubQueryExpr {
plan: sub_query,
}),
as_key: "_1".into(),
at_key: None,
}));
let project_value_op_id =
plan.add_operator(partiql_logical::BindingsOp::ProjectValue(ProjectValue {
expr: partiql_logical::ValueExpr::VarRef(
BindingsName::CaseSensitive("_1".into()),
VarRefType::Local,
),
}));
plan.add_flow(scan_op_id, project_value_op_id);
let sink_op_id = plan.add_operator(partiql_logical::BindingsOp::Sink);
plan.add_flow(project_value_op_id, sink_op_id);
let catalog = PartiqlCatalog::default();
let bindings = MapBindings::default();
let res = evaluate(&catalog, plan, bindings, &[]).expect("should eval correctly");
dbg!(&res);
assert!(res != Value::Missing);
assert_eq!(res, Value::from(bag![tuple![("a", "b")]]));
}
#[test]
fn globals_in_subqueries() {
let mut sub_query = partiql_logical::LogicalPlan::new();
let scan_op_id =
sub_query.add_operator(partiql_logical::BindingsOp::Scan(partiql_logical::Scan {
expr: partiql_logical::ValueExpr::VarRef(
BindingsName::CaseSensitive("foo".into()),
VarRefType::Global,
),
as_key: "foo".into(),
at_key: None,
}));
let project_value_op_id = sub_query.add_operator(
partiql_logical::BindingsOp::ProjectValue(partiql_logical::ProjectValue {
expr: partiql_logical::ValueExpr::VarRef(
BindingsName::CaseSensitive("foo".into()),
VarRefType::Local,
),
}),
);
sub_query.add_flow(scan_op_id, project_value_op_id);
let sink_op_id = sub_query.add_operator(partiql_logical::BindingsOp::Sink);
sub_query.add_flow(project_value_op_id, sink_op_id);
let mut plan = LogicalPlan::new();
let scan_op_id =
plan.add_operator(partiql_logical::BindingsOp::Scan(partiql_logical::Scan {
expr: partiql_logical::ValueExpr::SubQueryExpr(partiql_logical::SubQueryExpr {
plan: sub_query,
}),
as_key: "_1".into(),
at_key: None,
}));
let project_value_op_id =
plan.add_operator(partiql_logical::BindingsOp::ProjectValue(ProjectValue {
expr: partiql_logical::ValueExpr::VarRef(
BindingsName::CaseSensitive("_1".into()),
VarRefType::Local,
),
}));
plan.add_flow(scan_op_id, project_value_op_id);
let sink_op_id = plan.add_operator(partiql_logical::BindingsOp::Sink);
plan.add_flow(project_value_op_id, sink_op_id);
let catalog = PartiqlCatalog::default();
let mut bindings = MapBindings::default();
bindings.insert(
"foo",
Value::Bag(Box::new(Bag::from(vec![tuple![("a", "b")].into()]))),
);
let res = evaluate(&catalog, plan, bindings, &[]).expect("should eval correctly");
dbg!(&res);
assert!(res != Value::Missing);
assert_eq!(res, Value::from(bag![tuple![("a", "b")]]));
}
}