mirror of
https://github.com/ModernRelay/omnigraph.git
synced 2026-07-21 03:41:03 +02:00
schema-lint v1 commit 4: emit + apply DropType { Soft } (#99)
Wire the second half of the dormant Drop* family. Per docs/dev/schema-lint-v1-plan.md, commit #4 of the schema-lint chassis v1 series (MR-694). Builds on commit #3 (PR #90, DropProperty Soft). Planner (schema_plan.rs): - plan_nodes leftover loop: emit DropType { Node, name, Soft } instead of UnsupportedChange (OG-DS-102) for node-type removals. - plan_edges leftover loop: emit DropType { Edge, name, Soft } instead of UnsupportedChange (OG-DS-103) for edge-type removals. Apply (schema_apply.rs): - New dropped_tables: BTreeSet<String> accumulator alongside added_tables / renamed_tables / rewritten_tables. - DropType arm in the metadata loop populates dropped_tables for Soft mode. Hard mode errors (lands in commit #5 with --allow-data-loss). - New tombstone-emission loop after the rename sidecar build: for each dropped table, push to sidecar_tombstones AND populate table_tombstones with table_version + 1. The existing manifest publish path converts table_tombstones into ManifestChange::Tombstone operations — no new manifest plumbing needed. - Soft DropType has no Phase B per-table write; the tombstone is the entire change. Lance dataset files are retained — prior __manifest versions still reference them, so time travel + branch-from-snapshot can read the dropped table until cleanup_old_versions runs. - Rides on SidecarKind::SchemaApply per MR-847 (already established by commit #3). Tests: - Planner unit test plan_emits_soft_drop_for_removed_node_and_edge_types asserts both Node and Edge DropType { Soft } emission for the Company + WorksAt combined drop, plus no UnsupportedChange. - Integration test apply_schema_drops_node_and_referencing_edge_softly (replaces apply_schema_rejects_dropping_a_node_type): asserts plan emission, apply success, current manifest entries absent, pre-drop manifest entries present (time-travel reversibility), reopen consistency. - Integration test apply_schema_drops_an_edge_type_softly (replaces apply_schema_rejects_dropping_an_edge_type): single edge drop, asserts other tables untouched, time-travel reversibility. Test results: - cargo test -p omnigraph-compiler --lib: 239 passed (1 new + 238) - cargo test -p omnigraph-engine --test schema_apply: 11 passed (2 converted + 9 unchanged) Pending for v1 completion: - Commit #5: --allow-data-loss CLI flag + Hard mode promotion in planner + immediate compact_files + cleanup_old_versions for both DropProperty and DropType. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
e98347eb7b
commit
58cee158d8
3 changed files with 273 additions and 45 deletions
|
|
@ -324,13 +324,18 @@ fn plan_nodes(
|
|||
.iter()
|
||||
.filter(|node| !consumed.contains(&node.name))
|
||||
{
|
||||
steps.push(SchemaMigrationStep::UnsupportedChange {
|
||||
entity: format!("node:{}", leftover.name),
|
||||
reason: format!(
|
||||
"removing node type '{}' is not supported in schema migration v1",
|
||||
leftover.name
|
||||
),
|
||||
code: Some(crate::lint::codes::OG_DS_102.code.to_string()),
|
||||
// Node type removed from the desired schema: emit
|
||||
// DropType { Node, Soft } per docs/dev/schema-lint-v1-plan.md
|
||||
// commit #4. Soft = remove the table's entry from the current
|
||||
// __manifest version; data files retained; previous manifest
|
||||
// versions still reference the table, so Lance time travel
|
||||
// restores it until cleanup_old_versions ages out the older
|
||||
// __manifest entries. Hard mode (immediate dataset deletion)
|
||||
// lands in commit #5 gated by --allow-data-loss.
|
||||
steps.push(SchemaMigrationStep::DropType {
|
||||
type_kind: SchemaTypeKind::Node,
|
||||
name: leftover.name.clone(),
|
||||
mode: DropMode::Soft,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -442,13 +447,15 @@ fn plan_edges(
|
|||
.iter()
|
||||
.filter(|edge| !consumed.contains(&edge.name))
|
||||
{
|
||||
steps.push(SchemaMigrationStep::UnsupportedChange {
|
||||
entity: format!("edge:{}", leftover.name),
|
||||
reason: format!(
|
||||
"removing edge type '{}' is not supported in schema migration v1",
|
||||
leftover.name
|
||||
),
|
||||
code: Some(crate::lint::codes::OG_DS_103.code.to_string()),
|
||||
// Edge type removed from the desired schema: emit
|
||||
// DropType { Edge, Soft } per docs/dev/schema-lint-v1-plan.md
|
||||
// commit #4. Same Soft mechanics as node-type drops — manifest
|
||||
// entry tombstoned, data files retained, reversible via Lance
|
||||
// time travel until cleanup.
|
||||
steps.push(SchemaMigrationStep::DropType {
|
||||
type_kind: SchemaTypeKind::Edge,
|
||||
name: leftover.name.clone(),
|
||||
mode: DropMode::Soft,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -991,6 +998,81 @@ node Person {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn plan_emits_soft_drop_for_removed_node_and_edge_types() {
|
||||
// Removing a node type + the edge type that references it
|
||||
// emits two DropType { Soft } steps (chassis v1 commit #4,
|
||||
// MR-694). The plan is `supported = true` — apply tombstones
|
||||
// both manifest entries. Time-travel reversibility is verified
|
||||
// at the integration level by
|
||||
// `apply_schema_drops_node_and_referencing_edge_softly`
|
||||
// in `crates/omnigraph/tests/schema_apply.rs`.
|
||||
let accepted = build_schema_ir(
|
||||
&parse_schema(
|
||||
r#"
|
||||
node Person {
|
||||
name: String @key
|
||||
}
|
||||
|
||||
node Company {
|
||||
name: String @key
|
||||
}
|
||||
|
||||
edge WorksAt: Person -> Company
|
||||
"#,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
let desired = build_schema_ir(
|
||||
&parse_schema(
|
||||
r#"
|
||||
node Person {
|
||||
name: String @key
|
||||
}
|
||||
"#,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let plan = plan_schema_migration(&accepted, &desired).unwrap();
|
||||
assert!(
|
||||
plan.supported,
|
||||
"drop-type plan must be supported: {plan:?}"
|
||||
);
|
||||
assert!(
|
||||
plan.steps.iter().any(|step| matches!(
|
||||
step,
|
||||
SchemaMigrationStep::DropType {
|
||||
type_kind: SchemaTypeKind::Node,
|
||||
name,
|
||||
mode: DropMode::Soft,
|
||||
} if name == "Company"
|
||||
)),
|
||||
"expected DropType {{ Node, Company, Soft }} in plan: {plan:?}",
|
||||
);
|
||||
assert!(
|
||||
plan.steps.iter().any(|step| matches!(
|
||||
step,
|
||||
SchemaMigrationStep::DropType {
|
||||
type_kind: SchemaTypeKind::Edge,
|
||||
name,
|
||||
mode: DropMode::Soft,
|
||||
} if name == "WorksAt"
|
||||
)),
|
||||
"expected DropType {{ Edge, WorksAt, Soft }} in plan: {plan:?}",
|
||||
);
|
||||
// Negative: no UnsupportedChange anywhere in the plan.
|
||||
assert!(
|
||||
!plan
|
||||
.steps
|
||||
.iter()
|
||||
.any(|step| matches!(step, UnsupportedChange { .. })),
|
||||
"soft type drop must not emit UnsupportedChange: {plan:?}",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn plan_rejects_required_property_addition() {
|
||||
let accepted = build_schema_ir(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue