2023-08-29 21:34:01 +02:00
|
|
|
use std::time;
|
|
|
|
|
|
2023-08-29 21:34:01 +02:00
|
|
|
use tracing::Instrument;
|
|
|
|
|
|
2023-08-29 21:34:00 +02:00
|
|
|
use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions};
|
2023-08-29 21:34:01 +02:00
|
|
|
use sqlx::ConnectOptions;
|
2023-08-29 21:34:00 +02:00
|
|
|
pub use sqlx::{Pool, Sqlite};
|
|
|
|
|
|
|
|
|
|
use std::str::FromStr as _;
|
|
|
|
|
|
|
|
|
|
use crate::StartError;
|
|
|
|
|
|
2023-08-29 21:34:01 +02:00
|
|
|
#[tracing::instrument]
|
2023-08-29 21:34:00 +02:00
|
|
|
pub async fn init_database_pool(url: &str) -> Result<Pool<Sqlite>, StartError> {
|
2023-08-29 21:34:01 +02:00
|
|
|
async {
|
|
|
|
|
SqlitePoolOptions::new()
|
|
|
|
|
.max_connections(5)
|
|
|
|
|
.connect_with(
|
|
|
|
|
SqliteConnectOptions::from_str(url)?
|
|
|
|
|
.log_statements(log::LevelFilter::Debug)
|
|
|
|
|
.log_slow_statements(log::LevelFilter::Warn, time::Duration::from_millis(100))
|
|
|
|
|
.pragma("foreign_keys", "1"),
|
|
|
|
|
)
|
|
|
|
|
.await
|
|
|
|
|
}
|
|
|
|
|
.instrument(tracing::info_span!("packager::sql::pool"))
|
|
|
|
|
.await
|
|
|
|
|
.map_err(Into::into)
|
2023-08-29 21:34:00 +02:00
|
|
|
}
|
|
|
|
|
|
2023-08-29 21:34:01 +02:00
|
|
|
#[tracing::instrument]
|
2023-08-29 21:34:00 +02:00
|
|
|
pub async fn migrate(url: &str) -> Result<(), StartError> {
|
2023-08-29 21:34:01 +02:00
|
|
|
async {
|
|
|
|
|
let pool = SqlitePoolOptions::new()
|
|
|
|
|
.max_connections(5)
|
|
|
|
|
.connect_with(
|
|
|
|
|
SqliteConnectOptions::from_str(url)?
|
|
|
|
|
.pragma("foreign_keys", "0")
|
|
|
|
|
.log_statements(log::LevelFilter::Debug),
|
|
|
|
|
)
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
sqlx::migrate!().run(&pool).await
|
|
|
|
|
}
|
|
|
|
|
.instrument(tracing::info_span!("packager::sql::migrate"))
|
|
|
|
|
.await?;
|
2023-08-29 21:34:01 +02:00
|
|
|
|
2023-08-29 21:34:00 +02:00
|
|
|
Ok(())
|
|
|
|
|
}
|
2023-08-29 21:34:01 +02:00
|
|
|
|
|
|
|
|
#[macro_export]
|
|
|
|
|
macro_rules! query_all {
|
|
|
|
|
( $pool:expr, $struct_row:path, $struct_into:path, $query:expr, $( $args:tt )* ) => {
|
|
|
|
|
async {
|
|
|
|
|
let result: Result<Vec<$struct_into>, Error> = sqlx::query_as!(
|
|
|
|
|
$struct_row,
|
|
|
|
|
$query,
|
|
|
|
|
$( $args )*
|
|
|
|
|
)
|
|
|
|
|
.fetch($pool)
|
|
|
|
|
.map_ok(|row: $struct_row| row.try_into())
|
|
|
|
|
.try_collect::<Vec<Result<$struct_into, Error>>>()
|
|
|
|
|
.await?
|
|
|
|
|
.into_iter()
|
|
|
|
|
.collect::<Result<Vec<$struct_into>, Error>>();
|
|
|
|
|
|
|
|
|
|
result
|
|
|
|
|
|
|
|
|
|
}.instrument(tracing::info_span!("packager::sql::query", "query"))
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[macro_export]
|
|
|
|
|
macro_rules! query_one {
|
|
|
|
|
( $pool:expr, $struct_row:path, $struct_into:path, $query:expr, $( $args:tt )*) => {
|
|
|
|
|
async {
|
|
|
|
|
let result: Result<Option<$struct_into>, Error> = sqlx::query_as!(
|
|
|
|
|
$struct_row,
|
|
|
|
|
$query,
|
|
|
|
|
$( $args )*
|
|
|
|
|
)
|
|
|
|
|
.fetch_optional($pool)
|
|
|
|
|
.await?
|
|
|
|
|
.map(|row: $struct_row| row.try_into())
|
|
|
|
|
.transpose();
|
|
|
|
|
|
|
|
|
|
result
|
|
|
|
|
|
|
|
|
|
}.instrument(tracing::info_span!("packager::sql::query", "query"))
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[macro_export]
|
|
|
|
|
macro_rules! query_exists {
|
|
|
|
|
( $pool:expr, $query:expr, $( $args:tt )*) => {
|
|
|
|
|
async {
|
|
|
|
|
let result: bool = sqlx::query!(
|
|
|
|
|
$query,
|
|
|
|
|
$( $args )*
|
|
|
|
|
)
|
|
|
|
|
.fetch_optional($pool)
|
|
|
|
|
.await?
|
|
|
|
|
.is_some();
|
|
|
|
|
|
|
|
|
|
Ok(result)
|
|
|
|
|
|
|
|
|
|
}.instrument(tracing::info_span!("packager::sql::query", "query"))
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[macro_export]
|
|
|
|
|
macro_rules! execute {
|
|
|
|
|
( $pool:expr, $query:expr, $( $args:tt )*) => {
|
|
|
|
|
async {
|
|
|
|
|
let result: Result<sqlx::sqlite::SqliteQueryResult, Error> = sqlx::query!(
|
|
|
|
|
$query,
|
|
|
|
|
$( $args )*
|
|
|
|
|
)
|
|
|
|
|
.execute($pool)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(|e| e.into());
|
|
|
|
|
|
|
|
|
|
result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}.instrument(tracing::info_span!("packager::sql::query", "query"))
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[macro_export]
|
|
|
|
|
macro_rules! execute_returning {
|
|
|
|
|
( $pool:expr, $query:expr, $t:path, $fn:expr, $( $args:tt )*) => {
|
|
|
|
|
async {
|
|
|
|
|
let result: Result<$t, Error> = sqlx::query!(
|
|
|
|
|
$query,
|
|
|
|
|
$( $args )*
|
|
|
|
|
)
|
|
|
|
|
.fetch_one($pool)
|
|
|
|
|
.map_ok($fn)
|
|
|
|
|
.await
|
|
|
|
|
.map_err(Into::into);
|
|
|
|
|
|
|
|
|
|
result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}.instrument(tracing::info_span!("packager::sql::query", "query"))
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[macro_export]
|
|
|
|
|
macro_rules! execute_returning_uuid {
|
|
|
|
|
( $pool:expr, $query:expr, $( $args:tt )*) => {
|
|
|
|
|
async {
|
|
|
|
|
let result: Result<Uuid, Error> = sqlx::query!(
|
|
|
|
|
$query,
|
|
|
|
|
$( $args )*
|
|
|
|
|
)
|
|
|
|
|
.fetch_one($pool)
|
|
|
|
|
.map_ok(|row| Uuid::try_parse(&row.id))
|
|
|
|
|
.await?
|
|
|
|
|
.map_err(Into::into);
|
|
|
|
|
|
|
|
|
|
result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}.instrument(tracing::info_span!("packager::sql::query", "query"))
|
|
|
|
|
};
|
|
|
|
|
}
|