A bit about my app, I have multiple databases (SQLite, PostgreSQL, ...) and I want to create an interactive UI (a simple text box) for users to run raw SQL queries only if they select and start querying a database (create/ reuse a DB connection)
My idea is I want a route to initiate a database connection and another route to check if the connection exists and use it.
The ro_db connection was created successfully but still is None in async fn get_db_connection. Is there any way to solve it or any better approach?
use anyhow::Context;
use axum::extract::{Path, State};
use sqlx::sqlite::SqlitePool;
#[derive(Clone)]
pub(crate) struct ApiContext {
ro_db: Option<SqlitePool>, // Read-only connection use for UI interaction
}
pub(crate) fn router() -> Router<ApiContext> {
Router::new()
.route(
"/api/db_conns/:conn_id",
get(get_db_connection),
)
.route(
"/api/db_conns",
post(create_db_connection),
)
}
async fn create_db_connection(
mut ctx: State<ApiContext>,
Path(download_id): Path<i64>,
) -> Result<()> {
let ro_db = SqlitePool::connect("sqlite:data.db?mode=ro")
.await
.context("could not connect to database_url")?;
ctx.ro_db = Some(ro_db);
Ok(())
}
async fn get_db_connection(ctx: State<ApiContext>, Path(conn_id): Path<i64>) -> Result<()> {
match &ctx.ro_db {
Some(ro_db) => {
let _ = sqlx::query!("SELECT * FROM table").execute(ro_db).await?;
}
None => {
// ro_db still is None here
}
}
Ok(())
}
That's not what your code is doing, it's a bad idea to have endpoints implicitly depend on one another that way, and it's completely unnecessary anyway:
Stateis a per-router global, your handler gets aCloneof the state, in order to modify the global state you need some sort of inner mutation e.g. aMutexSo just initialise the state as a properly configured
SqlitePoolin the first place.