Eval

Struct Eval 

Source
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>

Source

pub fn new( schema: &'a Schema, fields: &'a [Field], rows: &'a dyn Rows, ) -> Eval<'a>

Source

pub fn resolve(&self, n: &Name) -> Result<usize, SqlError>

Where a name’s value sits in a row.

Source

pub fn holds(&self, terms: &[Expr], row: &[Cell]) -> Result<bool, SqlError>

Whether every term of a conjunction is true of this row.

Source

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.

Source

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.

Auto Trait Implementations§

§

impl<'a> !Freeze for Eval<'a>

§

impl<'a> !RefUnwindSafe for Eval<'a>

§

impl<'a> !Send for Eval<'a>

§

impl<'a> !Sync for Eval<'a>

§

impl<'a> Unpin for Eval<'a>

§

impl<'a> !UnwindSafe for Eval<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.