use crate::cypher::ast::*;
use crate::cypher::eval::EvalCx;
use crate::cypher::record_view::{view_to_named, RecordView};
use crate::types::Value;
pub(in crate::cypher::eval) fn eval_exists(
patterns: &[crate::cypher::ast::Pattern],
where_clause: Option<&Expr>,
record: &dyn RecordView,
ecx: EvalCx<'_>,
) -> crate::types::Result<Value> {
let conn = ecx.conn;
use crate::cypher::executor::execute_first_match;
use crate::cypher::ir::LogicalOp;
use crate::cypher::planner::plan_patterns;
let mut op = plan_patterns(conn, patterns)?;
if let Some(predicate) = where_clause {
op = LogicalOp::Filter {
input: Box::new(op),
predicate: predicate.clone(),
};
}
let mut outer_bindings: Vec<(String, Value)> = Vec::new();
record.for_each_field(&mut |k, v| {
if !k.contains('.') {
outer_bindings.push((k.to_string(), v.clone()));
}
});
let found = execute_first_match(conn, &op, &outer_bindings)?;
Ok(Value::Bool(found))
}
pub(in crate::cypher::eval) fn eval_exists_subquery(
stmt: &crate::cypher::ast::Statement,
record: &dyn RecordView,
ecx: EvalCx<'_>,
) -> crate::types::Result<Value> {
let conn = ecx.conn;
use crate::cypher::executor::exec_correlated_exists;
use crate::cypher::planner::plan_subquery;
let base_plan = plan_subquery(conn, stmt)?;
let outer = view_to_named(record);
let found = exec_correlated_exists(conn, &base_plan, &outer)?;
Ok(Value::Bool(found))
}