Skip to main content

Plan

Struct Plan 

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

A bound logical plan.

Ten flat pools and a root. Everything refers to everything else by u32 index, and the one structural rule is that a reference always points backwards: a node’s children have smaller indices than the node, and an expression’s operands have smaller indices than the expression. Building bottom up gives that for free, it makes a cycle impossible rather than merely unlikely, and it means a walk of the whole plan is a loop over a vector in either direction instead of a recursion with a visited set. Plan::validate checks it.

A fresh plan is Node::Dummy at the root, which is one row and no columns. That is a valid plan rather than a placeholder, so there is no state in which a Plan exists and cannot be printed.

There is no PartialEq. Two plans that compute the same thing can have different arena layouts after a rewrite reorders pools, so comparing arenas would report differences that are not differences. The textual form is what plans are compared by, and it is canonical because printing walks from the root and never touches an unreachable entry.

Implementations§

Source§

impl Plan

Source

pub fn parse(text: &str) -> Result<Self>

Reads a plan back from its textual form.

Printing the result produces the text that was read, which is a test in tests/roundtrip.rs rather than a claim here. The plan is validated before it is returned, so a text that parses is a text that names a plan somebody could have built.

§Errors

With the line number and the column, because the thing a person wants from a dump that will not read back is which character of which operator.

Source§

impl Plan

Source

pub fn new() -> Self

An empty plan, which is one row and no columns.

Source

pub fn root(&self) -> NodeRef

The node the plan is rooted at.

Source

pub fn set_root(&mut self, node: NodeRef)

Roots the plan at node.

Source

pub fn node_count(&self) -> usize

How many nodes are in the arena, reachable or not.

Source

pub fn expr_count(&self) -> usize

How many expressions are in the arena, reachable or not.

Source

pub fn add_node(&mut self, node: Node) -> NodeRef

Appends a node.

Source

pub fn add_expr(&mut self, expr: Expr, ty: LogicalType) -> ExprRef

Appends an expression and the type it evaluates to.

Source

pub fn add_value(&mut self, value: Value) -> ValueRef

Appends a constant.

Source

pub fn add_constant(&mut self, value: Value) -> ExprRef

Appends a constant expression, taking its type from the value.

The shorthand for the common case. A typed null needs Plan::add_expr with Expr::Constant instead, since a NULL literal knows its type from context and not from itself.

Source

pub fn intern(&mut self, text: &str) -> StrRef

Interns a string, returning an existing entry if there is one.

A linear scan, because a plan’s string table is table names, column names and function names and runs to tens of entries. A hash map here would be a second copy of every string to save a scan nobody can measure.

§Panics

If the string table has more than u32::MAX entries. Every pool in the arena is indexed by a u32 and the reference type says so, so a plan that large is not a plan this type can hold and there is nothing sensible to return instead.

Source

pub fn add_expr_list(&mut self, exprs: &[ExprRef]) -> Slice

Appends a run to the expression list pool.

Source

pub fn add_name_list(&mut self, names: &[StrRef]) -> Slice

Appends a run to the name list pool.

Source

pub fn add_fields(&mut self, fields: &[Field]) -> Slice

Appends a run to the field pool, which is what a scan’s or a VALUES’ output schema is.

Source

pub fn add_sort_keys(&mut self, keys: &[SortKey]) -> Slice

Appends a run to the sort key pool.

Source

pub fn add_arms(&mut self, arms: &[Arm]) -> Slice

Appends a run to the CASE arm pool.

Source

pub fn add_rows(&mut self, rows: &[Slice]) -> Slice

Appends a run to the row pool, each element itself a run of the expression list pool.

Source

pub fn node(&self, reference: NodeRef) -> &Node

The node at reference.

§Panics

If the reference is not in the arena.

Source

pub fn expr(&self, reference: ExprRef) -> &Expr

The expression at reference.

§Panics

If the reference is not in the arena.

Source

pub fn expr_type(&self, reference: ExprRef) -> &LogicalType

The type the expression at reference evaluates to.

§Panics

If the reference is not in the arena.

Source

pub fn value(&self, reference: ValueRef) -> &Value

The constant at reference.

§Panics

If the reference is not in the arena.

Source

pub fn string(&self, reference: StrRef) -> &str

The string at reference.

§Panics

If the reference is not in the arena.

Source

pub fn expr_list(&self, slice: Slice) -> &[ExprRef]

The expression run at slice.

§Panics

If the run is not in the pool.

Source

pub fn name_list(&self, slice: Slice) -> &[StrRef]

The name run at slice.

§Panics

If the run is not in the pool.

Source

pub fn field_list(&self, slice: Slice) -> &[Field]

The field run at slice.

§Panics

If the run is not in the pool.

Source

pub fn sort_key_list(&self, slice: Slice) -> &[SortKey]

The sort key run at slice.

§Panics

If the run is not in the pool.

Source

pub fn arm_list(&self, slice: Slice) -> &[Arm]

The CASE arm run at slice.

§Panics

If the run is not in the pool.

Source

pub fn row_list(&self, slice: Slice) -> &[Slice]

The row run at slice.

§Panics

If the run is not in the pool.

Source

pub fn rebind(&mut self, reference: ExprRef, binding: ColumnBinding)

Points a column reference at a different column.

What column pruning does after it narrows a scan, since dropping a column moves every column after it up. The type does not change, because it is the same column of the same operator read from a different position.

§Panics

If the reference is not in the arena, or if it is not a column reference, both of which are bugs in the pass rather than anything a plan can be.

Source

pub fn node_mut(&mut self, reference: NodeRef) -> &mut Node

The node at reference, to be rewritten in place.

§Panics

If the reference is not in the arena.

Source

pub fn validate(&self) -> Result<()>

Checks the plan invariant.

spec/09-optimizer.md section 9.1 says every pass preserves an invariant that is checked in debug builds, and this is that check. It is not a type checker and it does not know what any function returns. What it knows is what this crate can get wrong on its own: an index that points at nothing, an index that points forwards and could therefore be a cycle, a projection with more expressions than names, a ragged VALUES, a filter on something that is not boolean, a one-armed conjunction, and an aggregate somewhere an aggregate cannot be.

Every one of those is a bug that produces a wrong answer or a hang rather than an error, and spec/16-testing.md section 16.9 is specifically about not shipping the first kind.

§Errors

With a message naming the node or expression index that broke the rule, because the useful question about a malformed plan is always which part of it.

§Panics

If a pool has more than u32::MAX entries, which is the same bound every reference in the arena already carries.

Trait Implementations§

Source§

impl Clone for Plan

Source§

fn clone(&self) -> Plan

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Plan

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Default for Plan

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Display for Plan

Source§

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

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Plan

§

impl RefUnwindSafe for Plan

§

impl Send for Plan

§

impl Sync for Plan

§

impl Unpin for Plan

§

impl UnsafeUnpin for Plan

§

impl UnwindSafe for Plan

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
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.