use crate::format::pb;
#[derive(Clone, Debug, PartialEq)]
pub struct Transaction {
pub inner: pb::Transaction,
}
impl Transaction {
pub fn as_pb(&self) -> &pb::Transaction {
&self.inner
}
pub fn may_change_schema(&self) -> bool {
operation_may_change_schema(&self.inner)
}
}
pub fn operation_may_change_schema(transaction: &pb::Transaction) -> bool {
use pb::transaction::Operation;
match transaction.operation.as_ref() {
Some(Operation::UpdateConfig(update)) => {
!update.field_metadata_updates.is_empty() || !update.field_metadata.is_empty()
}
Some(
Operation::Append(_)
| Operation::Delete(_)
| Operation::CreateIndex(_)
| Operation::Rewrite(_)
| Operation::DataReplacement(_)
| Operation::ReserveFragments(_)
| Operation::Update(_)
| Operation::UpdateMemWalState(_)
| Operation::UpdateBases(_)
| Operation::DataOverlay(_),
) => false,
_ => true,
}
}
impl From<Transaction> for pb::Transaction {
fn from(tx: Transaction) -> Self {
tx.inner
}
}
impl From<pb::Transaction> for Transaction {
fn from(pb_tx: pb::Transaction) -> Self {
Self { inner: pb_tx }
}
}
#[cfg(test)]
mod tests {
use super::*;
use prost::Message;
#[test]
fn an_exempt_operation_is_classified_the_same_at_any_size() {
let small = pb::Transaction {
operation: Some(pb::transaction::Operation::Delete(
pb::transaction::Delete::default(),
)),
..Default::default()
};
let mut large = small.clone();
large.tag = "x".repeat(4 * 1024 * 1024);
assert!(large.encoded_len() > small.encoded_len() * 100);
assert!(!operation_may_change_schema(&small));
assert!(!operation_may_change_schema(&large));
}
#[test]
fn a_data_overlay_is_exempt() {
let overlay = pb::Transaction {
operation: Some(pb::transaction::Operation::DataOverlay(
pb::transaction::DataOverlay::default(),
)),
..Default::default()
};
assert!(!operation_may_change_schema(&overlay));
}
#[test]
fn field_metadata_updates_change_schema() {
let mut update = pb::transaction::UpdateConfig {
config_updates: Some(pb::transaction::UpdateMap::default()),
..Default::default()
};
let config_only = pb::Transaction {
operation: Some(pb::transaction::Operation::UpdateConfig(update.clone())),
..Default::default()
};
assert!(!operation_may_change_schema(&config_only));
update
.field_metadata_updates
.insert(0, pb::transaction::UpdateMap::default());
let field_update = pb::Transaction {
operation: Some(pb::transaction::Operation::UpdateConfig(update)),
..Default::default()
};
assert!(operation_may_change_schema(&field_update));
}
#[test]
fn a_schema_carrying_operation_is_never_exempt() {
let overwrite = pb::Transaction {
operation: Some(pb::transaction::Operation::Overwrite(
pb::transaction::Overwrite::default(),
)),
..Default::default()
};
assert!(operation_may_change_schema(&overwrite));
let unknown = pb::Transaction::default();
assert!(operation_may_change_schema(&unknown));
}
}