@lix-js/sdk 0.6.0-preview.3 → 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 +105 -65
- package/dist/engine-wasm/index.js +4 -4
- package/dist/engine-wasm/wasm/lix_engine.d.ts +30 -6
- package/dist/engine-wasm/wasm/lix_engine.js +187 -117
- package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
- package/dist/engine-wasm/wasm/lix_engine.wasm.d.ts +14 -8
- package/dist/generated/builtin-schemas.d.ts +69 -69
- package/dist/generated/builtin-schemas.js +94 -94
- package/dist/open-lix.d.ts +42 -28
- package/dist/open-lix.js +49 -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 +819 -124
- package/dist-engine-src/src/session/create_branch.rs +94 -0
- package/dist-engine-src/src/session/execute.rs +260 -57
- 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 +19 -16
- package/dist-engine-src/src/session/switch_branch.rs +113 -0
- package/dist-engine-src/src/session/transaction.rs +557 -0
- package/dist-engine-src/src/sql2/bind/classify.rs +102 -0
- 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} +98 -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 +4 -5
- 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 +30 -24
- 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 -109
- package/dist-engine-src/src/sql2/classify.rs +0 -182
- package/dist-engine-src/src/sql2/entity_provider.rs +0 -3211
- package/dist-engine-src/src/sql2/execute.rs +0 -3440
- 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 -166
- package/dist-engine-src/src/sql2/public_bind/mod.rs +0 -25
- 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
|
@@ -10,7 +10,7 @@ use datafusion::arrow::compute::{and, filter_record_batch};
|
|
|
10
10
|
use datafusion::arrow::datatypes::{DataType, Field, Schema, SchemaRef};
|
|
11
11
|
use datafusion::arrow::record_batch::RecordBatch;
|
|
12
12
|
use datafusion::catalog::{Session, TableProvider};
|
|
13
|
-
use datafusion::common::{not_impl_err, DFSchema, DataFusionError, Result, ScalarValue};
|
|
13
|
+
use datafusion::common::{not_impl_err, DFSchema, DataFusionError, Result, ScalarValue, SchemaExt};
|
|
14
14
|
use datafusion::datasource::TableType;
|
|
15
15
|
use datafusion::execution::TaskContext;
|
|
16
16
|
use datafusion::logical_expr::dml::InsertOp;
|
|
@@ -25,90 +25,108 @@ use datafusion::prelude::SessionContext;
|
|
|
25
25
|
use futures_util::{stream, TryStreamExt};
|
|
26
26
|
use serde::Deserialize;
|
|
27
27
|
|
|
28
|
+
use crate::branch::BranchRefReader;
|
|
28
29
|
use crate::functions::FunctionProviderHandle;
|
|
29
30
|
use crate::live_state::MaterializedLiveStateRow;
|
|
30
31
|
use crate::live_state::{
|
|
31
32
|
LiveStateFilter, LiveStateProjection, LiveStateReader, LiveStateScanRequest,
|
|
32
33
|
};
|
|
34
|
+
use crate::sql2::branch_scope::{
|
|
35
|
+
explicit_branch_ids_from_dml_filters, resolve_provider_branch_ids, resolve_write_branch_scope,
|
|
36
|
+
BranchBinding,
|
|
37
|
+
};
|
|
33
38
|
use crate::sql2::dml::{InsertExec, InsertSink};
|
|
34
39
|
use crate::sql2::filesystem_predicates::{
|
|
35
40
|
canonicalize_filesystem_path_filters, FilesystemPathKind,
|
|
36
41
|
};
|
|
37
|
-
use crate::sql2::predicate_typecheck::
|
|
38
|
-
|
|
39
|
-
explicit_version_ids_from_dml_filters, resolve_provider_version_ids,
|
|
40
|
-
resolve_write_version_scope, VersionBinding,
|
|
42
|
+
use crate::sql2::predicate_typecheck::{
|
|
43
|
+
canonicalize_json_identity_text_filters, validate_json_predicate_filters,
|
|
41
44
|
};
|
|
42
45
|
use crate::sql2::write_normalization::{InsertCell, SqlCell, UpdateAssignmentValues};
|
|
43
46
|
use crate::transaction::types::{
|
|
44
47
|
LogicalPrimaryKey, TransactionJson, TransactionWriteOperation, TransactionWriteOrigin,
|
|
45
48
|
TransactionWriteRow,
|
|
46
49
|
};
|
|
47
|
-
use crate::version::VersionRefReader;
|
|
48
50
|
use crate::{parse_row_metadata_value, serialize_row_metadata, LixError};
|
|
49
51
|
|
|
50
|
-
use
|
|
52
|
+
use crate::sql2::filesystem_planner::{
|
|
51
53
|
directory_descriptor_write_row, directory_path_resolvers_from_state_rows,
|
|
52
54
|
filesystem_storage_scope_key, plan_recursive_directory_delete, DirectoryDescriptorWriteIntent,
|
|
53
55
|
DirectoryPathResolver, FilesystemDeletePlan, FilesystemRowContext,
|
|
54
56
|
};
|
|
55
|
-
use
|
|
56
|
-
use
|
|
57
|
+
use crate::sql2::filesystem_visibility::VisibleFilesystem;
|
|
58
|
+
use crate::sql2::result_metadata::json_field;
|
|
57
59
|
use crate::sql2::{
|
|
58
|
-
SqlWriteContext, WriteAccess,
|
|
60
|
+
SqlWriteContext, WriteAccess, WriteContextBranchRefReader, WriteContextLiveStateReader,
|
|
59
61
|
};
|
|
60
62
|
use crate::transaction::types::{TransactionWrite, TransactionWriteMode};
|
|
61
63
|
|
|
62
64
|
const DIRECTORY_SCHEMA_KEY: &str = "lix_directory_descriptor";
|
|
63
65
|
const FILE_DESCRIPTOR_SCHEMA_KEY: &str = "lix_file_descriptor";
|
|
64
66
|
|
|
65
|
-
pub(
|
|
67
|
+
pub(super) async fn register_lix_directory_active_provider(
|
|
66
68
|
session: &SessionContext,
|
|
67
|
-
|
|
69
|
+
surface_name: &str,
|
|
70
|
+
active_branch_id: &str,
|
|
68
71
|
live_state: Arc<dyn LiveStateReader>,
|
|
69
|
-
|
|
72
|
+
branch_ref: Arc<dyn BranchRefReader>,
|
|
70
73
|
functions: FunctionProviderHandle,
|
|
71
74
|
) -> Result<(), LixError> {
|
|
72
75
|
session
|
|
73
76
|
.register_table(
|
|
74
|
-
|
|
75
|
-
Arc::new(LixDirectoryProvider::
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
surface_name,
|
|
78
|
+
Arc::new(LixDirectoryProvider::active_branch(
|
|
79
|
+
active_branch_id,
|
|
80
|
+
live_state,
|
|
81
|
+
branch_ref,
|
|
82
|
+
functions,
|
|
79
83
|
)),
|
|
80
84
|
)
|
|
81
85
|
.map_err(datafusion_error_to_lix_error)?;
|
|
86
|
+
Ok(())
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
pub(super) async fn register_lix_directory_by_branch_provider(
|
|
90
|
+
session: &SessionContext,
|
|
91
|
+
surface_name: &str,
|
|
92
|
+
live_state: Arc<dyn LiveStateReader>,
|
|
93
|
+
branch_ref: Arc<dyn BranchRefReader>,
|
|
94
|
+
functions: FunctionProviderHandle,
|
|
95
|
+
) -> Result<(), LixError> {
|
|
82
96
|
session
|
|
83
97
|
.register_table(
|
|
84
|
-
|
|
85
|
-
Arc::new(LixDirectoryProvider::
|
|
86
|
-
|
|
87
|
-
live_state,
|
|
88
|
-
version_ref,
|
|
89
|
-
functions,
|
|
98
|
+
surface_name,
|
|
99
|
+
Arc::new(LixDirectoryProvider::by_branch(
|
|
100
|
+
live_state, branch_ref, functions,
|
|
90
101
|
)),
|
|
91
102
|
)
|
|
92
103
|
.map_err(datafusion_error_to_lix_error)?;
|
|
93
104
|
Ok(())
|
|
94
105
|
}
|
|
95
106
|
|
|
96
|
-
pub(
|
|
107
|
+
pub(super) async fn register_by_branch_write_provider(
|
|
97
108
|
session: &SessionContext,
|
|
109
|
+
surface_name: &str,
|
|
98
110
|
write_ctx: SqlWriteContext,
|
|
99
111
|
) -> Result<(), LixError> {
|
|
100
112
|
session
|
|
101
113
|
.register_table(
|
|
102
|
-
|
|
103
|
-
Arc::new(LixDirectoryProvider::
|
|
104
|
-
write_ctx.clone(),
|
|
105
|
-
)),
|
|
114
|
+
surface_name,
|
|
115
|
+
Arc::new(LixDirectoryProvider::by_branch_with_write(write_ctx)),
|
|
106
116
|
)
|
|
107
117
|
.map_err(datafusion_error_to_lix_error)?;
|
|
118
|
+
Ok(())
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
pub(super) async fn register_active_write_provider(
|
|
122
|
+
session: &SessionContext,
|
|
123
|
+
surface_name: &str,
|
|
124
|
+
write_ctx: SqlWriteContext,
|
|
125
|
+
) -> Result<(), LixError> {
|
|
108
126
|
session
|
|
109
127
|
.register_table(
|
|
110
|
-
|
|
111
|
-
Arc::new(LixDirectoryProvider::
|
|
128
|
+
surface_name,
|
|
129
|
+
Arc::new(LixDirectoryProvider::active_branch_with_write(write_ctx)),
|
|
112
130
|
)
|
|
113
131
|
.map_err(datafusion_error_to_lix_error)?;
|
|
114
132
|
Ok(())
|
|
@@ -117,10 +135,10 @@ pub(crate) async fn register_lix_directory_write_providers(
|
|
|
117
135
|
pub(crate) struct LixDirectoryProvider {
|
|
118
136
|
schema: SchemaRef,
|
|
119
137
|
live_state: Arc<dyn LiveStateReader>,
|
|
120
|
-
|
|
138
|
+
branch_ref: Arc<dyn BranchRefReader>,
|
|
121
139
|
write_access: WriteAccess,
|
|
122
140
|
functions: FunctionProviderHandle,
|
|
123
|
-
|
|
141
|
+
branch_binding: BranchBinding,
|
|
124
142
|
}
|
|
125
143
|
|
|
126
144
|
impl std::fmt::Debug for LixDirectoryProvider {
|
|
@@ -130,63 +148,63 @@ impl std::fmt::Debug for LixDirectoryProvider {
|
|
|
130
148
|
}
|
|
131
149
|
|
|
132
150
|
impl LixDirectoryProvider {
|
|
133
|
-
fn
|
|
134
|
-
|
|
151
|
+
fn active_branch(
|
|
152
|
+
active_branch_id: impl Into<String>,
|
|
135
153
|
live_state: Arc<dyn LiveStateReader>,
|
|
136
|
-
|
|
154
|
+
branch_ref: Arc<dyn BranchRefReader>,
|
|
137
155
|
functions: FunctionProviderHandle,
|
|
138
156
|
) -> Self {
|
|
139
157
|
Self {
|
|
140
158
|
schema: lix_directory_schema(),
|
|
141
159
|
live_state,
|
|
142
|
-
|
|
160
|
+
branch_ref,
|
|
143
161
|
write_access: WriteAccess::read_only(),
|
|
144
162
|
functions,
|
|
145
|
-
|
|
163
|
+
branch_binding: BranchBinding::active(active_branch_id),
|
|
146
164
|
}
|
|
147
165
|
}
|
|
148
166
|
|
|
149
|
-
fn
|
|
150
|
-
let
|
|
167
|
+
fn active_branch_with_write(write_ctx: SqlWriteContext) -> Self {
|
|
168
|
+
let active_branch_id = write_ctx.active_branch_id();
|
|
151
169
|
let functions = write_ctx.functions();
|
|
152
170
|
let live_state = Arc::new(WriteContextLiveStateReader::new(write_ctx.clone()));
|
|
153
|
-
let
|
|
171
|
+
let branch_ref = Arc::new(WriteContextBranchRefReader::new(write_ctx.clone()));
|
|
154
172
|
Self {
|
|
155
173
|
schema: lix_directory_schema(),
|
|
156
174
|
live_state,
|
|
157
|
-
|
|
175
|
+
branch_ref,
|
|
158
176
|
write_access: WriteAccess::write(write_ctx),
|
|
159
177
|
functions,
|
|
160
|
-
|
|
178
|
+
branch_binding: BranchBinding::active(active_branch_id),
|
|
161
179
|
}
|
|
162
180
|
}
|
|
163
181
|
|
|
164
|
-
fn
|
|
182
|
+
fn by_branch(
|
|
165
183
|
live_state: Arc<dyn LiveStateReader>,
|
|
166
|
-
|
|
184
|
+
branch_ref: Arc<dyn BranchRefReader>,
|
|
167
185
|
functions: FunctionProviderHandle,
|
|
168
186
|
) -> Self {
|
|
169
187
|
Self {
|
|
170
|
-
schema:
|
|
188
|
+
schema: lix_directory_by_branch_schema(),
|
|
171
189
|
live_state,
|
|
172
|
-
|
|
190
|
+
branch_ref,
|
|
173
191
|
write_access: WriteAccess::read_only(),
|
|
174
192
|
functions,
|
|
175
|
-
|
|
193
|
+
branch_binding: BranchBinding::explicit(),
|
|
176
194
|
}
|
|
177
195
|
}
|
|
178
196
|
|
|
179
|
-
fn
|
|
197
|
+
fn by_branch_with_write(write_ctx: SqlWriteContext) -> Self {
|
|
180
198
|
let functions = write_ctx.functions();
|
|
181
199
|
let live_state = Arc::new(WriteContextLiveStateReader::new(write_ctx.clone()));
|
|
182
|
-
let
|
|
200
|
+
let branch_ref = Arc::new(WriteContextBranchRefReader::new(write_ctx.clone()));
|
|
183
201
|
Self {
|
|
184
|
-
schema:
|
|
202
|
+
schema: lix_directory_by_branch_schema(),
|
|
185
203
|
live_state,
|
|
186
|
-
|
|
204
|
+
branch_ref,
|
|
187
205
|
write_access: WriteAccess::write(write_ctx),
|
|
188
206
|
functions,
|
|
189
|
-
|
|
207
|
+
branch_binding: BranchBinding::explicit(),
|
|
190
208
|
}
|
|
191
209
|
}
|
|
192
210
|
}
|
|
@@ -225,24 +243,14 @@ impl TableProvider for LixDirectoryProvider {
|
|
|
225
243
|
let projected_schema = projected_schema(&self.schema, projection)?;
|
|
226
244
|
let scan_limit = if filters.is_empty() { limit } else { None };
|
|
227
245
|
let mut request = lix_directory_scan_request(
|
|
228
|
-
self.
|
|
246
|
+
self.branch_binding.active_branch_id(),
|
|
229
247
|
Some(projected_schema.as_ref()),
|
|
230
248
|
scan_limit,
|
|
231
249
|
);
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
return Err(DataFusionError::Plan(
|
|
237
|
-
"DELETE FROM lix_directory_by_version requires an explicit lixcol_version_id predicate"
|
|
238
|
-
.to_string(),
|
|
239
|
-
));
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
request.filter.version_ids = resolve_provider_version_ids(
|
|
243
|
-
self.version_ref.as_ref(),
|
|
244
|
-
&self.version_binding,
|
|
245
|
-
request.filter.version_ids,
|
|
250
|
+
request.filter.branch_ids = resolve_provider_branch_ids(
|
|
251
|
+
self.branch_ref.as_ref(),
|
|
252
|
+
&self.branch_binding,
|
|
253
|
+
request.filter.branch_ids,
|
|
246
254
|
)
|
|
247
255
|
.await
|
|
248
256
|
.map_err(lix_error_to_datafusion_error)?;
|
|
@@ -273,16 +281,15 @@ impl TableProvider for LixDirectoryProvider {
|
|
|
273
281
|
if insert_op != InsertOp::Append {
|
|
274
282
|
return not_impl_err!("{insert_op} not implemented for lix_directory yet");
|
|
275
283
|
}
|
|
276
|
-
|
|
277
284
|
let write_ctx = self
|
|
278
285
|
.write_access
|
|
279
286
|
.require_write("INSERT into lix_directory")?;
|
|
280
|
-
|
|
287
|
+
self.schema
|
|
288
|
+
.logically_equivalent_names_and_types(&input.schema())?;
|
|
281
289
|
let sink = LixDirectoryInsertSink::new(
|
|
282
|
-
|
|
283
|
-
write_ctx.clone(),
|
|
290
|
+
write_ctx,
|
|
284
291
|
self.functions.clone(),
|
|
285
|
-
self.
|
|
292
|
+
self.branch_binding.clone(),
|
|
286
293
|
);
|
|
287
294
|
Ok(Arc::new(InsertExec::new(input, Arc::new(sink))))
|
|
288
295
|
}
|
|
@@ -295,31 +302,29 @@ impl TableProvider for LixDirectoryProvider {
|
|
|
295
302
|
let write_ctx = self
|
|
296
303
|
.write_access
|
|
297
304
|
.require_write("DELETE FROM lix_directory")?;
|
|
298
|
-
|
|
299
|
-
let df_schema = DFSchema::try_from(Arc::clone(&self.schema))?;
|
|
300
305
|
let filters =
|
|
301
306
|
canonicalize_filesystem_path_filters(&filters, FilesystemPathKind::Directory)?;
|
|
307
|
+
let filters = canonicalize_json_identity_text_filters(self.schema.as_ref(), &filters)?;
|
|
308
|
+
let df_schema = DFSchema::try_from(Arc::clone(&self.schema))?;
|
|
302
309
|
validate_json_predicate_filters(self.schema.as_ref(), &filters)?;
|
|
303
310
|
let physical_filters = filters
|
|
304
311
|
.iter()
|
|
305
312
|
.map(|expr| create_physical_expr(expr, &df_schema, state.execution_props()))
|
|
306
313
|
.collect::<Result<Vec<_>>>()?;
|
|
307
314
|
let mut request =
|
|
308
|
-
lix_directory_scan_request(self.
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
}
|
|
318
|
-
|
|
315
|
+
lix_directory_scan_request(self.branch_binding.active_branch_id(), None, None);
|
|
316
|
+
request.filter.branch_ids = explicit_branch_ids_from_dml_filters(&filters);
|
|
317
|
+
request.filter.branch_ids = resolve_provider_branch_ids(
|
|
318
|
+
self.branch_ref.as_ref(),
|
|
319
|
+
&self.branch_binding,
|
|
320
|
+
request.filter.branch_ids,
|
|
321
|
+
)
|
|
322
|
+
.await
|
|
323
|
+
.map_err(lix_error_to_datafusion_error)?;
|
|
319
324
|
Ok(Arc::new(LixDirectoryDeleteExec::new(
|
|
320
|
-
write_ctx
|
|
325
|
+
write_ctx,
|
|
321
326
|
Arc::clone(&self.schema),
|
|
322
|
-
self.
|
|
327
|
+
self.branch_binding.clone(),
|
|
323
328
|
request,
|
|
324
329
|
physical_filters,
|
|
325
330
|
)))
|
|
@@ -332,10 +337,12 @@ impl TableProvider for LixDirectoryProvider {
|
|
|
332
337
|
filters: Vec<Expr>,
|
|
333
338
|
) -> Result<Arc<dyn ExecutionPlan>> {
|
|
334
339
|
let write_ctx = self.write_access.require_write("UPDATE lix_directory")?;
|
|
335
|
-
|
|
336
340
|
validate_lix_directory_update_assignments(&self.schema, &assignments)?;
|
|
337
|
-
|
|
341
|
+
let filters =
|
|
342
|
+
canonicalize_filesystem_path_filters(&filters, FilesystemPathKind::Directory)?;
|
|
343
|
+
let filters = canonicalize_json_identity_text_filters(self.schema.as_ref(), &filters)?;
|
|
338
344
|
let df_schema = DFSchema::try_from(Arc::clone(&self.schema))?;
|
|
345
|
+
validate_json_predicate_filters(self.schema.as_ref(), &filters)?;
|
|
339
346
|
let physical_assignments = assignments
|
|
340
347
|
.iter()
|
|
341
348
|
.map(|(column_name, expr)| {
|
|
@@ -345,20 +352,24 @@ impl TableProvider for LixDirectoryProvider {
|
|
|
345
352
|
))
|
|
346
353
|
})
|
|
347
354
|
.collect::<Result<Vec<_>>>()?;
|
|
348
|
-
let filters =
|
|
349
|
-
canonicalize_filesystem_path_filters(&filters, FilesystemPathKind::Directory)?;
|
|
350
|
-
validate_json_predicate_filters(self.schema.as_ref(), &filters)?;
|
|
351
355
|
let physical_filters = filters
|
|
352
356
|
.iter()
|
|
353
357
|
.map(|expr| create_physical_expr(expr, &df_schema, state.execution_props()))
|
|
354
358
|
.collect::<Result<Vec<_>>>()?;
|
|
355
|
-
let request =
|
|
356
|
-
lix_directory_scan_request(self.
|
|
357
|
-
|
|
359
|
+
let mut request =
|
|
360
|
+
lix_directory_scan_request(self.branch_binding.active_branch_id(), None, None);
|
|
361
|
+
request.filter.branch_ids = explicit_branch_ids_from_dml_filters(&filters);
|
|
362
|
+
request.filter.branch_ids = resolve_provider_branch_ids(
|
|
363
|
+
self.branch_ref.as_ref(),
|
|
364
|
+
&self.branch_binding,
|
|
365
|
+
request.filter.branch_ids,
|
|
366
|
+
)
|
|
367
|
+
.await
|
|
368
|
+
.map_err(lix_error_to_datafusion_error)?;
|
|
358
369
|
Ok(Arc::new(LixDirectoryUpdateExec::new(
|
|
359
|
-
write_ctx
|
|
370
|
+
write_ctx,
|
|
360
371
|
Arc::clone(&self.schema),
|
|
361
|
-
self.
|
|
372
|
+
self.branch_binding.clone(),
|
|
362
373
|
request,
|
|
363
374
|
physical_assignments,
|
|
364
375
|
physical_filters,
|
|
@@ -369,7 +380,7 @@ impl TableProvider for LixDirectoryProvider {
|
|
|
369
380
|
struct LixDirectoryInsertSink {
|
|
370
381
|
write_ctx: SqlWriteContext,
|
|
371
382
|
functions: FunctionProviderHandle,
|
|
372
|
-
|
|
383
|
+
branch_binding: BranchBinding,
|
|
373
384
|
surface_name: &'static str,
|
|
374
385
|
}
|
|
375
386
|
|
|
@@ -381,16 +392,15 @@ impl std::fmt::Debug for LixDirectoryInsertSink {
|
|
|
381
392
|
|
|
382
393
|
impl LixDirectoryInsertSink {
|
|
383
394
|
fn new(
|
|
384
|
-
_schema: SchemaRef,
|
|
385
395
|
write_ctx: SqlWriteContext,
|
|
386
396
|
functions: FunctionProviderHandle,
|
|
387
|
-
|
|
397
|
+
branch_binding: BranchBinding,
|
|
388
398
|
) -> Self {
|
|
389
|
-
let surface_name = lix_directory_surface_name(&
|
|
399
|
+
let surface_name = lix_directory_surface_name(&branch_binding);
|
|
390
400
|
Self {
|
|
391
401
|
write_ctx,
|
|
392
402
|
functions,
|
|
393
|
-
|
|
403
|
+
branch_binding,
|
|
394
404
|
surface_name,
|
|
395
405
|
}
|
|
396
406
|
}
|
|
@@ -422,7 +432,7 @@ impl InsertSink for LixDirectoryInsertSink {
|
|
|
422
432
|
path_resolvers = Some(
|
|
423
433
|
directory_path_resolvers_from_live_state(
|
|
424
434
|
Arc::new(WriteContextLiveStateReader::new(self.write_ctx.clone())),
|
|
425
|
-
self.
|
|
435
|
+
self.branch_binding.active_branch_id(),
|
|
426
436
|
)
|
|
427
437
|
.await
|
|
428
438
|
.map_err(lix_error_to_datafusion_error)?,
|
|
@@ -438,7 +448,7 @@ impl InsertSink for LixDirectoryInsertSink {
|
|
|
438
448
|
if record_batch_has_non_null_column(&batch, "path")? {
|
|
439
449
|
rows.extend(lix_directory_write_rows_from_batch_with_path_resolvers(
|
|
440
450
|
&batch,
|
|
441
|
-
self.
|
|
451
|
+
self.branch_binding.active_branch_id(),
|
|
442
452
|
self.surface_name,
|
|
443
453
|
path_resolvers
|
|
444
454
|
.as_mut()
|
|
@@ -449,7 +459,7 @@ impl InsertSink for LixDirectoryInsertSink {
|
|
|
449
459
|
rows.extend(
|
|
450
460
|
lix_directory_write_rows_from_batch_with_options_and_path_resolvers(
|
|
451
461
|
&batch,
|
|
452
|
-
self.
|
|
462
|
+
self.branch_binding.active_branch_id(),
|
|
453
463
|
self.surface_name,
|
|
454
464
|
true,
|
|
455
465
|
path_resolvers.as_mut(),
|
|
@@ -471,10 +481,10 @@ impl InsertSink for LixDirectoryInsertSink {
|
|
|
471
481
|
}
|
|
472
482
|
}
|
|
473
483
|
|
|
474
|
-
fn lix_directory_surface_name(
|
|
475
|
-
match
|
|
476
|
-
|
|
477
|
-
|
|
484
|
+
fn lix_directory_surface_name(branch_binding: &BranchBinding) -> &'static str {
|
|
485
|
+
match branch_binding {
|
|
486
|
+
BranchBinding::Active { .. } => "lix_directory",
|
|
487
|
+
BranchBinding::Explicit => "lix_directory_by_branch",
|
|
478
488
|
}
|
|
479
489
|
}
|
|
480
490
|
|
|
@@ -482,7 +492,7 @@ fn lix_directory_surface_name(version_binding: &VersionBinding) -> &'static str
|
|
|
482
492
|
struct LixDirectoryDeleteExec {
|
|
483
493
|
write_ctx: SqlWriteContext,
|
|
484
494
|
table_schema: SchemaRef,
|
|
485
|
-
|
|
495
|
+
branch_binding: BranchBinding,
|
|
486
496
|
request: LiveStateScanRequest,
|
|
487
497
|
filters: Vec<Arc<dyn PhysicalExpr>>,
|
|
488
498
|
result_schema: SchemaRef,
|
|
@@ -499,7 +509,7 @@ impl LixDirectoryDeleteExec {
|
|
|
499
509
|
fn new(
|
|
500
510
|
write_ctx: SqlWriteContext,
|
|
501
511
|
table_schema: SchemaRef,
|
|
502
|
-
|
|
512
|
+
branch_binding: BranchBinding,
|
|
503
513
|
request: LiveStateScanRequest,
|
|
504
514
|
filters: Vec<Arc<dyn PhysicalExpr>>,
|
|
505
515
|
) -> Self {
|
|
@@ -513,7 +523,7 @@ impl LixDirectoryDeleteExec {
|
|
|
513
523
|
Self {
|
|
514
524
|
write_ctx,
|
|
515
525
|
table_schema,
|
|
516
|
-
|
|
526
|
+
branch_binding,
|
|
517
527
|
request,
|
|
518
528
|
filters,
|
|
519
529
|
result_schema,
|
|
@@ -574,7 +584,7 @@ impl ExecutionPlan for LixDirectoryDeleteExec {
|
|
|
574
584
|
}
|
|
575
585
|
let write_ctx = self.write_ctx.clone();
|
|
576
586
|
let table_schema = Arc::clone(&self.table_schema);
|
|
577
|
-
let
|
|
587
|
+
let branch_binding = self.branch_binding.clone();
|
|
578
588
|
let request = self.request.clone();
|
|
579
589
|
let filters = self.filters.clone();
|
|
580
590
|
let result_schema = Arc::clone(&self.result_schema);
|
|
@@ -588,17 +598,15 @@ impl ExecutionPlan for LixDirectoryDeleteExec {
|
|
|
588
598
|
let source_batch = lix_directory_record_batch(&table_schema, rows)
|
|
589
599
|
.map_err(lix_error_to_datafusion_error)?;
|
|
590
600
|
let matched_batch = filter_lix_directory_batch(source_batch, &filters)?;
|
|
591
|
-
let
|
|
592
|
-
&matched_batch,
|
|
593
|
-
version_binding.active_version_id(),
|
|
594
|
-
)?;
|
|
601
|
+
let branch_ids =
|
|
602
|
+
directory_branch_ids_from_batch(&matched_batch, branch_binding.active_branch_id())?;
|
|
595
603
|
let mut visible_filesystems = BTreeMap::new();
|
|
596
|
-
for
|
|
604
|
+
for branch_id in branch_ids {
|
|
597
605
|
visible_filesystems.insert(
|
|
598
|
-
|
|
606
|
+
branch_id.clone(),
|
|
599
607
|
VisibleFilesystem::load(
|
|
600
608
|
Arc::new(WriteContextLiveStateReader::new(write_ctx.clone())),
|
|
601
|
-
&
|
|
609
|
+
&branch_id,
|
|
602
610
|
)
|
|
603
611
|
.await
|
|
604
612
|
.map_err(lix_error_to_datafusion_error)?,
|
|
@@ -606,7 +614,7 @@ impl ExecutionPlan for LixDirectoryDeleteExec {
|
|
|
606
614
|
}
|
|
607
615
|
let (write_rows, count) = lix_directory_recursive_delete_rows_from_batch(
|
|
608
616
|
&matched_batch,
|
|
609
|
-
|
|
617
|
+
branch_binding.active_branch_id(),
|
|
610
618
|
&visible_filesystems,
|
|
611
619
|
)?;
|
|
612
620
|
|
|
@@ -637,7 +645,7 @@ impl ExecutionPlan for LixDirectoryDeleteExec {
|
|
|
637
645
|
struct LixDirectoryUpdateExec {
|
|
638
646
|
write_ctx: SqlWriteContext,
|
|
639
647
|
table_schema: SchemaRef,
|
|
640
|
-
|
|
648
|
+
branch_binding: BranchBinding,
|
|
641
649
|
request: LiveStateScanRequest,
|
|
642
650
|
assignments: Vec<(String, Arc<dyn PhysicalExpr>)>,
|
|
643
651
|
filters: Vec<Arc<dyn PhysicalExpr>>,
|
|
@@ -655,7 +663,7 @@ impl LixDirectoryUpdateExec {
|
|
|
655
663
|
fn new(
|
|
656
664
|
write_ctx: SqlWriteContext,
|
|
657
665
|
table_schema: SchemaRef,
|
|
658
|
-
|
|
666
|
+
branch_binding: BranchBinding,
|
|
659
667
|
request: LiveStateScanRequest,
|
|
660
668
|
assignments: Vec<(String, Arc<dyn PhysicalExpr>)>,
|
|
661
669
|
filters: Vec<Arc<dyn PhysicalExpr>>,
|
|
@@ -670,7 +678,7 @@ impl LixDirectoryUpdateExec {
|
|
|
670
678
|
Self {
|
|
671
679
|
write_ctx,
|
|
672
680
|
table_schema,
|
|
673
|
-
|
|
681
|
+
branch_binding,
|
|
674
682
|
request,
|
|
675
683
|
assignments,
|
|
676
684
|
filters,
|
|
@@ -737,7 +745,7 @@ impl ExecutionPlan for LixDirectoryUpdateExec {
|
|
|
737
745
|
}
|
|
738
746
|
let write_ctx = self.write_ctx.clone();
|
|
739
747
|
let table_schema = Arc::clone(&self.table_schema);
|
|
740
|
-
let
|
|
748
|
+
let branch_binding = self.branch_binding.clone();
|
|
741
749
|
let request = self.request.clone();
|
|
742
750
|
let assignments = self.assignments.clone();
|
|
743
751
|
let filters = self.filters.clone();
|
|
@@ -754,14 +762,14 @@ impl ExecutionPlan for LixDirectoryUpdateExec {
|
|
|
754
762
|
let matched_batch = filter_lix_directory_batch(source_batch, &filters)?;
|
|
755
763
|
let mut path_resolvers = directory_path_resolvers_from_live_state(
|
|
756
764
|
Arc::new(WriteContextLiveStateReader::new(write_ctx.clone())),
|
|
757
|
-
|
|
765
|
+
branch_binding.active_branch_id(),
|
|
758
766
|
)
|
|
759
767
|
.await
|
|
760
768
|
.map_err(lix_error_to_datafusion_error)?;
|
|
761
769
|
let write_rows = lix_directory_update_write_rows_from_batch(
|
|
762
770
|
&matched_batch,
|
|
763
771
|
&assignments,
|
|
764
|
-
|
|
772
|
+
branch_binding.active_branch_id(),
|
|
765
773
|
&mut path_resolvers,
|
|
766
774
|
)?;
|
|
767
775
|
let count = u64::try_from(write_rows.len()).map_err(|_| {
|
|
@@ -942,21 +950,21 @@ struct DirectoryDescriptorSnapshot {
|
|
|
942
950
|
#[cfg(test)]
|
|
943
951
|
fn lix_directory_write_rows_from_batch(
|
|
944
952
|
batch: &RecordBatch,
|
|
945
|
-
|
|
953
|
+
branch_binding: Option<&str>,
|
|
946
954
|
) -> Result<Vec<TransactionWriteRow>> {
|
|
947
|
-
lix_directory_write_rows_from_batch_with_options(batch,
|
|
955
|
+
lix_directory_write_rows_from_batch_with_options(batch, branch_binding, "lix_directory", true)
|
|
948
956
|
}
|
|
949
957
|
|
|
950
958
|
fn lix_directory_write_rows_from_batch_with_path_resolvers(
|
|
951
959
|
batch: &RecordBatch,
|
|
952
|
-
|
|
960
|
+
branch_binding: Option<&str>,
|
|
953
961
|
surface_name: &str,
|
|
954
962
|
path_resolvers: &mut BTreeMap<String, DirectoryPathResolver>,
|
|
955
963
|
generate_directory_id: &mut dyn FnMut() -> String,
|
|
956
964
|
) -> Result<Vec<TransactionWriteRow>> {
|
|
957
965
|
lix_directory_write_rows_from_batch_with_options_and_path_resolvers(
|
|
958
966
|
batch,
|
|
959
|
-
|
|
967
|
+
branch_binding,
|
|
960
968
|
surface_name,
|
|
961
969
|
true,
|
|
962
970
|
Some(path_resolvers),
|
|
@@ -967,7 +975,7 @@ fn lix_directory_write_rows_from_batch_with_path_resolvers(
|
|
|
967
975
|
fn lix_directory_update_write_rows_from_batch(
|
|
968
976
|
batch: &RecordBatch,
|
|
969
977
|
assignments: &[(String, Arc<dyn PhysicalExpr>)],
|
|
970
|
-
|
|
978
|
+
branch_binding: Option<&str>,
|
|
971
979
|
path_resolvers: &mut BTreeMap<String, DirectoryPathResolver>,
|
|
972
980
|
) -> Result<Vec<TransactionWriteRow>> {
|
|
973
981
|
let assignment_values = UpdateAssignmentValues::evaluate(batch, assignments)?;
|
|
@@ -978,7 +986,7 @@ fn lix_directory_update_write_rows_from_batch(
|
|
|
978
986
|
batch,
|
|
979
987
|
&assignment_values,
|
|
980
988
|
row_index,
|
|
981
|
-
|
|
989
|
+
branch_binding,
|
|
982
990
|
)?;
|
|
983
991
|
let parent_id =
|
|
984
992
|
update_optional_string_value(batch, &assignment_values, row_index, "parent_id")?;
|
|
@@ -1004,22 +1012,21 @@ fn lix_directory_update_write_rows_from_batch(
|
|
|
1004
1012
|
Ok(rows)
|
|
1005
1013
|
}
|
|
1006
1014
|
|
|
1007
|
-
fn
|
|
1015
|
+
fn directory_branch_ids_from_batch(
|
|
1008
1016
|
batch: &RecordBatch,
|
|
1009
|
-
|
|
1017
|
+
branch_binding: Option<&str>,
|
|
1010
1018
|
) -> Result<BTreeSet<String>> {
|
|
1011
|
-
let mut
|
|
1019
|
+
let mut branch_ids = BTreeSet::new();
|
|
1012
1020
|
for row_index in 0..batch.num_rows() {
|
|
1013
|
-
|
|
1014
|
-
directory_row_context_from_batch(batch, row_index,
|
|
1015
|
-
);
|
|
1021
|
+
branch_ids
|
|
1022
|
+
.insert(directory_row_context_from_batch(batch, row_index, branch_binding)?.branch_id);
|
|
1016
1023
|
}
|
|
1017
|
-
Ok(
|
|
1024
|
+
Ok(branch_ids)
|
|
1018
1025
|
}
|
|
1019
1026
|
|
|
1020
1027
|
fn lix_directory_recursive_delete_rows_from_batch(
|
|
1021
1028
|
batch: &RecordBatch,
|
|
1022
|
-
|
|
1029
|
+
branch_binding: Option<&str>,
|
|
1023
1030
|
visible_filesystems: &BTreeMap<String, VisibleFilesystem>,
|
|
1024
1031
|
) -> Result<(Vec<TransactionWriteRow>, u64)> {
|
|
1025
1032
|
let mut rows = Vec::new();
|
|
@@ -1027,15 +1034,13 @@ fn lix_directory_recursive_delete_rows_from_batch(
|
|
|
1027
1034
|
let mut count = 0u64;
|
|
1028
1035
|
for row_index in 0..batch.num_rows() {
|
|
1029
1036
|
let directory_id = required_string_value(batch, row_index, "id")?;
|
|
1030
|
-
let context = directory_row_context_from_batch(batch, row_index,
|
|
1031
|
-
let visible_filesystem = visible_filesystems
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
))
|
|
1038
|
-
})?;
|
|
1037
|
+
let context = directory_row_context_from_batch(batch, row_index, branch_binding)?;
|
|
1038
|
+
let visible_filesystem = visible_filesystems.get(&context.branch_id).ok_or_else(|| {
|
|
1039
|
+
DataFusionError::Execution(format!(
|
|
1040
|
+
"DELETE FROM lix_directory missing visible filesystem for branch '{}'",
|
|
1041
|
+
context.branch_id
|
|
1042
|
+
))
|
|
1043
|
+
})?;
|
|
1039
1044
|
append_deduped_delete_plan(
|
|
1040
1045
|
&mut rows,
|
|
1041
1046
|
&mut seen,
|
|
@@ -1071,10 +1076,10 @@ fn is_user_visible_filesystem_delete_row(row: &TransactionWriteRow) -> bool {
|
|
|
1071
1076
|
|
|
1072
1077
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
|
1073
1078
|
struct StateRowDedupeKey {
|
|
1074
|
-
|
|
1079
|
+
entity_pk: String,
|
|
1075
1080
|
schema_key: String,
|
|
1076
1081
|
file_id: Option<String>,
|
|
1077
|
-
|
|
1082
|
+
branch_id: String,
|
|
1078
1083
|
global: bool,
|
|
1079
1084
|
untracked: bool,
|
|
1080
1085
|
}
|
|
@@ -1082,15 +1087,15 @@ struct StateRowDedupeKey {
|
|
|
1082
1087
|
impl From<&TransactionWriteRow> for StateRowDedupeKey {
|
|
1083
1088
|
fn from(row: &TransactionWriteRow) -> Self {
|
|
1084
1089
|
Self {
|
|
1085
|
-
|
|
1086
|
-
.
|
|
1090
|
+
entity_pk: row
|
|
1091
|
+
.entity_pk
|
|
1087
1092
|
.as_ref()
|
|
1088
|
-
.expect("directory provider staged row should carry
|
|
1093
|
+
.expect("directory provider staged row should carry entity_pk")
|
|
1089
1094
|
.as_single_string_owned()
|
|
1090
|
-
.expect("directory provider staged row entity
|
|
1095
|
+
.expect("directory provider staged row entity primary key should project"),
|
|
1091
1096
|
schema_key: row.schema_key.clone(),
|
|
1092
1097
|
file_id: row.file_id.clone(),
|
|
1093
|
-
|
|
1098
|
+
branch_id: row.branch_id.clone(),
|
|
1094
1099
|
global: row.global,
|
|
1095
1100
|
untracked: row.untracked,
|
|
1096
1101
|
}
|
|
@@ -1100,13 +1105,13 @@ impl From<&TransactionWriteRow> for StateRowDedupeKey {
|
|
|
1100
1105
|
#[cfg(test)]
|
|
1101
1106
|
fn lix_directory_write_rows_from_batch_with_options(
|
|
1102
1107
|
batch: &RecordBatch,
|
|
1103
|
-
|
|
1108
|
+
branch_binding: Option<&str>,
|
|
1104
1109
|
surface_name: &str,
|
|
1105
1110
|
reject_read_only_fields: bool,
|
|
1106
1111
|
) -> Result<Vec<TransactionWriteRow>> {
|
|
1107
1112
|
lix_directory_write_rows_from_batch_with_options_and_path_resolvers(
|
|
1108
1113
|
batch,
|
|
1109
|
-
|
|
1114
|
+
branch_binding,
|
|
1110
1115
|
surface_name,
|
|
1111
1116
|
reject_read_only_fields,
|
|
1112
1117
|
None,
|
|
@@ -1116,7 +1121,7 @@ fn lix_directory_write_rows_from_batch_with_options(
|
|
|
1116
1121
|
|
|
1117
1122
|
fn lix_directory_write_rows_from_batch_with_options_and_path_resolvers(
|
|
1118
1123
|
batch: &RecordBatch,
|
|
1119
|
-
|
|
1124
|
+
branch_binding: Option<&str>,
|
|
1120
1125
|
surface_name: &str,
|
|
1121
1126
|
reject_read_only_fields: bool,
|
|
1122
1127
|
mut path_resolvers: Option<&mut BTreeMap<String, DirectoryPathResolver>>,
|
|
@@ -1125,7 +1130,7 @@ fn lix_directory_write_rows_from_batch_with_options_and_path_resolvers(
|
|
|
1125
1130
|
let mut rows = Vec::new();
|
|
1126
1131
|
for row_index in 0..batch.num_rows() {
|
|
1127
1132
|
if reject_read_only_fields {
|
|
1128
|
-
reject_read_only_lix_directory_insert_field(batch, row_index, "
|
|
1133
|
+
reject_read_only_lix_directory_insert_field(batch, row_index, "lixcol_entity_pk")?;
|
|
1129
1134
|
reject_read_only_lix_directory_insert_field(batch, row_index, "lixcol_schema_key")?;
|
|
1130
1135
|
reject_read_only_lix_directory_insert_field(batch, row_index, "lixcol_change_id")?;
|
|
1131
1136
|
reject_read_only_lix_directory_insert_field(batch, row_index, "lixcol_created_at")?;
|
|
@@ -1136,7 +1141,7 @@ fn lix_directory_write_rows_from_batch_with_options_and_path_resolvers(
|
|
|
1136
1141
|
let path = optional_string_value(batch, row_index, "path")?;
|
|
1137
1142
|
let id = optional_string_value(batch, row_index, "id")?;
|
|
1138
1143
|
let hidden = optional_bool_value(batch, row_index, "hidden")?;
|
|
1139
|
-
let context = directory_row_context_from_batch(batch, row_index,
|
|
1144
|
+
let context = directory_row_context_from_batch(batch, row_index, branch_binding)?;
|
|
1140
1145
|
|
|
1141
1146
|
if let Some(path) = path.filter(|_| reject_read_only_fields) {
|
|
1142
1147
|
reject_read_only_lix_directory_insert_field(batch, row_index, "parent_id")?;
|
|
@@ -1209,14 +1214,14 @@ fn attach_lix_directory_insert_origin(
|
|
|
1209
1214
|
if row.schema_key != DIRECTORY_SCHEMA_KEY {
|
|
1210
1215
|
continue;
|
|
1211
1216
|
}
|
|
1212
|
-
let Some(
|
|
1213
|
-
.
|
|
1217
|
+
let Some(entity_pk) = row
|
|
1218
|
+
.entity_pk
|
|
1214
1219
|
.as_ref()
|
|
1215
|
-
.and_then(|
|
|
1220
|
+
.and_then(|entity_pk| entity_pk.as_single_string_owned().ok())
|
|
1216
1221
|
else {
|
|
1217
1222
|
continue;
|
|
1218
1223
|
};
|
|
1219
|
-
if
|
|
1224
|
+
if entity_pk == directory_id {
|
|
1220
1225
|
row.origin = Some(origin.clone());
|
|
1221
1226
|
}
|
|
1222
1227
|
}
|
|
@@ -1236,18 +1241,18 @@ fn lix_directory_insert_origin(surface_name: &str, directory_id: &str) -> Transa
|
|
|
1236
1241
|
fn directory_row_context_from_batch(
|
|
1237
1242
|
batch: &RecordBatch,
|
|
1238
1243
|
row_index: usize,
|
|
1239
|
-
|
|
1244
|
+
branch_binding: Option<&str>,
|
|
1240
1245
|
) -> Result<FilesystemRowContext> {
|
|
1241
|
-
let scope =
|
|
1246
|
+
let scope = resolve_write_branch_scope(
|
|
1242
1247
|
optional_bool_value(batch, row_index, "lixcol_global")?,
|
|
1243
|
-
optional_string_value(batch, row_index, "
|
|
1244
|
-
|
|
1245
|
-
"INSERT into
|
|
1248
|
+
optional_string_value(batch, row_index, "lixcol_branch_id")?,
|
|
1249
|
+
branch_binding,
|
|
1250
|
+
"INSERT into lix_directory_by_branch",
|
|
1246
1251
|
"lix_directory",
|
|
1247
1252
|
)?;
|
|
1248
1253
|
|
|
1249
1254
|
Ok(FilesystemRowContext {
|
|
1250
|
-
|
|
1255
|
+
branch_id: scope.branch_id,
|
|
1251
1256
|
global: scope.global,
|
|
1252
1257
|
untracked: optional_bool_value(batch, row_index, "lixcol_untracked")?.unwrap_or(false),
|
|
1253
1258
|
file_id: optional_string_value(batch, row_index, "lixcol_file_id")?,
|
|
@@ -1259,18 +1264,18 @@ fn directory_row_context_from_update(
|
|
|
1259
1264
|
batch: &RecordBatch,
|
|
1260
1265
|
assignment_values: &UpdateAssignmentValues,
|
|
1261
1266
|
row_index: usize,
|
|
1262
|
-
|
|
1267
|
+
branch_binding: Option<&str>,
|
|
1263
1268
|
) -> Result<FilesystemRowContext> {
|
|
1264
|
-
let scope =
|
|
1269
|
+
let scope = resolve_write_branch_scope(
|
|
1265
1270
|
optional_bool_value(batch, row_index, "lixcol_global")?,
|
|
1266
|
-
optional_string_value(batch, row_index, "
|
|
1267
|
-
|
|
1268
|
-
"UPDATE into
|
|
1271
|
+
optional_string_value(batch, row_index, "lixcol_branch_id")?,
|
|
1272
|
+
branch_binding,
|
|
1273
|
+
"UPDATE into lix_directory_by_branch",
|
|
1269
1274
|
"lix_directory",
|
|
1270
1275
|
)?;
|
|
1271
1276
|
|
|
1272
1277
|
Ok(FilesystemRowContext {
|
|
1273
|
-
|
|
1278
|
+
branch_id: scope.branch_id,
|
|
1274
1279
|
global: scope.global,
|
|
1275
1280
|
untracked: optional_bool_value(batch, row_index, "lixcol_untracked")?.unwrap_or(false),
|
|
1276
1281
|
file_id: optional_string_value(batch, row_index, "lixcol_file_id")?,
|
|
@@ -1286,7 +1291,7 @@ fn directory_row_context_from_update(
|
|
|
1286
1291
|
|
|
1287
1292
|
fn directory_path_resolver_key(context: &FilesystemRowContext) -> String {
|
|
1288
1293
|
filesystem_storage_scope_key(
|
|
1289
|
-
&context.
|
|
1294
|
+
&context.branch_id,
|
|
1290
1295
|
context.global,
|
|
1291
1296
|
context.untracked,
|
|
1292
1297
|
context.file_id.as_deref(),
|
|
@@ -1295,7 +1300,7 @@ fn directory_path_resolver_key(context: &FilesystemRowContext) -> String {
|
|
|
1295
1300
|
|
|
1296
1301
|
async fn directory_path_resolvers_from_live_state(
|
|
1297
1302
|
live_state: Arc<dyn LiveStateReader>,
|
|
1298
|
-
|
|
1303
|
+
branch_binding: Option<&str>,
|
|
1299
1304
|
) -> std::result::Result<BTreeMap<String, DirectoryPathResolver>, LixError> {
|
|
1300
1305
|
let rows = live_state
|
|
1301
1306
|
.scan_rows(&LiveStateScanRequest {
|
|
@@ -1304,8 +1309,8 @@ async fn directory_path_resolvers_from_live_state(
|
|
|
1304
1309
|
DIRECTORY_SCHEMA_KEY.to_string(),
|
|
1305
1310
|
FILE_DESCRIPTOR_SCHEMA_KEY.to_string(),
|
|
1306
1311
|
],
|
|
1307
|
-
|
|
1308
|
-
.map(|
|
|
1312
|
+
branch_ids: branch_binding
|
|
1313
|
+
.map(|branch_id| vec![branch_id.to_string()])
|
|
1309
1314
|
.unwrap_or_default(),
|
|
1310
1315
|
..Default::default()
|
|
1311
1316
|
},
|
|
@@ -1313,8 +1318,8 @@ async fn directory_path_resolvers_from_live_state(
|
|
|
1313
1318
|
})
|
|
1314
1319
|
.await?;
|
|
1315
1320
|
let mut resolvers = directory_path_resolvers_from_state_rows(rows)?;
|
|
1316
|
-
if let Some(
|
|
1317
|
-
let key = filesystem_storage_scope_key(
|
|
1321
|
+
if let Some(branch_id) = branch_binding {
|
|
1322
|
+
let key = filesystem_storage_scope_key(branch_id, false, false, None);
|
|
1318
1323
|
resolvers
|
|
1319
1324
|
.entry(key)
|
|
1320
1325
|
.or_insert_with(DirectoryPathResolver::default);
|
|
@@ -1357,7 +1362,7 @@ fn lix_directory_record_batch(
|
|
|
1357
1362
|
let mut parent_ids = Vec::new();
|
|
1358
1363
|
let mut names = Vec::new();
|
|
1359
1364
|
let mut hiddens = Vec::new();
|
|
1360
|
-
let mut
|
|
1365
|
+
let mut entity_pks = Vec::new();
|
|
1361
1366
|
let mut schema_keys = Vec::new();
|
|
1362
1367
|
let mut file_ids = Vec::new();
|
|
1363
1368
|
let mut globals = Vec::new();
|
|
@@ -1367,19 +1372,19 @@ fn lix_directory_record_batch(
|
|
|
1367
1372
|
let mut commit_ids = Vec::new();
|
|
1368
1373
|
let mut untracked_values = Vec::new();
|
|
1369
1374
|
let mut metadata_values = Vec::new();
|
|
1370
|
-
let mut
|
|
1375
|
+
let mut branch_ids = Vec::new();
|
|
1371
1376
|
|
|
1372
1377
|
for directory in directory_rows {
|
|
1373
1378
|
ids.push(Some(directory.id.clone()));
|
|
1374
1379
|
paths.push(
|
|
1375
1380
|
directory_paths
|
|
1376
|
-
.get(&(directory.live.
|
|
1381
|
+
.get(&(directory.live.branch_id.clone(), directory.id.clone()))
|
|
1377
1382
|
.cloned(),
|
|
1378
1383
|
);
|
|
1379
1384
|
parent_ids.push(directory.parent_id);
|
|
1380
1385
|
names.push(Some(directory.name));
|
|
1381
1386
|
hiddens.push(Some(directory.hidden));
|
|
1382
|
-
|
|
1387
|
+
entity_pks.push(Some(directory.live.entity_pk.as_json_array_text()?));
|
|
1383
1388
|
schema_keys.push(Some(directory.live.schema_key));
|
|
1384
1389
|
file_ids.push(directory.live.file_id);
|
|
1385
1390
|
globals.push(Some(directory.live.global));
|
|
@@ -1389,7 +1394,7 @@ fn lix_directory_record_batch(
|
|
|
1389
1394
|
commit_ids.push(directory.live.commit_id);
|
|
1390
1395
|
untracked_values.push(Some(directory.live.untracked));
|
|
1391
1396
|
metadata_values.push(directory.live.metadata.as_ref().map(serialize_row_metadata));
|
|
1392
|
-
|
|
1397
|
+
branch_ids.push(Some(directory.live.branch_id));
|
|
1393
1398
|
}
|
|
1394
1399
|
|
|
1395
1400
|
let mut columns = Vec::<ArrayRef>::with_capacity(schema.fields().len());
|
|
@@ -1400,7 +1405,7 @@ fn lix_directory_record_batch(
|
|
|
1400
1405
|
"parent_id" => Arc::new(StringArray::from(parent_ids.clone())),
|
|
1401
1406
|
"name" => Arc::new(StringArray::from(names.clone())),
|
|
1402
1407
|
"hidden" => Arc::new(BooleanArray::from(hiddens.clone())),
|
|
1403
|
-
"
|
|
1408
|
+
"lixcol_entity_pk" => Arc::new(StringArray::from(entity_pks.clone())),
|
|
1404
1409
|
"lixcol_schema_key" => Arc::new(StringArray::from(schema_keys.clone())),
|
|
1405
1410
|
"lixcol_file_id" => Arc::new(StringArray::from(file_ids.clone())),
|
|
1406
1411
|
"lixcol_global" => Arc::new(BooleanArray::from(globals.clone())),
|
|
@@ -1410,7 +1415,7 @@ fn lix_directory_record_batch(
|
|
|
1410
1415
|
"lixcol_commit_id" => Arc::new(StringArray::from(commit_ids.clone())),
|
|
1411
1416
|
"lixcol_untracked" => Arc::new(BooleanArray::from(untracked_values.clone())),
|
|
1412
1417
|
"lixcol_metadata" => Arc::new(StringArray::from(metadata_values.clone())),
|
|
1413
|
-
"
|
|
1418
|
+
"lixcol_branch_id" => Arc::new(StringArray::from(branch_ids.clone())),
|
|
1414
1419
|
other => {
|
|
1415
1420
|
return Err(LixError::new(
|
|
1416
1421
|
"LIX_ERROR_UNKNOWN",
|
|
@@ -1435,19 +1440,19 @@ fn lix_directory_record_batch(
|
|
|
1435
1440
|
fn derive_directory_paths(
|
|
1436
1441
|
rows: &[DirectoryDescriptorRecord],
|
|
1437
1442
|
) -> std::result::Result<BTreeMap<(String, String), String>, LixError> {
|
|
1438
|
-
let mut
|
|
1443
|
+
let mut by_branch = BTreeMap::<String, BTreeMap<String, &DirectoryDescriptorRecord>>::new();
|
|
1439
1444
|
for row in rows {
|
|
1440
|
-
|
|
1441
|
-
.entry(row.live.
|
|
1445
|
+
by_branch
|
|
1446
|
+
.entry(row.live.branch_id.clone())
|
|
1442
1447
|
.or_default()
|
|
1443
1448
|
.insert(row.id.clone(), row);
|
|
1444
1449
|
}
|
|
1445
1450
|
|
|
1446
1451
|
let mut paths = BTreeMap::<(String, String), String>::new();
|
|
1447
|
-
for (
|
|
1452
|
+
for (branch_id, records) in by_branch {
|
|
1448
1453
|
for directory_id in records.keys() {
|
|
1449
1454
|
derive_directory_path_for(
|
|
1450
|
-
&
|
|
1455
|
+
&branch_id,
|
|
1451
1456
|
directory_id,
|
|
1452
1457
|
&records,
|
|
1453
1458
|
&mut paths,
|
|
@@ -1459,17 +1464,17 @@ fn derive_directory_paths(
|
|
|
1459
1464
|
}
|
|
1460
1465
|
|
|
1461
1466
|
fn derive_directory_path_for(
|
|
1462
|
-
|
|
1467
|
+
branch_id: &str,
|
|
1463
1468
|
directory_id: &str,
|
|
1464
1469
|
records: &BTreeMap<String, &DirectoryDescriptorRecord>,
|
|
1465
1470
|
paths: &mut BTreeMap<(String, String), String>,
|
|
1466
1471
|
visiting: &mut BTreeSet<String>,
|
|
1467
1472
|
) -> std::result::Result<Option<String>, LixError> {
|
|
1468
|
-
if let Some(path) = paths.get(&(
|
|
1473
|
+
if let Some(path) = paths.get(&(branch_id.to_string(), directory_id.to_string())) {
|
|
1469
1474
|
return Ok(Some(path.clone()));
|
|
1470
1475
|
}
|
|
1471
1476
|
if !visiting.insert(directory_id.to_string()) {
|
|
1472
|
-
return Err(directory_parent_cycle_error(
|
|
1477
|
+
return Err(directory_parent_cycle_error(branch_id, directory_id));
|
|
1473
1478
|
}
|
|
1474
1479
|
let Some(row) = records.get(directory_id) else {
|
|
1475
1480
|
visiting.remove(directory_id);
|
|
@@ -1478,7 +1483,7 @@ fn derive_directory_path_for(
|
|
|
1478
1483
|
let path = match row.parent_id.as_deref() {
|
|
1479
1484
|
Some(parent_id) => {
|
|
1480
1485
|
let Some(parent_path) =
|
|
1481
|
-
derive_directory_path_for(
|
|
1486
|
+
derive_directory_path_for(branch_id, parent_id, records, paths, visiting)?
|
|
1482
1487
|
else {
|
|
1483
1488
|
visiting.remove(directory_id);
|
|
1484
1489
|
return Ok(None);
|
|
@@ -1489,17 +1494,17 @@ fn derive_directory_path_for(
|
|
|
1489
1494
|
};
|
|
1490
1495
|
visiting.remove(directory_id);
|
|
1491
1496
|
paths.insert(
|
|
1492
|
-
(
|
|
1497
|
+
(branch_id.to_string(), directory_id.to_string()),
|
|
1493
1498
|
path.clone(),
|
|
1494
1499
|
);
|
|
1495
1500
|
Ok(Some(path))
|
|
1496
1501
|
}
|
|
1497
1502
|
|
|
1498
|
-
fn directory_parent_cycle_error(
|
|
1503
|
+
fn directory_parent_cycle_error(branch_id: &str, directory_id: &str) -> LixError {
|
|
1499
1504
|
LixError::new(
|
|
1500
1505
|
LixError::CODE_CONSTRAINT_VIOLATION,
|
|
1501
1506
|
format!(
|
|
1502
|
-
"lix_directory_descriptor parent_id cycle in
|
|
1507
|
+
"lix_directory_descriptor parent_id cycle in branch '{branch_id}' while resolving directory '{directory_id}'"
|
|
1503
1508
|
),
|
|
1504
1509
|
)
|
|
1505
1510
|
}
|
|
@@ -1520,15 +1525,15 @@ fn projected_schema(base_schema: &SchemaRef, projection: Option<&Vec<usize>>) ->
|
|
|
1520
1525
|
}
|
|
1521
1526
|
|
|
1522
1527
|
fn lix_directory_scan_request(
|
|
1523
|
-
|
|
1528
|
+
branch_binding: Option<&str>,
|
|
1524
1529
|
projected_schema: Option<&Schema>,
|
|
1525
1530
|
limit: Option<usize>,
|
|
1526
1531
|
) -> LiveStateScanRequest {
|
|
1527
1532
|
LiveStateScanRequest {
|
|
1528
1533
|
filter: LiveStateFilter {
|
|
1529
1534
|
schema_keys: vec![DIRECTORY_SCHEMA_KEY.to_string()],
|
|
1530
|
-
|
|
1531
|
-
.map(|
|
|
1535
|
+
branch_ids: branch_binding
|
|
1536
|
+
.map(|branch_id| vec![branch_id.to_string()])
|
|
1532
1537
|
.unwrap_or_default(),
|
|
1533
1538
|
..LiveStateFilter::default()
|
|
1534
1539
|
},
|
|
@@ -1717,9 +1722,9 @@ fn update_optional_metadata_value(
|
|
|
1717
1722
|
update_optional_string_value(batch, assignment_values, row_index, column_name)?
|
|
1718
1723
|
.map(|value| {
|
|
1719
1724
|
let metadata = parse_row_metadata_value(&value, context)
|
|
1720
|
-
.map_err(
|
|
1725
|
+
.map_err(crate::sql2::error::lix_error_to_datafusion_error)?;
|
|
1721
1726
|
TransactionJson::from_value(metadata, &format!("{context} metadata"))
|
|
1722
|
-
.map_err(
|
|
1727
|
+
.map_err(crate::sql2::error::lix_error_to_datafusion_error)
|
|
1723
1728
|
})
|
|
1724
1729
|
.transpose()
|
|
1725
1730
|
}
|
|
@@ -1768,9 +1773,9 @@ fn optional_metadata_value(
|
|
|
1768
1773
|
optional_string_value(batch, row_index, column_name)?
|
|
1769
1774
|
.map(|value| {
|
|
1770
1775
|
let metadata = parse_row_metadata_value(&value, context)
|
|
1771
|
-
.map_err(
|
|
1776
|
+
.map_err(crate::sql2::error::lix_error_to_datafusion_error)?;
|
|
1772
1777
|
TransactionJson::from_value(metadata, &format!("{context} metadata"))
|
|
1773
|
-
.map_err(
|
|
1778
|
+
.map_err(crate::sql2::error::lix_error_to_datafusion_error)
|
|
1774
1779
|
})
|
|
1775
1780
|
.transpose()
|
|
1776
1781
|
}
|
|
@@ -1814,14 +1819,14 @@ fn optional_scalar_value(
|
|
|
1814
1819
|
})
|
|
1815
1820
|
}
|
|
1816
1821
|
|
|
1817
|
-
fn lix_directory_schema() -> SchemaRef {
|
|
1822
|
+
pub(super) fn lix_directory_schema() -> SchemaRef {
|
|
1818
1823
|
Arc::new(Schema::new(vec![
|
|
1819
1824
|
Field::new("id", DataType::Utf8, true),
|
|
1820
1825
|
Field::new("path", DataType::Utf8, true),
|
|
1821
1826
|
Field::new("parent_id", DataType::Utf8, true),
|
|
1822
1827
|
Field::new("name", DataType::Utf8, false),
|
|
1823
1828
|
Field::new("hidden", DataType::Boolean, true),
|
|
1824
|
-
json_field("
|
|
1829
|
+
json_field("lixcol_entity_pk", false),
|
|
1825
1830
|
Field::new("lixcol_schema_key", DataType::Utf8, false),
|
|
1826
1831
|
Field::new("lixcol_file_id", DataType::Utf8, true),
|
|
1827
1832
|
Field::new("lixcol_global", DataType::Boolean, true),
|
|
@@ -1834,22 +1839,22 @@ fn lix_directory_schema() -> SchemaRef {
|
|
|
1834
1839
|
]))
|
|
1835
1840
|
}
|
|
1836
1841
|
|
|
1837
|
-
fn
|
|
1842
|
+
pub(super) fn lix_directory_by_branch_schema() -> SchemaRef {
|
|
1838
1843
|
let mut fields = lix_directory_schema()
|
|
1839
1844
|
.fields()
|
|
1840
1845
|
.iter()
|
|
1841
1846
|
.map(|field| field.as_ref().clone())
|
|
1842
1847
|
.collect::<Vec<_>>();
|
|
1843
|
-
fields.push(Field::new("
|
|
1848
|
+
fields.push(Field::new("lixcol_branch_id", DataType::Utf8, false));
|
|
1844
1849
|
Arc::new(Schema::new(fields))
|
|
1845
1850
|
}
|
|
1846
1851
|
|
|
1847
1852
|
fn datafusion_error_to_lix_error(error: DataFusionError) -> LixError {
|
|
1848
|
-
|
|
1853
|
+
crate::sql2::error::datafusion_error_to_lix_error(error)
|
|
1849
1854
|
}
|
|
1850
1855
|
|
|
1851
1856
|
fn lix_error_to_datafusion_error(error: LixError) -> DataFusionError {
|
|
1852
|
-
|
|
1857
|
+
crate::sql2::error::lix_error_to_datafusion_error(error)
|
|
1853
1858
|
}
|
|
1854
1859
|
|
|
1855
1860
|
#[cfg(test)]
|
|
@@ -1868,9 +1873,7 @@ mod tests {
|
|
|
1868
1873
|
use crate::functions::{
|
|
1869
1874
|
FunctionProvider, FunctionProviderHandle, SharedFunctionProvider, SystemFunctionProvider,
|
|
1870
1875
|
};
|
|
1871
|
-
use crate::live_state::{
|
|
1872
|
-
LiveStateReader, LiveStateRowRequest, LiveStateScanRequest, MaterializedLiveStateRow,
|
|
1873
|
-
};
|
|
1876
|
+
use crate::live_state::{LiveStateScanRequest, MaterializedLiveStateRow};
|
|
1874
1877
|
use crate::sql2::dml::InsertSink;
|
|
1875
1878
|
use crate::sql2::{SqlWriteContext, SqlWriteExecutionContext};
|
|
1876
1879
|
use crate::transaction::types::{
|
|
@@ -1881,10 +1884,10 @@ mod tests {
|
|
|
1881
1884
|
|
|
1882
1885
|
use super::{
|
|
1883
1886
|
derive_directory_path_for, directory_path_resolvers_from_state_rows,
|
|
1884
|
-
|
|
1887
|
+
lix_directory_by_branch_schema, lix_directory_insert_origin, lix_directory_record_batch,
|
|
1885
1888
|
lix_directory_recursive_delete_rows_from_batch, lix_directory_write_rows_from_batch,
|
|
1886
|
-
lix_directory_write_rows_from_batch_with_path_resolvers,
|
|
1887
|
-
|
|
1889
|
+
lix_directory_write_rows_from_batch_with_path_resolvers, BranchBinding,
|
|
1890
|
+
DirectoryDescriptorRecord, LixDirectoryInsertSink,
|
|
1888
1891
|
};
|
|
1889
1892
|
use crate::sql2::filesystem_visibility::VisibleFilesystem;
|
|
1890
1893
|
|
|
@@ -1920,8 +1923,8 @@ mod tests {
|
|
|
1920
1923
|
|
|
1921
1924
|
#[async_trait]
|
|
1922
1925
|
impl SqlWriteExecutionContext for CapturingWriteContext {
|
|
1923
|
-
fn
|
|
1924
|
-
"
|
|
1926
|
+
fn active_branch_id(&self) -> &str {
|
|
1927
|
+
"branch-a"
|
|
1925
1928
|
}
|
|
1926
1929
|
|
|
1927
1930
|
fn functions(&self) -> FunctionProviderHandle {
|
|
@@ -1946,14 +1949,11 @@ mod tests {
|
|
|
1946
1949
|
Ok(self.rows.clone())
|
|
1947
1950
|
}
|
|
1948
1951
|
|
|
1949
|
-
async fn
|
|
1950
|
-
|
|
1951
|
-
version_id: &str,
|
|
1952
|
-
) -> Result<Option<String>, LixError> {
|
|
1953
|
-
if version_id == "ghost-version" {
|
|
1952
|
+
async fn load_branch_head(&mut self, branch_id: &str) -> Result<Option<String>, LixError> {
|
|
1953
|
+
if branch_id == "ghost-branch" {
|
|
1954
1954
|
return Ok(None);
|
|
1955
1955
|
}
|
|
1956
|
-
Ok(Some(format!("commit-{
|
|
1956
|
+
Ok(Some(format!("commit-{branch_id}")))
|
|
1957
1957
|
}
|
|
1958
1958
|
|
|
1959
1959
|
async fn stage_write(
|
|
@@ -1965,60 +1965,37 @@ mod tests {
|
|
|
1965
1965
|
}
|
|
1966
1966
|
}
|
|
1967
1967
|
|
|
1968
|
-
#[derive(Default)]
|
|
1969
|
-
#[allow(dead_code)]
|
|
1970
|
-
struct RowsLiveStateReader {
|
|
1971
|
-
rows: Vec<MaterializedLiveStateRow>,
|
|
1972
|
-
}
|
|
1973
|
-
|
|
1974
|
-
#[async_trait]
|
|
1975
|
-
impl LiveStateReader for RowsLiveStateReader {
|
|
1976
|
-
async fn scan_rows(
|
|
1977
|
-
&self,
|
|
1978
|
-
_request: &LiveStateScanRequest,
|
|
1979
|
-
) -> Result<Vec<MaterializedLiveStateRow>, LixError> {
|
|
1980
|
-
Ok(self.rows.clone())
|
|
1981
|
-
}
|
|
1982
|
-
|
|
1983
|
-
async fn load_row(
|
|
1984
|
-
&self,
|
|
1985
|
-
_request: &LiveStateRowRequest,
|
|
1986
|
-
) -> Result<Option<MaterializedLiveStateRow>, LixError> {
|
|
1987
|
-
Ok(None)
|
|
1988
|
-
}
|
|
1989
|
-
}
|
|
1990
|
-
|
|
1991
1968
|
fn live_row(
|
|
1992
|
-
|
|
1993
|
-
|
|
1969
|
+
entity_pk: &str,
|
|
1970
|
+
branch_id: &str,
|
|
1994
1971
|
snapshot_content: &str,
|
|
1995
1972
|
) -> MaterializedLiveStateRow {
|
|
1996
1973
|
live_filesystem_row(
|
|
1997
|
-
|
|
1974
|
+
entity_pk,
|
|
1998
1975
|
super::DIRECTORY_SCHEMA_KEY,
|
|
1999
1976
|
None,
|
|
2000
|
-
|
|
1977
|
+
branch_id,
|
|
2001
1978
|
snapshot_content,
|
|
2002
1979
|
)
|
|
2003
1980
|
}
|
|
2004
1981
|
|
|
2005
1982
|
fn live_filesystem_row(
|
|
2006
|
-
|
|
1983
|
+
entity_pk: &str,
|
|
2007
1984
|
schema_key: &str,
|
|
2008
1985
|
file_id: Option<&str>,
|
|
2009
|
-
|
|
1986
|
+
branch_id: &str,
|
|
2010
1987
|
snapshot_content: &str,
|
|
2011
1988
|
) -> MaterializedLiveStateRow {
|
|
2012
1989
|
MaterializedLiveStateRow {
|
|
2013
|
-
|
|
1990
|
+
entity_pk: crate::entity_pk::EntityPk::single(entity_pk),
|
|
2014
1991
|
schema_key: schema_key.to_string(),
|
|
2015
1992
|
file_id: file_id.map(ToOwned::to_owned),
|
|
2016
1993
|
snapshot_content: Some(snapshot_content.to_string()),
|
|
2017
1994
|
metadata: Some(json!({"source": "test"}).to_string()),
|
|
2018
1995
|
deleted: false,
|
|
2019
|
-
|
|
2020
|
-
change_id: Some(format!("change-{
|
|
2021
|
-
commit_id: Some(format!("commit-{
|
|
1996
|
+
branch_id: branch_id.to_string(),
|
|
1997
|
+
change_id: Some(format!("change-{entity_pk}")),
|
|
1998
|
+
commit_id: Some(format!("commit-{entity_pk}")),
|
|
2022
1999
|
global: false,
|
|
2023
2000
|
untracked: false,
|
|
2024
2001
|
created_at: "2026-04-23T00:00:00Z".to_string(),
|
|
@@ -2032,35 +2009,35 @@ mod tests {
|
|
|
2032
2009
|
"dir-docs",
|
|
2033
2010
|
"lix_directory_descriptor",
|
|
2034
2011
|
None,
|
|
2035
|
-
"
|
|
2012
|
+
"branch-a",
|
|
2036
2013
|
r#"{"id":"dir-docs","parent_id":null,"name":"docs","hidden":false}"#,
|
|
2037
2014
|
),
|
|
2038
2015
|
live_filesystem_row(
|
|
2039
2016
|
"dir-guides",
|
|
2040
2017
|
"lix_directory_descriptor",
|
|
2041
2018
|
None,
|
|
2042
|
-
"
|
|
2019
|
+
"branch-a",
|
|
2043
2020
|
r#"{"id":"dir-guides","parent_id":"dir-docs","name":"guides","hidden":false}"#,
|
|
2044
2021
|
),
|
|
2045
2022
|
live_filesystem_row(
|
|
2046
2023
|
"file-index",
|
|
2047
2024
|
"lix_file_descriptor",
|
|
2048
2025
|
None,
|
|
2049
|
-
"
|
|
2026
|
+
"branch-a",
|
|
2050
2027
|
r#"{"id":"file-index","directory_id":"dir-docs","name":"index.md","hidden":false}"#,
|
|
2051
2028
|
),
|
|
2052
2029
|
live_filesystem_row(
|
|
2053
2030
|
"file-readme",
|
|
2054
2031
|
"lix_file_descriptor",
|
|
2055
2032
|
None,
|
|
2056
|
-
"
|
|
2033
|
+
"branch-a",
|
|
2057
2034
|
r#"{"id":"file-readme","directory_id":"dir-guides","name":"readme.md","hidden":false}"#,
|
|
2058
2035
|
),
|
|
2059
2036
|
live_filesystem_row(
|
|
2060
2037
|
"file-readme",
|
|
2061
2038
|
"lix_binary_blob_ref",
|
|
2062
2039
|
Some("file-readme"),
|
|
2063
|
-
"
|
|
2040
|
+
"branch-a",
|
|
2064
2041
|
r#"{"id":"file-readme","blob_hash":"abc123","size_bytes":5}"#,
|
|
2065
2042
|
),
|
|
2066
2043
|
]
|
|
@@ -2070,7 +2047,7 @@ mod tests {
|
|
|
2070
2047
|
Arc::new(StringArray::from(values)) as ArrayRef
|
|
2071
2048
|
}
|
|
2072
2049
|
|
|
2073
|
-
fn directory_insert_batch(
|
|
2050
|
+
fn directory_insert_batch(include_branch: bool, global: bool) -> RecordBatch {
|
|
2074
2051
|
let mut fields = vec![
|
|
2075
2052
|
Field::new("id", DataType::Utf8, false),
|
|
2076
2053
|
Field::new("parent_id", DataType::Utf8, true),
|
|
@@ -2087,9 +2064,9 @@ mod tests {
|
|
|
2087
2064
|
Arc::new(BooleanArray::from(vec![global])) as ArrayRef,
|
|
2088
2065
|
string_column(vec![Some("{\"source\":\"directory\"}")]),
|
|
2089
2066
|
];
|
|
2090
|
-
if
|
|
2091
|
-
fields.push(Field::new("
|
|
2092
|
-
columns.push(string_column(vec![Some("
|
|
2067
|
+
if include_branch {
|
|
2068
|
+
fields.push(Field::new("lixcol_branch_id", DataType::Utf8, false));
|
|
2069
|
+
columns.push(string_column(vec![Some("branch-a")]));
|
|
2093
2070
|
}
|
|
2094
2071
|
RecordBatch::try_new(Arc::new(Schema::new(fields)), columns)
|
|
2095
2072
|
.expect("directory insert batch should build")
|
|
@@ -2101,13 +2078,13 @@ mod tests {
|
|
|
2101
2078
|
Field::new("id", DataType::Utf8, false),
|
|
2102
2079
|
Field::new("path", DataType::Utf8, true),
|
|
2103
2080
|
Field::new("hidden", DataType::Boolean, false),
|
|
2104
|
-
Field::new("
|
|
2081
|
+
Field::new("lixcol_branch_id", DataType::Utf8, false),
|
|
2105
2082
|
])),
|
|
2106
2083
|
vec![
|
|
2107
2084
|
string_column(vec![Some("dir-nested")]),
|
|
2108
2085
|
string_column(vec![Some(path)]),
|
|
2109
2086
|
Arc::new(BooleanArray::from(vec![false])) as ArrayRef,
|
|
2110
|
-
string_column(vec![Some("
|
|
2087
|
+
string_column(vec![Some("branch-a")]),
|
|
2111
2088
|
],
|
|
2112
2089
|
)
|
|
2113
2090
|
.expect("directory path insert batch should build")
|
|
@@ -2117,11 +2094,11 @@ mod tests {
|
|
|
2117
2094
|
RecordBatch::try_new(
|
|
2118
2095
|
Arc::new(Schema::new(vec![
|
|
2119
2096
|
Field::new("id", DataType::Utf8, false),
|
|
2120
|
-
Field::new("
|
|
2097
|
+
Field::new("lixcol_branch_id", DataType::Utf8, false),
|
|
2121
2098
|
])),
|
|
2122
2099
|
vec![
|
|
2123
2100
|
string_column(ids.iter().copied().map(Some).collect::<Vec<_>>()),
|
|
2124
|
-
string_column(vec![Some("
|
|
2101
|
+
string_column(vec![Some("branch-a"); ids.len()]),
|
|
2125
2102
|
],
|
|
2126
2103
|
)
|
|
2127
2104
|
.expect("directory delete batch should build")
|
|
@@ -2136,7 +2113,7 @@ mod tests {
|
|
|
2136
2113
|
hidden: false,
|
|
2137
2114
|
live: live_row(
|
|
2138
2115
|
"dir-docs",
|
|
2139
|
-
"
|
|
2116
|
+
"branch-a",
|
|
2140
2117
|
"{\"id\":\"dir-docs\",\"parent_id\":null,\"name\":\"docs\",\"hidden\":false}",
|
|
2141
2118
|
),
|
|
2142
2119
|
};
|
|
@@ -2147,7 +2124,7 @@ mod tests {
|
|
|
2147
2124
|
hidden: false,
|
|
2148
2125
|
live: live_row(
|
|
2149
2126
|
"dir-guides",
|
|
2150
|
-
"
|
|
2127
|
+
"branch-a",
|
|
2151
2128
|
"{\"id\":\"dir-guides\",\"parent_id\":\"dir-docs\",\"name\":\"guides\",\"hidden\":false}",
|
|
2152
2129
|
),
|
|
2153
2130
|
};
|
|
@@ -2158,7 +2135,7 @@ mod tests {
|
|
|
2158
2135
|
|
|
2159
2136
|
assert_eq!(
|
|
2160
2137
|
derive_directory_path_for(
|
|
2161
|
-
"
|
|
2138
|
+
"branch-a",
|
|
2162
2139
|
"dir-guides",
|
|
2163
2140
|
&records,
|
|
2164
2141
|
&mut paths,
|
|
@@ -2174,17 +2151,17 @@ mod tests {
|
|
|
2174
2151
|
let rows = vec![
|
|
2175
2152
|
live_row(
|
|
2176
2153
|
"dir-docs",
|
|
2177
|
-
"
|
|
2154
|
+
"branch-a",
|
|
2178
2155
|
"{\"id\":\"dir-docs\",\"parent_id\":null,\"name\":\"docs\",\"hidden\":false}",
|
|
2179
2156
|
),
|
|
2180
2157
|
live_row(
|
|
2181
2158
|
"dir-guides",
|
|
2182
|
-
"
|
|
2159
|
+
"branch-a",
|
|
2183
2160
|
"{\"id\":\"dir-guides\",\"parent_id\":\"dir-docs\",\"name\":\"guides\",\"hidden\":true}",
|
|
2184
2161
|
),
|
|
2185
2162
|
];
|
|
2186
2163
|
|
|
2187
|
-
let batch = lix_directory_record_batch(&
|
|
2164
|
+
let batch = lix_directory_record_batch(&lix_directory_by_branch_schema(), rows)
|
|
2188
2165
|
.expect("directory batch should build");
|
|
2189
2166
|
|
|
2190
2167
|
assert_eq!(batch.num_rows(), 2);
|
|
@@ -2200,13 +2177,13 @@ mod tests {
|
|
|
2200
2177
|
);
|
|
2201
2178
|
assert_eq!(
|
|
2202
2179
|
batch
|
|
2203
|
-
.column_by_name("
|
|
2204
|
-
.expect("
|
|
2180
|
+
.column_by_name("lixcol_branch_id")
|
|
2181
|
+
.expect("branch column")
|
|
2205
2182
|
.as_any()
|
|
2206
2183
|
.downcast_ref::<StringArray>()
|
|
2207
|
-
.expect("
|
|
2184
|
+
.expect("branch is string")
|
|
2208
2185
|
.value(1),
|
|
2209
|
-
"
|
|
2186
|
+
"branch-a"
|
|
2210
2187
|
);
|
|
2211
2188
|
}
|
|
2212
2189
|
|
|
@@ -2218,7 +2195,7 @@ mod tests {
|
|
|
2218
2195
|
assert_eq!(
|
|
2219
2196
|
rows,
|
|
2220
2197
|
vec![TransactionWriteRow {
|
|
2221
|
-
|
|
2198
|
+
entity_pk: Some(crate::entity_pk::EntityPk::single("dir-docs")),
|
|
2222
2199
|
schema_key: super::DIRECTORY_SCHEMA_KEY.to_string(),
|
|
2223
2200
|
file_id: None,
|
|
2224
2201
|
snapshot: Some(TransactionJson::from_value_for_test(
|
|
@@ -2234,43 +2211,43 @@ mod tests {
|
|
|
2234
2211
|
change_id: None,
|
|
2235
2212
|
commit_id: None,
|
|
2236
2213
|
untracked: false,
|
|
2237
|
-
|
|
2214
|
+
branch_id: "branch-a".to_string(),
|
|
2238
2215
|
}]
|
|
2239
2216
|
);
|
|
2240
2217
|
}
|
|
2241
2218
|
|
|
2242
2219
|
#[test]
|
|
2243
|
-
fn
|
|
2220
|
+
fn active_directory_insert_defaults_branch_id() {
|
|
2244
2221
|
let rows = lix_directory_write_rows_from_batch(
|
|
2245
2222
|
&directory_insert_batch(false, false),
|
|
2246
|
-
Some("
|
|
2223
|
+
Some("branch-active"),
|
|
2247
2224
|
)
|
|
2248
2225
|
.expect("active directory batch should decode");
|
|
2249
2226
|
|
|
2250
|
-
assert_eq!(rows[0].
|
|
2227
|
+
assert_eq!(rows[0].branch_id, "branch-active");
|
|
2251
2228
|
}
|
|
2252
2229
|
|
|
2253
2230
|
#[test]
|
|
2254
|
-
fn
|
|
2231
|
+
fn by_branch_directory_insert_requires_branch_id_for_non_global_rows() {
|
|
2255
2232
|
let error =
|
|
2256
2233
|
lix_directory_write_rows_from_batch(&directory_insert_batch(false, false), None)
|
|
2257
|
-
.expect_err("by-
|
|
2234
|
+
.expect_err("by-branch insert should require branch id");
|
|
2258
2235
|
|
|
2259
2236
|
assert!(
|
|
2260
|
-
error.to_string().contains("requires
|
|
2237
|
+
error.to_string().contains("requires lixcol_branch_id"),
|
|
2261
2238
|
"unexpected error: {error}"
|
|
2262
2239
|
);
|
|
2263
2240
|
}
|
|
2264
2241
|
|
|
2265
2242
|
#[test]
|
|
2266
|
-
fn
|
|
2243
|
+
fn directory_insert_rejects_global_with_non_global_branch_id() {
|
|
2267
2244
|
let error = lix_directory_write_rows_from_batch(&directory_insert_batch(true, true), None)
|
|
2268
|
-
.expect_err("global directory write should reject conflicting
|
|
2245
|
+
.expect_err("global directory write should reject conflicting branch id");
|
|
2269
2246
|
|
|
2270
2247
|
assert!(
|
|
2271
2248
|
error
|
|
2272
2249
|
.to_string()
|
|
2273
|
-
.contains("cannot set lixcol_global=true with non-global
|
|
2250
|
+
.contains("cannot set lixcol_global=true with non-global lixcol_branch_id"),
|
|
2274
2251
|
"unexpected error: {error}"
|
|
2275
2252
|
);
|
|
2276
2253
|
}
|
|
@@ -2279,7 +2256,7 @@ mod tests {
|
|
|
2279
2256
|
fn directory_path_insert_reuses_existing_parent_descriptor() {
|
|
2280
2257
|
let existing_rows = vec![live_row(
|
|
2281
2258
|
"dir-docs",
|
|
2282
|
-
"
|
|
2259
|
+
"branch-a",
|
|
2283
2260
|
"{\"id\":\"dir-docs\",\"parent_id\":null,\"name\":\"docs\",\"hidden\":false}",
|
|
2284
2261
|
)];
|
|
2285
2262
|
let mut resolvers = directory_path_resolvers_from_state_rows(existing_rows)
|
|
@@ -2306,7 +2283,7 @@ mod tests {
|
|
|
2306
2283
|
let visible_filesystem = VisibleFilesystem::from_live_rows(filesystem_rows())
|
|
2307
2284
|
.expect("visible filesystem should build");
|
|
2308
2285
|
let mut visible_filesystems = BTreeMap::new();
|
|
2309
|
-
visible_filesystems.insert("
|
|
2286
|
+
visible_filesystems.insert("branch-a".to_string(), visible_filesystem);
|
|
2310
2287
|
|
|
2311
2288
|
let (rows, count) = lix_directory_recursive_delete_rows_from_batch(
|
|
2312
2289
|
&directory_delete_batch(&["dir-docs"]),
|
|
@@ -2321,11 +2298,11 @@ mod tests {
|
|
|
2321
2298
|
.map(|row| {
|
|
2322
2299
|
(
|
|
2323
2300
|
row.schema_key.as_str(),
|
|
2324
|
-
row.
|
|
2301
|
+
row.entity_pk
|
|
2325
2302
|
.as_ref()
|
|
2326
|
-
.expect("planned delete row should carry
|
|
2303
|
+
.expect("planned delete row should carry entity_pk")
|
|
2327
2304
|
.as_single_string_owned()
|
|
2328
|
-
.expect("planned delete row should project
|
|
2305
|
+
.expect("planned delete row should project entity_pk"),
|
|
2329
2306
|
)
|
|
2330
2307
|
})
|
|
2331
2308
|
.collect::<Vec<_>>(),
|
|
@@ -2345,7 +2322,7 @@ mod tests {
|
|
|
2345
2322
|
let visible_filesystem = VisibleFilesystem::from_live_rows(filesystem_rows())
|
|
2346
2323
|
.expect("visible filesystem should build");
|
|
2347
2324
|
let mut visible_filesystems = BTreeMap::new();
|
|
2348
|
-
visible_filesystems.insert("
|
|
2325
|
+
visible_filesystems.insert("branch-a".to_string(), visible_filesystem);
|
|
2349
2326
|
|
|
2350
2327
|
let (rows, count) = lix_directory_recursive_delete_rows_from_batch(
|
|
2351
2328
|
&directory_delete_batch(&["dir-docs", "dir-guides"]),
|
|
@@ -2360,9 +2337,9 @@ mod tests {
|
|
|
2360
2337
|
.map(|row| {
|
|
2361
2338
|
(
|
|
2362
2339
|
row.schema_key.clone(),
|
|
2363
|
-
row.
|
|
2340
|
+
row.entity_pk.clone(),
|
|
2364
2341
|
row.file_id.clone(),
|
|
2365
|
-
row.
|
|
2342
|
+
row.branch_id.clone(),
|
|
2366
2343
|
)
|
|
2367
2344
|
})
|
|
2368
2345
|
.collect::<std::collections::BTreeSet<_>>();
|
|
@@ -2375,12 +2352,8 @@ mod tests {
|
|
|
2375
2352
|
let mut write_context = CapturingWriteContext::default();
|
|
2376
2353
|
let write_ctx = SqlWriteContext::new(&mut write_context);
|
|
2377
2354
|
let batch = directory_insert_batch(true, false);
|
|
2378
|
-
let sink =
|
|
2379
|
-
|
|
2380
|
-
write_ctx,
|
|
2381
|
-
test_functions(),
|
|
2382
|
-
VersionBinding::explicit(),
|
|
2383
|
-
);
|
|
2355
|
+
let sink =
|
|
2356
|
+
LixDirectoryInsertSink::new(write_ctx, test_functions(), BranchBinding::explicit());
|
|
2384
2357
|
let count = sink
|
|
2385
2358
|
.write_batches(vec![batch], &Arc::new(TaskContext::default()))
|
|
2386
2359
|
.await
|
|
@@ -2392,7 +2365,7 @@ mod tests {
|
|
|
2392
2365
|
&[TransactionWrite::Rows {
|
|
2393
2366
|
mode: TransactionWriteMode::Insert,
|
|
2394
2367
|
rows: vec![TransactionWriteRow {
|
|
2395
|
-
|
|
2368
|
+
entity_pk: Some(crate::entity_pk::EntityPk::single("dir-docs")),
|
|
2396
2369
|
schema_key: super::DIRECTORY_SCHEMA_KEY.to_string(),
|
|
2397
2370
|
file_id: None,
|
|
2398
2371
|
snapshot: Some(TransactionJson::from_value_for_test(
|
|
@@ -2402,7 +2375,7 @@ mod tests {
|
|
|
2402
2375
|
json!({"source": "directory"})
|
|
2403
2376
|
)),
|
|
2404
2377
|
origin: Some(lix_directory_insert_origin(
|
|
2405
|
-
"
|
|
2378
|
+
"lix_directory_by_branch",
|
|
2406
2379
|
"dir-docs"
|
|
2407
2380
|
)),
|
|
2408
2381
|
created_at: None,
|
|
@@ -2411,7 +2384,7 @@ mod tests {
|
|
|
2411
2384
|
change_id: None,
|
|
2412
2385
|
commit_id: None,
|
|
2413
2386
|
untracked: false,
|
|
2414
|
-
|
|
2387
|
+
branch_id: "branch-a".to_string(),
|
|
2415
2388
|
}]
|
|
2416
2389
|
}]
|
|
2417
2390
|
);
|
|
@@ -2422,19 +2395,15 @@ mod tests {
|
|
|
2422
2395
|
let mut write_context = CapturingWriteContext {
|
|
2423
2396
|
rows: vec![live_row(
|
|
2424
2397
|
"dir-docs",
|
|
2425
|
-
"
|
|
2398
|
+
"branch-a",
|
|
2426
2399
|
"{\"id\":\"dir-docs\",\"parent_id\":null,\"name\":\"docs\",\"hidden\":false}",
|
|
2427
2400
|
)],
|
|
2428
2401
|
writes: Vec::new(),
|
|
2429
2402
|
};
|
|
2430
2403
|
let write_ctx = SqlWriteContext::new(&mut write_context);
|
|
2431
2404
|
let batch = directory_path_insert_batch("/docs/nested/");
|
|
2432
|
-
let sink =
|
|
2433
|
-
|
|
2434
|
-
write_ctx,
|
|
2435
|
-
test_functions(),
|
|
2436
|
-
VersionBinding::explicit(),
|
|
2437
|
-
);
|
|
2405
|
+
let sink =
|
|
2406
|
+
LixDirectoryInsertSink::new(write_ctx, test_functions(), BranchBinding::explicit());
|
|
2438
2407
|
let count = sink
|
|
2439
2408
|
.write_batches(vec![batch], &Arc::new(TaskContext::default()))
|
|
2440
2409
|
.await
|