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>>>;
    async fn execute(
        &self,
        sql: &str,
        params: Vec<Value>,
    ) -> Result<ExecOutcome>;

    // 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>>> { ... }
    async fn execute_routed(
        &self,
        _route: ShardRoute,
        sql: &str,
        params: Vec<Value>,
    ) -> Result<ExecOutcome> { ... }
}
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>>>

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>

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

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>

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§