Skip to main content

Prepared

Struct Prepared 

Source
pub struct Prepared { /* private fields */ }
Expand description

One or more bound expressions, flattened and resolved against a schema.

Built once per pipeline with Prepared::new and evaluated per chunk with Prepared::evaluate or Prepared::evaluate_one, each of which wants the Scratch that Prepared::scratch hands out.

Implementations§

Source§

impl Prepared

Source

pub fn new(plan: &Plan, exprs: &[ExprRef], schema: &Schema) -> Result<Self>

Prepares exprs against schema.

§Errors

If a column reference names a binding the schema does not have, or if an aggregate appears where an ordinary expression was expected. Both are failures of the plan rather than of the data, which is why they are found here, once, rather than on some chunk in the middle of a scan.

Source

pub fn one(plan: &Plan, expr: ExprRef, schema: &Schema) -> Result<Self>

Prepares one expression, which is the common case and saves the caller a slice.

§Errors

Whatever Prepared::new reports.

Source

pub fn scratch(&self) -> Scratch

Working space sized for this expression.

Source

pub fn len(&self) -> usize

How many expressions this was built from.

Source

pub fn is_empty(&self) -> bool

Whether it was built from no expressions at all.

Source

pub fn evaluate( &self, chunk: &Chunk, scratch: &mut Scratch, out: &mut Vec<Vector>, ) -> Result<()>

Evaluates every expression over chunk, appending one vector each to out.

Appends rather than returns a Vec, so a caller in a loop reuses one buffer.

§Errors

Anything a kernel reports, on the first expression that reports it.

Source

pub fn evaluate_one<'s>( &'s self, chunk: &'s Chunk, scratch: &'s mut Scratch, ) -> Result<&'s Vector>

Evaluates a single expression over chunk, handing back a reference to the answer.

A reference rather than a vector, because the caller of this is a filter, which reads the flags to build a selection and then drops them. Nothing about that wants ownership, and a predicate that is a bare column reference, which WHERE flag is, would otherwise copy the column to hand it over.

§Errors

Anything a kernel reports, and an internal error if this was not built from exactly one expression.

Source

pub fn evaluate_filter( &self, chunk: &Chunk, scratch: &mut Scratch, ) -> Result<Selection>

Evaluates a single expression as a filter, handing back the rows it keeps.

The difference between this and evaluate_one followed by selection is the whole of what a threaded filter is. An AND evaluated as an expression runs every conjunct over every row and then combines the flag vectors, so a predicate of four conjuncts that each pass a fifth of the rows does five times the work of one that stops looking at a row as soon as a conjunct rejects it. TPC-H Q6 is exactly that predicate.

So the conjuncts of a top level AND are run one at a time, each over the rows the ones before it left, and the moment nothing is left the rest of the predicate is not run at all. The order they run in starts as the order the plan gives and then moves, because which conjunct is worth running first is a question about the data and the scan is the thing holding the answer. The ordering module has what is measured and how.

A top level OR is threaded the same way against the complement. A row the first branch accepts is a row the filter keeps whatever the rest of the predicate says about it, so each branch is run over the rows no branch before it accepted, and the moment every row has been accepted the rest of the predicate is not run either. That is the mirror of the AND case and not an approximation of it: the answer is the same set of rows, because OR over three valued logic is true wherever any branch is true and nothing a later branch says can take a row back. It is worth less than the AND case in practice, since an OR of selective branches leaves almost every row in play for the branch after, and it is worth having anyway because the cost of finding that out is one merge per branch.

What is threaded is the operand’s own comparison rather than the whole of its subtree. A conjunct of a + b > 5 still adds over the whole chunk, because the scalar kernels take a vector rather than a selection, and it is the comparison and everything downstream of it that reads only the rows still in play. An operand that is a bare column or a function produces flags over the chunk and is narrowed with refine_flags, which is what keeps one awkward operand from putting the others back on the unthreaded path. An operand that is itself a connective recurses, so the two conjuncts of each half of (a AND b) OR (c AND d) are threaded the same way the halves are.

None of this is available to a projection. SELECT a > 5 AND b LIKE 'x%' wants a value per row and the rows a selection dropped have no value in it, so evaluate and evaluate_one evaluate the whole tree over the whole chunk and combine flags. The two are separate entry points picked when the pipeline is built rather than one path with a flag in it, because conflating them is a wrong answer rather than a slow one.

§Errors

Anything a kernel reports, and an internal error if this was not built from exactly one expression.

Trait Implementations§

Source§

impl Debug for Prepared

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

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 = !

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

fn try_from(value: U) -> Result<T, !>

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.