use crate::{
Result,
engine::{exec::Exec, mir},
};
use toasty_core::{
driver::{ExecResponse, Rows},
stmt::Value,
};
impl Exec<'_> {
pub(super) async fn exec_eval(&mut self, action: &mir::Eval) -> Result<ExecResponse> {
match action.row_input {
Some(row_input) => self.exec_eval_map_over(action, row_input).await,
None => self.exec_eval_compute(action).await,
}
}
async fn exec_eval_compute(&mut self, action: &mir::Eval) -> Result<ExecResponse> {
let mut input = Vec::with_capacity(action.inputs.len());
for &node_id in &action.inputs {
let response = self.vars.load(node_id).await?;
debug_assert!(response.is_unpaginated());
input.push(response.values.collect_as_value().await?);
}
let result = action.body.eval(&self.engine.schema, &input)?;
Ok(ExecResponse::from_rows(Rows::Value(result)))
}
async fn exec_eval_map_over(
&mut self,
action: &mir::Eval,
row_input: mir::NodeId,
) -> Result<ExecResponse> {
let ExecResponse {
values,
next_cursor,
prev_cursor,
} = self.vars.load(row_input).await?;
let input_rows = values.collect_as_value().await?;
if input_rows.is_list_empty() {
return Ok(self.exec_eval_map_over_empty_input(action, next_cursor, prev_cursor));
}
let mut input = Vec::with_capacity(1 + action.inputs.len());
input.push(input_rows);
for &node_id in &action.inputs {
let input_response = self.vars.load(node_id).await?;
debug_assert!(input_response.is_unpaginated());
input.push(input_response.values.collect_as_value().await?);
}
let result = action.body.eval(&self.engine.schema, &input)?;
Ok(ExecResponse {
values: Rows::Value(result),
next_cursor,
prev_cursor,
})
}
fn exec_eval_map_over_empty_input(
&mut self,
action: &mir::Eval,
next_cursor: Option<Box<Value>>,
prev_cursor: Option<Box<Value>>,
) -> ExecResponse {
for &node_id in &action.inputs {
self.vars.release(node_id);
}
ExecResponse {
values: Rows::Value(Value::List(vec![])),
next_cursor,
prev_cursor,
}
}
}