use super::*;
fn legacy_definition(current: i64, log_count: i64) -> Vec<u8> {
encode_value(&StoredSequence {
security: crate::SequenceSecurityRow::bootstrap(),
object_id: [1; 16],
definition_generation: [2; 16],
start: 1,
increment: 1,
current: Some(current),
called: Some(true),
log_count: Some(log_count),
persistence: "p".into(),
owner: None,
options: SequenceOptions {
min_value: Some(1),
max_value: Some(i64::MAX),
..SequenceOptions::default()
},
})
.unwrap()
}
fn value_state(catalog: &KeyValueCatalog) -> (i64, bool, i64) {
let row = catalog.load_sequence_rows().unwrap().remove(0);
(row.current, row.called, row.log_count)
}
#[test]
fn the_value_state_of_a_legacy_definition_moves_into_its_value_record_once() {
let store: Arc<dyn KeyValueStore> = Arc::new(MemoryKeyValueStore::new());
let catalog = KeyValueCatalog::new(Arc::clone(&store));
catalog.save_schema("public").unwrap();
let relation = RelationIdentity::new("public", "ids");
let key = relation_key(TAG_SEQUENCE, &relation).unwrap();
store.put(&key, &legacy_definition(41, 7)).unwrap();
assert_eq!(value_state(&catalog), (41, true, 7));
catalog.migrate_sequence_values().unwrap();
let definition: serde_json::Value =
serde_json::from_slice(&store.get(&key).unwrap().unwrap()).unwrap();
for field in ["current", "called", "log_count"] {
assert!(definition.get(field).is_none(), "{field}");
}
assert_eq!(value_state(&catalog), (41, true, 7));
assert_eq!(
catalog.next_sequence_value("public.ids", [1; 16]).unwrap(),
Some(42)
);
assert_eq!(value_state(&catalog), (42, true, 6));
catalog.migrate_sequence_values().unwrap();
assert_eq!(value_state(&catalog), (42, true, 6));
store.put(&key, &legacy_definition(42, 6)).unwrap();
for error in [
catalog.load_sequence_rows().unwrap_err(),
catalog.migrate_sequence_values().unwrap_err(),
] {
assert!(
error.to_string().contains("written by an earlier release"),
"{error}"
);
}
}
#[test]
fn a_definition_without_value_state_is_refused_by_earlier_releases() {
let store: Arc<dyn KeyValueStore> = Arc::new(MemoryKeyValueStore::new());
let catalog = KeyValueCatalog::new(Arc::clone(&store));
catalog.save_schema("public").unwrap();
let mut row = crate::SequenceRow {
relation: RelationIdentity::new("public", "ids"),
security: crate::SequenceSecurityRow::bootstrap(),
object_id: [1; 16],
definition_generation: [2; 16],
start: 1,
increment: 1,
current: 1,
called: false,
log_count: 0,
persistence: "p".into(),
owner: None,
options: SequenceOptions::default(),
};
assert!(catalog.create_sequence_row(&row).unwrap());
let encoded = store
.get(&relation_key(TAG_SEQUENCE, &row.relation).unwrap())
.unwrap()
.unwrap();
assert!(!serde_json::from_slice::<serde_json::Value>(&encoded)
.unwrap()
.as_object()
.unwrap()
.contains_key("current"));
row.options.min_value = Some(1);
row.options.max_value = Some(i64::MAX);
assert_eq!(catalog.load_sequence_rows().unwrap(), [row]);
}