mod sealed {
pub trait Sealed {}
}
pub trait IsolationLevel: sealed::Sealed + Copy + Default + Send + Sync + 'static {
const NAME: &'static str;
const REFRESH_SNAPSHOT_PER_STATEMENT: bool;
const FIRST_COMMITTER_WINS: bool;
const VALIDATES_READS: bool;
}
macro_rules! define_level {
(
$(#[$meta:meta])*
$name:ident {
refresh: $refresh:expr,
first_committer_wins: $fcw:expr,
validates_reads: $validates:expr $(,)?
}
) => {
$(#[$meta])*
#[derive(Clone, Copy, Default, Debug)]
pub struct $name;
impl sealed::Sealed for $name {}
impl IsolationLevel for $name {
const NAME: &'static str = stringify!($name);
const REFRESH_SNAPSHOT_PER_STATEMENT: bool = $refresh;
const FIRST_COMMITTER_WINS: bool = $fcw;
const VALIDATES_READS: bool = $validates;
}
};
}
define_level! {
ReadCommitted {
refresh: true,
first_committer_wins: false,
validates_reads: false,
}
}
define_level! {
RepeatableRead {
refresh: false,
first_committer_wins: true,
validates_reads: false,
}
}
define_level! {
Snapshot {
refresh: false,
first_committer_wins: true,
validates_reads: false,
}
}
define_level! {
Serializable {
refresh: false,
first_committer_wins: true,
validates_reads: true,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[allow(clippy::assertions_on_constants)]
fn the_levels_differ_only_in_their_declared_constants() {
assert!(ReadCommitted::REFRESH_SNAPSHOT_PER_STATEMENT);
assert!(!Snapshot::REFRESH_SNAPSHOT_PER_STATEMENT);
assert!(!RepeatableRead::REFRESH_SNAPSHOT_PER_STATEMENT);
assert!(!Serializable::REFRESH_SNAPSHOT_PER_STATEMENT);
assert!(!ReadCommitted::FIRST_COMMITTER_WINS);
assert!(Snapshot::FIRST_COMMITTER_WINS);
assert!(Serializable::FIRST_COMMITTER_WINS);
assert!(!Snapshot::VALIDATES_READS);
assert!(!RepeatableRead::VALIDATES_READS);
assert!(
Serializable::VALIDATES_READS,
"this is what stops write skew"
);
}
}