Skip to content

Commit 4d9ae54

Browse files
authored
Add session context to evaluation (#446)
1 parent 00924f2 commit 4d9ae54

File tree

29 files changed

+660
-151
lines changed

29 files changed

+660
-151
lines changed

.github/workflows/ci_build_test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ jobs:
9292
- name: Rust Toolchain
9393
uses: dtolnay/rust-toolchain@master
9494
with:
95-
toolchain: nightly-2023-03-09
95+
toolchain: nightly-2023-06-09
9696
- uses: actions/cache@v3
9797
id: restore-build
9898
with:
@@ -132,7 +132,7 @@ jobs:
132132
- name: Rust Toolchain
133133
uses: dtolnay/rust-toolchain@master
134134
with:
135-
toolchain: nightly-2023-03-09
135+
toolchain: nightly-2023-06-09
136136
- uses: actions/cache@v3
137137
id: restore-build-and-conformance
138138
with:

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## [Unreleased]
99
### Changed
1010
- Adds quotes to the attributes of PartiQL tuple's debug output so it can be read and transformed using Kotlin `partiql-cli`
11+
- [breaking] Changes the interface to `EvalPlan` to accept an `EvalContext`
1112

1213
### Added
1314
- Add `partiql-extension-visualize` for visualizing AST and logical plan
15+
- Add a `SessionContext` containing both a system-level and a user-level context object usable by expression evaluation
1416

1517
### Fixed
1618
- Fixed `ORDER BY`'s ability to see into projection aliases

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ homepage = "https://github.com/partiql/partiql-lang-rust"
44
repository = "https://github.com/partiql/partiql-lang-rust"
55
version = "0.6.0"
66
edition = "2021"
7-
resolver = 2
87

98
[workspace]
9+
resolver = "2"
1010

1111
members = [
1212
"partiql",

extension/partiql-extension-ion-functions/src/lib.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use partiql_logical as logical;
1111
use partiql_value::Value;
1212
use std::borrow::Cow;
1313

14+
use partiql_catalog::context::SessionContext;
1415
use std::error::Error;
1516
use std::fmt::Debug;
1617
use std::fs::File;
@@ -98,7 +99,11 @@ impl BaseTableFunctionInfo for ReadIonFunction {
9899
pub(crate) struct EvalFnReadIon {}
99100

100101
impl BaseTableExpr for EvalFnReadIon {
101-
fn evaluate(&self, args: &[Cow<Value>]) -> BaseTableExprResult {
102+
fn evaluate<'c>(
103+
&self,
104+
args: &[Cow<Value>],
105+
_ctx: &'c dyn SessionContext<'c>,
106+
) -> BaseTableExprResult<'c> {
102107
if let Some(arg1) = args.first() {
103108
match arg1.as_ref() {
104109
Value::String(path) => parse_ion_file(path),
@@ -155,11 +160,13 @@ fn parse_ion_buff<'a, I: 'a + ToIonDataSource>(input: I) -> BaseTableExprResult<
155160
mod tests {
156161
use super::*;
157162

163+
use partiql_catalog::context::SystemContext;
158164
use partiql_catalog::{Catalog, Extension, PartiqlCatalog};
159165
use partiql_eval::env::basic::MapBindings;
166+
use partiql_eval::eval::BasicContext;
160167
use partiql_eval::plan::EvaluationMode;
161168
use partiql_parser::{Parsed, ParserResult};
162-
use partiql_value::{bag, tuple, Value};
169+
use partiql_value::{bag, tuple, DateTime, Value};
163170

164171
#[track_caller]
165172
#[inline]
@@ -189,7 +196,11 @@ mod tests {
189196

190197
let mut plan = planner.compile(&logical).expect("Expect no plan error");
191198

192-
if let Ok(out) = plan.execute_mut(bindings) {
199+
let sys = SystemContext {
200+
now: DateTime::from_system_now_utc(),
201+
};
202+
let ctx = BasicContext::new(bindings, sys);
203+
if let Ok(out) = plan.execute_mut(&ctx) {
193204
out.result
194205
} else {
195206
Value::Missing

partiql-catalog/src/context.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use partiql_value::{BindingsName, DateTime, Tuple, Value};
2+
use std::any::Any;
3+
use std::fmt::Debug;
4+
5+
pub trait Bindings<T>: Debug {
6+
fn get(&self, name: &BindingsName) -> Option<&T>;
7+
}
8+
9+
impl Bindings<Value> for Tuple {
10+
fn get(&self, name: &BindingsName) -> Option<&Value> {
11+
self.get(name)
12+
}
13+
}
14+
15+
#[derive(Debug)]
16+
pub struct SystemContext {
17+
pub now: DateTime,
18+
}
19+
20+
/// Represents a session context that is used during evaluation of a plan.
21+
pub trait SessionContext<'a>: Debug {
22+
fn bindings(&self) -> &dyn Bindings<Value>;
23+
24+
fn system_context(&self) -> &SystemContext;
25+
26+
fn user_context(&self, name: &str) -> Option<&(dyn Any)>;
27+
}

partiql-catalog/src/lib.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use partiql_types::PartiqlType;
44
use partiql_value::Value;
55
use std::borrow::Cow;
66

7+
use crate::context::SessionContext;
78
use std::collections::HashMap;
89
use std::error::Error;
910
use std::fmt::Debug;
@@ -13,6 +14,8 @@ use unicase::UniCase;
1314

1415
pub mod call_defs;
1516

17+
pub mod context;
18+
1619
pub trait Extension: Debug {
1720
fn name(&self) -> String;
1821
fn load(&self, catalog: &mut dyn Catalog) -> Result<(), Box<dyn Error>>;
@@ -49,7 +52,11 @@ pub type BaseTableExprResult<'a> =
4952
Result<BaseTableExprResultValueIter<'a>, BaseTableExprResultError>;
5053

5154
pub trait BaseTableExpr: Debug {
52-
fn evaluate(&self, args: &[Cow<Value>]) -> BaseTableExprResult;
55+
fn evaluate<'c>(
56+
&self,
57+
args: &[Cow<Value>],
58+
ctx: &'c dyn SessionContext<'c>,
59+
) -> BaseTableExprResult<'c>;
5360
}
5461

5562
pub trait BaseTableFunctionInfo: Debug {

partiql-conformance-tests/tests/mod.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use partiql_ast_passes::error::AstTransformationError;
22
use partiql_catalog::{Catalog, PartiqlCatalog};
33
use partiql_eval as eval;
4-
use partiql_eval::env::basic::MapBindings;
4+
55
use partiql_eval::error::{EvalErr, PlanErr};
6-
use partiql_eval::eval::{EvalPlan, EvalResult, Evaluated};
6+
use partiql_eval::eval::{BasicContext, EvalContext, EvalPlan, EvalResult, Evaluated};
77
use partiql_logical as logical;
88
use partiql_parser::{Parsed, ParserError, ParserResult};
9-
use partiql_value::Value;
9+
use partiql_value::DateTime;
1010

11+
use partiql_catalog::context::SystemContext;
1112
use thiserror::Error;
1213

1314
mod test_value;
@@ -58,8 +59,8 @@ pub(crate) fn compile(
5859

5960
#[track_caller]
6061
#[inline]
61-
pub(crate) fn evaluate(mut plan: EvalPlan, bindings: MapBindings<Value>) -> EvalResult {
62-
plan.execute_mut(bindings)
62+
pub(crate) fn evaluate<'c>(mut plan: EvalPlan, ctx: &'c dyn EvalContext<'c>) -> EvalResult {
63+
plan.execute_mut(ctx)
6364
}
6465

6566
#[track_caller]
@@ -161,9 +162,15 @@ pub(crate) fn eval<'a>(
161162

162163
let parsed = parse(statement)?;
163164
let lowered = lower(&catalog, &parsed)?;
165+
164166
let bindings = env.as_ref().map(|e| (&e.value).into()).unwrap_or_default();
167+
let sys = SystemContext {
168+
now: DateTime::from_system_now_utc(),
169+
};
170+
let ctx = BasicContext::new(bindings, sys);
165171
let plan = compile(mode, &catalog, lowered)?;
166-
Ok(evaluate(plan, bindings)?)
172+
173+
Ok(evaluate(plan, &ctx)?)
167174
}
168175

169176
#[track_caller]

partiql-eval/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ assert_matches = "1.5.*"
3636
regex = "1.7"
3737
regex-syntax = "0.6"
3838
rustc-hash = "1"
39+
delegate = "0.12"
3940

4041
[dev-dependencies]
4142
criterion = "0.4"

partiql-eval/benches/bench_eval.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,19 @@ use std::borrow::Cow;
22
use std::time::Duration;
33

44
use criterion::{black_box, criterion_group, criterion_main, Criterion};
5+
use partiql_catalog::context::SystemContext;
56
use partiql_catalog::PartiqlCatalog;
67

78
use partiql_eval::env::basic::MapBindings;
8-
use partiql_eval::eval::EvalPlan;
9+
use partiql_eval::eval::{BasicContext, EvalPlan};
910
use partiql_eval::plan;
1011
use partiql_eval::plan::EvaluationMode;
1112
use partiql_logical as logical;
1213
use partiql_logical::BindingsOp::{Project, ProjectAll};
1314
use partiql_logical::{
1415
BinaryOp, BindingsOp, JoinKind, LogicalPlan, PathComponent, ValueExpr, VarRefType,
1516
};
16-
use partiql_value::{bag, list, tuple, BindingsName, Value};
17+
use partiql_value::{bag, list, tuple, BindingsName, DateTime, Value};
1718

1819
fn data() -> MapBindings<Value> {
1920
let hr = tuple![(
@@ -134,7 +135,11 @@ fn eval_plan(logical: &LogicalPlan<BindingsOp>) -> EvalPlan {
134135
}
135136

136137
fn evaluate(mut plan: EvalPlan, bindings: MapBindings<Value>) -> Value {
137-
if let Ok(out) = plan.execute_mut(bindings) {
138+
let sys = SystemContext {
139+
now: DateTime::from_system_now_utc(),
140+
};
141+
let ctx = BasicContext::new(bindings, sys);
142+
if let Ok(out) = plan.execute_mut(&ctx) {
138143
out.result
139144
} else {
140145
Value::Missing

partiql-eval/src/env.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,8 @@
1+
use partiql_catalog::context::Bindings;
12
use partiql_value::{BindingsName, Tuple, Value};
23
use std::fmt::Debug;
34
use unicase::UniCase;
45

5-
pub trait Bindings<T>: Debug {
6-
fn get(&self, name: &BindingsName) -> Option<&T>;
7-
}
8-
9-
impl Bindings<Value> for Tuple {
10-
fn get(&self, name: &BindingsName) -> Option<&Value> {
11-
self.get(name)
12-
}
13-
}
14-
156
pub mod basic {
167
use super::*;
178
use std::collections::HashMap;

0 commit comments

Comments
 (0)