pub struct Eval<'a> { /* private fields */ }Expand description
What an Expr is evaluated against: the columns a row has, and the reader behind them.
Two things are memoised, and both are memoised because they are the same answer for every row:
- A name’s column index. Resolution is a scan of the query’s fields, and a query over a million rows would otherwise do it a million times per reference.
- A subquery’s value. See
Eval::subquery— what is evaluated there is by construction uncorrelated, so it cannot depend on the row.
Neither memo can make an answer wrong, only repeated: a name resolves to one index for the
whole query, and a query whose fields changed would be a different Eval.
Implementations§
Source§impl<'a> Eval<'a>
impl<'a> Eval<'a>
pub fn new( schema: &'a Schema, fields: &'a [Field], rows: &'a dyn Rows, ) -> Eval<'a>
Sourcepub fn holds(&self, terms: &[Expr], row: &[Cell]) -> Result<bool, SqlError>
pub fn holds(&self, terms: &[Expr], row: &[Cell]) -> Result<bool, SqlError>
Whether every term of a conjunction is true of this row.
Sourcepub fn cell(&self, e: &Expr, row: &[Cell]) -> Result<Cell, SqlError>
pub fn cell(&self, e: &Expr, row: &[Cell]) -> Result<Cell, SqlError>
One expression’s value for one row.
O(1) per node, and every node is visited at most once — except the arms of a case,
which are visited until one matches and never after.
Sourcepub fn subquery(&self, id: usize, select: &Select) -> Result<Cell, SqlError>
pub fn subquery(&self, id: usize, select: &Select) -> Result<Cell, SqlError>
A scalar subquery’s value, when it can be established without correlation.
The rule, and it is the whole of it: drop the terms that name something this subquery’s own tables do not have — those are the ones correlated to the outer row — and run what is left. Dropping a term can only add rows, so a widened query that answers nothing proves the original answers nothing, and a scalar subquery with no rows is NULL. That is the answer for every outer row, which is why it is computed once.
When the widened query does have rows the answer depends on the correlation, and it is
refused by name rather than guessed at. Every scalar subquery psql sends the catalogue
asks about a default expression or a collation — relations a read model has none of — so
the empty case is the one that happens, and the refusal is what would happen if that ever
stopped being true.