mod compatibility;
mod defaults;
mod migration;
mod registry;
mod version;
pub use compatibility::{CompatibilityMatrix, CompatibilityReport, SchemaChange};
pub use defaults::{DefaultProvider, DefaultRegistry, FieldDefault, MapDefaultProvider};
pub use migration::{Migration, MigrationFn, MigrationRegistry, compose_migrations};
pub use registry::VersionedSchemaRegistry;
pub use version::{ChangeKind, SchemaVersion, VersionRange};
#[cfg(test)]
mod tests {
use super::*;
use crate::traits::{FieldInfo, TypeInfo};
use std::sync::Arc;
#[test]
fn integration_test_schema_evolution() {
let migration_registry = Arc::new(MigrationRegistry::new());
let schema_registry = VersionedSchemaRegistry::new();
let default_registry = DefaultRegistry::new();
let v1 = TypeInfo::new("Order", 1).with_hash(100).with_fields(vec![
FieldInfo::new("id", "String"),
FieldInfo::new("amount", "f64"),
]);
let v2 = TypeInfo::new("Order", 2).with_hash(200).with_fields(vec![
FieldInfo::new("id", "String"),
FieldInfo::new("amount", "f64"),
FieldInfo::new("currency", "String").optional(),
]);
schema_registry.register(v1.clone());
schema_registry.register(v2.clone());
default_registry.register(
"Order@v2",
MapDefaultProvider::new().with_string("currency", "USD"),
);
let compat_matrix = CompatibilityMatrix::new(Arc::clone(&migration_registry));
let report = compat_matrix.check(&v1, &v2);
assert!(report.compatible);
assert!(!report.migration_required);
assert_eq!(report.changes.len(), 1);
assert_eq!(report.changes[0].kind, ChangeKind::AddOptionalField);
let versions = schema_registry.get_versions("Order");
assert_eq!(versions.len(), 2);
assert_eq!(versions[0], SchemaVersion::new(1, 0));
assert_eq!(versions[1], SchemaVersion::new(2, 0));
let latest = schema_registry.get_latest("Order").unwrap();
assert_eq!(latest.version, 2);
}
#[test]
fn integration_test_breaking_change_with_migration() {
let migration_registry = Arc::new(MigrationRegistry::new());
let v1 = TypeInfo::new("User", 1).with_hash(1000).with_fields(vec![
FieldInfo::new("name", "String"),
FieldInfo::new("age", "i32"),
]);
let v2 = TypeInfo::new("User", 2).with_hash(2000).with_fields(vec![
FieldInfo::new("name", "String"),
FieldInfo::new("age", "f64"), ]);
let compat_matrix = CompatibilityMatrix::new(Arc::clone(&migration_registry));
let report = compat_matrix.check(&v1, &v2);
assert!(!report.compatible);
assert!(report.migration_required);
assert!(!report.migration_available);
migration_registry
.register(Migration::new(
"User@v1",
1000,
"User@v2",
2000,
|_arena, offset| Ok(offset), ))
.unwrap();
let report = compat_matrix.check(&v1, &v2);
assert!(!report.compatible);
assert!(report.migration_required);
assert!(report.migration_available);
}
}