Skip to main content

ReadSource

Trait ReadSource 

Source
pub trait ReadSource<M, PK>: Send + Sync {
Show 14 methods // Required methods fn schema_name(&self) -> &'static str; fn table_name(&self) -> &'static str; fn columns(&self) -> &'static [ModelColumn]; fn primary_key(&self) -> &'static str; fn allowed_fields(&self) -> &'static [&'static str]; fn allowed_includes(&self) -> &'static [&'static str]; fn allowed_sorts(&self) -> &'static [&'static str]; fn read_allow_policies(&self) -> &'static [ReadPolicy]; fn read_deny_policies(&self) -> &'static [ReadPolicy]; fn detail_allow_policies(&self) -> &'static [ReadPolicy]; fn detail_deny_policies(&self) -> &'static [ReadPolicy]; fn soft_delete_column(&self) -> Option<&'static str>; // Provided methods fn select_projection(&self) -> String { ... } fn select_projection_subset(&self, columns: &[&str]) -> String { ... }
}
Expand description

Anything a read-path query builder needs to plan and emit SQL.

M is the Rust struct deserialized from a row; PK is the primary-key Rust type. Both descriptors and the read builders are generic over the same (M, PK) pair so the bounds line up.

Send + Sync are required so that &'static dyn ReadSource<M, PK> is Send. Axum handler futures capture the trait object across await points; without these bounds those futures stop being Send, which makes them unusable as Axum handlers. Both first-party impls (ModelDescriptor, ViewDescriptor) are trivially Send + Sync — every field is either a &'static reference to a primitive slice or a PhantomData<fn() -> _>, all of which are themselves Send + Sync regardless of M / PK.

Required Methods§

Source

fn schema_name(&self) -> &'static str

Logical schema name the model / view lives under. Currently always the dataset schema declared in datasource db { ... }; kept on the trait so future per-source schemas (e.g. analytics views in a dedicated schema) are a non-breaking change.

Source

fn table_name(&self) -> &'static str

SQL identifier of the table or view this source reads from. Both backends quote it verbatim when constructing FROM clauses.

Source

fn columns(&self) -> &'static [ModelColumn]

All projectable columns, ordered as the descriptor declares them. The read builder relies on this order when binding row decoders.

Source

fn primary_key(&self) -> &'static str

SQL column name of the primary key. For views declared with @@no_unique (ADR-0003 §“Schema surface”) this is the empty string — find_unique is not emitted on the delegate so the builder never reads this slot.

Source

fn allowed_fields(&self) -> &'static [&'static str]

Names accepted in where = { <name>: <op> } filter payloads — the same allow-list the model uses for read-policy scoping.

Source

fn allowed_includes(&self) -> &'static [&'static str]

Names accepted in include = { <name>: ... } payloads. Empty on views in v1 (relation-follow off a view is out of scope — see ADR-0003 “Deferred”).

Source

fn allowed_sorts(&self) -> &'static [&'static str]

Names accepted in orderBy = [ <name>, ... ] payloads.

Source

fn read_allow_policies(&self) -> &'static [ReadPolicy]

@@allow("read", ...) policy literals for the list / search shape (returns one row per matching record).

Source

fn read_deny_policies(&self) -> &'static [ReadPolicy]

@@deny("read", ...) policy literals for the list shape.

Source

fn detail_allow_policies(&self) -> &'static [ReadPolicy]

@@allow("read", ...) policy literals for the detail shape (find_unique — returns at most one record). Models can carry stricter detail policies than list ones; views inherit a single set declared via @@allow("read", ...) on the view itself.

Source

fn detail_deny_policies(&self) -> &'static [ReadPolicy]

@@deny("read", ...) policy literals for the detail shape.

Source

fn soft_delete_column(&self) -> Option<&'static str>

Soft-delete sentinel column name. None on views (and on models without @@soft_delete), in which case the read builder skips the <col> IS NULL predicate it would otherwise inject.

Provided Methods§

Source

fn select_projection(&self) -> String

Returns the <col> AS "<alias>", ... projection list the builder splices into SELECT. The default impl delegates to Self::columns so any descriptor that just stores a column list gets a working projection for free.

Source

fn select_projection_subset(&self, columns: &[&str]) -> String

Like Self::select_projection but emits only the named columns. Unknown names are silently dropped — same contract as super::ModelDescriptor::select_projection_subset.

Implementors§

Source§

impl<M, PK> ReadSource<M, PK> for ModelDescriptor<M, PK>

Source§

impl<V, PK> ReadSource<V, PK> for ViewDescriptor<V, PK>