pub trait TableShell:
Send
+ Sync
+ 'static {
Show 39 methods
// Required methods
fn columns(&self) -> &IndexMap<String, Column>;
fn references(&self) -> &IndexMap<String, Reference>;
fn id_column(&self) -> Option<&str>;
fn list_vista_values<'life0, 'life1, 'async_trait>(
&'life0 self,
vista: &'life1 Vista,
) -> Pin<Box<dyn Future<Output = Result<IndexMap<String, Record<CborValue>>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn get_vista_value<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
vista: &'life1 Vista,
id: &'life2 String,
) -> Pin<Box<dyn Future<Output = Result<Option<Record<CborValue>>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn get_vista_some_value<'life0, 'life1, 'async_trait>(
&'life0 self,
vista: &'life1 Vista,
) -> Pin<Box<dyn Future<Output = Result<Option<(String, Record<CborValue>)>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn capabilities(&self) -> &VistaCapabilities;
// Provided methods
fn get_vista_value_with_row<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
vista: &'life1 Vista,
id: &'life2 String,
_row: &'life3 Record<CborValue>,
) -> Pin<Box<dyn Future<Output = Result<Option<Record<CborValue>>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait { ... }
fn stream_vista_values<'a>(
&'a self,
vista: &'a Vista,
) -> Pin<Box<dyn Stream<Item = Result<(String, Record<CborValue>)>> + Send + 'a>>
where Self: Sync { ... }
fn insert_vista_value<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_id: &'life2 String,
_record: &'life3 Record<CborValue>,
) -> Pin<Box<dyn Future<Output = Result<Record<CborValue>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait { ... }
fn replace_vista_value<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_id: &'life2 String,
_record: &'life3 Record<CborValue>,
) -> Pin<Box<dyn Future<Output = Result<Record<CborValue>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait { ... }
fn patch_vista_value<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_id: &'life2 String,
_partial: &'life3 Record<CborValue>,
) -> Pin<Box<dyn Future<Output = Result<Record<CborValue>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait { ... }
fn delete_vista_value<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_id: &'life2 String,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn delete_vista_all_values<'life0, 'life1, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn insert_vista_return_id_value<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_record: &'life2 Record<CborValue>,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
fn get_vista_count<'life0, 'life1, 'async_trait>(
&'life0 self,
vista: &'life1 Vista,
) -> Pin<Box<dyn Future<Output = Result<i64>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn aggregate_vista(
&self,
_vista: &Vista,
_spec: &AggregateSpec,
) -> Result<Option<Vista>> { ... }
fn add_eq_condition(
&mut self,
_field: &str,
_value: &CborValue,
) -> Result<()> { ... }
fn add_op_condition(
&mut self,
field: &str,
op: FilterOp,
value: &CborValue,
) -> Result<()> { ... }
fn add_raw_condition(
&mut self,
_condition: Box<dyn Any + Send + Sync>,
) -> Result<()> { ... }
fn set_page_size(&mut self, _size: usize) -> Result<()> { ... }
fn fetch_page<'life0, 'life1, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_page: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<(String, Record<CborValue>)>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn fetch_next<'life0, 'life1, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_token: Option<CborValue>,
) -> Pin<Box<dyn Future<Output = Result<(Vec<(String, Record<CborValue>)>, Option<CborValue>)>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn fetch_window<'life0, 'life1, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_offset: usize,
_limit: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<(String, Record<CborValue>)>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn fetch_window_counted<'life0, 'life1, 'async_trait>(
&'life0 self,
vista: &'life1 Vista,
offset: usize,
limit: usize,
) -> Pin<Box<dyn Future<Output = Result<(Vec<(String, Record<CborValue>)>, Option<i64>)>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn add_search(&mut self, _text: &str) -> Result<()> { ... }
fn clear_search(&mut self) -> Result<()> { ... }
fn add_order(&mut self, _field: &str, _dir: SortDirection) -> Result<()> { ... }
fn clear_orders(&mut self) -> Result<()> { ... }
fn clone_shell(&self) -> Option<Box<dyn TableShell>> { ... }
fn get_ref(&self, relation: &str, _row: &Record<CborValue>) -> Result<Vista> { ... }
fn get_ref_target(&self, relation: &str) -> Result<Vista> { ... }
fn contained(&self) -> &IndexMap<String, ContainedSpec> { ... }
fn get_contained_ref(
&self,
relation: &str,
_row: &Record<CborValue>,
) -> Result<Vista> { ... }
fn get_ref_kinds(&self) -> Vec<(String, ReferenceKind)> { ... }
fn driver_name(&self) -> &'static str { ... }
fn watch_vista<'life0, 'life1, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
) -> Pin<Box<dyn Future<Output = Result<VistaChangeStream>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn capability_flag(&self, name: &str) -> bool { ... }
fn default_error(&self, method: &str, capability: &str) -> VantageError { ... }
}Expand description
Per-driver executor for a Vista.
Implementations live in driver crates (vantage-sqlite, vantage-mongodb,
vantage-aws, etc.). Each method receives &Vista so the driver can read
the current condition state, columns, and other metadata.
Id = String and Value = ciborium::Value at this boundary, so every
driver’s native id (Mongo ObjectId, Surreal Thing, …) stringifies
here. Methods are named with the _vista_ infix to mirror
TableSource’s _table_ convention; Vista’s ValueSet impls
delegate by stripping the infix.
id: &String (rather than &str) is intentional: the upstream
vantage_dataset::ValueSet trait family fixes Id = String and uses
&Self::Id in its signatures, so impls receive &String and forward
it through unchanged.
Required Methods§
fn columns(&self) -> &IndexMap<String, Column>
fn references(&self) -> &IndexMap<String, Reference>
fn id_column(&self) -> Option<&str>
fn list_vista_values<'life0, 'life1, 'async_trait>(
&'life0 self,
vista: &'life1 Vista,
) -> Pin<Box<dyn Future<Output = Result<IndexMap<String, Record<CborValue>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_vista_value<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
vista: &'life1 Vista,
id: &'life2 String,
) -> Pin<Box<dyn Future<Output = Result<Option<Record<CborValue>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn get_vista_some_value<'life0, 'life1, 'async_trait>(
&'life0 self,
vista: &'life1 Vista,
) -> Pin<Box<dyn Future<Output = Result<Option<(String, Record<CborValue>)>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn capabilities(&self) -> &VistaCapabilities
Provided Methods§
Sourcefn get_vista_value_with_row<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
vista: &'life1 Vista,
id: &'life2 String,
_row: &'life3 Record<CborValue>,
) -> Pin<Box<dyn Future<Output = Result<Option<Record<CborValue>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn get_vista_value_with_row<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
vista: &'life1 Vista,
id: &'life2 String,
_row: &'life3 Record<CborValue>,
) -> Pin<Box<dyn Future<Output = Result<Option<Record<CborValue>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Fetch one record by id, with the caller’s existing (cheap) record
available to drivers that can use it (e.g. a cmd detail script reading
list-pass columns). The default ignores row and delegates to
get_vista_value; only drivers that benefit
override it.
Sourcefn stream_vista_values<'a>(
&'a self,
vista: &'a Vista,
) -> Pin<Box<dyn Stream<Item = Result<(String, Record<CborValue>)>> + Send + 'a>>where
Self: Sync,
fn stream_vista_values<'a>(
&'a self,
vista: &'a Vista,
) -> Pin<Box<dyn Stream<Item = Result<(String, Record<CborValue>)>> + Send + 'a>>where
Self: Sync,
Default implementation wraps list_vista_values. Drivers with native
streaming (cursor-based queries, paginated REST APIs) override.
fn insert_vista_value<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_id: &'life2 String,
_record: &'life3 Record<CborValue>,
) -> Pin<Box<dyn Future<Output = Result<Record<CborValue>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn replace_vista_value<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_id: &'life2 String,
_record: &'life3 Record<CborValue>,
) -> Pin<Box<dyn Future<Output = Result<Record<CborValue>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn patch_vista_value<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_id: &'life2 String,
_partial: &'life3 Record<CborValue>,
) -> Pin<Box<dyn Future<Output = Result<Record<CborValue>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn delete_vista_value<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_id: &'life2 String,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn delete_vista_all_values<'life0, 'life1, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
) -> Pin<Box<dyn Future<Output = Result<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn insert_vista_return_id_value<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_record: &'life2 Record<CborValue>,
) -> Pin<Box<dyn Future<Output = Result<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Sourcefn get_vista_count<'life0, 'life1, 'async_trait>(
&'life0 self,
vista: &'life1 Vista,
) -> Pin<Box<dyn Future<Output = Result<i64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_vista_count<'life0, 'life1, 'async_trait>(
&'life0 self,
vista: &'life1 Vista,
) -> Pin<Box<dyn Future<Output = Result<i64>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Default impl falls back to list_vista_values — drivers with native
count (SELECT COUNT(*), etc.) override.
Sourcefn aggregate_vista(
&self,
_vista: &Vista,
_spec: &AggregateSpec,
) -> Result<Option<Vista>>
fn aggregate_vista( &self, _vista: &Vista, _spec: &AggregateSpec, ) -> Result<Option<Vista>>
Derive a new vista that reduces this one — the driver’s equivalent of selecting from a subquery.
An aggregation is not a value, it is a different set: count(*) yields
one row, GROUP BY yields one per group, and either can then be
conditioned, ordered or counted like any other set. Returning a
Vista is what lets every consumer keep the single shape it already
handles instead of growing a scalar special case.
Ok(None) means this driver cannot answer this request — not that
the result is empty. The caller then reduces locally, which is a
different question (the rows it holds, not every row that matches) with
a different answer, so “can’t” must never collapse into a number.
Narrow before aggregating. Conditions belong to the source, applied
with add_eq_condition before this call — the order SQL uses, where the
filter is the inner query and the aggregate selects from its result.
Narrowing reports its own failure, so a driver is never handed a filter
it would silently ignore.
The returned vista’s capabilities describe the DERIVED set, not the
source. In particular it must not advertise condition support unless
the driver really implements it: adding a condition to an aggregate is
HAVING, a different operation over different values, and inheriting
the source’s flag would promise a filter that silently does nothing.
An aggregator holding its entire output in memory is the exception —
it can filter what it produced, and may say so.
This is construction, not a query — nothing is fetched until someone lists the returned vista.
Sourcefn add_eq_condition(&mut self, _field: &str, _value: &CborValue) -> Result<()>
fn add_eq_condition(&mut self, _field: &str, _value: &CborValue) -> Result<()>
Translate field == value into the driver’s native condition type and
apply it to the wrapped table. The default impl returns Unimplemented
— every driver is expected to override.
value is the universal CBOR carrier; the driver picks the appropriate
translation (e.g. cbor_to_bson for Mongo, cbor → AnyCsvType for CSV).
Sourcefn add_op_condition(
&mut self,
field: &str,
op: FilterOp,
value: &CborValue,
) -> Result<()>
fn add_op_condition( &mut self, field: &str, op: FilterOp, value: &CborValue, ) -> Result<()>
Translate field <op> value into the driver’s native condition and
apply it. The default routes Eq to add_eq_condition
(so every driver gets equality for free) and returns Unimplemented
for every richer operator. Drivers whose query language expresses the
operators (SQL, SurrealDB) override this and advertise
can_filter_operators;
consumers that see false skip the call and filter locally instead.
Sourcefn add_raw_condition(
&mut self,
_condition: Box<dyn Any + Send + Sync>,
) -> Result<()>
fn add_raw_condition( &mut self, _condition: Box<dyn Any + Send + Sync>, ) -> Result<()>
Push a driver-native condition into the wrapped table. The
caller boxes the condition as dyn Any and the driver
downcasts to its own T::Condition. Used by YAML-driven
relation traversal, where the factory constructs a
DeferredFn-bearing condition outside the value-set surface
(which only accepts scalar eq) and pushes it through this
channel. Default is Unimplemented.
Sourcefn set_page_size(&mut self, _size: usize) -> Result<()>
fn set_page_size(&mut self, _size: usize) -> Result<()>
Declare how many records constitute one page. Used by both
fetch_page and fetch_next.
Default returns default_error("set_page_size", "can_set_page_size").
Sourcefn fetch_page<'life0, 'life1, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_page: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<(String, Record<CborValue>)>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn fetch_page<'life0, 'life1, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_page: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<(String, Record<CborValue>)>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Fetch a specific page (1-based) using offset-style pagination. The
per-page count comes from the most recent
set_page_size.
Drivers without random-access pagination (DynamoDB, most token-paginated
REST APIs) leave the default in place, which produces Unsupported.
Callers should branch on vista.capabilities().can_fetch_page first.
Sourcefn fetch_next<'life0, 'life1, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_token: Option<CborValue>,
) -> Pin<Box<dyn Future<Output = Result<(Vec<(String, Record<CborValue>)>, Option<CborValue>)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn fetch_next<'life0, 'life1, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_token: Option<CborValue>,
) -> Pin<Box<dyn Future<Output = Result<(Vec<(String, Record<CborValue>)>, Option<CborValue>)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Cursor-style chain fetch. Pass None on the first call; pass the
previous call’s returned token on subsequent calls. Returned token is
None when the result set is exhausted.
The token is driver-private — its shape is whatever the backend
finds convenient (DynamoDB LastEvaluatedKey as a CBOR map, REST
nextToken as CborValue::Text, offset-based as CborValue::Integer).
Consumers treat it as opaque and round-trip it back unchanged.
Default returns default_error("fetch_next", "can_fetch_next").
Sourcefn fetch_window<'life0, 'life1, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_offset: usize,
_limit: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<(String, Record<CborValue>)>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn fetch_window<'life0, 'life1, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
_offset: usize,
_limit: usize,
) -> Pin<Box<dyn Future<Output = Result<Vec<(String, Record<CborValue>)>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Fetch the half-open row window [offset, offset + limit) in the
source’s natural order. Offset-style like fetch_page
but addressed by absolute row index rather than page number, so it
maps directly onto a diorama on_load_chunk Range<usize> — which
is not guaranteed page-aligned. This is the primitive a paged,
lazily-loaded grid drives on scroll.
Drivers leave the default in place (producing Unsupported) until
they implement it; callers branch on
vista.capabilities().can_fetch_window first. Default returns
default_error("fetch_window", "can_fetch_window").
Sourcefn fetch_window_counted<'life0, 'life1, 'async_trait>(
&'life0 self,
vista: &'life1 Vista,
offset: usize,
limit: usize,
) -> Pin<Box<dyn Future<Output = Result<(Vec<(String, Record<CborValue>)>, Option<i64>)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn fetch_window_counted<'life0, 'life1, 'async_trait>(
&'life0 self,
vista: &'life1 Vista,
offset: usize,
limit: usize,
) -> Pin<Box<dyn Future<Output = Result<(Vec<(String, Record<CborValue>)>, Option<i64>)>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fetch_window, plus the grand total of matching
rows when this fetch already learned it.
Paged sources typically report the total in every response envelope, alongside the window’s rows. A caller needing both — a lazily-loaded grid sizing its scrollbar — would otherwise pay a second round trip for a number the first reply already carried.
Drivers that can answer override this. The default delegates and
reports None, so no existing driver changes and no caller is told a
total exists when it doesn’t. None means “this fetch didn’t say”,
never “zero”.
Sourcefn add_search(&mut self, _text: &str) -> Result<()>
fn add_search(&mut self, _text: &str) -> Result<()>
Apply a quicksearch filter — a single string the driver fans out across
the columns it considers searchable (typically those flagged
SEARCHABLE, but each driver decides).
Replace semantics: calling add_search again wipes the previous
search filter before applying the new one. Default produces
Unimplemented (when can_search: true) or Unsupported (when
can_search: false).
Sourcefn clear_search(&mut self) -> Result<()>
fn clear_search(&mut self) -> Result<()>
Drop the search filter previously applied via
add_search. Default mirrors add_search.
Sourcefn add_order(&mut self, _field: &str, _dir: SortDirection) -> Result<()>
fn add_order(&mut self, _field: &str, _dir: SortDirection) -> Result<()>
Push a single ORDER BY clause onto the wrapped table.
Vista’s add_order is replace-semantics: the driver shell should clear
any previously-set order before pushing the new one. Default produces
Unimplemented (when can_order: true) or Unsupported (when
can_order: false).
Sourcefn clear_orders(&mut self) -> Result<()>
fn clear_orders(&mut self) -> Result<()>
Wipe every order clause. Default mirrors add_order.
Sourcefn clone_shell(&self) -> Option<Box<dyn TableShell>>
fn clone_shell(&self) -> Option<Box<dyn TableShell>>
Produce an independent copy of this shell, or None if the driver can’t
be cloned cheaply. The copy must share the backing store / connection
(typically Arc) but own its own query state (conditions / order /
search) so a caller can narrow it — set an ORDER BY, add a WHERE — without
disturbing the original. This is how a consumer builds a per-view ordered
Vista to fetch from: clone_shell() → add_order(...) → fetch_window.
Default None: drivers opt in only where a clone is genuinely cheap
(query state is small; the store is Arc-shared). Callers that get None
fall back to reading the shared shell and ordering client-side.
Sourcefn get_ref(&self, relation: &str, _row: &Record<CborValue>) -> Result<Vista>
fn get_ref(&self, relation: &str, _row: &Record<CborValue>) -> Result<Vista>
Resolve a same-persistence relation using a known source row, returning
the related table as a new Vista.
Drivers override by forwarding into the wrapped typed Table’s
get_ref_from_row::<EmptyEntity>(relation, &native_row) and then
wrapping the result back as a Vista through the driver’s factory.
The default returns Unimplemented. Cross-persistence refs are
handled one layer up by vantage-vista-factory’s VistaCatalog,
never here.
Sourcefn get_ref_target(&self, relation: &str) -> Result<Vista>
fn get_ref_target(&self, relation: &str) -> Result<Vista>
Build the bare target of a same-persistence relation as a Vista —
the table a new related row would be inserted into, with no join
condition applied. Used by Vista’s nested insert to reach a has-one /
has-many child’s destination.
Drivers override by forwarding into the wrapped typed Table’s
get_ref_target::<EmptyEntity>(relation) and wrapping the result back
through the driver’s factory — the same path as get_ref
minus the row-derived condition. The default returns Unimplemented;
cross-persistence relations are rejected at the Vista layer before
this is reached.
Sourcefn contained(&self) -> &IndexMap<String, ContainedSpec>
fn contained(&self) -> &IndexMap<String, ContainedSpec>
Contained (embedded-in-row) relations this shell exposes, keyed by name. Default empty — only shells that model embedded objects/arrays override.
Sourcefn get_contained_ref(
&self,
relation: &str,
_row: &Record<CborValue>,
) -> Result<Vista>
fn get_contained_ref( &self, relation: &str, _row: &Record<CborValue>, ) -> Result<Vista>
Resolve a contained relation against a known parent row, returning the
embedded records as a sub-Vista. Writes to that sub-Vista patch the
host column of row’s record back through the shell. Default returns
Unimplemented; shells override to seed crate::build_contained_vista
with a writeback that patches the parent.
Sourcefn get_ref_kinds(&self) -> Vec<(String, ReferenceKind)>
fn get_ref_kinds(&self) -> Vec<(String, ReferenceKind)>
Names + cardinalities of the shell’s same-persistence references.
Derived from references by default; impls
should rarely need to override.
Sourcefn driver_name(&self) -> &'static str
fn driver_name(&self) -> &'static str
Short human label for the underlying driver (e.g. "csv", "sqlite",
"postgres", "mongodb"). Used for diagnostics and CLI output.
Drivers should override; the default is a placeholder.
Sourcefn watch_vista<'life0, 'life1, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
) -> Pin<Box<dyn Future<Output = Result<VistaChangeStream>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn watch_vista<'life0, 'life1, 'async_trait>(
&'life0 self,
_vista: &'life1 Vista,
) -> Pin<Box<dyn Future<Output = Result<VistaChangeStream>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Subscribe to changes on the set and stream them as VistaChanges.
Drivers whose backend can push changes (SurrealDB LIVE, Postgres
LISTEN/NOTIFY) override this and advertise
can_subscribe. The row-bearing
variants carry the record in the same projected shape as
list_vista_values, so a consumer can apply
them to a cache directly; VistaChange::Invalidated carries nothing at
all and means “re-read the set”. The default produces Unimplemented (when
can_subscribe: true) or Unsupported (when false); callers branch on
vista.capabilities().can_subscribe first.
§The subscription contract
Callers always pass the full vista, and drivers deliver on a best-effort
basis. A consumer must not need to know whether a given backend filters
row-, select- or table-wide — that is what keeps consumer code identical
across drivers, and lets a driver tighten its scope later without
breaking anyone. Four promises hold for every implementation:
- The stream may be coarser than the vista. Subscribing table-wide
and letting the consumer discard what it doesn’t want is a valid
implementation;
vistais a hint about what’s interesting, not a filter the driver is obliged to apply. - Payload rows may fall outside the vista’s conditions, precisely
because of (1). Either the driver reconciles (SurrealDB re-reads each
notified id through the vista’s conditions, so a row that no longer
matches surfaces as
VistaChange::Deleted) or the consumer must. Never assume anInserted/Updatedrow belongs in the set. VistaChange::Invalidatedmeans “re-read everything”. It carries no id and implies nothing about how much changed — a driver with no row payload to offer may emit it for every single write.- Stream end is normal, not an error. Connections drop and sessions expire; consumers resubscribe (with backoff) and reconcile the gap. A driver need not reconnect internally.
Delivery is not guaranteed even while subscribed — see
can_subscribe.
Sourcefn capability_flag(&self, name: &str) -> bool
fn capability_flag(&self, name: &str) -> bool
Look up a capability flag by name. Used by default_error to decide
between Unsupported and Unimplemented. Drivers don’t normally
need to override this.
Sourcefn default_error(&self, method: &str, capability: &str) -> VantageError
fn default_error(&self, method: &str, capability: &str) -> VantageError
Build the standard error returned by default trait method impls.
Picks the kind based on the capability flag: a true flag means the
driver advertised support but didn’t override the method (placeholder
→ Unimplemented); a false flag means the driver honestly doesn’t
claim the op (caller should have checked → Unsupported).
Only the Unimplemented kind traces at error level — it’s a driver
bug. An Unsupported refusal is a legitimate answer to a caller
probing a capability (e.g. an exploratory data script calling
set_page_size on a cache-mode vista): the error value carries the
full message to the caller, so it logs at debug only.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".