Skip to main content

EmbedPlan

Struct EmbedPlan 

Source
pub struct EmbedPlan {
    pub local_column: String,
    pub foreign_column: String,
    pub foreign_column_type: String,
    pub foreign_schema: String,
    pub foreign_table: String,
    pub is_list: bool,
    pub columns: Vec<(String, String)>,
    pub junction: Option<EmbedJunction>,
    pub function: Option<QualifiedIdentifier>,
    pub row_argument: Option<String>,
}
Expand description

Everything needed to fetch one relationship’s rows for a set of parents.

Fields§

§local_column: String

Column on the parent row whose value identifies the parent.

§foreign_column: String

Column on the related table that points back at the parent.

§foreign_column_type: String

PostgreSQL type of the foreign column, used to cast the bound array.

§foreign_schema: String

Schema of the related table.

§foreign_table: String

Name of the related table.

§is_list: bool

Whether the relationship yields many rows per parent.

§columns: Vec<(String, String)>

Every column pair the join is on, parent side first.

Usually one. A foreign key over several columns joins on all of them, and the pairs are ordered so each parent column sits with the child column it actually references.

§junction: Option<EmbedJunction>

The junction of a many-to-many relationship, if that is what this is.

The parent and the child share no key; each points at a table that exists to join them, so reaching the child means going through it.

§function: Option<QualifiedIdentifier>

The function behind a computed relationship, if that is what this is.

A computed relationship is a function taking the parent row and returning rows of the related table. There is no key to join on – the parent row is the argument – so the columns above are empty and the relationship can only be expressed as a call correlated to the parent.

§row_argument: Option<String>

The name of the parameter that takes the parent’s row, where the function has more than one and the call has to be written by name.

Implementations§

Source§

impl EmbedPlan

Source

pub fn resolve( relationship: &Relationship, schema_cache: &SchemaCache, ) -> Result<Self>

Resolve a relationship into an embed plan.

Returns an error for relationships this cannot express yet, rather than silently omitting the embedded data.

Source

pub fn children_sql( &self, limit: Option<i64>, columns: &[String], ) -> Result<String>

SQL that fetches every related row for the given parent key values.

The keys are bound as a single text array and cast to the foreign column’s type, so the column itself is never wrapped in a cast and an index on it remains usable. limit bounds the rows per query, not per parent.

columns is the set of columns the client asked for. An empty set means every column. Projecting here rather than discarding columns after the fact matters: an unprojected column is read from the heap, serialised to JSON by PostgreSQL, sent over the socket and parsed, before being thrown away. The join column is always included even when it was not requested, because grouping needs it; the caller strips it afterwards.

Source

pub fn children_grouped_sql( &self, limit: Option<i64>, columns: &[String], ) -> Result<String>

SQL that fetches related rows already grouped by their join key.

One row comes back per distinct key: the key itself and a JSON array of that key’s children. Grouping in PostgreSQL rather than in this process removes a per-child-row JSON parse, the per-row hash insert, and the clone of each group onto its parent.

The key is returned as JSON rather than cast to text, so it is rendered by the same code that renders the parents’ keys. Casting to text in SQL would agree for integers and uuids and disagree for a NUMERIC join column, where PostgreSQL and serde_json format differently.

limit still bounds the rows scanned, not the rows per parent, so it is applied to the inner select exactly as the ungrouped form does.

Source

pub fn correlated_rows( &self, parent_alias: &str, parent_row: &str, child_alias: &str, inner_select: &str, limit: Option<i64>, offset: i64, child_where: Option<&str>, order_by: Option<&str>, function_arguments: Option<&str>, ) -> Result<String>

The child rows belonging to one parent row, as a SELECT correlated against the parent’s alias.

This is the single-query form of embedding: instead of fetching parents, collecting their keys and issuing a second query, the relationship is attached to the parent query as an expression, so PostgreSQL builds the array while it already has the parent row.

inner_select is the child’s SELECT list, which the caller assembles – its columns, plus any deeper relationship expressions built by calling this again. Only the caller knows the shape of its own selection tree, so the recursion lives there and the SQL assembly lives here.

What is done with those rows is the caller’s: [embed_expression] renders them as JSON, [aggregate_expression] summarises them.

Source

pub fn embed_expression( &self, parent_alias: &str, parent_row: &str, child_alias: &str, inner_select: &str, limit: Option<i64>, offset: i64, child_where: Option<&str>, order_by: Option<&str>, function_arguments: Option<&str>, rendering: EmbedRendering, ) -> Result<String>

A correlated subselect that yields this relationship as one JSON column.

The rows come from [correlated_rows]; this decides how they are rendered – an array for a to-many relationship, one object or null for a to-one.

Source

pub fn aggregate_expression( &self, parent_alias: &str, parent_row: &str, child_alias: &str, aggregate_select: &str, limit: Option<i64>, offset: i64, child_where: Option<&str>, order_by: Option<&str>, function_arguments: Option<&str>, distinct_on: &str, rendering: EmbedRendering, ) -> Result<String>

A correlated subselect that summarises this relationship as one JSON column.

author { articles_aggregate { aggregate { count } } }. The rows are the same correlated set an embed would render, but a limit here bounds what is counted rather than what is returned – so the aggregate reads from the rows as a subquery instead of selecting over them directly. The subquery carries the child’s own alias, so a predicate or an ordering written against it goes on reading the same name.

Parent columns are deliberately left alone: they stay ordinary typed columns and are converted to JSON by the same code as an unembedded request, so embedding does not change how a NUMERIC or a timestamp is rendered.

Source

pub fn order_expression( &self, parent_alias: &str, parent_row: &str, child_alias: &str, column_sql: &str, ) -> String

A scalar subselect yielding one column of the related row.

This is what order=clients(name) orders by: the parent has no such column, so the value is fetched per parent row exactly as the embed itself is. A to-many relationship has no single value to order by, so the first row wins – which is what LIMIT 1 says and what PostgREST does.

Source

pub fn inner_join_predicate( &self, parent_alias: &str, parent_row: &str, child_alias: &str, child_where: Option<&str>, ) -> String

An EXISTS predicate restricting parents to those with a matching child.

This is what !inner means. The embed expression on its own only decides what the relationship column contains; without this the parent row survives even when the relationship matched nothing, which is a left join. child_where should be the same predicate given to Self::embed_expression – placeholders may be referenced from both places, so no parameter needs binding twice.

Trait Implementations§

Source§

impl Clone for EmbedPlan

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 EmbedPlan

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> 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> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> MaybeSend for T
where T: Send + ?Sized,

Source§

impl<T> MaybeSync for T
where T: Sync + ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
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.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more