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§
Sourcefn schema_name(&self) -> &'static str
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.
Sourcefn table_name(&self) -> &'static str
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.
Sourcefn columns(&self) -> &'static [ModelColumn]
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.
Sourcefn primary_key(&self) -> &'static str
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.
Sourcefn allowed_fields(&self) -> &'static [&'static str]
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.
Sourcefn allowed_includes(&self) -> &'static [&'static str]
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”).
Sourcefn allowed_sorts(&self) -> &'static [&'static str]
fn allowed_sorts(&self) -> &'static [&'static str]
Names accepted in orderBy = [ <name>, ... ] payloads.
Sourcefn read_allow_policies(&self) -> &'static [ReadPolicy]
fn read_allow_policies(&self) -> &'static [ReadPolicy]
@@allow("read", ...) policy literals for the list / search
shape (returns one row per matching record).
Sourcefn read_deny_policies(&self) -> &'static [ReadPolicy]
fn read_deny_policies(&self) -> &'static [ReadPolicy]
@@deny("read", ...) policy literals for the list shape.
Sourcefn detail_allow_policies(&self) -> &'static [ReadPolicy]
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.
Sourcefn detail_deny_policies(&self) -> &'static [ReadPolicy]
fn detail_deny_policies(&self) -> &'static [ReadPolicy]
@@deny("read", ...) policy literals for the detail shape.
Sourcefn soft_delete_column(&self) -> Option<&'static str>
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§
Sourcefn select_projection(&self) -> String
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.
Sourcefn select_projection_subset(&self, columns: &[&str]) -> String
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.