use crate::{Dialect, RelError, RelationalTx, Value};
fn require_postgres(dialect: &Dialect) -> Result<(), RelError> {
match dialect {
Dialect::Postgres => Ok(()),
other => Err(RelError::Unsupported(format!(
"advisory locks are PostgreSQL's; {other} has no transaction-scoped named lock"
))),
}
}
pub async fn lock<T: RelationalTx>(
tx: &mut T,
dialect: &Dialect,
name: &str,
) -> Result<(), RelError> {
require_postgres(dialect)?;
tx.execute(
"SELECT pg_advisory_xact_lock(hashtext($1))",
&[Value::Text(name.to_string())],
)
.await
.map(|_| ())
}
pub async fn try_lock<T: RelationalTx>(
tx: &mut T,
dialect: &Dialect,
name: &str,
) -> Result<bool, RelError> {
require_postgres(dialect)?;
let rows = tx
.query(
"SELECT pg_try_advisory_xact_lock(hashtext($1))",
&[Value::Text(name.to_string())],
)
.await?;
match rows.first().and_then(|r| r.values.first()) {
Some(Value::Bool(got)) => Ok(*got),
other => Err(RelError::Unsupported(format!(
"pg_try_advisory_xact_lock returned {other:?}, not a boolean"
))),
}
}