Skip to main content

Executor

Trait Executor 

Source
pub trait Executor {
    // Required methods
    fn dialect(&self) -> Dialect;
    async fn fetch_all(
        &self,
        sql: &str,
        params: Vec<Value>,
    ) -> Result<Vec<Box<dyn Row>>, Error>;
    async fn execute(
        &self,
        sql: &str,
        params: Vec<Value>,
    ) -> Result<ExecOutcome, Error>;

    // Provided methods
    fn shard_family(&self) -> Option<&str> { ... }
    fn is_sharded(&self) -> bool { ... }
    fn allocate_id(&self, _shard_key: u64) -> Option<u64> { ... }
    async fn fetch_all_routed(
        &self,
        _route: ShardRoute,
        sql: &str,
        params: Vec<Value>,
    ) -> Result<Vec<Box<dyn Row>>, Error> { ... }
    async fn execute_routed(
        &self,
        _route: ShardRoute,
        sql: &str,
        params: Vec<Value>,
    ) -> Result<ExecOutcome, Error> { ... }
}
Expand description

A database backend. The single integration point: implement this and the generic CRUD layer works against your store unchanged.

async fn in trait (stable since Rust 1.75) keeps this dyn-free and wasm-safe; callers hold a concrete executor and monomorphise.

The trait deliberately does not require Send + Sync. A multi-threaded server’s concrete executors (SeaOrmExecutor, D1Executor<reqwest-transport>) are Send + Sync, so state that holds them is too — the bound is provided by the concrete type, not demanded by the trait. Leaving it off lets a single-threaded Cloudflare Worker implement the trait over its !Send native D1 binding, so the exact same generic services run there.

Required Methods§

Source

fn dialect(&self) -> Dialect

The SQL dialect this backend speaks, so callers render matching SQL.

Source

async fn fetch_all( &self, sql: &str, params: Vec<Value>, ) -> Result<Vec<Box<dyn Row>>, Error>

Run a query and return every row. Parameters are bound positionally in the order sea-query emitted them.

Source

async fn execute( &self, sql: &str, params: Vec<Value>, ) -> Result<ExecOutcome, Error>

Run a write and report its ExecOutcome.

Provided Methods§

Source

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

The shard family this connector routes within, or None for a single, unsharded database.

This is the explicit “am I sharded, and as what?” marker: a Some(name) connector uses sharded reasoning (ids are shard-encoded; operations route within the named family), while None is a plain one-database connector. Callers and migrations can branch on it without knowing the concrete executor — and an entity’s shard_columns should match the connector it runs on. Defaults to None.

Source

fn is_sharded(&self) -> bool

true when this connector is sharded — sugar for shard_family().is_some().

Source

fn allocate_id(&self, _shard_key: u64) -> Option<u64>

Mint a shard-encoded primary key for a row whose shard-key value is shard_key (e.g. the owning user_id). repo::insert calls this when an entity’s primary key is itself a shard key, is not auto-increment, and is unset — so id assignment for the sharded data tier happens here, in the connector, transparently, not in the service. The default is None (no allocation: the caller’s id or the DB’s auto-increment stands) so single, unsharded executors are unaffected.

Source

async fn fetch_all_routed( &self, _route: ShardRoute, sql: &str, params: Vec<Value>, ) -> Result<Vec<Box<dyn Row>>, Error>

Run a query against the physical database the ShardRoute selects.

This is the sharding transparency seam. The repo/query layer always calls the routed variants; a single-database executor inherits the default below — which ignores the route and runs on its one connection — so it needs no change and sharding stays invisible above. A sharding executor overrides this to dispatch to the right shard.

Source

async fn execute_routed( &self, _route: ShardRoute, sql: &str, params: Vec<Value>, ) -> Result<ExecOutcome, Error>

Routed counterpart of execute. Defaults to ignoring the route — see fetch_all_routed.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§

Source§

impl Executor for Database

Implementing Executor is what keeps Rainier ORM’s whole surface available.

repo::insert, repo::query::<E>(), Cursor and Migrator::run are all generic over X: Executor, so they accept a Database directly. Their futures are !Send (see the module docs), so use them from a console command, a migration, or a Worker — not from a request handler, which needs the Send path above.

Source§

impl<C, L> Executor for ShardedExecutor<C, L>