Skip to main content

udb/backend/plugins/
sqlite.rs

1//! NW3-2 — SQLite plugin.
2//!
3//! Same shape as the MySQL plugin. The runtime register function
4//! detects `sqlite::memory:` / `:memory:` in the DSN and clamps to
5//! `max_connections = 1` so the in-memory schema and data survive
6//! across operations on a single shared connection — that's what
7//! makes SQLite usable as the long-pending in-memory test profile.
8
9use crate::backend::BackendKind;
10use crate::backend::plugin::{Backend, RegisterCtx};
11
12/// Zero-sized plugin for SQLite.
13#[derive(Debug, Default)]
14pub struct SqlitePlugin;
15
16/// Static instance referenced by `backend::plugins::all()`.
17pub static PLUGIN: SqlitePlugin = SqlitePlugin;
18
19#[async_trait::async_trait]
20impl Backend for SqlitePlugin {
21    fn kind(&self) -> BackendKind {
22        BackendKind::Sqlite
23    }
24
25    async fn register(&self, ctx: &mut RegisterCtx<'_>) {
26        crate::runtime::core::setup_data::register_sqlite(ctx).await;
27    }
28
29    fn generate_artifacts(
30        &self,
31        manifest: &crate::generation::CatalogManifest,
32        sql_config: &crate::generation::sql::SqlGenerationConfig,
33    ) -> Result<Vec<crate::generation::GeneratedArtifact>, String> {
34        crate::generation::backends::generate_sqlite_artifacts(manifest, sql_config)
35            .map_err(|err| err.to_string())
36    }
37}
38
39impl crate::runtime::executors::handle::DispatchFactory for SqlitePlugin {
40    fn build_dispatch_executor(
41        &self,
42        runtime: &crate::runtime::core::DataBrokerRuntime,
43        instance: Option<&str>,
44        _write: bool,
45        context: Option<&crate::broker::RequestContext>,
46    ) -> Result<crate::runtime::executors::handle::DispatchExecutor, tonic::Status> {
47        let instance_name = instance.unwrap_or("primary");
48        let pool = runtime
49            .sqlite_pool_for_instance(instance_name)
50            .ok_or_else(|| {
51                super::dispatch_instance_not_configured_status(
52                    "sqlite",
53                    format!(
54                        "SQLite instance '{instance_name}' is not configured (set UDB_SQLITE_DSN)"
55                    ),
56                )
57            })?
58            .clone();
59        // Thread the request context so generic-dispatch populates the
60        // `_udb_context` table the RLS-style views read. Mirrors the PG plugin.
61        let executor = match context {
62            Some(ctx) => crate::runtime::executors::sqlite::SqliteExecutor::with_context(
63                pool,
64                std::sync::Arc::new(ctx.clone()),
65            ),
66            None => crate::runtime::executors::sqlite::SqliteExecutor::with_pool(pool),
67        };
68        Ok(crate::runtime::executors::handle::DispatchExecutor::Sqlite(
69            executor,
70        ))
71    }
72}