@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
|
@@ -9,9 +9,10 @@ use crate::common::{
|
|
|
9
9
|
directory_ancestor_paths, directory_name_from_path, normalize_directory_path,
|
|
10
10
|
parent_directory_path, stable_content_fingerprint_hex, ParsedFilePath,
|
|
11
11
|
};
|
|
12
|
-
use crate::
|
|
12
|
+
use crate::entity_pk::EntityPk;
|
|
13
13
|
use crate::live_state::MaterializedLiveStateRow;
|
|
14
14
|
use crate::LixError;
|
|
15
|
+
use crate::GLOBAL_BRANCH_ID;
|
|
15
16
|
|
|
16
17
|
use super::filesystem_visibility::VisibleFilesystem;
|
|
17
18
|
use crate::transaction::types::{TransactionFileData, TransactionJson, TransactionWriteRow};
|
|
@@ -44,7 +45,7 @@ pub(crate) struct FilesystemDeletePlan {
|
|
|
44
45
|
/// Common state-row lane fields shared by filesystem descriptor/blob rows.
|
|
45
46
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
46
47
|
pub(crate) struct FilesystemRowContext {
|
|
47
|
-
pub(crate)
|
|
48
|
+
pub(crate) branch_id: String,
|
|
48
49
|
pub(crate) global: bool,
|
|
49
50
|
pub(crate) untracked: bool,
|
|
50
51
|
pub(crate) file_id: Option<String>,
|
|
@@ -52,9 +53,9 @@ pub(crate) struct FilesystemRowContext {
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
impl FilesystemRowContext {
|
|
55
|
-
pub(crate) fn
|
|
56
|
+
pub(crate) fn active_branch(branch_id: impl Into<String>) -> Self {
|
|
56
57
|
Self {
|
|
57
|
-
|
|
58
|
+
branch_id: branch_id.into(),
|
|
58
59
|
global: false,
|
|
59
60
|
untracked: false,
|
|
60
61
|
file_id: None,
|
|
@@ -478,8 +479,8 @@ pub(crate) fn blob_ref_row(input: BlobRefRowInput) -> Result<TransactionWriteRow
|
|
|
478
479
|
LixError::new(
|
|
479
480
|
"LIX_ERROR_UNKNOWN",
|
|
480
481
|
format!(
|
|
481
|
-
"binary blob size exceeds supported range for file '{}'
|
|
482
|
-
input.file_id, input.context.
|
|
482
|
+
"binary blob size exceeds supported range for file '{}' branch '{}'",
|
|
483
|
+
input.file_id, input.context.branch_id
|
|
483
484
|
),
|
|
484
485
|
)
|
|
485
486
|
})?;
|
|
@@ -546,7 +547,7 @@ pub(crate) fn plan_file_path_write(
|
|
|
546
547
|
})?);
|
|
547
548
|
file_data.push(TransactionFileData {
|
|
548
549
|
file_id,
|
|
549
|
-
|
|
550
|
+
branch_id: input.context.branch_id,
|
|
550
551
|
untracked: input.context.untracked,
|
|
551
552
|
data,
|
|
552
553
|
});
|
|
@@ -675,8 +676,13 @@ pub(crate) fn directory_path_resolvers_from_state_rows(
|
|
|
675
676
|
let Some(snapshot_content) = row.snapshot_content.as_deref() else {
|
|
676
677
|
continue;
|
|
677
678
|
};
|
|
679
|
+
let storage_branch_id = if row.global {
|
|
680
|
+
GLOBAL_BRANCH_ID
|
|
681
|
+
} else {
|
|
682
|
+
row.branch_id.as_str()
|
|
683
|
+
};
|
|
678
684
|
let resolver_key = filesystem_storage_scope_key(
|
|
679
|
-
|
|
685
|
+
storage_branch_id,
|
|
680
686
|
row.global,
|
|
681
687
|
row.untracked,
|
|
682
688
|
row.file_id.as_deref(),
|
|
@@ -718,7 +724,7 @@ pub(crate) fn directory_path_resolvers_from_state_rows(
|
|
|
718
724
|
}
|
|
719
725
|
|
|
720
726
|
let mut resolvers = BTreeMap::new();
|
|
721
|
-
for (
|
|
727
|
+
for (branch_id, records) in directory_rows {
|
|
722
728
|
let mut paths = BTreeMap::<String, String>::new();
|
|
723
729
|
for directory_id in records.keys() {
|
|
724
730
|
resolve_directory_seed_path(directory_id, &records, &mut paths, &mut BTreeSet::new())?;
|
|
@@ -727,15 +733,15 @@ pub(crate) fn directory_path_resolvers_from_state_rows(
|
|
|
727
733
|
.into_iter()
|
|
728
734
|
.map(|(directory_id, path)| (path, directory_id))
|
|
729
735
|
.collect::<Vec<_>>();
|
|
730
|
-
let files = file_rows.remove(&
|
|
736
|
+
let files = file_rows.remove(&branch_id).unwrap_or_default();
|
|
731
737
|
resolvers.insert(
|
|
732
|
-
|
|
738
|
+
branch_id,
|
|
733
739
|
DirectoryPathResolver::from_existing_filesystem(seeds, files)?,
|
|
734
740
|
);
|
|
735
741
|
}
|
|
736
|
-
for (
|
|
742
|
+
for (branch_id, files) in file_rows {
|
|
737
743
|
resolvers.insert(
|
|
738
|
-
|
|
744
|
+
branch_id,
|
|
739
745
|
DirectoryPathResolver::from_existing_filesystem(std::iter::empty(), files)?,
|
|
740
746
|
);
|
|
741
747
|
}
|
|
@@ -743,13 +749,13 @@ pub(crate) fn directory_path_resolvers_from_state_rows(
|
|
|
743
749
|
}
|
|
744
750
|
|
|
745
751
|
pub(crate) fn filesystem_storage_scope_key(
|
|
746
|
-
|
|
752
|
+
branch_id: &str,
|
|
747
753
|
global: bool,
|
|
748
754
|
untracked: bool,
|
|
749
755
|
file_id: Option<&str>,
|
|
750
756
|
) -> String {
|
|
751
757
|
format!(
|
|
752
|
-
"
|
|
758
|
+
"branch={branch_id}\0global={global}\0untracked={untracked}\0file_id={}",
|
|
753
759
|
file_id.unwrap_or("<null>")
|
|
754
760
|
)
|
|
755
761
|
}
|
|
@@ -804,23 +810,23 @@ fn directory_parent_cycle_error(directory_id: &str) -> LixError {
|
|
|
804
810
|
}
|
|
805
811
|
|
|
806
812
|
fn state_row(
|
|
807
|
-
|
|
813
|
+
entity_pk: String,
|
|
808
814
|
schema_key: &str,
|
|
809
815
|
snapshot: Option<JsonValue>,
|
|
810
816
|
context: FilesystemRowContext,
|
|
811
817
|
) -> TransactionWriteRow {
|
|
812
|
-
partial_state_row(Some(
|
|
818
|
+
partial_state_row(Some(entity_pk), schema_key, snapshot, context)
|
|
813
819
|
}
|
|
814
820
|
|
|
815
821
|
fn partial_state_row(
|
|
816
|
-
|
|
822
|
+
entity_pk: Option<String>,
|
|
817
823
|
schema_key: &str,
|
|
818
824
|
snapshot: Option<JsonValue>,
|
|
819
825
|
context: FilesystemRowContext,
|
|
820
826
|
) -> TransactionWriteRow {
|
|
821
827
|
let snapshot = snapshot.map(TransactionJson::from_value_unchecked);
|
|
822
828
|
TransactionWriteRow {
|
|
823
|
-
|
|
829
|
+
entity_pk: entity_pk.map(EntityPk::single),
|
|
824
830
|
schema_key: schema_key.to_string(),
|
|
825
831
|
file_id: context.file_id,
|
|
826
832
|
snapshot,
|
|
@@ -832,16 +838,16 @@ fn partial_state_row(
|
|
|
832
838
|
change_id: None,
|
|
833
839
|
commit_id: None,
|
|
834
840
|
untracked: context.untracked,
|
|
835
|
-
|
|
841
|
+
branch_id: context.branch_id,
|
|
836
842
|
}
|
|
837
843
|
}
|
|
838
844
|
|
|
839
845
|
fn tombstone_row(
|
|
840
|
-
|
|
846
|
+
entity_pk: String,
|
|
841
847
|
schema_key: &str,
|
|
842
848
|
context: FilesystemRowContext,
|
|
843
849
|
) -> TransactionWriteRow {
|
|
844
|
-
state_row(
|
|
850
|
+
state_row(entity_pk, schema_key, None, context)
|
|
845
851
|
}
|
|
846
852
|
|
|
847
853
|
fn collect_recursive_directory_delete(
|
|
@@ -900,7 +906,7 @@ mod tests {
|
|
|
900
906
|
use crate::sql2::filesystem_visibility::{
|
|
901
907
|
VisibleBlobRef, VisibleDirectory, VisibleFile, VisibleFilesystem,
|
|
902
908
|
};
|
|
903
|
-
use crate::{
|
|
909
|
+
use crate::{entity_pk::EntityPk, live_state::MaterializedLiveStateRow};
|
|
904
910
|
|
|
905
911
|
fn test_id_generator(ids: &'static [&'static str]) -> impl FnMut() -> String {
|
|
906
912
|
let mut ids = ids.iter();
|
|
@@ -914,15 +920,15 @@ mod tests {
|
|
|
914
920
|
parent_id: None,
|
|
915
921
|
name: "docs".to_string(),
|
|
916
922
|
hidden: false,
|
|
917
|
-
context: FilesystemRowContext::
|
|
923
|
+
context: FilesystemRowContext::active_branch("branch-a"),
|
|
918
924
|
});
|
|
919
925
|
|
|
920
926
|
assert_eq!(
|
|
921
|
-
row.
|
|
922
|
-
Some(&crate::
|
|
927
|
+
row.entity_pk.as_ref(),
|
|
928
|
+
Some(&crate::entity_pk::EntityPk::single("dir-docs"))
|
|
923
929
|
);
|
|
924
930
|
assert_eq!(row.schema_key, "lix_directory_descriptor");
|
|
925
|
-
assert_eq!(row.
|
|
931
|
+
assert_eq!(row.branch_id, "branch-a");
|
|
926
932
|
let snapshot: JsonValue = row.snapshot.as_ref().unwrap().value().clone();
|
|
927
933
|
assert_eq!(snapshot["id"], "dir-docs");
|
|
928
934
|
assert_eq!(snapshot["parent_id"], JsonValue::Null);
|
|
@@ -937,14 +943,12 @@ mod tests {
|
|
|
937
943
|
directory_id: Some("dir-docs".to_string()),
|
|
938
944
|
name: "readme.md".to_string(),
|
|
939
945
|
hidden: false,
|
|
940
|
-
context: FilesystemRowContext::
|
|
946
|
+
context: FilesystemRowContext::active_branch("branch-a"),
|
|
941
947
|
});
|
|
942
948
|
|
|
943
949
|
assert_eq!(
|
|
944
|
-
row.
|
|
945
|
-
Some(&crate::
|
|
946
|
-
"file-readme"
|
|
947
|
-
))
|
|
950
|
+
row.entity_pk.as_ref(),
|
|
951
|
+
Some(&crate::entity_pk::EntityPk::single("file-readme"))
|
|
948
952
|
);
|
|
949
953
|
assert_eq!(row.schema_key, "lix_file_descriptor");
|
|
950
954
|
let snapshot: JsonValue = row.snapshot.as_ref().unwrap().value().clone();
|
|
@@ -957,15 +961,13 @@ mod tests {
|
|
|
957
961
|
let row = blob_ref_row(BlobRefRowInput {
|
|
958
962
|
file_id: "file-readme".to_string(),
|
|
959
963
|
data: b"Hello".to_vec(),
|
|
960
|
-
context: FilesystemRowContext::
|
|
964
|
+
context: FilesystemRowContext::active_branch("branch-a"),
|
|
961
965
|
})
|
|
962
966
|
.expect("blob ref row should build");
|
|
963
967
|
|
|
964
968
|
assert_eq!(
|
|
965
|
-
row.
|
|
966
|
-
Some(&crate::
|
|
967
|
-
"file-readme"
|
|
968
|
-
))
|
|
969
|
+
row.entity_pk.as_ref(),
|
|
970
|
+
Some(&crate::entity_pk::EntityPk::single("file-readme"))
|
|
969
971
|
);
|
|
970
972
|
assert_eq!(row.file_id.as_deref(), Some("file-readme"));
|
|
971
973
|
assert_eq!(row.schema_key, "lix_binary_blob_ref");
|
|
@@ -986,7 +988,7 @@ mod tests {
|
|
|
986
988
|
let rows = resolver
|
|
987
989
|
.ensure_directory_path(
|
|
988
990
|
"/docs/nested/",
|
|
989
|
-
FilesystemRowContext::
|
|
991
|
+
FilesystemRowContext::active_branch("branch-a"),
|
|
990
992
|
false,
|
|
991
993
|
&mut test_id_generator(&["dir-generated-nested"]),
|
|
992
994
|
)
|
|
@@ -1013,7 +1015,7 @@ mod tests {
|
|
|
1013
1015
|
let docs_rows = resolver
|
|
1014
1016
|
.ensure_directory_path(
|
|
1015
1017
|
"/docs/",
|
|
1016
|
-
FilesystemRowContext::
|
|
1018
|
+
FilesystemRowContext::active_branch("branch-a"),
|
|
1017
1019
|
false,
|
|
1018
1020
|
&mut test_id_generator(&["dir-generated-docs"]),
|
|
1019
1021
|
)
|
|
@@ -1023,7 +1025,7 @@ mod tests {
|
|
|
1023
1025
|
let nested_rows = resolver
|
|
1024
1026
|
.ensure_directory_path(
|
|
1025
1027
|
"/docs/nested/",
|
|
1026
|
-
FilesystemRowContext::
|
|
1028
|
+
FilesystemRowContext::active_branch("branch-a"),
|
|
1027
1029
|
false,
|
|
1028
1030
|
&mut test_id_generator(&["dir-generated-nested"]),
|
|
1029
1031
|
)
|
|
@@ -1045,7 +1047,7 @@ mod tests {
|
|
|
1045
1047
|
.ensure_directory_path_with_leaf_id(
|
|
1046
1048
|
"/docs/nested/",
|
|
1047
1049
|
Some("dir-nested".to_string()),
|
|
1048
|
-
FilesystemRowContext::
|
|
1050
|
+
FilesystemRowContext::active_branch("branch-a"),
|
|
1049
1051
|
false,
|
|
1050
1052
|
&mut test_id_generator(&["dir-generated-docs"]),
|
|
1051
1053
|
)
|
|
@@ -1075,7 +1077,7 @@ mod tests {
|
|
|
1075
1077
|
let rows = resolver
|
|
1076
1078
|
.ensure_directory_path(
|
|
1077
1079
|
"/docs/nested/",
|
|
1078
|
-
FilesystemRowContext::
|
|
1080
|
+
FilesystemRowContext::active_branch("branch-a"),
|
|
1079
1081
|
false,
|
|
1080
1082
|
&mut test_id_generator(&["dir-generated-docs", "dir-generated-nested"]),
|
|
1081
1083
|
)
|
|
@@ -1085,7 +1087,7 @@ mod tests {
|
|
|
1085
1087
|
let rows = resolver
|
|
1086
1088
|
.ensure_directory_path(
|
|
1087
1089
|
"/docs/nested/",
|
|
1088
|
-
FilesystemRowContext::
|
|
1090
|
+
FilesystemRowContext::active_branch("branch-a"),
|
|
1089
1091
|
false,
|
|
1090
1092
|
&mut test_id_generator(&["should-not-be-used"]),
|
|
1091
1093
|
)
|
|
@@ -1105,7 +1107,7 @@ mod tests {
|
|
|
1105
1107
|
path: "/docs/guides/readme.md".to_string(),
|
|
1106
1108
|
data: Some(b"hello".to_vec()),
|
|
1107
1109
|
hidden: Some(false),
|
|
1108
|
-
context: FilesystemRowContext::
|
|
1110
|
+
context: FilesystemRowContext::active_branch("branch-a"),
|
|
1109
1111
|
},
|
|
1110
1112
|
&mut test_id_generator(&["dir-generated-docs", "dir-generated-guides"]),
|
|
1111
1113
|
)
|
|
@@ -1114,7 +1116,7 @@ mod tests {
|
|
|
1114
1116
|
assert_eq!(plan.count, 1);
|
|
1115
1117
|
assert_eq!(plan.file_data.len(), 1);
|
|
1116
1118
|
assert_eq!(plan.file_data[0].file_id, "file-readme");
|
|
1117
|
-
assert_eq!(plan.file_data[0].
|
|
1119
|
+
assert_eq!(plan.file_data[0].branch_id, "branch-a");
|
|
1118
1120
|
assert_eq!(plan.file_data[0].data, b"hello");
|
|
1119
1121
|
assert_eq!(plan.rows.len(), 4);
|
|
1120
1122
|
assert_eq!(
|
|
@@ -1155,7 +1157,7 @@ mod tests {
|
|
|
1155
1157
|
path: "/docs/guides/readme.md".to_string(),
|
|
1156
1158
|
data: Some(b"hello".to_vec()),
|
|
1157
1159
|
hidden: Some(false),
|
|
1158
|
-
context: FilesystemRowContext::
|
|
1160
|
+
context: FilesystemRowContext::active_branch("branch-a"),
|
|
1159
1161
|
},
|
|
1160
1162
|
&mut test_id_generator(&["should-not-be-used"]),
|
|
1161
1163
|
)
|
|
@@ -1190,7 +1192,7 @@ mod tests {
|
|
|
1190
1192
|
"/docs/renamed.md".to_string(),
|
|
1191
1193
|
false,
|
|
1192
1194
|
Some(b"hello".to_vec()),
|
|
1193
|
-
FilesystemRowContext::
|
|
1195
|
+
FilesystemRowContext::active_branch("branch-a"),
|
|
1194
1196
|
&mut test_id_generator(&["should-not-be-used"]),
|
|
1195
1197
|
)
|
|
1196
1198
|
.expect("file path update should plan");
|
|
@@ -1221,7 +1223,7 @@ mod tests {
|
|
|
1221
1223
|
"/docs/guides/readme.md".to_string(),
|
|
1222
1224
|
true,
|
|
1223
1225
|
Some(b"hello".to_vec()),
|
|
1224
|
-
FilesystemRowContext::
|
|
1226
|
+
FilesystemRowContext::active_branch("branch-a"),
|
|
1225
1227
|
&mut test_id_generator(&["dir-generated-docs", "dir-generated-guides"]),
|
|
1226
1228
|
)
|
|
1227
1229
|
.expect("file path update should plan");
|
|
@@ -1257,12 +1259,12 @@ mod tests {
|
|
|
1257
1259
|
let resolvers = super::directory_path_resolvers_from_state_rows(vec![
|
|
1258
1260
|
live_directory_row(
|
|
1259
1261
|
"dir-docs",
|
|
1260
|
-
"
|
|
1262
|
+
"branch-a",
|
|
1261
1263
|
"{\"id\":\"dir-docs\",\"parent_id\":null,\"name\":\"docs\"}",
|
|
1262
1264
|
),
|
|
1263
1265
|
live_directory_row(
|
|
1264
1266
|
"dir-guides",
|
|
1265
|
-
"
|
|
1267
|
+
"branch-a",
|
|
1266
1268
|
"{\"id\":\"dir-guides\",\"parent_id\":\"dir-docs\",\"name\":\"guides\"}",
|
|
1267
1269
|
),
|
|
1268
1270
|
])
|
|
@@ -1270,10 +1272,7 @@ mod tests {
|
|
|
1270
1272
|
|
|
1271
1273
|
let resolver = resolvers
|
|
1272
1274
|
.get(&super::filesystem_storage_scope_key(
|
|
1273
|
-
"
|
|
1274
|
-
false,
|
|
1275
|
-
false,
|
|
1276
|
-
None,
|
|
1275
|
+
"branch-a", false, false, None,
|
|
1277
1276
|
))
|
|
1278
1277
|
.expect("storage-scope resolver should exist");
|
|
1279
1278
|
assert_eq!(resolver.directory_id("/docs/").unwrap(), Some("dir-docs"));
|
|
@@ -1288,7 +1287,7 @@ mod tests {
|
|
|
1288
1287
|
let plan = super::plan_file_delete(FileDeleteInput {
|
|
1289
1288
|
file_id: "file-readme".to_string(),
|
|
1290
1289
|
has_blob_ref: true,
|
|
1291
|
-
context: FilesystemRowContext::
|
|
1290
|
+
context: FilesystemRowContext::active_branch("branch-a"),
|
|
1292
1291
|
});
|
|
1293
1292
|
|
|
1294
1293
|
assert_eq!(plan.count, 1);
|
|
@@ -1299,10 +1298,8 @@ mod tests {
|
|
|
1299
1298
|
.find(|row| row.schema_key == "lix_file_descriptor")
|
|
1300
1299
|
.expect("file descriptor tombstone should be planned");
|
|
1301
1300
|
assert_eq!(
|
|
1302
|
-
descriptor.
|
|
1303
|
-
Some(&crate::
|
|
1304
|
-
"file-readme"
|
|
1305
|
-
))
|
|
1301
|
+
descriptor.entity_pk.as_ref(),
|
|
1302
|
+
Some(&crate::entity_pk::EntityPk::single("file-readme"))
|
|
1306
1303
|
);
|
|
1307
1304
|
assert_eq!(descriptor.file_id, None);
|
|
1308
1305
|
assert_eq!(descriptor.snapshot, None);
|
|
@@ -1313,10 +1310,8 @@ mod tests {
|
|
|
1313
1310
|
.find(|row| row.schema_key == "lix_binary_blob_ref")
|
|
1314
1311
|
.expect("blob ref tombstone should be planned");
|
|
1315
1312
|
assert_eq!(
|
|
1316
|
-
blob_ref.
|
|
1317
|
-
Some(&crate::
|
|
1318
|
-
"file-readme"
|
|
1319
|
-
))
|
|
1313
|
+
blob_ref.entity_pk.as_ref(),
|
|
1314
|
+
Some(&crate::entity_pk::EntityPk::single("file-readme"))
|
|
1320
1315
|
);
|
|
1321
1316
|
assert_eq!(blob_ref.file_id.as_deref(), Some("file-readme"));
|
|
1322
1317
|
assert_eq!(blob_ref.snapshot, None);
|
|
@@ -1327,7 +1322,7 @@ mod tests {
|
|
|
1327
1322
|
let plan = super::plan_file_delete(FileDeleteInput {
|
|
1328
1323
|
file_id: "file-readme".to_string(),
|
|
1329
1324
|
has_blob_ref: false,
|
|
1330
|
-
context: FilesystemRowContext::
|
|
1325
|
+
context: FilesystemRowContext::active_branch("branch-a"),
|
|
1331
1326
|
});
|
|
1332
1327
|
|
|
1333
1328
|
assert_eq!(plan.count, 1);
|
|
@@ -1340,14 +1335,14 @@ mod tests {
|
|
|
1340
1335
|
fn directory_delete_plans_descriptor_tombstone() {
|
|
1341
1336
|
let plan = super::plan_directory_delete(DirectoryDeleteInput {
|
|
1342
1337
|
directory_id: "dir-docs".to_string(),
|
|
1343
|
-
context: FilesystemRowContext::
|
|
1338
|
+
context: FilesystemRowContext::active_branch("branch-a"),
|
|
1344
1339
|
});
|
|
1345
1340
|
|
|
1346
1341
|
assert_eq!(plan.count, 1);
|
|
1347
1342
|
assert_eq!(plan.rows.len(), 1);
|
|
1348
1343
|
assert_eq!(
|
|
1349
|
-
plan.rows[0].
|
|
1350
|
-
Some(&crate::
|
|
1344
|
+
plan.rows[0].entity_pk.as_ref(),
|
|
1345
|
+
Some(&crate::entity_pk::EntityPk::single("dir-docs"))
|
|
1351
1346
|
);
|
|
1352
1347
|
assert_eq!(plan.rows[0].schema_key, "lix_directory_descriptor");
|
|
1353
1348
|
assert_eq!(plan.rows[0].file_id, None);
|
|
@@ -1356,7 +1351,7 @@ mod tests {
|
|
|
1356
1351
|
|
|
1357
1352
|
#[test]
|
|
1358
1353
|
fn recursive_directory_delete_plans_files_blobs_and_deepest_directories_first() {
|
|
1359
|
-
let context = FilesystemRowContext::
|
|
1354
|
+
let context = FilesystemRowContext::active_branch("branch-a");
|
|
1360
1355
|
let mut directories_by_id = BTreeMap::new();
|
|
1361
1356
|
directories_by_id.insert(
|
|
1362
1357
|
"dir-docs".to_string(),
|
|
@@ -1408,11 +1403,11 @@ mod tests {
|
|
|
1408
1403
|
.map(|row| {
|
|
1409
1404
|
(
|
|
1410
1405
|
row.schema_key.as_str(),
|
|
1411
|
-
row.
|
|
1406
|
+
row.entity_pk
|
|
1412
1407
|
.as_ref()
|
|
1413
|
-
.expect("planned recursive delete row should carry
|
|
1408
|
+
.expect("planned recursive delete row should carry entity_pk")
|
|
1414
1409
|
.as_single_string_owned()
|
|
1415
|
-
.expect("planned recursive delete row should project
|
|
1410
|
+
.expect("planned recursive delete row should project entity_pk"),
|
|
1416
1411
|
)
|
|
1417
1412
|
})
|
|
1418
1413
|
.collect::<Vec<_>>(),
|
|
@@ -1467,20 +1462,20 @@ mod tests {
|
|
|
1467
1462
|
}
|
|
1468
1463
|
|
|
1469
1464
|
fn live_directory_row(
|
|
1470
|
-
|
|
1471
|
-
|
|
1465
|
+
entity_pk: &str,
|
|
1466
|
+
branch_id: &str,
|
|
1472
1467
|
snapshot_content: &str,
|
|
1473
1468
|
) -> MaterializedLiveStateRow {
|
|
1474
1469
|
MaterializedLiveStateRow {
|
|
1475
|
-
|
|
1470
|
+
entity_pk: EntityPk::single(entity_pk),
|
|
1476
1471
|
schema_key: "lix_directory_descriptor".to_string(),
|
|
1477
1472
|
file_id: None,
|
|
1478
1473
|
snapshot_content: Some(snapshot_content.to_string()),
|
|
1479
1474
|
metadata: None,
|
|
1480
1475
|
deleted: false,
|
|
1481
|
-
|
|
1482
|
-
change_id: Some(format!("change-{
|
|
1483
|
-
commit_id: Some(format!("commit-{
|
|
1476
|
+
branch_id: branch_id.to_string(),
|
|
1477
|
+
change_id: Some(format!("change-{entity_pk}")),
|
|
1478
|
+
commit_id: Some(format!("commit-{entity_pk}")),
|
|
1484
1479
|
global: false,
|
|
1485
1480
|
untracked: false,
|
|
1486
1481
|
created_at: "2026-04-23T00:00:00Z".to_string(),
|
|
@@ -28,11 +28,11 @@ pub(crate) struct VisibleFilesystem {
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
impl VisibleFilesystem {
|
|
31
|
-
/// Loads filesystem rows for a single
|
|
31
|
+
/// Loads filesystem rows for a single branch from execution-visible live
|
|
32
32
|
/// state and builds lookup indexes used by filesystem write planning.
|
|
33
33
|
pub(crate) async fn load(
|
|
34
34
|
live_state: Arc<dyn LiveStateReader>,
|
|
35
|
-
|
|
35
|
+
branch_id: &str,
|
|
36
36
|
) -> Result<Self, LixError> {
|
|
37
37
|
let rows = live_state
|
|
38
38
|
.scan_rows(&LiveStateScanRequest {
|
|
@@ -42,7 +42,7 @@ impl VisibleFilesystem {
|
|
|
42
42
|
FILE_DESCRIPTOR_SCHEMA_KEY.to_string(),
|
|
43
43
|
BLOB_REF_SCHEMA_KEY.to_string(),
|
|
44
44
|
],
|
|
45
|
-
|
|
45
|
+
branch_ids: vec![branch_id.to_string()],
|
|
46
46
|
..LiveStateFilter::default()
|
|
47
47
|
},
|
|
48
48
|
..LiveStateScanRequest::default()
|
|
@@ -185,7 +185,7 @@ fn filesystem_row_context(
|
|
|
185
185
|
row: &MaterializedLiveStateRow,
|
|
186
186
|
) -> Result<FilesystemRowContext, LixError> {
|
|
187
187
|
Ok(FilesystemRowContext {
|
|
188
|
-
|
|
188
|
+
branch_id: row.branch_id.clone(),
|
|
189
189
|
global: row.global,
|
|
190
190
|
untracked: row.untracked,
|
|
191
191
|
file_id: row.file_id.clone(),
|
|
@@ -232,7 +232,7 @@ mod tests {
|
|
|
232
232
|
r#"{"id":"dir-guides","parent_id":"dir-docs","name":"guides","hidden":false}"#,
|
|
233
233
|
),
|
|
234
234
|
]),
|
|
235
|
-
"
|
|
235
|
+
"branch-a",
|
|
236
236
|
)
|
|
237
237
|
.await
|
|
238
238
|
.expect("visible filesystem should load");
|
|
@@ -261,7 +261,7 @@ mod tests {
|
|
|
261
261
|
"file-readme",
|
|
262
262
|
r#"{"id":"file-readme","directory_id":"dir-guides","name":"readme.md","hidden":false}"#,
|
|
263
263
|
)]),
|
|
264
|
-
"
|
|
264
|
+
"branch-a",
|
|
265
265
|
)
|
|
266
266
|
.await
|
|
267
267
|
.expect("visible filesystem should load");
|
|
@@ -283,7 +283,7 @@ mod tests {
|
|
|
283
283
|
"file-readme",
|
|
284
284
|
r#"{"id":"file-readme","blob_hash":"abc123","size_bytes":5}"#,
|
|
285
285
|
)]),
|
|
286
|
-
"
|
|
286
|
+
"branch-a",
|
|
287
287
|
)
|
|
288
288
|
.await
|
|
289
289
|
.expect("visible filesystem should load");
|
|
@@ -316,8 +316,8 @@ mod tests {
|
|
|
316
316
|
.filter(|row| {
|
|
317
317
|
(request.filter.schema_keys.is_empty()
|
|
318
318
|
|| request.filter.schema_keys.contains(&row.schema_key))
|
|
319
|
-
&& (request.filter.
|
|
320
|
-
|| request.filter.
|
|
319
|
+
&& (request.filter.branch_ids.is_empty()
|
|
320
|
+
|| request.filter.branch_ids.contains(&row.branch_id))
|
|
321
321
|
})
|
|
322
322
|
.cloned()
|
|
323
323
|
.collect())
|
|
@@ -331,49 +331,49 @@ mod tests {
|
|
|
331
331
|
}
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
-
fn directory_row(
|
|
334
|
+
fn directory_row(entity_pk: &str, snapshot_content: &str) -> MaterializedLiveStateRow {
|
|
335
335
|
live_row(
|
|
336
|
-
|
|
336
|
+
entity_pk,
|
|
337
337
|
DIRECTORY_DESCRIPTOR_SCHEMA_KEY,
|
|
338
338
|
None,
|
|
339
339
|
snapshot_content,
|
|
340
340
|
)
|
|
341
341
|
}
|
|
342
342
|
|
|
343
|
-
fn file_row(
|
|
343
|
+
fn file_row(entity_pk: &str, snapshot_content: &str) -> MaterializedLiveStateRow {
|
|
344
344
|
live_row(
|
|
345
|
-
|
|
345
|
+
entity_pk,
|
|
346
346
|
FILE_DESCRIPTOR_SCHEMA_KEY,
|
|
347
347
|
None,
|
|
348
348
|
snapshot_content,
|
|
349
349
|
)
|
|
350
350
|
}
|
|
351
351
|
|
|
352
|
-
fn blob_ref_row(
|
|
352
|
+
fn blob_ref_row(entity_pk: &str, snapshot_content: &str) -> MaterializedLiveStateRow {
|
|
353
353
|
live_row(
|
|
354
|
-
|
|
354
|
+
entity_pk,
|
|
355
355
|
BLOB_REF_SCHEMA_KEY,
|
|
356
|
-
Some(
|
|
356
|
+
Some(entity_pk.to_string()),
|
|
357
357
|
snapshot_content,
|
|
358
358
|
)
|
|
359
359
|
}
|
|
360
360
|
|
|
361
361
|
fn live_row(
|
|
362
|
-
|
|
362
|
+
entity_pk: &str,
|
|
363
363
|
schema_key: &str,
|
|
364
364
|
file_id: Option<String>,
|
|
365
365
|
snapshot_content: &str,
|
|
366
366
|
) -> MaterializedLiveStateRow {
|
|
367
367
|
MaterializedLiveStateRow {
|
|
368
|
-
|
|
368
|
+
entity_pk: crate::entity_pk::EntityPk::single(entity_pk),
|
|
369
369
|
schema_key: schema_key.to_string(),
|
|
370
370
|
file_id,
|
|
371
371
|
snapshot_content: Some(snapshot_content.to_string()),
|
|
372
372
|
metadata: None,
|
|
373
373
|
deleted: false,
|
|
374
|
-
|
|
375
|
-
change_id: Some(format!("change-{
|
|
376
|
-
commit_id: Some(format!("commit-{
|
|
374
|
+
branch_id: "branch-a".to_string(),
|
|
375
|
+
change_id: Some(format!("change-{entity_pk}")),
|
|
376
|
+
commit_id: Some(format!("commit-{entity_pk}")),
|
|
377
377
|
global: false,
|
|
378
378
|
untracked: false,
|
|
379
379
|
created_at: "2026-04-23T00:00:00Z".to_string(),
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
use serde_json::Value as JsonValue;
|
|
2
2
|
|
|
3
|
-
use crate::
|
|
3
|
+
use crate::entity_pk::EntityPk;
|
|
4
4
|
use crate::LixError;
|
|
5
5
|
|
|
6
6
|
/// Shared projection contract for typed history views.
|
|
7
7
|
///
|
|
8
8
|
/// On tombstone rows (`snapshot_content IS NULL`), identity columns survive by
|
|
9
|
-
/// projecting from canonical entity
|
|
9
|
+
/// projecting from canonical entity primary key. Non-identity columns must remain
|
|
10
10
|
/// NULL because there is no snapshot to project payload from.
|
|
11
11
|
pub(crate) enum HistoryIdentityProjection<'a> {
|
|
12
12
|
PrimaryKeyPaths(&'a [Vec<String>]),
|
|
@@ -15,26 +15,26 @@ pub(crate) enum HistoryIdentityProjection<'a> {
|
|
|
15
15
|
|
|
16
16
|
pub(crate) fn tombstone_identity_column_value(
|
|
17
17
|
column_name: &str,
|
|
18
|
-
|
|
18
|
+
entity_pk: &str,
|
|
19
19
|
projection: HistoryIdentityProjection<'_>,
|
|
20
20
|
) -> Result<Option<JsonValue>, LixError> {
|
|
21
21
|
match projection {
|
|
22
22
|
HistoryIdentityProjection::SingleColumn { column } => {
|
|
23
23
|
if column_name == column {
|
|
24
|
-
Ok(Some(JsonValue::String(
|
|
24
|
+
Ok(Some(JsonValue::String(entity_pk.to_string())))
|
|
25
25
|
} else {
|
|
26
26
|
Ok(None)
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
HistoryIdentityProjection::PrimaryKeyPaths(primary_key_paths) => {
|
|
30
|
-
primary_key_tombstone_value(column_name,
|
|
30
|
+
primary_key_tombstone_value(column_name, entity_pk, primary_key_paths)
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
fn primary_key_tombstone_value(
|
|
36
36
|
column_name: &str,
|
|
37
|
-
|
|
37
|
+
entity_pk: &str,
|
|
38
38
|
primary_key_paths: &[Vec<String>],
|
|
39
39
|
) -> Result<Option<JsonValue>, LixError> {
|
|
40
40
|
let Some(part_index) = primary_key_paths
|
|
@@ -44,9 +44,9 @@ fn primary_key_tombstone_value(
|
|
|
44
44
|
return Ok(None);
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
-
let identity =
|
|
47
|
+
let identity = EntityPk::from_json_array_text(entity_pk).map_err(|error| {
|
|
48
48
|
LixError::unknown(format!(
|
|
49
|
-
"failed to decode history tombstone entity
|
|
49
|
+
"failed to decode history tombstone entity primary key: {error}"
|
|
50
50
|
))
|
|
51
51
|
})?;
|
|
52
52
|
Ok(identity
|