Skip to main content

Ast

Struct Ast 

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

The arena every node of one parse lives in.

Implementations§

Source§

impl Ast

Source

pub fn new() -> Ast

Returns an empty arena.

Source

pub fn clear(&mut self)

Empties the arena, keeping the memory it has already taken.

So that a second statement costs no allocations. Every one of these vectors is empty at Ast::new and grows on its first push, so parsing SELECT 1 takes half a dozen trips to the allocator - about 270 ns of a 1,337 ns prepare on this platform’s CRT heap. A parser handed a cleared arena pushes into capacity that is already there.

It is a clear rather than a new for exactly that reason, and the names are cleared with everything else: intern returns an existing id for equal text, so a name left behind from the previous statement would be a live id in the next one’s arena.

The names keep their byte buffers even though the names go (task-2039). Clearing names drops every Name, and a Name owns two Vec<u8> - so the vector’s capacity survived a clear and the two allocations behind each entry in it did not, and a connection re-compiling one statement went back to the allocator twice per distinct name for ever. The buffers go on spare instead and intern fills them again. [SPARE_NAME_BUFFERS] is what bounds the list.

Source

pub fn charged_bytes(&self) -> usize

Returns the number of arena bytes charged so far.

This is what the max_ast_bytes limit is charged against. It counts the node structures rather than the source, because the source is borrowed.

Source

pub fn intern(&mut self, text: Vec<u8>, quote: QuoteForm, span: Span) -> NameId

Interns an identifier, returning the id of an equal existing entry when there is one.

A map rather than a scan (task-1932, H8). This walked every name interned so far and compared three fields against each, so a statement naming N distinct identifiers cost N-squared comparisons - and the SqlLength default is 1 GiB, which leaves room for hundreds of thousands of them. The key is exactly what the scan compared, so the answer is the same one and only the cost changed.

The count is charged against Limit::Column for the same reason the depth is charged below: a bound that exists in compat/limits.toml and is enforced nowhere is not a bound. It is generous - a name is a column, a table, an alias, a function or a collation, so one statement legitimately interns more names than any one table has columns - and it is a ceiling on an arena that has to fit in memory rather than a statement about the schema.

Source

pub fn intern_bytes( &mut self, text: &[u8], quote: QuoteForm, span: Span, ) -> NameId

Interns an identifier the caller does not own, returning the id of an equal existing entry when there is one.

The entry point that allocates nothing on a hit (task-2039). The owned form above had to exist before the lookup could happen, so the parser called identifier_text(..).into_owned() on every identifier token whether or not the name was already interned - and intern then folded a copy and cloned the key, four allocations for a name the arena already held. This hashes the bytes where the source already has them.

A miss allocates what it stores and nothing else: the spelling and the folded key, each taken from spare when a previous parse left one there.

@param text - the identifier as written, with quoting already undone @param quote - how it was quoted, which decides whether it may become a string @param span - where this occurrence came from

Source

pub fn name_count(&self) -> usize

Returns how many distinct identifiers have been interned.

Source

pub fn max_expr_depth(&self) -> u32

Returns the depth of the deepest expression tree in the arena.

What Limit::ExprDepth is charged against. See expr_depths.

Source

pub fn expr_depth(&self, id: ExprId) -> u32

Returns how deep one expression’s own subtree is.

@param id - the node

Source

pub fn name(&self, id: NameId) -> Option<&Name>

Returns an interned name.

Source

pub fn folded(&self, id: NameId) -> &[u8] ⓘ

Returns the folded key of an interned name, or an empty slice.

Source

pub fn text(&self, id: NameId) -> &[u8] ⓘ

Returns the written spelling of an interned name, or an empty slice.

Source

pub fn add_expr(&mut self, expr: Expr, span: Span) -> ExprId

Adds an expression node.

Source

pub fn expr(&self, id: ExprId) -> Option<&Expr>

Returns an expression node.

Source

pub fn expr_span(&self, id: ExprId) -> Span

Returns the span an expression was parsed from.

Source

pub fn expr_count(&self) -> usize

Returns the number of expression nodes in the arena.

Source

pub fn add_select(&mut self, select: Select) -> SelectId

Adds a compound SELECT.

Source

pub fn select(&self, id: SelectId) -> Option<&Select>

Returns a compound SELECT.

Source

pub fn add_core(&mut self, core: SelectCore) -> SelectCoreId

Adds one arm of a compound SELECT.

Source

pub fn core(&self, id: SelectCoreId) -> Option<&SelectCore>

Returns one arm of a compound SELECT.

Source

pub fn add_from_term(&mut self, term: FromTerm) -> FromTermId

Adds a FROM term.

Source

pub fn from_term(&self, id: FromTermId) -> Option<&FromTerm>

Returns a FROM term.

Source

pub fn from_term_mut(&mut self, id: FromTermId) -> Option<&mut FromTerm>

Returns a FROM term for modification.

A join’s ON or USING clause follows the table it constrains, so the term is stored first and its constraint attached once the parser has read it. Building the term out of order instead would mean holding a half-built node across a recursive parse.

Source

pub fn add_window(&mut self, window: Window) -> WindowId

Adds a window definition.

Source

pub fn window(&self, id: WindowId) -> Option<&Window>

Returns a window definition.

Trait Implementations§

Source§

impl Clone for Ast

Source§

fn clone(&self) -> Self

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 Ast

Source§

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

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

impl Default for Ast

Source§

fn default() -> Self

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

impl Eq for Ast

Source§

impl PartialEq for Ast

Two arenas are equal when they hold the same nodes.

Hand-written rather than derived, because interned and spare are not content (task-2039). interned is an index over names keyed by a hash the arena seeds for itself, so two arenas parsed from the same text hold the same names under different keys; spare is buffers the allocator has not been given back yet, which the next parse may or may not use. Comparing either would report two identical parses as different. The fields are destructured by name and none is skipped with .., so a field added later fails to compile here rather than being silently left out of equality.

Source§

fn eq(&self, other: &Ast) -> bool

@param other - the arena to compare against

1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more

Auto Trait Implementations§

§

impl Freeze for Ast

§

impl RefUnwindSafe for Ast

§

impl Send for Ast

§

impl Sync for Ast

§

impl Unpin for Ast

§

impl UnsafeUnpin for Ast

§

impl UnwindSafe for Ast

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, 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.