Skip to main content

SqlBackend

Trait SqlBackend 

Source
pub trait SqlBackend: Send + Sync {
    // Required method
    fn begin<'life0, 'async_trait>(
        &'life0 self,
    ) -> Pin<Box<dyn Future<Output = Result<Box<dyn SqlTransaction>, SqlError>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait;

    // Provided methods
    fn dialect(&self) -> Dialect { ... }
    fn rls_guc(&self) -> Option<&RlsGuc> { ... }
    fn begin_read_only<'life0, 'async_trait>(
        &'life0 self,
    ) -> Pin<Box<dyn Future<Output = Result<Box<dyn SqlTransaction>, SqlError>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait { ... }
    fn run_script<'life0, 'life1, 'async_trait>(
        &'life0 self,
        _sql: &'life1 str,
    ) -> Pin<Box<dyn Future<Output = Result<(), SqlError>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait { ... }
    fn run_query<'life0, 'life1, 'async_trait>(
        &'life0 self,
        sql: &'life1 str,
    ) -> Pin<Box<dyn Future<Output = Result<SqlRows, SqlError>> + Send + 'async_trait>>
       where Self: 'async_trait,
             'life0: 'async_trait,
             'life1: 'async_trait { ... }
    fn injects_session_context(&self) -> bool { ... }
}
Expand description

A per-site SQL backend (libsql — a local file or a remote sqld namespace).

One instance serves one site. The handler engine calls begin once per invocation that uses SQL and drives the resulting SqlTransaction to a commit (on a successful response) or rollback (on trap/error).

Required Methods§

Source

fn begin<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<Box<dyn SqlTransaction>, SqlError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Open a new read-write transaction. Backends are free to draw the underlying connection from a pool, a fresh embedded connection, or a remote session. Writes always land on the primary.

Provided Methods§

Source

fn dialect(&self) -> Dialect

The SQL dialect this backend speaks — used by the orm compiler for the few dialect-divergent constructs (e.g. JSON extraction). Defaults to SQLite-family (libsql); the Postgres/MySQL backends override it.

Source

fn rls_guc(&self) -> Option<&RlsGuc>

The operator-configured RLS session-GUC names (RlsGuc) this backend carries, or None (the common case). When Some and dialect is Postgres, the handler sql/orm binding sets the host-resolved tenant (own/target/session) per transaction, and the row’s tenant per all write, via render_set_local_guc, so an app’s RLS mirrors the injected predicate. The guest can never set these itself (reject_reserved_session_writes blocks the configured names).

Source

fn begin_read_only<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = Result<Box<dyn SqlTransaction>, SqlError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Open a transaction for a read-only invocation, which a backend configured with a read replica may route to that replica (separate read vs write endpoint: reads → replicas, writes → primary). A replica may lag the primary, so such reads are eventually consistent; issuing a write on this transaction is a caller error (it hits the read endpoint, which a replica rejects).

The default has no replica and simply opens a normal transaction, so single-node and replica-less deployments behave identically.

Source

fn run_script<'life0, 'life1, 'async_trait>( &'life0 self, _sql: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<(), SqlError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Run a multi-statement SQL script as one unit (the simple-query protocol), for operator migrations: CREATE EXTENSION and long chains of DDL/DML that the parameterized per-statement path can’t express. Only the external Postgres/MySQL backends implement it (the per-site libsql backend rejects it); it is an operator tool, not a guest capability.

Source

fn run_query<'life0, 'life1, 'async_trait>( &'life0 self, sql: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<SqlRows, SqlError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Run one row-returning statement directly, in its own short-lived read-only transaction — backs the operator sql query. The default composes the existing transaction methods, so every backend supports it.

Source

fn injects_session_context(&self) -> bool

Whether this backend injects a reserved boatramp session context (rls_session — the boatramp.project / boatramp.site GUC on Postgres, or the @boatramp_project / @boatramp_site MySQL session var) that an app’s row-level-security policy keys on. Default false.

When true, the guest sql binding must refuse any guest statement that would set/reset those reserved keys (see reject_reserved_session_writes): otherwise a hostile guest could spoof its injected tenant and defeat the app’s RLS. This is a security signal, not a routing one — see the rls_session doc for the trust model (the real isolation boundary is the per-tenant database + role).

Dyn Compatibility§

This trait is dyn compatible.

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

Implementors§