@lix-js/sdk 0.6.0-preview.4 → 0.6.0-preview.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/SKILL.md +65 -64
- package/dist/engine-wasm/index.js +4 -4
- package/dist/engine-wasm/wasm/lix_engine.d.ts +5 -5
- package/dist/engine-wasm/wasm/lix_engine.js +130 -118
- package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
- package/dist/engine-wasm/wasm/lix_engine.wasm.d.ts +9 -8
- package/dist/generated/builtin-schemas.d.ts +69 -69
- package/dist/generated/builtin-schemas.js +94 -94
- package/dist/open-lix.d.ts +33 -26
- package/dist/open-lix.js +10 -10
- package/dist/sqlite/index.js +86 -30
- package/dist-engine-src/README.md +3 -3
- package/dist-engine-src/src/backend/capabilities.rs +67 -0
- package/dist-engine-src/src/backend/conformance/baseline.rs +1127 -0
- package/dist-engine-src/src/backend/conformance/factory.rs +93 -0
- package/dist-engine-src/src/backend/conformance/failure_tests.rs +608 -0
- package/dist-engine-src/src/backend/conformance/fixtures.rs +26 -0
- package/dist-engine-src/src/backend/conformance/mod.rs +75 -0
- package/dist-engine-src/src/backend/conformance/model.rs +28 -0
- package/dist-engine-src/src/backend/conformance/model_based.rs +257 -0
- package/dist-engine-src/src/backend/conformance/persistence.rs +204 -0
- package/dist-engine-src/src/backend/conformance/projection.rs +21 -0
- package/dist-engine-src/src/backend/conformance/pushdown.rs +24 -0
- package/dist-engine-src/src/backend/conformance/runner.rs +90 -0
- package/dist-engine-src/src/backend/conformance/scan.rs +24 -0
- package/dist-engine-src/src/backend/conformance/write.rs +16 -0
- package/dist-engine-src/src/backend/error.rs +94 -0
- package/dist-engine-src/src/backend/in_memory.rs +670 -0
- package/dist-engine-src/src/backend/mod.rs +36 -9
- package/dist-engine-src/src/backend/predicate.rs +80 -0
- package/dist-engine-src/src/backend/traits.rs +260 -0
- package/dist-engine-src/src/backend/types.rs +224 -81
- package/dist-engine-src/src/binary_cas/context.rs +8 -8
- package/dist-engine-src/src/binary_cas/kv.rs +234 -259
- package/dist-engine-src/src/{version → branch}/context.rs +12 -12
- package/dist-engine-src/src/branch/lifecycle.rs +221 -0
- package/dist-engine-src/src/branch/mod.rs +13 -0
- package/dist-engine-src/src/branch/refs.rs +321 -0
- package/dist-engine-src/src/branch/stage_rows.rs +67 -0
- package/dist-engine-src/src/branch/types.rs +21 -0
- package/dist-engine-src/src/catalog/context.rs +18 -18
- package/dist-engine-src/src/catalog/snapshot.rs +8 -8
- package/dist-engine-src/src/changelog/bench_support.rs +785 -0
- package/dist-engine-src/src/changelog/change.rs +1 -0
- package/dist-engine-src/src/changelog/codec.rs +497 -0
- package/dist-engine-src/src/changelog/commit.rs +1 -0
- package/dist-engine-src/src/changelog/context.rs +1614 -0
- package/dist-engine-src/src/changelog/mod.rs +29 -0
- package/dist-engine-src/src/changelog/store.rs +163 -0
- package/dist-engine-src/src/changelog/test_support.rs +54 -0
- package/dist-engine-src/src/changelog/types.rs +213 -0
- package/dist-engine-src/src/commit_graph/context.rs +317 -274
- package/dist-engine-src/src/commit_graph/mod.rs +2 -4
- package/dist-engine-src/src/commit_graph/types.rs +22 -42
- package/dist-engine-src/src/commit_graph/walker.rs +133 -103
- package/dist-engine-src/src/common/error.rs +52 -18
- package/dist-engine-src/src/common/identity.rs +2 -2
- package/dist-engine-src/src/common/mod.rs +1 -1
- package/dist-engine-src/src/domain.rs +42 -46
- package/dist-engine-src/src/engine.rs +74 -96
- package/dist-engine-src/src/{entity_identity.rs → entity_pk.rs} +89 -92
- package/dist-engine-src/src/functions/context.rs +56 -52
- package/dist-engine-src/src/functions/state.rs +51 -52
- package/dist-engine-src/src/init.rs +288 -154
- package/dist-engine-src/src/json_store/context.rs +15 -266
- package/dist-engine-src/src/json_store/mod.rs +26 -0
- package/dist-engine-src/src/json_store/store.rs +103 -718
- package/dist-engine-src/src/json_store/types.rs +4 -9
- package/dist-engine-src/src/lib.rs +49 -19
- package/dist-engine-src/src/live_state/context.rs +654 -790
- package/dist-engine-src/src/live_state/mod.rs +9 -3
- package/dist-engine-src/src/live_state/overlay.rs +4 -4
- package/dist-engine-src/src/live_state/types.rs +30 -21
- package/dist-engine-src/src/live_state/visibility.rs +514 -71
- package/dist-engine-src/src/plugin/install.rs +48 -48
- package/dist-engine-src/src/plugin/manifest.rs +7 -7
- package/dist-engine-src/src/plugin/materializer.rs +0 -275
- package/dist-engine-src/src/plugin/plugin_manifest.json +4 -3
- package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +2 -2
- package/dist-engine-src/src/schema/builtin/lix_branch_descriptor.json +34 -0
- package/dist-engine-src/src/schema/builtin/lix_branch_ref.json +48 -0
- package/dist-engine-src/src/schema/builtin/lix_change.json +3 -3
- package/dist-engine-src/src/schema/builtin/lix_commit.json +1 -1
- package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +6 -6
- package/dist-engine-src/src/schema/builtin/mod.rs +18 -20
- package/dist-engine-src/src/schema/compatibility.rs +11 -11
- package/dist-engine-src/src/schema/definition.json +2 -2
- package/dist-engine-src/src/schema/definition.rs +5 -5
- package/dist-engine-src/src/schema/key.rs +3 -3
- package/dist-engine-src/src/schema/mod.rs +1 -1
- package/dist-engine-src/src/schema/tests.rs +18 -18
- package/dist-engine-src/src/session/context.rs +803 -148
- package/dist-engine-src/src/session/create_branch.rs +94 -0
- package/dist-engine-src/src/session/execute.rs +223 -83
- package/dist-engine-src/src/session/merge/analysis.rs +9 -3
- package/dist-engine-src/src/session/merge/{version.rs → branch.rs} +119 -129
- package/dist-engine-src/src/session/merge/conflicts.rs +2 -2
- package/dist-engine-src/src/session/merge/mod.rs +5 -6
- package/dist-engine-src/src/session/merge/stats.rs +7 -11
- package/dist-engine-src/src/session/mod.rs +15 -12
- package/dist-engine-src/src/session/switch_branch.rs +113 -0
- package/dist-engine-src/src/session/transaction.rs +495 -14
- package/dist-engine-src/src/sql2/{classify.rs → bind/classify.rs} +3 -75
- package/dist-engine-src/src/sql2/bind/error.rs +5 -0
- package/dist-engine-src/src/sql2/bind/expr.rs +29 -0
- package/dist-engine-src/src/sql2/bind/mod.rs +12 -0
- package/dist-engine-src/src/sql2/{udfs/public_call.rs → bind/public_udf.rs} +71 -3
- package/dist-engine-src/src/sql2/bind/read.rs +65 -0
- package/dist-engine-src/src/sql2/bind/statement.rs +2236 -0
- package/dist-engine-src/src/sql2/bind/table.rs +273 -0
- package/dist-engine-src/src/sql2/bind/write.rs +86 -0
- package/dist-engine-src/src/sql2/branch_scope.rs +436 -0
- package/dist-engine-src/src/sql2/catalog/capability.rs +20 -0
- package/dist-engine-src/src/sql2/catalog/entity_surface.rs +296 -0
- package/dist-engine-src/src/sql2/catalog/mod.rs +15 -0
- package/dist-engine-src/src/sql2/catalog/registry.rs +556 -0
- package/dist-engine-src/src/sql2/catalog/schema.rs +88 -0
- package/dist-engine-src/src/sql2/catalog/surface.rs +41 -0
- package/dist-engine-src/src/sql2/change_materialization.rs +122 -0
- package/dist-engine-src/src/sql2/context.rs +36 -30
- package/dist-engine-src/src/sql2/error.rs +1 -1
- package/dist-engine-src/src/sql2/exec/bound_public_write.rs +1593 -0
- package/dist-engine-src/src/sql2/exec/datafusion.rs +5266 -0
- package/dist-engine-src/src/sql2/exec/fast_write.rs +82 -0
- package/dist-engine-src/src/sql2/exec/mod.rs +24 -0
- package/dist-engine-src/src/sql2/exec/write.rs +661 -0
- package/dist-engine-src/src/sql2/filesystem_planner.rs +72 -77
- package/dist-engine-src/src/sql2/filesystem_visibility.rs +21 -21
- package/dist-engine-src/src/sql2/history_projection.rs +8 -8
- package/dist-engine-src/src/sql2/history_route.rs +35 -31
- package/dist-engine-src/src/sql2/mod.rs +28 -23
- package/dist-engine-src/src/sql2/optimize/datafusion.rs +1 -0
- package/dist-engine-src/src/sql2/optimize/mod.rs +2 -0
- package/dist-engine-src/src/sql2/optimize/simple_write.rs +116 -0
- package/dist-engine-src/src/sql2/parse/mod.rs +69 -0
- package/dist-engine-src/src/sql2/parse/normalize.rs +1 -0
- package/dist-engine-src/src/sql2/plan/branch_scope.rs +24 -0
- package/dist-engine-src/src/sql2/plan/mod.rs +5 -0
- package/dist-engine-src/src/sql2/plan/predicate.rs +22 -0
- package/dist-engine-src/src/sql2/plan/write.rs +147 -0
- package/dist-engine-src/src/sql2/predicate_typecheck.rs +258 -0
- package/dist-engine-src/src/sql2/{version_provider.rs → providers/branch.rs} +218 -214
- package/dist-engine-src/src/sql2/{change_provider.rs → providers/change.rs} +156 -42
- package/dist-engine-src/src/sql2/{directory_provider.rs → providers/directory.rs} +291 -322
- package/dist-engine-src/src/sql2/{directory_history_provider.rs → providers/directory_history.rs} +56 -42
- package/dist-engine-src/src/sql2/providers/entity.rs +1484 -0
- package/dist-engine-src/src/sql2/{entity_history_provider.rs → providers/entity_history.rs} +43 -31
- package/dist-engine-src/src/sql2/{file_provider.rs → providers/file.rs} +323 -316
- package/dist-engine-src/src/sql2/{file_history_provider.rs → providers/file_history.rs} +60 -46
- package/dist-engine-src/src/sql2/{history_provider.rs → providers/history.rs} +46 -32
- package/dist-engine-src/src/sql2/{lix_state_provider.rs → providers/lix_state.rs} +359 -329
- package/dist-engine-src/src/sql2/providers/mod.rs +508 -0
- package/dist-engine-src/src/sql2/read_only.rs +2 -2
- package/dist-engine-src/src/sql2/session.rs +47 -96
- package/dist-engine-src/src/sql2/storage/constraints.rs +1 -0
- package/dist-engine-src/src/sql2/storage/mod.rs +1 -0
- package/dist-engine-src/src/sql2/test_support/differential.rs +712 -0
- package/dist-engine-src/src/sql2/test_support/generators.rs +354 -0
- package/dist-engine-src/src/sql2/test_support/mod.rs +2 -0
- package/dist-engine-src/src/sql2/udfs/{lix_active_version_commit_id.rs → lix_active_branch_commit_id.rs} +7 -7
- package/dist-engine-src/src/sql2/udfs/mod.rs +3 -6
- package/dist-engine-src/src/sql2/write_normalization.rs +45 -22
- package/dist-engine-src/src/storage/conformance.rs +399 -0
- package/dist-engine-src/src/storage/context.rs +552 -288
- package/dist-engine-src/src/storage/mod.rs +48 -10
- package/dist-engine-src/src/storage/point.rs +440 -0
- package/dist-engine-src/src/storage/read_scope.rs +43 -64
- package/dist-engine-src/src/storage/reader.rs +867 -0
- package/dist-engine-src/src/storage/scan.rs +784 -0
- package/dist-engine-src/src/storage/spaces.rs +236 -0
- package/dist-engine-src/src/storage/stats.rs +80 -0
- package/dist-engine-src/src/storage/write_set.rs +962 -0
- package/dist-engine-src/src/storage_bench.rs +136 -4828
- package/dist-engine-src/src/test_support.rs +360 -138
- package/dist-engine-src/src/tracked_state/bench_support.rs +394 -0
- package/dist-engine-src/src/tracked_state/codec.rs +155 -1057
- package/dist-engine-src/src/tracked_state/commit_root_rebuild.rs +358 -0
- package/dist-engine-src/src/tracked_state/context.rs +1927 -993
- package/dist-engine-src/src/tracked_state/diff.rs +1715 -261
- package/dist-engine-src/src/tracked_state/merge.rs +74 -88
- package/dist-engine-src/src/tracked_state/mod.rs +19 -16
- package/dist-engine-src/src/tracked_state/{materialization.rs → row_materialization.rs} +50 -178
- package/dist-engine-src/src/tracked_state/storage.rs +243 -191
- package/dist-engine-src/src/tracked_state/tree.rs +247 -371
- package/dist-engine-src/src/tracked_state/types.rs +49 -42
- package/dist-engine-src/src/transaction/bench_support.rs +407 -0
- package/dist-engine-src/src/transaction/commit.rs +821 -713
- package/dist-engine-src/src/transaction/context.rs +705 -600
- package/dist-engine-src/src/transaction/mod.rs +13 -2
- package/dist-engine-src/src/transaction/normalization.rs +63 -76
- package/dist-engine-src/src/transaction/prep.rs +13 -13
- package/dist-engine-src/src/transaction/schema_resolver.rs +19 -5
- package/dist-engine-src/src/transaction/staging.rs +228 -434
- package/dist-engine-src/src/transaction/types.rs +41 -98
- package/dist-engine-src/src/transaction/validation.rs +382 -446
- package/dist-engine-src/src/untracked_state/codec.rs +337 -29
- package/dist-engine-src/src/untracked_state/context.rs +7 -7
- package/dist-engine-src/src/untracked_state/materialization.rs +2 -2
- package/dist-engine-src/src/untracked_state/mod.rs +1 -1
- package/dist-engine-src/src/untracked_state/storage.rs +659 -157
- package/dist-engine-src/src/untracked_state/types.rs +21 -21
- package/package.json +71 -68
- package/dist-engine-src/src/backend/kv.rs +0 -358
- package/dist-engine-src/src/backend/testing.rs +0 -658
- package/dist-engine-src/src/commit_store/codec.rs +0 -887
- package/dist-engine-src/src/commit_store/context.rs +0 -944
- package/dist-engine-src/src/commit_store/materialization.rs +0 -84
- package/dist-engine-src/src/commit_store/mod.rs +0 -16
- package/dist-engine-src/src/commit_store/storage.rs +0 -600
- package/dist-engine-src/src/commit_store/types.rs +0 -215
- package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +0 -34
- package/dist-engine-src/src/schema/builtin/lix_version_ref.json +0 -48
- package/dist-engine-src/src/session/create_version.rs +0 -88
- package/dist-engine-src/src/session/merge/apply.rs +0 -23
- package/dist-engine-src/src/session/optimization9_sql2_bench.rs +0 -100
- package/dist-engine-src/src/session/switch_version.rs +0 -110
- package/dist-engine-src/src/sql2/entity_provider.rs +0 -3211
- package/dist-engine-src/src/sql2/execute.rs +0 -3533
- package/dist-engine-src/src/sql2/public_bind/assignment.rs +0 -46
- package/dist-engine-src/src/sql2/public_bind/capability.rs +0 -41
- package/dist-engine-src/src/sql2/public_bind/dml.rs +0 -172
- package/dist-engine-src/src/sql2/public_bind/mod.rs +0 -26
- package/dist-engine-src/src/sql2/public_bind/table.rs +0 -168
- package/dist-engine-src/src/sql2/version_scope.rs +0 -394
- package/dist-engine-src/src/storage/types.rs +0 -501
- package/dist-engine-src/src/tracked_state/by_file_index.rs +0 -98
- package/dist-engine-src/src/tracked_state/materializer.rs +0 -488
- package/dist-engine-src/src/transaction/live_state_overlay.rs +0 -35
- package/dist-engine-src/src/version/lifecycle.rs +0 -221
- package/dist-engine-src/src/version/mod.rs +0 -13
- package/dist-engine-src/src/version/refs.rs +0 -330
- package/dist-engine-src/src/version/stage_rows.rs +0 -67
- package/dist-engine-src/src/version/types.rs +0 -21
|
@@ -1,61 +1,53 @@
|
|
|
1
1
|
use std::collections::{BTreeMap, BTreeSet};
|
|
2
2
|
|
|
3
3
|
use crate::tracked_state::{
|
|
4
|
-
|
|
4
|
+
TrackedStateDiff, TrackedStateDiffEntry, TrackedStateDiffIdentity, TrackedStateDiffRow,
|
|
5
5
|
};
|
|
6
6
|
use crate::LixError;
|
|
7
7
|
|
|
8
8
|
/// Planned tracked-state merge result.
|
|
9
9
|
///
|
|
10
|
-
/// This is intentionally a pure planner. It does not know about
|
|
10
|
+
/// This is intentionally a pure planner. It does not know about branches,
|
|
11
11
|
/// sessions, changelog writes, or live-state overlays. Callers provide two
|
|
12
12
|
/// diffs from the same merge base:
|
|
13
13
|
///
|
|
14
|
-
/// - `base -> target`: what the destination
|
|
15
|
-
/// - `base -> source`: what the incoming
|
|
14
|
+
/// - `base -> target`: what the destination branch changed.
|
|
15
|
+
/// - `base -> source`: what the incoming branch changed.
|
|
16
16
|
///
|
|
17
|
-
/// The planner returns source-side
|
|
18
|
-
///
|
|
19
|
-
/// sides.
|
|
17
|
+
/// The planner returns source-side picks plus first-class conflicts for
|
|
18
|
+
/// identities changed differently on both sides.
|
|
20
19
|
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
|
21
20
|
pub(crate) struct TrackedStateMergePlan {
|
|
22
|
-
pub(crate)
|
|
21
|
+
pub(crate) picks: Vec<TrackedStateMergePick>,
|
|
23
22
|
pub(crate) conflicts: Vec<TrackedStateMergeConflict>,
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
/// One source-side
|
|
25
|
+
/// One source-side change selected for the merge result.
|
|
27
26
|
///
|
|
28
|
-
/// Merge
|
|
29
|
-
///
|
|
30
|
-
/// including tombstones
|
|
31
|
-
/// change identity.
|
|
27
|
+
/// Merge picks describe source-side state that will be selected into
|
|
28
|
+
/// the target root. The selected row carries the target-root materialization
|
|
29
|
+
/// shape, including tombstones.
|
|
32
30
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
33
|
-
pub(crate)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
projected_row: MaterializedTrackedStateRow,
|
|
38
|
-
},
|
|
31
|
+
pub(crate) struct TrackedStateMergePick {
|
|
32
|
+
pub(crate) identity: TrackedStateDiffIdentity,
|
|
33
|
+
pub(crate) change_id: String,
|
|
34
|
+
pub(crate) selected_row: TrackedStateDiffRow,
|
|
39
35
|
}
|
|
40
36
|
|
|
41
|
-
impl
|
|
37
|
+
impl TrackedStateMergePick {
|
|
42
38
|
#[cfg(test)]
|
|
43
39
|
pub(crate) fn identity(&self) -> &TrackedStateDiffIdentity {
|
|
44
|
-
|
|
45
|
-
Self::Adopt { identity, .. } => identity,
|
|
46
|
-
}
|
|
40
|
+
&self.identity
|
|
47
41
|
}
|
|
48
42
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
43
|
+
#[cfg(test)]
|
|
44
|
+
pub(crate) fn source_change_id(&self) -> &str {
|
|
45
|
+
&self.change_id
|
|
53
46
|
}
|
|
54
47
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
}
|
|
48
|
+
#[cfg(test)]
|
|
49
|
+
pub(crate) fn source_row(&self) -> &TrackedStateDiffRow {
|
|
50
|
+
&self.selected_row
|
|
59
51
|
}
|
|
60
52
|
}
|
|
61
53
|
|
|
@@ -70,7 +62,7 @@ pub(crate) struct TrackedStateMergeConflict {
|
|
|
70
62
|
/// Plans a three-way tracked-state merge from two base-relative diffs.
|
|
71
63
|
///
|
|
72
64
|
/// This follows the same shape as prolly-tree merge systems: compare
|
|
73
|
-
/// `base -> target` and `base -> source` by identity, emit source-only
|
|
65
|
+
/// `base -> target` and `base -> source` by identity, emit source-only picks
|
|
74
66
|
/// for the target root, ignore target-only changes, collapse convergent
|
|
75
67
|
/// changes, and report divergent same-identity changes as conflicts.
|
|
76
68
|
pub(crate) fn plan_merge(
|
|
@@ -94,11 +86,10 @@ pub(crate) fn plan_merge(
|
|
|
94
86
|
(None, None) => {}
|
|
95
87
|
(Some(_target), None) => {
|
|
96
88
|
// Target already changed this identity. Source did not, so
|
|
97
|
-
// there is nothing to
|
|
89
|
+
// there is nothing to pick.
|
|
98
90
|
}
|
|
99
91
|
(None, Some(source)) => {
|
|
100
|
-
plan.
|
|
101
|
-
.push(adopt_source_change_patch(identity, source)?);
|
|
92
|
+
plan.picks.push(source_change_pick(identity, source)?);
|
|
102
93
|
}
|
|
103
94
|
(Some(target), Some(source)) if same_final_state(target, source) => {
|
|
104
95
|
// Both sides reached the same visible state. Keep target to
|
|
@@ -122,13 +113,16 @@ fn diff_by_identity(
|
|
|
122
113
|
) -> Result<BTreeMap<TrackedStateDiffIdentity, &TrackedStateDiffEntry>, LixError> {
|
|
123
114
|
let mut entries = BTreeMap::new();
|
|
124
115
|
for entry in &diff.entries {
|
|
116
|
+
if entry.identity.schema_key == "lix_commit" {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
125
119
|
if entries.insert(entry.identity.clone(), entry).is_some() {
|
|
126
120
|
return Err(LixError::new(
|
|
127
121
|
"LIX_ERROR_UNKNOWN",
|
|
128
122
|
format!(
|
|
129
123
|
"tracked-state merge received duplicate diff entry for schema '{}' entity '{}'",
|
|
130
124
|
entry.identity.schema_key,
|
|
131
|
-
entry.identity.
|
|
125
|
+
entry.identity.entity_pk.as_json_array_text()?
|
|
132
126
|
),
|
|
133
127
|
));
|
|
134
128
|
}
|
|
@@ -136,24 +130,24 @@ fn diff_by_identity(
|
|
|
136
130
|
Ok(entries)
|
|
137
131
|
}
|
|
138
132
|
|
|
139
|
-
fn
|
|
133
|
+
fn source_change_pick(
|
|
140
134
|
identity: TrackedStateDiffIdentity,
|
|
141
135
|
entry: &TrackedStateDiffEntry,
|
|
142
|
-
) -> Result<
|
|
136
|
+
) -> Result<TrackedStateMergePick, LixError> {
|
|
143
137
|
let Some(row) = entry.after.clone() else {
|
|
144
138
|
return Err(LixError::new(
|
|
145
139
|
"LIX_ERROR_UNKNOWN",
|
|
146
140
|
format!(
|
|
147
|
-
"tracked-state merge cannot
|
|
141
|
+
"tracked-state merge cannot pick source removal for schema '{}' entity '{}' without a tombstone row",
|
|
148
142
|
entry.identity.schema_key,
|
|
149
|
-
entry.identity.
|
|
143
|
+
entry.identity.entity_pk.as_json_array_text()?
|
|
150
144
|
),
|
|
151
145
|
));
|
|
152
146
|
};
|
|
153
|
-
Ok(
|
|
147
|
+
Ok(TrackedStateMergePick {
|
|
154
148
|
identity,
|
|
155
149
|
change_id: row.change_id.clone(),
|
|
156
|
-
|
|
150
|
+
selected_row: row,
|
|
157
151
|
})
|
|
158
152
|
}
|
|
159
153
|
|
|
@@ -168,21 +162,19 @@ fn same_final_state(target: &TrackedStateDiffEntry, source: &TrackedStateDiffEnt
|
|
|
168
162
|
}
|
|
169
163
|
}
|
|
170
164
|
|
|
171
|
-
fn row_is_live(row: &
|
|
172
|
-
row.
|
|
165
|
+
fn row_is_live(row: &TrackedStateDiffRow) -> bool {
|
|
166
|
+
!row.deleted
|
|
173
167
|
}
|
|
174
168
|
|
|
175
|
-
fn tracked_row_payload_eq(
|
|
176
|
-
left
|
|
177
|
-
right: &MaterializedTrackedStateRow,
|
|
178
|
-
) -> bool {
|
|
179
|
-
left.snapshot_content == right.snapshot_content && left.metadata == right.metadata
|
|
169
|
+
fn tracked_row_payload_eq(left: &TrackedStateDiffRow, right: &TrackedStateDiffRow) -> bool {
|
|
170
|
+
left.snapshot_ref == right.snapshot_ref && left.metadata_ref == right.metadata_ref
|
|
180
171
|
}
|
|
181
172
|
|
|
182
173
|
#[cfg(test)]
|
|
183
174
|
mod tests {
|
|
184
175
|
use super::*;
|
|
185
|
-
use crate::
|
|
176
|
+
use crate::entity_pk::EntityPk;
|
|
177
|
+
use crate::json_store::JsonRef;
|
|
186
178
|
use crate::tracked_state::TrackedStateDiffKind;
|
|
187
179
|
|
|
188
180
|
#[test]
|
|
@@ -198,7 +190,7 @@ mod tests {
|
|
|
198
190
|
)
|
|
199
191
|
.expect("merge should plan");
|
|
200
192
|
|
|
201
|
-
assert_eq!(
|
|
193
|
+
assert_eq!(pick_ids(&plan), vec!["entity-a"]);
|
|
202
194
|
assert!(plan.conflicts.is_empty());
|
|
203
195
|
}
|
|
204
196
|
|
|
@@ -215,12 +207,9 @@ mod tests {
|
|
|
215
207
|
)
|
|
216
208
|
.expect("merge should plan");
|
|
217
209
|
|
|
218
|
-
assert_eq!(
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
Some("{\"value\":\"source\"}")
|
|
222
|
-
);
|
|
223
|
-
assert_eq!(plan.patches[0].change_id(), "source");
|
|
210
|
+
assert_eq!(pick_ids(&plan), vec!["entity-a"]);
|
|
211
|
+
assert!(plan.picks[0].source_row().snapshot_ref.is_some());
|
|
212
|
+
assert_eq!(plan.picks[0].source_change_id(), "source");
|
|
224
213
|
}
|
|
225
214
|
|
|
226
215
|
#[test]
|
|
@@ -236,9 +225,9 @@ mod tests {
|
|
|
236
225
|
)
|
|
237
226
|
.expect("merge should plan");
|
|
238
227
|
|
|
239
|
-
assert_eq!(
|
|
240
|
-
|
|
241
|
-
assert_eq!(plan.
|
|
228
|
+
assert_eq!(pick_ids(&plan), vec!["entity-a"]);
|
|
229
|
+
assert!(plan.picks[0].source_row().deleted);
|
|
230
|
+
assert_eq!(plan.picks[0].source_change_id(), "source-delete");
|
|
242
231
|
}
|
|
243
232
|
|
|
244
233
|
#[test]
|
|
@@ -254,7 +243,7 @@ mod tests {
|
|
|
254
243
|
)
|
|
255
244
|
.expect("merge should plan");
|
|
256
245
|
|
|
257
|
-
assert!(plan.
|
|
246
|
+
assert!(plan.picks.is_empty());
|
|
258
247
|
assert!(plan.conflicts.is_empty());
|
|
259
248
|
}
|
|
260
249
|
|
|
@@ -275,7 +264,7 @@ mod tests {
|
|
|
275
264
|
|
|
276
265
|
let plan = plan_merge(&diff(vec![target]), &diff(vec![source])).expect("merge should plan");
|
|
277
266
|
|
|
278
|
-
assert!(plan.
|
|
267
|
+
assert!(plan.picks.is_empty());
|
|
279
268
|
assert!(plan.conflicts.is_empty());
|
|
280
269
|
}
|
|
281
270
|
|
|
@@ -296,7 +285,7 @@ mod tests {
|
|
|
296
285
|
|
|
297
286
|
let plan = plan_merge(&diff(vec![target]), &diff(vec![source])).expect("merge should plan");
|
|
298
287
|
|
|
299
|
-
assert!(plan.
|
|
288
|
+
assert!(plan.picks.is_empty());
|
|
300
289
|
assert!(plan.conflicts.is_empty());
|
|
301
290
|
}
|
|
302
291
|
|
|
@@ -317,7 +306,7 @@ mod tests {
|
|
|
317
306
|
|
|
318
307
|
let plan = plan_merge(&diff(vec![target]), &diff(vec![source])).expect("merge should plan");
|
|
319
308
|
|
|
320
|
-
assert!(plan.
|
|
309
|
+
assert!(plan.picks.is_empty());
|
|
321
310
|
assert_eq!(conflict_ids(&plan), vec!["entity-a"]);
|
|
322
311
|
}
|
|
323
312
|
|
|
@@ -378,7 +367,7 @@ mod tests {
|
|
|
378
367
|
}
|
|
379
368
|
|
|
380
369
|
#[test]
|
|
381
|
-
fn
|
|
370
|
+
fn pick_and_conflict_order_is_deterministic_by_identity() {
|
|
382
371
|
let target = diff(vec![entry(
|
|
383
372
|
"entity-b",
|
|
384
373
|
TrackedStateDiffKind::Modified,
|
|
@@ -408,7 +397,7 @@ mod tests {
|
|
|
408
397
|
|
|
409
398
|
let plan = plan_merge(&target, &source).expect("merge should plan");
|
|
410
399
|
|
|
411
|
-
assert_eq!(
|
|
400
|
+
assert_eq!(pick_ids(&plan), vec!["entity-a", "entity-c"]);
|
|
412
401
|
assert_eq!(conflict_ids(&plan), vec!["entity-b"]);
|
|
413
402
|
}
|
|
414
403
|
|
|
@@ -417,15 +406,15 @@ mod tests {
|
|
|
417
406
|
}
|
|
418
407
|
|
|
419
408
|
fn entry(
|
|
420
|
-
|
|
409
|
+
entity_pk: &str,
|
|
421
410
|
kind: TrackedStateDiffKind,
|
|
422
|
-
before: Option<
|
|
423
|
-
after: Option<
|
|
411
|
+
before: Option<TrackedStateDiffRow>,
|
|
412
|
+
after: Option<TrackedStateDiffRow>,
|
|
424
413
|
) -> TrackedStateDiffEntry {
|
|
425
414
|
TrackedStateDiffEntry {
|
|
426
415
|
identity: TrackedStateDiffIdentity {
|
|
427
416
|
schema_key: "test_schema".to_string(),
|
|
428
|
-
|
|
417
|
+
entity_pk: EntityPk::single(entity_pk),
|
|
429
418
|
file_id: None,
|
|
430
419
|
},
|
|
431
420
|
kind,
|
|
@@ -434,13 +423,13 @@ mod tests {
|
|
|
434
423
|
}
|
|
435
424
|
}
|
|
436
425
|
|
|
437
|
-
fn
|
|
438
|
-
plan.
|
|
426
|
+
fn pick_ids(plan: &TrackedStateMergePlan) -> Vec<String> {
|
|
427
|
+
plan.picks
|
|
439
428
|
.iter()
|
|
440
429
|
.map(|entry| {
|
|
441
430
|
entry
|
|
442
431
|
.identity()
|
|
443
|
-
.
|
|
432
|
+
.entity_pk
|
|
444
433
|
.as_single_string_owned()
|
|
445
434
|
.expect("identity")
|
|
446
435
|
})
|
|
@@ -453,36 +442,33 @@ mod tests {
|
|
|
453
442
|
.map(|entry| {
|
|
454
443
|
entry
|
|
455
444
|
.identity
|
|
456
|
-
.
|
|
445
|
+
.entity_pk
|
|
457
446
|
.as_single_string_owned()
|
|
458
447
|
.expect("identity")
|
|
459
448
|
})
|
|
460
449
|
.collect()
|
|
461
450
|
}
|
|
462
451
|
|
|
463
|
-
fn tombstone(
|
|
464
|
-
let mut row = row(
|
|
465
|
-
row.
|
|
452
|
+
fn tombstone(entity_pk: &str, change_id: &str) -> TrackedStateDiffRow {
|
|
453
|
+
let mut row = row(entity_pk, change_id);
|
|
454
|
+
row.snapshot_ref = None;
|
|
466
455
|
row.deleted = true;
|
|
467
456
|
row
|
|
468
457
|
}
|
|
469
458
|
|
|
470
|
-
fn row(
|
|
471
|
-
row_with_value(
|
|
459
|
+
fn row(entity_pk: &str, change_id: &str) -> TrackedStateDiffRow {
|
|
460
|
+
row_with_value(entity_pk, change_id, "value")
|
|
472
461
|
}
|
|
473
462
|
|
|
474
|
-
fn row_with_value(
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
) -> MaterializedTrackedStateRow {
|
|
479
|
-
MaterializedTrackedStateRow {
|
|
480
|
-
entity_id: EntityIdentity::single(entity_id),
|
|
463
|
+
fn row_with_value(entity_pk: &str, change_id: &str, value: &str) -> TrackedStateDiffRow {
|
|
464
|
+
let snapshot = format!("{{\"value\":\"{value}\"}}");
|
|
465
|
+
TrackedStateDiffRow {
|
|
466
|
+
entity_pk: EntityPk::single(entity_pk),
|
|
481
467
|
schema_key: "test_schema".to_string(),
|
|
482
468
|
file_id: None,
|
|
483
|
-
snapshot_content: Some(format!("{{\"value\":\"{value}\"}}")),
|
|
484
|
-
metadata: None,
|
|
485
469
|
deleted: false,
|
|
470
|
+
snapshot_ref: Some(JsonRef::for_content(snapshot.as_bytes())),
|
|
471
|
+
metadata_ref: None,
|
|
486
472
|
created_at: "2026-01-01T00:00:00Z".to_string(),
|
|
487
473
|
updated_at: "2026-01-01T00:00:00Z".to_string(),
|
|
488
474
|
change_id: change_id.to_string(),
|
|
@@ -1,32 +1,35 @@
|
|
|
1
|
-
|
|
1
|
+
#[cfg(feature = "storage-benches")]
|
|
2
|
+
mod bench_support;
|
|
2
3
|
mod codec;
|
|
4
|
+
mod commit_root_rebuild;
|
|
3
5
|
mod context;
|
|
4
6
|
mod diff;
|
|
5
|
-
mod materialization;
|
|
6
|
-
mod materializer;
|
|
7
7
|
mod merge;
|
|
8
|
+
mod row_materialization;
|
|
8
9
|
mod storage;
|
|
9
10
|
mod tree;
|
|
10
11
|
mod types;
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
pub(crate) use context::{
|
|
14
|
-
TrackedStateContext, TrackedStateMaterializer, TrackedStateStoreReader, TrackedStateWriter,
|
|
15
|
-
};
|
|
16
|
-
#[allow(unused_imports)]
|
|
13
|
+
pub(crate) use context::{TrackedStateContext, TrackedStateStoreReader};
|
|
17
14
|
pub(crate) use diff::{
|
|
18
15
|
TrackedStateDiff, TrackedStateDiffEntry, TrackedStateDiffIdentity, TrackedStateDiffKind,
|
|
19
|
-
TrackedStateDiffRequest,
|
|
16
|
+
TrackedStateDiffRequest, TrackedStateDiffRow,
|
|
20
17
|
};
|
|
21
|
-
pub(crate) use materialization::{materialize_index_entries, TrackedMaterializationProjection};
|
|
22
|
-
#[allow(unused_imports)]
|
|
23
18
|
pub(crate) use merge::{
|
|
24
|
-
plan_merge, TrackedStateMergeConflict,
|
|
19
|
+
plan_merge, TrackedStateMergeConflict, TrackedStateMergePick, TrackedStateMergePlan,
|
|
20
|
+
};
|
|
21
|
+
pub(crate) use row_materialization::{
|
|
22
|
+
materialize_rows_from_index_entries, TrackedRowMaterialization,
|
|
25
23
|
};
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
#[cfg(feature = "storage-benches")]
|
|
25
|
+
pub(crate) use storage::{TRACKED_STATE_COMMIT_ROOT_SPACE, TRACKED_STATE_TREE_CHUNK_SPACE};
|
|
26
|
+
#[cfg(any(test, feature = "storage-benches"))]
|
|
27
|
+
pub(crate) use types::TrackedStateKey;
|
|
28
28
|
pub(crate) use types::{
|
|
29
|
-
MaterializedTrackedStateRow, TrackedStateDeltaRef, TrackedStateFilter,
|
|
30
|
-
TrackedStateIndexValueRef, TrackedStateKeyRef, TrackedStateProjection, TrackedStateRowRequest,
|
|
29
|
+
MaterializedTrackedStateRow, TrackedStateDeltaRef, TrackedStateFilter, TrackedStateReadColumns,
|
|
31
30
|
TrackedStateScanRequest,
|
|
32
31
|
};
|
|
32
|
+
#[cfg(feature = "storage-benches")]
|
|
33
|
+
pub mod bench {
|
|
34
|
+
pub use super::bench_support::*;
|
|
35
|
+
}
|