use std::sync::Arc;
use sqlx::sqlite::SqlitePool;
use thiserror::Error;
use tracing::warn;
use crate::sync::EagerFutureCell;
#[derive(Debug, Error)]
pub enum VersionError {
#[error("failed to parse the sqlite version: {0}")]
Parsing(#[from] semver::Error),
#[error("failed to query the sqlite version: {0}")]
Query(#[from] sqlx::Error),
}
#[derive(Debug, Clone)]
pub struct Info {
pub variable_number_limit: usize,
pub version: Result<semver::Version, Arc<VersionError>>,
}
impl Info {
const MAX_BIND_PARAMS_FALLBACK: usize = 999;
pub fn new_eager_future(pool: SqlitePool) -> EagerFutureCell<Self> {
EagerFutureCell::new(
async move {
let version = Self::query_version(&pool).await.map_err(Arc::new);
let variable_number_limit = Self::query_variable_number_limit(&pool).await;
Self {
variable_number_limit,
version,
}
},
&tokio::runtime::Handle::current(),
)
}
async fn query_version(pool: &SqlitePool) -> Result<semver::Version, VersionError> {
let str: String = sqlx::query_scalar("SELECT sqlite_version()").fetch_one(pool).await?;
Ok(semver::Version::parse(&str)?)
}
async fn query_variable_number_limit(pool: &SqlitePool) -> usize {
let mut conn = match pool.acquire().await {
Ok(c) => c,
Err(err) => {
warn!(
"failed to grab a connection to query bind param count: {err}. performance \
could be degraded."
);
return Self::MAX_BIND_PARAMS_FALLBACK;
}
};
let mut handle = match conn.lock_handle().await {
Ok(h) => h,
Err(err) => {
warn!(
"failed to lock the connection to query bind param count: {err}. performance \
could be degraded."
);
return Self::MAX_BIND_PARAMS_FALLBACK;
}
};
let raw_handle = handle.as_raw_handle();
#[allow(unsafe_code, reason = "FFI call to read SQLITE_LIMIT_VARIABLE_NUMBER")]
let limit = unsafe {
libsqlite3_sys::sqlite3_limit(
raw_handle.as_ptr(),
libsqlite3_sys::SQLITE_LIMIT_VARIABLE_NUMBER,
-1,
)
};
drop(handle);
match usize::try_from(limit) {
Ok(l) => l,
Err(err) => {
warn!(
"failed to convert {limit} to a number to compute bind param count: {err}. \
performance could be degraded."
);
Self::MAX_BIND_PARAMS_FALLBACK
}
}
}
}