#[cfg(feature = "postgres")]
use super::claim::ORDER_KEYS;
use super::{BuiltIn, SqlWriter};
#[cfg(any(feature = "postgres", feature = "sqlite"))]
use crate::role::Role;
#[cfg(any(feature = "postgres", feature = "sqlite"))]
use crate::spec::TableSpec;
#[cfg(any(feature = "postgres", feature = "sqlite"))]
use crate::statement::ClaimShape;
use crate::statement::Param;
impl<D> SqlWriter<'_, D>
where
D: BuiltIn + ?Sized,
{
pub(crate) fn lease_free(&mut self, expiry: &str) -> &mut Self {
self.push("(")
.ident(expiry)
.push(" IS NULL OR ")
.ident(expiry)
.push(" <= ")
.param(Param::LeaseNow)
.push(")")
}
#[cfg(feature = "postgres")]
pub(crate) fn lease_claim(
&mut self,
spec: &TableSpec<'_>,
shape: ClaimShape,
expiry: &str,
lock: &str,
) -> &mut Self {
let id = spec.id().name();
let claimed_id = match shape {
ClaimShape::Roles => Role::Id.attribute(),
ClaimShape::Rows | ClaimShape::Ids => id,
};
self.push("WITH __claimed AS (SELECT ")
.claimed_columns(spec, shape);
if matches!(shape, ClaimShape::Ids | ClaimShape::Roles) {
for column in ORDER_KEYS.iter().filter_map(|&role| spec.column(role)) {
self.push(", ").ident(column.name());
}
}
self.claimed_rows(spec, lock)
.push("), __stamped AS (UPDATE ")
.table(spec)
.push(" AS __row SET ")
.ident(expiry)
.push(" = ")
.param(Param::Lease);
if let Some(attempt) = spec.column(Role::Attempt) {
self.push(", ")
.ident(attempt.name())
.push(" = __row.")
.ident(attempt.name())
.push(" + 1");
}
self.push(" FROM __claimed WHERE __row.")
.ident(id)
.push(" = __claimed.")
.ident(claimed_id)
.push(") SELECT ");
match shape {
ClaimShape::Rows => self.push("*"),
ClaimShape::Ids => self.ident(id),
ClaimShape::Roles => self.role_names(spec),
};
self.push(" FROM __claimed").claim_order(spec, claimed_id)
}
#[cfg(feature = "sqlite")]
pub(crate) fn returning_claim(
&mut self,
spec: &TableSpec<'_>,
shape: ClaimShape,
expiry: &str,
) -> &mut Self {
let id = spec.id().name();
self.push("UPDATE ")
.table(spec)
.push(" SET ")
.ident(expiry)
.push(" = ")
.param(Param::Lease);
if let Some(attempt) = spec.column(Role::Attempt) {
self.push(", ").increment(attempt.name());
}
self.push(" WHERE ")
.ident(id)
.push(" IN (SELECT ")
.ident(id)
.claimed_rows(spec, "")
.push(") RETURNING ")
.counted_columns(spec, shape)
}
}