Skip to main content

TableShell

Trait TableShell 

Source
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§

Source

fn columns(&self) -> &IndexMap<String, Column>

Source

fn references(&self) -> &IndexMap<String, Reference>

Source

fn id_column(&self) -> Option<&str>

Source

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,

Source

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,

Source

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,

Source

fn capabilities(&self) -> &VistaCapabilities

Provided Methods§

Source

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.

Source

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.

Source

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,

Source

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,

Source

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,

Source

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,

Source

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,

Source

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,

Source

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.

Source

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.

Source

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

Source

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.

Source

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.

Source

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").

Source

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.

Source

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").

Source

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").

Source

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

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

Drop the search filter previously applied via add_search. Default mirrors add_search.

Source

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

Source

fn clear_orders(&mut self) -> Result<()>

Wipe every order clause. Default mirrors add_order.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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:

  1. 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; vista is a hint about what’s interesting, not a filter the driver is obliged to apply.
  2. 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 an Inserted/Updated row belongs in the set.
  3. VistaChange::Invalidated means “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.
  4. 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.

Source

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.

Source

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

Implementors§