@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
|
@@ -7,7 +7,7 @@ use datafusion::arrow::compute::{and, filter_record_batch};
|
|
|
7
7
|
use datafusion::arrow::datatypes::{DataType, Field, Schema, SchemaRef};
|
|
8
8
|
use datafusion::arrow::record_batch::RecordBatch;
|
|
9
9
|
use datafusion::catalog::{Session, TableProvider};
|
|
10
|
-
use datafusion::common::{not_impl_err, DFSchema, DataFusionError, Result, ScalarValue};
|
|
10
|
+
use datafusion::common::{not_impl_err, DFSchema, DataFusionError, Result, ScalarValue, SchemaExt};
|
|
11
11
|
use datafusion::datasource::TableType;
|
|
12
12
|
use datafusion::execution::TaskContext;
|
|
13
13
|
use datafusion::logical_expr::dml::InsertOp;
|
|
@@ -21,6 +21,10 @@ use datafusion::physical_plan::{
|
|
|
21
21
|
use futures_util::{stream, TryStreamExt};
|
|
22
22
|
use serde_json::Value as JsonValue;
|
|
23
23
|
|
|
24
|
+
use crate::branch::{
|
|
25
|
+
branch_descriptor_stage_row, branch_descriptor_tombstone_row, branch_ref_stage_row,
|
|
26
|
+
branch_ref_tombstone_row, BranchRefReader,
|
|
27
|
+
};
|
|
24
28
|
use crate::live_state::{
|
|
25
29
|
LiveStateFilter, LiveStateReader, LiveStateScanRequest, MaterializedLiveStateRow,
|
|
26
30
|
};
|
|
@@ -28,83 +32,81 @@ use crate::sql2::dml::{InsertExec, InsertSink};
|
|
|
28
32
|
use crate::sql2::record_batch::record_batch_with_row_count;
|
|
29
33
|
use crate::sql2::write_normalization::{InsertCell, SqlCell, UpdateAssignmentValues};
|
|
30
34
|
use crate::sql2::{
|
|
31
|
-
SqlWriteContext, WriteAccess,
|
|
35
|
+
SqlWriteContext, WriteAccess, WriteContextBranchRefReader, WriteContextLiveStateReader,
|
|
32
36
|
};
|
|
33
37
|
use crate::transaction::types::{
|
|
34
38
|
LogicalPrimaryKey, TransactionWrite, TransactionWriteMode, TransactionWriteOperation,
|
|
35
39
|
TransactionWriteOrigin, TransactionWriteRow,
|
|
36
40
|
};
|
|
37
|
-
use crate::version::{
|
|
38
|
-
version_descriptor_stage_row, version_descriptor_tombstone_row, version_ref_stage_row,
|
|
39
|
-
version_ref_tombstone_row, VersionRefReader,
|
|
40
|
-
};
|
|
41
41
|
use crate::LixError;
|
|
42
|
-
use crate::
|
|
42
|
+
use crate::GLOBAL_BRANCH_ID;
|
|
43
43
|
|
|
44
|
-
pub(
|
|
44
|
+
pub(super) async fn register_lix_branch_read_provider(
|
|
45
45
|
session: &datafusion::prelude::SessionContext,
|
|
46
|
+
surface_name: &str,
|
|
46
47
|
live_state: Arc<dyn LiveStateReader>,
|
|
47
|
-
|
|
48
|
+
branch_ref: Arc<dyn BranchRefReader>,
|
|
48
49
|
) -> Result<(), LixError> {
|
|
49
50
|
session
|
|
50
51
|
.register_table(
|
|
51
|
-
|
|
52
|
-
Arc::new(
|
|
52
|
+
surface_name,
|
|
53
|
+
Arc::new(LixBranchProvider::new(live_state, branch_ref)),
|
|
53
54
|
)
|
|
54
55
|
.map_err(datafusion_error_to_lix_error)?;
|
|
55
56
|
Ok(())
|
|
56
57
|
}
|
|
57
58
|
|
|
58
|
-
pub(
|
|
59
|
+
pub(super) async fn register_write_provider(
|
|
59
60
|
session: &datafusion::prelude::SessionContext,
|
|
61
|
+
surface_name: &str,
|
|
60
62
|
write_ctx: SqlWriteContext,
|
|
61
63
|
) -> Result<(), LixError> {
|
|
62
64
|
session
|
|
63
65
|
.register_table(
|
|
64
|
-
|
|
65
|
-
Arc::new(
|
|
66
|
+
surface_name,
|
|
67
|
+
Arc::new(LixBranchProvider::with_write(write_ctx)),
|
|
66
68
|
)
|
|
67
69
|
.map_err(datafusion_error_to_lix_error)?;
|
|
68
70
|
Ok(())
|
|
69
71
|
}
|
|
70
72
|
|
|
71
|
-
struct
|
|
73
|
+
struct LixBranchProvider {
|
|
72
74
|
schema: SchemaRef,
|
|
73
75
|
live_state: Arc<dyn LiveStateReader>,
|
|
74
|
-
|
|
76
|
+
branch_ref: Arc<dyn BranchRefReader>,
|
|
75
77
|
write_access: WriteAccess,
|
|
76
78
|
}
|
|
77
79
|
|
|
78
|
-
impl std::fmt::Debug for
|
|
80
|
+
impl std::fmt::Debug for LixBranchProvider {
|
|
79
81
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
80
|
-
f.debug_struct("
|
|
82
|
+
f.debug_struct("LixBranchProvider").finish()
|
|
81
83
|
}
|
|
82
84
|
}
|
|
83
85
|
|
|
84
|
-
impl
|
|
85
|
-
fn new(live_state: Arc<dyn LiveStateReader>,
|
|
86
|
+
impl LixBranchProvider {
|
|
87
|
+
fn new(live_state: Arc<dyn LiveStateReader>, branch_ref: Arc<dyn BranchRefReader>) -> Self {
|
|
86
88
|
Self {
|
|
87
|
-
schema:
|
|
89
|
+
schema: lix_branch_schema(),
|
|
88
90
|
live_state,
|
|
89
|
-
|
|
91
|
+
branch_ref,
|
|
90
92
|
write_access: WriteAccess::read_only(),
|
|
91
93
|
}
|
|
92
94
|
}
|
|
93
95
|
|
|
94
96
|
fn with_write(write_ctx: SqlWriteContext) -> Self {
|
|
95
97
|
let live_state = Arc::new(WriteContextLiveStateReader::new(write_ctx.clone()));
|
|
96
|
-
let
|
|
98
|
+
let branch_ref = Arc::new(WriteContextBranchRefReader::new(write_ctx.clone()));
|
|
97
99
|
Self {
|
|
98
|
-
schema:
|
|
100
|
+
schema: lix_branch_schema(),
|
|
99
101
|
live_state,
|
|
100
|
-
|
|
102
|
+
branch_ref,
|
|
101
103
|
write_access: WriteAccess::write(write_ctx),
|
|
102
104
|
}
|
|
103
105
|
}
|
|
104
106
|
}
|
|
105
107
|
|
|
106
108
|
#[async_trait]
|
|
107
|
-
impl TableProvider for
|
|
109
|
+
impl TableProvider for LixBranchProvider {
|
|
108
110
|
fn as_any(&self) -> &dyn Any {
|
|
109
111
|
self
|
|
110
112
|
}
|
|
@@ -134,9 +136,9 @@ impl TableProvider for LixVersionProvider {
|
|
|
134
136
|
_filters: &[Expr],
|
|
135
137
|
_limit: Option<usize>,
|
|
136
138
|
) -> Result<Arc<dyn ExecutionPlan>> {
|
|
137
|
-
Ok(Arc::new(
|
|
139
|
+
Ok(Arc::new(LixBranchScanExec::new(
|
|
138
140
|
Arc::clone(&self.live_state),
|
|
139
|
-
Arc::clone(&self.
|
|
141
|
+
Arc::clone(&self.branch_ref),
|
|
140
142
|
projected_schema(&self.schema, projection),
|
|
141
143
|
projection.cloned(),
|
|
142
144
|
)))
|
|
@@ -149,11 +151,12 @@ impl TableProvider for LixVersionProvider {
|
|
|
149
151
|
insert_op: InsertOp,
|
|
150
152
|
) -> Result<Arc<dyn ExecutionPlan>> {
|
|
151
153
|
if insert_op != InsertOp::Append {
|
|
152
|
-
return not_impl_err!("{insert_op} not implemented for
|
|
154
|
+
return not_impl_err!("{insert_op} not implemented for lix_branch yet");
|
|
153
155
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
156
|
+
let write_ctx = self.write_access.require_write("INSERT into lix_branch")?;
|
|
157
|
+
self.schema
|
|
158
|
+
.logically_equivalent_names_and_types(&input.schema())?;
|
|
159
|
+
let sink = LixBranchInsertSink::new(write_ctx);
|
|
157
160
|
Ok(Arc::new(InsertExec::new(input, Arc::new(sink))))
|
|
158
161
|
}
|
|
159
162
|
|
|
@@ -162,17 +165,16 @@ impl TableProvider for LixVersionProvider {
|
|
|
162
165
|
state: &dyn Session,
|
|
163
166
|
filters: Vec<Expr>,
|
|
164
167
|
) -> Result<Arc<dyn ExecutionPlan>> {
|
|
165
|
-
let write_ctx = self.write_access.require_write("DELETE FROM
|
|
168
|
+
let write_ctx = self.write_access.require_write("DELETE FROM lix_branch")?;
|
|
166
169
|
let df_schema = DFSchema::try_from(Arc::clone(&self.schema))?;
|
|
167
170
|
let physical_filters = filters
|
|
168
171
|
.iter()
|
|
169
172
|
.map(|expr| create_physical_expr(expr, &df_schema, state.execution_props()))
|
|
170
173
|
.collect::<Result<Vec<_>>>()?;
|
|
171
|
-
|
|
172
|
-
Ok(Arc::new(LixVersionDeleteExec::new(
|
|
174
|
+
Ok(Arc::new(LixBranchDeleteExec::new(
|
|
173
175
|
write_ctx,
|
|
174
176
|
Arc::clone(&self.live_state),
|
|
175
|
-
Arc::clone(&self.
|
|
177
|
+
Arc::clone(&self.branch_ref),
|
|
176
178
|
Arc::clone(&self.schema),
|
|
177
179
|
physical_filters,
|
|
178
180
|
)))
|
|
@@ -184,9 +186,8 @@ impl TableProvider for LixVersionProvider {
|
|
|
184
186
|
assignments: Vec<(String, Expr)>,
|
|
185
187
|
filters: Vec<Expr>,
|
|
186
188
|
) -> Result<Arc<dyn ExecutionPlan>> {
|
|
187
|
-
let write_ctx = self.write_access.require_write("UPDATE
|
|
188
|
-
|
|
189
|
-
|
|
189
|
+
let write_ctx = self.write_access.require_write("UPDATE lix_branch")?;
|
|
190
|
+
validate_lix_branch_update_assignments(&assignments)?;
|
|
190
191
|
let df_schema = DFSchema::try_from(Arc::clone(&self.schema))?;
|
|
191
192
|
let physical_assignments = assignments
|
|
192
193
|
.iter()
|
|
@@ -201,11 +202,10 @@ impl TableProvider for LixVersionProvider {
|
|
|
201
202
|
.iter()
|
|
202
203
|
.map(|expr| create_physical_expr(expr, &df_schema, state.execution_props()))
|
|
203
204
|
.collect::<Result<Vec<_>>>()?;
|
|
204
|
-
|
|
205
|
-
Ok(Arc::new(LixVersionUpdateExec::new(
|
|
205
|
+
Ok(Arc::new(LixBranchUpdateExec::new(
|
|
206
206
|
write_ctx,
|
|
207
207
|
Arc::clone(&self.live_state),
|
|
208
|
-
Arc::clone(&self.
|
|
208
|
+
Arc::clone(&self.branch_ref),
|
|
209
209
|
Arc::clone(&self.schema),
|
|
210
210
|
physical_assignments,
|
|
211
211
|
physical_filters,
|
|
@@ -213,35 +213,35 @@ impl TableProvider for LixVersionProvider {
|
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
-
struct
|
|
216
|
+
struct LixBranchInsertSink {
|
|
217
217
|
write_ctx: SqlWriteContext,
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
-
impl std::fmt::Debug for
|
|
220
|
+
impl std::fmt::Debug for LixBranchInsertSink {
|
|
221
221
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
222
|
-
f.debug_struct("
|
|
222
|
+
f.debug_struct("LixBranchInsertSink").finish()
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
-
impl
|
|
227
|
-
fn new(
|
|
226
|
+
impl LixBranchInsertSink {
|
|
227
|
+
fn new(write_ctx: SqlWriteContext) -> Self {
|
|
228
228
|
Self { write_ctx }
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
231
|
|
|
232
|
-
impl DisplayAs for
|
|
232
|
+
impl DisplayAs for LixBranchInsertSink {
|
|
233
233
|
fn fmt_as(&self, t: DisplayFormatType, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
234
234
|
match t {
|
|
235
235
|
DisplayFormatType::Default | DisplayFormatType::Verbose => {
|
|
236
|
-
write!(f, "
|
|
236
|
+
write!(f, "LixBranchInsertSink")
|
|
237
237
|
}
|
|
238
|
-
DisplayFormatType::TreeRender => write!(f, "
|
|
238
|
+
DisplayFormatType::TreeRender => write!(f, "LixBranchInsertSink"),
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
241
|
}
|
|
242
242
|
|
|
243
243
|
#[async_trait]
|
|
244
|
-
impl InsertSink for
|
|
244
|
+
impl InsertSink for LixBranchInsertSink {
|
|
245
245
|
async fn write_batches(
|
|
246
246
|
&self,
|
|
247
247
|
batches: Vec<RecordBatch>,
|
|
@@ -249,24 +249,24 @@ impl InsertSink for LixVersionInsertSink {
|
|
|
249
249
|
) -> Result<u64> {
|
|
250
250
|
let default_commit_id = self
|
|
251
251
|
.write_ctx
|
|
252
|
-
.
|
|
252
|
+
.load_branch_head(&self.write_ctx.active_branch_id())
|
|
253
253
|
.await
|
|
254
254
|
.map_err(lix_error_to_datafusion_error)?
|
|
255
255
|
.ok_or_else(|| {
|
|
256
256
|
DataFusionError::Execution(
|
|
257
|
-
"INSERT into
|
|
257
|
+
"INSERT into lix_branch could not resolve active branch head".to_string(),
|
|
258
258
|
)
|
|
259
259
|
})?;
|
|
260
260
|
let mut rows = Vec::new();
|
|
261
261
|
let mut count = 0u64;
|
|
262
262
|
for batch in batches {
|
|
263
|
-
let
|
|
263
|
+
let branch_rows = branch_insert_rows_from_batch(&batch, &default_commit_id)?;
|
|
264
264
|
count = count
|
|
265
|
-
.checked_add(u64::try_from(
|
|
265
|
+
.checked_add(u64::try_from(branch_rows.len()).map_err(|_| {
|
|
266
266
|
DataFusionError::Execution("INSERT row count overflow".to_string())
|
|
267
267
|
})?)
|
|
268
268
|
.ok_or_else(|| DataFusionError::Execution("INSERT row count overflow".into()))?;
|
|
269
|
-
rows.extend(
|
|
269
|
+
rows.extend(branch_rows.into_iter().flat_map(branch_insert_stage_rows));
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
if !rows.is_empty() {
|
|
@@ -283,39 +283,39 @@ impl InsertSink for LixVersionInsertSink {
|
|
|
283
283
|
}
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
-
struct
|
|
286
|
+
struct LixBranchDeleteExec {
|
|
287
287
|
write_ctx: SqlWriteContext,
|
|
288
|
-
|
|
288
|
+
active_branch_id: String,
|
|
289
289
|
live_state: Arc<dyn LiveStateReader>,
|
|
290
|
-
|
|
290
|
+
branch_ref: Arc<dyn BranchRefReader>,
|
|
291
291
|
table_schema: SchemaRef,
|
|
292
292
|
filters: Vec<Arc<dyn PhysicalExpr>>,
|
|
293
293
|
result_schema: SchemaRef,
|
|
294
294
|
properties: Arc<PlanProperties>,
|
|
295
295
|
}
|
|
296
296
|
|
|
297
|
-
impl std::fmt::Debug for
|
|
297
|
+
impl std::fmt::Debug for LixBranchDeleteExec {
|
|
298
298
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
299
|
-
f.debug_struct("
|
|
299
|
+
f.debug_struct("LixBranchDeleteExec").finish()
|
|
300
300
|
}
|
|
301
301
|
}
|
|
302
302
|
|
|
303
|
-
impl
|
|
303
|
+
impl LixBranchDeleteExec {
|
|
304
304
|
fn new(
|
|
305
305
|
write_ctx: SqlWriteContext,
|
|
306
306
|
live_state: Arc<dyn LiveStateReader>,
|
|
307
|
-
|
|
307
|
+
branch_ref: Arc<dyn BranchRefReader>,
|
|
308
308
|
table_schema: SchemaRef,
|
|
309
309
|
filters: Vec<Arc<dyn PhysicalExpr>>,
|
|
310
310
|
) -> Self {
|
|
311
311
|
let result_schema = dml_count_schema();
|
|
312
312
|
let properties = dml_plan_properties(Arc::clone(&result_schema));
|
|
313
|
-
let
|
|
313
|
+
let active_branch_id = write_ctx.active_branch_id();
|
|
314
314
|
Self {
|
|
315
315
|
write_ctx,
|
|
316
|
-
|
|
316
|
+
active_branch_id,
|
|
317
317
|
live_state,
|
|
318
|
-
|
|
318
|
+
branch_ref,
|
|
319
319
|
table_schema,
|
|
320
320
|
filters,
|
|
321
321
|
result_schema,
|
|
@@ -324,20 +324,20 @@ impl LixVersionDeleteExec {
|
|
|
324
324
|
}
|
|
325
325
|
}
|
|
326
326
|
|
|
327
|
-
impl DisplayAs for
|
|
327
|
+
impl DisplayAs for LixBranchDeleteExec {
|
|
328
328
|
fn fmt_as(&self, t: DisplayFormatType, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
329
329
|
match t {
|
|
330
330
|
DisplayFormatType::Default | DisplayFormatType::Verbose => {
|
|
331
|
-
write!(f, "
|
|
331
|
+
write!(f, "LixBranchDeleteExec(filters={})", self.filters.len())
|
|
332
332
|
}
|
|
333
|
-
DisplayFormatType::TreeRender => write!(f, "
|
|
333
|
+
DisplayFormatType::TreeRender => write!(f, "LixBranchDeleteExec"),
|
|
334
334
|
}
|
|
335
335
|
}
|
|
336
336
|
}
|
|
337
337
|
|
|
338
|
-
impl ExecutionPlan for
|
|
338
|
+
impl ExecutionPlan for LixBranchDeleteExec {
|
|
339
339
|
fn name(&self) -> &str {
|
|
340
|
-
"
|
|
340
|
+
"LixBranchDeleteExec"
|
|
341
341
|
}
|
|
342
342
|
|
|
343
343
|
fn as_any(&self) -> &dyn Any {
|
|
@@ -358,7 +358,7 @@ impl ExecutionPlan for LixVersionDeleteExec {
|
|
|
358
358
|
) -> Result<Arc<dyn ExecutionPlan>> {
|
|
359
359
|
if !children.is_empty() {
|
|
360
360
|
return Err(DataFusionError::Execution(
|
|
361
|
-
"
|
|
361
|
+
"LixBranchDeleteExec does not accept children".to_string(),
|
|
362
362
|
));
|
|
363
363
|
}
|
|
364
364
|
Ok(self)
|
|
@@ -371,31 +371,31 @@ impl ExecutionPlan for LixVersionDeleteExec {
|
|
|
371
371
|
) -> Result<SendableRecordBatchStream> {
|
|
372
372
|
if partition != 0 {
|
|
373
373
|
return Err(DataFusionError::Execution(format!(
|
|
374
|
-
"
|
|
374
|
+
"LixBranchDeleteExec only exposes one partition, got {partition}"
|
|
375
375
|
)));
|
|
376
376
|
}
|
|
377
377
|
let write_ctx = self.write_ctx.clone();
|
|
378
|
-
let
|
|
378
|
+
let active_branch_id = self.active_branch_id.clone();
|
|
379
379
|
let live_state = Arc::clone(&self.live_state);
|
|
380
|
-
let
|
|
380
|
+
let branch_ref = Arc::clone(&self.branch_ref);
|
|
381
381
|
let filters = self.filters.clone();
|
|
382
382
|
let table_schema = Arc::clone(&self.table_schema);
|
|
383
383
|
let result_schema = Arc::clone(&self.result_schema);
|
|
384
384
|
let stream_schema = Arc::clone(&result_schema);
|
|
385
385
|
|
|
386
386
|
let stream = stream::once(async move {
|
|
387
|
-
let rows =
|
|
387
|
+
let rows = load_branch_rows(live_state, branch_ref)
|
|
388
388
|
.await
|
|
389
389
|
.map_err(lix_error_to_datafusion_error)?;
|
|
390
|
-
let source_batch =
|
|
391
|
-
let matched_batch =
|
|
392
|
-
let
|
|
393
|
-
|
|
394
|
-
let count = u64::try_from(
|
|
390
|
+
let source_batch = branch_record_batch(&branch_projection_for_scan(None), &rows)?;
|
|
391
|
+
let matched_batch = filter_branch_batch(source_batch, &filters)?;
|
|
392
|
+
let branch_rows = branch_rows_from_batch(&matched_batch)?;
|
|
393
|
+
reject_protected_branch_deletes(&branch_rows, &active_branch_id)?;
|
|
394
|
+
let count = u64::try_from(branch_rows.len())
|
|
395
395
|
.map_err(|_| DataFusionError::Execution("DELETE row count overflow".to_string()))?;
|
|
396
|
-
let rows =
|
|
396
|
+
let rows = branch_rows
|
|
397
397
|
.into_iter()
|
|
398
|
-
.flat_map(
|
|
398
|
+
.flat_map(branch_tombstone_rows)
|
|
399
399
|
.collect::<Vec<_>>();
|
|
400
400
|
|
|
401
401
|
if !rows.is_empty() {
|
|
@@ -421,10 +421,10 @@ impl ExecutionPlan for LixVersionDeleteExec {
|
|
|
421
421
|
}
|
|
422
422
|
}
|
|
423
423
|
|
|
424
|
-
struct
|
|
424
|
+
struct LixBranchUpdateExec {
|
|
425
425
|
write_ctx: SqlWriteContext,
|
|
426
426
|
live_state: Arc<dyn LiveStateReader>,
|
|
427
|
-
|
|
427
|
+
branch_ref: Arc<dyn BranchRefReader>,
|
|
428
428
|
table_schema: SchemaRef,
|
|
429
429
|
assignments: Vec<(String, Arc<dyn PhysicalExpr>)>,
|
|
430
430
|
filters: Vec<Arc<dyn PhysicalExpr>>,
|
|
@@ -432,17 +432,17 @@ struct LixVersionUpdateExec {
|
|
|
432
432
|
properties: Arc<PlanProperties>,
|
|
433
433
|
}
|
|
434
434
|
|
|
435
|
-
impl std::fmt::Debug for
|
|
435
|
+
impl std::fmt::Debug for LixBranchUpdateExec {
|
|
436
436
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
437
|
-
f.debug_struct("
|
|
437
|
+
f.debug_struct("LixBranchUpdateExec").finish()
|
|
438
438
|
}
|
|
439
439
|
}
|
|
440
440
|
|
|
441
|
-
impl
|
|
441
|
+
impl LixBranchUpdateExec {
|
|
442
442
|
fn new(
|
|
443
443
|
write_ctx: SqlWriteContext,
|
|
444
444
|
live_state: Arc<dyn LiveStateReader>,
|
|
445
|
-
|
|
445
|
+
branch_ref: Arc<dyn BranchRefReader>,
|
|
446
446
|
table_schema: SchemaRef,
|
|
447
447
|
assignments: Vec<(String, Arc<dyn PhysicalExpr>)>,
|
|
448
448
|
filters: Vec<Arc<dyn PhysicalExpr>>,
|
|
@@ -452,7 +452,7 @@ impl LixVersionUpdateExec {
|
|
|
452
452
|
Self {
|
|
453
453
|
write_ctx,
|
|
454
454
|
live_state,
|
|
455
|
-
|
|
455
|
+
branch_ref,
|
|
456
456
|
table_schema,
|
|
457
457
|
assignments,
|
|
458
458
|
filters,
|
|
@@ -462,25 +462,25 @@ impl LixVersionUpdateExec {
|
|
|
462
462
|
}
|
|
463
463
|
}
|
|
464
464
|
|
|
465
|
-
impl DisplayAs for
|
|
465
|
+
impl DisplayAs for LixBranchUpdateExec {
|
|
466
466
|
fn fmt_as(&self, t: DisplayFormatType, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
467
467
|
match t {
|
|
468
468
|
DisplayFormatType::Default | DisplayFormatType::Verbose => {
|
|
469
469
|
write!(
|
|
470
470
|
f,
|
|
471
|
-
"
|
|
471
|
+
"LixBranchUpdateExec(assignments={}, filters={})",
|
|
472
472
|
self.assignments.len(),
|
|
473
473
|
self.filters.len()
|
|
474
474
|
)
|
|
475
475
|
}
|
|
476
|
-
DisplayFormatType::TreeRender => write!(f, "
|
|
476
|
+
DisplayFormatType::TreeRender => write!(f, "LixBranchUpdateExec"),
|
|
477
477
|
}
|
|
478
478
|
}
|
|
479
479
|
}
|
|
480
480
|
|
|
481
|
-
impl ExecutionPlan for
|
|
481
|
+
impl ExecutionPlan for LixBranchUpdateExec {
|
|
482
482
|
fn name(&self) -> &str {
|
|
483
|
-
"
|
|
483
|
+
"LixBranchUpdateExec"
|
|
484
484
|
}
|
|
485
485
|
|
|
486
486
|
fn as_any(&self) -> &dyn Any {
|
|
@@ -501,7 +501,7 @@ impl ExecutionPlan for LixVersionUpdateExec {
|
|
|
501
501
|
) -> Result<Arc<dyn ExecutionPlan>> {
|
|
502
502
|
if !children.is_empty() {
|
|
503
503
|
return Err(DataFusionError::Execution(
|
|
504
|
-
"
|
|
504
|
+
"LixBranchUpdateExec does not accept children".to_string(),
|
|
505
505
|
));
|
|
506
506
|
}
|
|
507
507
|
Ok(self)
|
|
@@ -514,12 +514,12 @@ impl ExecutionPlan for LixVersionUpdateExec {
|
|
|
514
514
|
) -> Result<SendableRecordBatchStream> {
|
|
515
515
|
if partition != 0 {
|
|
516
516
|
return Err(DataFusionError::Execution(format!(
|
|
517
|
-
"
|
|
517
|
+
"LixBranchUpdateExec only exposes one partition, got {partition}"
|
|
518
518
|
)));
|
|
519
519
|
}
|
|
520
520
|
let write_ctx = self.write_ctx.clone();
|
|
521
521
|
let live_state = Arc::clone(&self.live_state);
|
|
522
|
-
let
|
|
522
|
+
let branch_ref = Arc::clone(&self.branch_ref);
|
|
523
523
|
let table_schema = Arc::clone(&self.table_schema);
|
|
524
524
|
let assignments = self.assignments.clone();
|
|
525
525
|
let filters = self.filters.clone();
|
|
@@ -527,18 +527,19 @@ impl ExecutionPlan for LixVersionUpdateExec {
|
|
|
527
527
|
let stream_schema = Arc::clone(&result_schema);
|
|
528
528
|
|
|
529
529
|
let stream = stream::once(async move {
|
|
530
|
-
let rows =
|
|
530
|
+
let rows = load_branch_rows(live_state, branch_ref)
|
|
531
531
|
.await
|
|
532
532
|
.map_err(lix_error_to_datafusion_error)?;
|
|
533
|
-
let source_batch =
|
|
534
|
-
let matched_batch =
|
|
535
|
-
let
|
|
536
|
-
|
|
537
|
-
|
|
533
|
+
let source_batch = branch_record_batch(&branch_projection_for_scan(None), &rows)?;
|
|
534
|
+
let matched_batch = filter_branch_batch(source_batch, &filters)?;
|
|
535
|
+
let branch_rows =
|
|
536
|
+
branch_update_rows_from_batch(&matched_batch, &assignments, &table_schema)?;
|
|
537
|
+
reject_protected_branch_updates(&branch_rows)?;
|
|
538
|
+
let count = u64::try_from(branch_rows.len())
|
|
538
539
|
.map_err(|_| DataFusionError::Execution("UPDATE row count overflow".to_string()))?;
|
|
539
|
-
let rows =
|
|
540
|
+
let rows = branch_rows
|
|
540
541
|
.into_iter()
|
|
541
|
-
.flat_map(
|
|
542
|
+
.flat_map(branch_update_stage_rows)
|
|
542
543
|
.collect::<Vec<_>>();
|
|
543
544
|
|
|
544
545
|
if !rows.is_empty() {
|
|
@@ -563,24 +564,24 @@ impl ExecutionPlan for LixVersionUpdateExec {
|
|
|
563
564
|
}
|
|
564
565
|
}
|
|
565
566
|
|
|
566
|
-
struct
|
|
567
|
+
struct LixBranchScanExec {
|
|
567
568
|
live_state: Arc<dyn LiveStateReader>,
|
|
568
|
-
|
|
569
|
+
branch_ref: Arc<dyn BranchRefReader>,
|
|
569
570
|
schema: SchemaRef,
|
|
570
571
|
projection: Option<Vec<usize>>,
|
|
571
572
|
properties: Arc<PlanProperties>,
|
|
572
573
|
}
|
|
573
574
|
|
|
574
|
-
impl std::fmt::Debug for
|
|
575
|
+
impl std::fmt::Debug for LixBranchScanExec {
|
|
575
576
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
576
|
-
f.debug_struct("
|
|
577
|
+
f.debug_struct("LixBranchScanExec").finish()
|
|
577
578
|
}
|
|
578
579
|
}
|
|
579
580
|
|
|
580
|
-
impl
|
|
581
|
+
impl LixBranchScanExec {
|
|
581
582
|
fn new(
|
|
582
583
|
live_state: Arc<dyn LiveStateReader>,
|
|
583
|
-
|
|
584
|
+
branch_ref: Arc<dyn BranchRefReader>,
|
|
584
585
|
schema: SchemaRef,
|
|
585
586
|
projection: Option<Vec<usize>>,
|
|
586
587
|
) -> Self {
|
|
@@ -592,7 +593,7 @@ impl LixVersionScanExec {
|
|
|
592
593
|
);
|
|
593
594
|
Self {
|
|
594
595
|
live_state,
|
|
595
|
-
|
|
596
|
+
branch_ref,
|
|
596
597
|
schema,
|
|
597
598
|
projection,
|
|
598
599
|
properties: Arc::new(properties),
|
|
@@ -600,20 +601,20 @@ impl LixVersionScanExec {
|
|
|
600
601
|
}
|
|
601
602
|
}
|
|
602
603
|
|
|
603
|
-
impl DisplayAs for
|
|
604
|
+
impl DisplayAs for LixBranchScanExec {
|
|
604
605
|
fn fmt_as(&self, t: DisplayFormatType, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
605
606
|
match t {
|
|
606
607
|
DisplayFormatType::Default | DisplayFormatType::Verbose => {
|
|
607
|
-
write!(f, "
|
|
608
|
+
write!(f, "LixBranchScanExec")
|
|
608
609
|
}
|
|
609
|
-
DisplayFormatType::TreeRender => write!(f, "
|
|
610
|
+
DisplayFormatType::TreeRender => write!(f, "LixBranchScanExec"),
|
|
610
611
|
}
|
|
611
612
|
}
|
|
612
613
|
}
|
|
613
614
|
|
|
614
|
-
impl ExecutionPlan for
|
|
615
|
+
impl ExecutionPlan for LixBranchScanExec {
|
|
615
616
|
fn name(&self) -> &str {
|
|
616
|
-
"
|
|
617
|
+
"LixBranchScanExec"
|
|
617
618
|
}
|
|
618
619
|
|
|
619
620
|
fn as_any(&self) -> &dyn Any {
|
|
@@ -634,7 +635,7 @@ impl ExecutionPlan for LixVersionScanExec {
|
|
|
634
635
|
) -> Result<Arc<dyn ExecutionPlan>> {
|
|
635
636
|
if !children.is_empty() {
|
|
636
637
|
return Err(DataFusionError::Execution(
|
|
637
|
-
"
|
|
638
|
+
"LixBranchScanExec does not accept children".to_string(),
|
|
638
639
|
));
|
|
639
640
|
}
|
|
640
641
|
Ok(self)
|
|
@@ -647,26 +648,26 @@ impl ExecutionPlan for LixVersionScanExec {
|
|
|
647
648
|
) -> Result<SendableRecordBatchStream> {
|
|
648
649
|
if partition != 0 {
|
|
649
650
|
return Err(DataFusionError::Execution(format!(
|
|
650
|
-
"
|
|
651
|
+
"LixBranchScanExec only exposes one partition, got {partition}"
|
|
651
652
|
)));
|
|
652
653
|
}
|
|
653
654
|
|
|
654
655
|
let live_state = Arc::clone(&self.live_state);
|
|
655
|
-
let
|
|
656
|
-
let projection =
|
|
656
|
+
let branch_ref = Arc::clone(&self.branch_ref);
|
|
657
|
+
let projection = branch_projection_for_scan(self.projection.as_ref());
|
|
657
658
|
let schema = Arc::clone(&self.schema);
|
|
658
659
|
let stream = stream::once(async move {
|
|
659
|
-
let rows =
|
|
660
|
+
let rows = load_branch_rows(live_state, branch_ref)
|
|
660
661
|
.await
|
|
661
662
|
.map_err(lix_error_to_datafusion_error)?;
|
|
662
|
-
|
|
663
|
+
branch_record_batch(&projection, &rows)
|
|
663
664
|
});
|
|
664
665
|
Ok(Box::pin(RecordBatchStreamAdapter::new(schema, stream)))
|
|
665
666
|
}
|
|
666
667
|
}
|
|
667
668
|
|
|
668
669
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
669
|
-
struct
|
|
670
|
+
struct BranchRow {
|
|
670
671
|
id: String,
|
|
671
672
|
name: String,
|
|
672
673
|
hidden: bool,
|
|
@@ -674,22 +675,22 @@ struct VersionRow {
|
|
|
674
675
|
}
|
|
675
676
|
|
|
676
677
|
#[derive(Debug, Clone, Copy)]
|
|
677
|
-
enum
|
|
678
|
+
enum BranchColumn {
|
|
678
679
|
Id,
|
|
679
680
|
Name,
|
|
680
681
|
Hidden,
|
|
681
682
|
CommitId,
|
|
682
683
|
}
|
|
683
684
|
|
|
684
|
-
async fn
|
|
685
|
+
async fn load_branch_rows(
|
|
685
686
|
live_state: Arc<dyn LiveStateReader>,
|
|
686
|
-
|
|
687
|
-
) -> Result<Vec<
|
|
687
|
+
branch_ref: Arc<dyn BranchRefReader>,
|
|
688
|
+
) -> Result<Vec<BranchRow>, LixError> {
|
|
688
689
|
let descriptor_rows = live_state
|
|
689
690
|
.scan_rows(&LiveStateScanRequest {
|
|
690
691
|
filter: LiveStateFilter {
|
|
691
|
-
schema_keys: vec!["
|
|
692
|
-
|
|
692
|
+
schema_keys: vec!["lix_branch_descriptor".to_string()],
|
|
693
|
+
branch_ids: vec![GLOBAL_BRANCH_ID.to_string()],
|
|
693
694
|
..LiveStateFilter::default()
|
|
694
695
|
},
|
|
695
696
|
projection: Default::default(),
|
|
@@ -700,10 +701,10 @@ async fn load_version_rows(
|
|
|
700
701
|
let mut out = Vec::new();
|
|
701
702
|
for descriptor_row in descriptor_rows {
|
|
702
703
|
let descriptor = parse_descriptor(&descriptor_row)?;
|
|
703
|
-
let Some(commit_id) =
|
|
704
|
+
let Some(commit_id) = branch_ref.load_head_commit_id(&descriptor.id).await? else {
|
|
704
705
|
continue;
|
|
705
706
|
};
|
|
706
|
-
out.push(
|
|
707
|
+
out.push(BranchRow {
|
|
707
708
|
commit_id,
|
|
708
709
|
id: descriptor.id,
|
|
709
710
|
name: descriptor.name,
|
|
@@ -714,34 +715,29 @@ async fn load_version_rows(
|
|
|
714
715
|
}
|
|
715
716
|
|
|
716
717
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
717
|
-
struct
|
|
718
|
+
struct BranchDescriptor {
|
|
718
719
|
id: String,
|
|
719
720
|
name: String,
|
|
720
721
|
hidden: bool,
|
|
721
722
|
}
|
|
722
723
|
|
|
723
|
-
fn parse_descriptor(row: &MaterializedLiveStateRow) -> Result<
|
|
724
|
-
let snapshot = parse_snapshot(row, "
|
|
724
|
+
fn parse_descriptor(row: &MaterializedLiveStateRow) -> Result<BranchDescriptor, LixError> {
|
|
725
|
+
let snapshot = parse_snapshot(row, "lix_branch_descriptor")?;
|
|
725
726
|
let id = snapshot
|
|
726
727
|
.get("id")
|
|
727
728
|
.and_then(JsonValue::as_str)
|
|
728
|
-
.ok_or_else(|| LixError::new("LIX_ERROR_UNKNOWN", "
|
|
729
|
+
.ok_or_else(|| LixError::new("LIX_ERROR_UNKNOWN", "lix_branch_descriptor is missing id"))?
|
|
729
730
|
.to_string();
|
|
730
731
|
let name = snapshot
|
|
731
732
|
.get("name")
|
|
732
733
|
.and_then(JsonValue::as_str)
|
|
733
|
-
.ok_or_else(||
|
|
734
|
-
LixError::new(
|
|
735
|
-
"LIX_ERROR_UNKNOWN",
|
|
736
|
-
"lix_version_descriptor is missing name",
|
|
737
|
-
)
|
|
738
|
-
})?
|
|
734
|
+
.ok_or_else(|| LixError::new("LIX_ERROR_UNKNOWN", "lix_branch_descriptor is missing name"))?
|
|
739
735
|
.to_string();
|
|
740
736
|
let hidden = snapshot
|
|
741
737
|
.get("hidden")
|
|
742
738
|
.and_then(JsonValue::as_bool)
|
|
743
739
|
.unwrap_or(false);
|
|
744
|
-
Ok(
|
|
740
|
+
Ok(BranchDescriptor { id, name, hidden })
|
|
745
741
|
}
|
|
746
742
|
|
|
747
743
|
fn parse_snapshot(row: &MaterializedLiveStateRow, schema_key: &str) -> Result<JsonValue, LixError> {
|
|
@@ -759,18 +755,18 @@ fn parse_snapshot(row: &MaterializedLiveStateRow, schema_key: &str) -> Result<Js
|
|
|
759
755
|
})
|
|
760
756
|
}
|
|
761
757
|
|
|
762
|
-
fn
|
|
758
|
+
fn validate_lix_branch_update_assignments(assignments: &[(String, Expr)]) -> Result<()> {
|
|
763
759
|
for (column_name, _) in assignments {
|
|
764
760
|
match column_name.as_str() {
|
|
765
761
|
"name" | "hidden" | "commit_id" => {}
|
|
766
762
|
"id" => {
|
|
767
763
|
return Err(DataFusionError::Execution(
|
|
768
|
-
"UPDATE
|
|
764
|
+
"UPDATE lix_branch cannot change immutable column 'id'".to_string(),
|
|
769
765
|
));
|
|
770
766
|
}
|
|
771
767
|
other => {
|
|
772
768
|
return Err(DataFusionError::Plan(format!(
|
|
773
|
-
"UPDATE
|
|
769
|
+
"UPDATE lix_branch failed: column '{other}' does not exist"
|
|
774
770
|
)));
|
|
775
771
|
}
|
|
776
772
|
}
|
|
@@ -778,17 +774,17 @@ fn validate_lix_version_update_assignments(assignments: &[(String, Expr)]) -> Re
|
|
|
778
774
|
Ok(())
|
|
779
775
|
}
|
|
780
776
|
|
|
781
|
-
fn
|
|
777
|
+
fn filter_branch_batch(
|
|
782
778
|
batch: RecordBatch,
|
|
783
779
|
filters: &[Arc<dyn PhysicalExpr>],
|
|
784
780
|
) -> Result<RecordBatch> {
|
|
785
|
-
let Some(mask) =
|
|
781
|
+
let Some(mask) = evaluate_branch_filters(&batch, filters)? else {
|
|
786
782
|
return Ok(batch);
|
|
787
783
|
};
|
|
788
784
|
Ok(filter_record_batch(&batch, &mask)?)
|
|
789
785
|
}
|
|
790
786
|
|
|
791
|
-
fn
|
|
787
|
+
fn evaluate_branch_filters(
|
|
792
788
|
batch: &RecordBatch,
|
|
793
789
|
filters: &[Arc<dyn PhysicalExpr>],
|
|
794
790
|
) -> Result<Option<BooleanArray>> {
|
|
@@ -804,7 +800,7 @@ fn evaluate_version_filters(
|
|
|
804
800
|
.as_any()
|
|
805
801
|
.downcast_ref::<BooleanArray>()
|
|
806
802
|
.ok_or_else(|| {
|
|
807
|
-
DataFusionError::Execution("
|
|
803
|
+
DataFusionError::Execution("lix_branch filter was not boolean".to_string())
|
|
808
804
|
})?;
|
|
809
805
|
let normalized = bool_array
|
|
810
806
|
.iter()
|
|
@@ -818,10 +814,10 @@ fn evaluate_version_filters(
|
|
|
818
814
|
Ok(combined_mask)
|
|
819
815
|
}
|
|
820
816
|
|
|
821
|
-
fn
|
|
817
|
+
fn branch_insert_rows_from_batch(
|
|
822
818
|
batch: &RecordBatch,
|
|
823
819
|
default_commit_id: &str,
|
|
824
|
-
) -> Result<Vec<
|
|
820
|
+
) -> Result<Vec<BranchRow>> {
|
|
825
821
|
(0..batch.num_rows())
|
|
826
822
|
.map(|row_index| {
|
|
827
823
|
let id = required_string_value(batch, row_index, "id", "INSERT")?;
|
|
@@ -830,7 +826,7 @@ fn version_insert_rows_from_batch(
|
|
|
830
826
|
optional_bool_value(batch, row_index, "hidden", "INSERT")?.unwrap_or(false);
|
|
831
827
|
let commit_id = optional_string_value(batch, row_index, "commit_id", "INSERT")?
|
|
832
828
|
.unwrap_or_else(|| default_commit_id.to_string());
|
|
833
|
-
Ok(
|
|
829
|
+
Ok(BranchRow {
|
|
834
830
|
id,
|
|
835
831
|
name,
|
|
836
832
|
hidden,
|
|
@@ -840,10 +836,10 @@ fn version_insert_rows_from_batch(
|
|
|
840
836
|
.collect()
|
|
841
837
|
}
|
|
842
838
|
|
|
843
|
-
fn
|
|
839
|
+
fn branch_rows_from_batch(batch: &RecordBatch) -> Result<Vec<BranchRow>> {
|
|
844
840
|
(0..batch.num_rows())
|
|
845
841
|
.map(|row_index| {
|
|
846
|
-
Ok(
|
|
842
|
+
Ok(BranchRow {
|
|
847
843
|
id: required_string_value(batch, row_index, "id", "DELETE")?,
|
|
848
844
|
name: required_string_value(batch, row_index, "name", "DELETE")?,
|
|
849
845
|
hidden: required_bool_value(batch, row_index, "hidden", "DELETE")?,
|
|
@@ -853,16 +849,16 @@ fn version_rows_from_batch(batch: &RecordBatch) -> Result<Vec<VersionRow>> {
|
|
|
853
849
|
.collect()
|
|
854
850
|
}
|
|
855
851
|
|
|
856
|
-
fn
|
|
852
|
+
fn reject_protected_branch_deletes(rows: &[BranchRow], active_branch_id: &str) -> Result<()> {
|
|
857
853
|
for row in rows {
|
|
858
|
-
if row.id ==
|
|
854
|
+
if row.id == GLOBAL_BRANCH_ID {
|
|
859
855
|
return Err(DataFusionError::Execution(
|
|
860
|
-
"DELETE FROM
|
|
856
|
+
"DELETE FROM lix_branch cannot delete the global branch".to_string(),
|
|
861
857
|
));
|
|
862
858
|
}
|
|
863
|
-
if row.id ==
|
|
859
|
+
if row.id == active_branch_id {
|
|
864
860
|
return Err(DataFusionError::Execution(format!(
|
|
865
|
-
"DELETE FROM
|
|
861
|
+
"DELETE FROM lix_branch cannot delete active branch '{}'",
|
|
866
862
|
row.id
|
|
867
863
|
)));
|
|
868
864
|
}
|
|
@@ -870,15 +866,26 @@ fn reject_protected_version_deletes(rows: &[VersionRow], active_version_id: &str
|
|
|
870
866
|
Ok(())
|
|
871
867
|
}
|
|
872
868
|
|
|
873
|
-
fn
|
|
869
|
+
fn reject_protected_branch_updates(rows: &[BranchRow]) -> Result<()> {
|
|
870
|
+
for row in rows {
|
|
871
|
+
if row.id == GLOBAL_BRANCH_ID {
|
|
872
|
+
return Err(DataFusionError::Execution(
|
|
873
|
+
"UPDATE lix_branch cannot update the global branch".to_string(),
|
|
874
|
+
));
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
Ok(())
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
fn branch_update_rows_from_batch(
|
|
874
881
|
batch: &RecordBatch,
|
|
875
882
|
assignments: &[(String, Arc<dyn PhysicalExpr>)],
|
|
876
883
|
table_schema: &SchemaRef,
|
|
877
|
-
) -> Result<Vec<
|
|
884
|
+
) -> Result<Vec<BranchRow>> {
|
|
878
885
|
let assignment_values = UpdateAssignmentValues::evaluate(batch, assignments)?;
|
|
879
886
|
(0..batch.num_rows())
|
|
880
887
|
.map(|row_index| {
|
|
881
|
-
Ok(
|
|
888
|
+
Ok(BranchRow {
|
|
882
889
|
id: required_string_value(batch, row_index, "id", "UPDATE")?,
|
|
883
890
|
name: update_string_value(
|
|
884
891
|
batch,
|
|
@@ -906,38 +913,38 @@ fn version_update_rows_from_batch(
|
|
|
906
913
|
.collect()
|
|
907
914
|
}
|
|
908
915
|
|
|
909
|
-
fn
|
|
910
|
-
row:
|
|
916
|
+
fn branch_stage_rows(
|
|
917
|
+
row: BranchRow,
|
|
911
918
|
origin: Option<TransactionWriteOrigin>,
|
|
912
919
|
) -> Vec<TransactionWriteRow> {
|
|
913
920
|
vec![
|
|
914
921
|
with_origin(
|
|
915
|
-
|
|
922
|
+
branch_descriptor_stage_row(&row.id, &row.name, row.hidden),
|
|
916
923
|
origin.clone(),
|
|
917
924
|
),
|
|
918
|
-
with_origin(
|
|
925
|
+
with_origin(branch_ref_stage_row(&row.id, &row.commit_id), origin),
|
|
919
926
|
]
|
|
920
927
|
}
|
|
921
928
|
|
|
922
|
-
fn
|
|
923
|
-
let origin = Some(
|
|
929
|
+
fn branch_tombstone_rows(row: BranchRow) -> Vec<TransactionWriteRow> {
|
|
930
|
+
let origin = Some(lix_branch_origin(
|
|
924
931
|
TransactionWriteOperation::Delete,
|
|
925
932
|
&row.id,
|
|
926
933
|
));
|
|
927
934
|
vec![
|
|
928
|
-
with_origin(
|
|
929
|
-
with_origin(
|
|
935
|
+
with_origin(branch_descriptor_tombstone_row(&row.id), origin.clone()),
|
|
936
|
+
with_origin(branch_ref_tombstone_row(&row.id), origin),
|
|
930
937
|
]
|
|
931
938
|
}
|
|
932
939
|
|
|
933
|
-
fn
|
|
934
|
-
let origin =
|
|
935
|
-
|
|
940
|
+
fn branch_insert_stage_rows(row: BranchRow) -> Vec<TransactionWriteRow> {
|
|
941
|
+
let origin = lix_branch_origin(TransactionWriteOperation::Insert, &row.id);
|
|
942
|
+
branch_stage_rows(row, Some(origin))
|
|
936
943
|
}
|
|
937
944
|
|
|
938
|
-
fn
|
|
939
|
-
let origin =
|
|
940
|
-
|
|
945
|
+
fn branch_update_stage_rows(row: BranchRow) -> Vec<TransactionWriteRow> {
|
|
946
|
+
let origin = lix_branch_origin(TransactionWriteOperation::Update, &row.id);
|
|
947
|
+
branch_stage_rows(row, Some(origin))
|
|
941
948
|
}
|
|
942
949
|
|
|
943
950
|
fn with_origin(
|
|
@@ -948,16 +955,13 @@ fn with_origin(
|
|
|
948
955
|
row
|
|
949
956
|
}
|
|
950
957
|
|
|
951
|
-
fn
|
|
952
|
-
action: TransactionWriteOperation,
|
|
953
|
-
version_id: &str,
|
|
954
|
-
) -> TransactionWriteOrigin {
|
|
958
|
+
fn lix_branch_origin(action: TransactionWriteOperation, branch_id: &str) -> TransactionWriteOrigin {
|
|
955
959
|
TransactionWriteOrigin {
|
|
956
|
-
surface: "
|
|
960
|
+
surface: "lix_branch".to_string(),
|
|
957
961
|
operation: action,
|
|
958
962
|
primary_key: Some(LogicalPrimaryKey {
|
|
959
963
|
columns: vec!["id".to_string()],
|
|
960
|
-
values: vec![
|
|
964
|
+
values: vec![branch_id.to_string()],
|
|
961
965
|
}),
|
|
962
966
|
}
|
|
963
967
|
}
|
|
@@ -978,16 +982,16 @@ fn update_string_value(
|
|
|
978
982
|
| ScalarValue::LargeUtf8(Some(value)),
|
|
979
983
|
)) => Ok(value),
|
|
980
984
|
InsertCell::Provided(SqlCell::Null) => Err(DataFusionError::Execution(format!(
|
|
981
|
-
"UPDATE
|
|
985
|
+
"UPDATE lix_branch requires non-null text column '{column_name}'"
|
|
982
986
|
))),
|
|
983
987
|
InsertCell::Provided(SqlCell::Value(other)) => Err(DataFusionError::Execution(format!(
|
|
984
|
-
"UPDATE
|
|
988
|
+
"UPDATE lix_branch expected text-compatible column '{column_name}', got {other:?}"
|
|
985
989
|
))),
|
|
986
990
|
}
|
|
987
991
|
.or_else(|error| {
|
|
988
992
|
if batch.column(column_index).is_null(row_index) {
|
|
989
993
|
Err(DataFusionError::Execution(format!(
|
|
990
|
-
"UPDATE
|
|
994
|
+
"UPDATE lix_branch requires non-null text column '{column_name}'"
|
|
991
995
|
)))
|
|
992
996
|
} else {
|
|
993
997
|
Err(error)
|
|
@@ -1007,16 +1011,16 @@ fn update_bool_value(
|
|
|
1007
1011
|
InsertCell::Omitted => required_bool_value(batch, row_index, column_name, "UPDATE"),
|
|
1008
1012
|
InsertCell::Provided(SqlCell::Value(ScalarValue::Boolean(Some(value)))) => Ok(value),
|
|
1009
1013
|
InsertCell::Provided(SqlCell::Null) => Err(DataFusionError::Execution(format!(
|
|
1010
|
-
"UPDATE
|
|
1014
|
+
"UPDATE lix_branch requires non-null boolean column '{column_name}'"
|
|
1011
1015
|
))),
|
|
1012
1016
|
InsertCell::Provided(SqlCell::Value(other)) => Err(DataFusionError::Execution(format!(
|
|
1013
|
-
"UPDATE
|
|
1017
|
+
"UPDATE lix_branch expected boolean column '{column_name}', got {other:?}"
|
|
1014
1018
|
))),
|
|
1015
1019
|
}
|
|
1016
1020
|
.or_else(|error| {
|
|
1017
1021
|
if batch.column(column_index).is_null(row_index) {
|
|
1018
1022
|
Err(DataFusionError::Execution(format!(
|
|
1019
|
-
"UPDATE
|
|
1023
|
+
"UPDATE lix_branch requires non-null boolean column '{column_name}'"
|
|
1020
1024
|
)))
|
|
1021
1025
|
} else {
|
|
1022
1026
|
Err(error)
|
|
@@ -1032,7 +1036,7 @@ fn required_string_value(
|
|
|
1032
1036
|
) -> Result<String> {
|
|
1033
1037
|
optional_string_value(batch, row_index, column_name, action)?.ok_or_else(|| {
|
|
1034
1038
|
DataFusionError::Execution(format!(
|
|
1035
|
-
"{action}
|
|
1039
|
+
"{action} lix_branch requires non-null text column '{column_name}'"
|
|
1036
1040
|
))
|
|
1037
1041
|
})
|
|
1038
1042
|
}
|
|
@@ -1053,7 +1057,7 @@ fn optional_string_value(
|
|
|
1053
1057
|
| Some(ScalarValue::Utf8View(Some(value)))
|
|
1054
1058
|
| Some(ScalarValue::LargeUtf8(Some(value))) => Ok(Some(value)),
|
|
1055
1059
|
Some(other) => Err(DataFusionError::Execution(format!(
|
|
1056
|
-
"{action}
|
|
1060
|
+
"{action} lix_branch expected text-compatible column '{column_name}', got {other:?}"
|
|
1057
1061
|
))),
|
|
1058
1062
|
}
|
|
1059
1063
|
}
|
|
@@ -1066,7 +1070,7 @@ fn required_bool_value(
|
|
|
1066
1070
|
) -> Result<bool> {
|
|
1067
1071
|
optional_bool_value(batch, row_index, column_name, action)?.ok_or_else(|| {
|
|
1068
1072
|
DataFusionError::Execution(format!(
|
|
1069
|
-
"{action}
|
|
1073
|
+
"{action} lix_branch requires non-null boolean column '{column_name}'"
|
|
1070
1074
|
))
|
|
1071
1075
|
})
|
|
1072
1076
|
}
|
|
@@ -1081,7 +1085,7 @@ fn optional_bool_value(
|
|
|
1081
1085
|
None | Some(ScalarValue::Null) | Some(ScalarValue::Boolean(None)) => Ok(None),
|
|
1082
1086
|
Some(ScalarValue::Boolean(Some(value))) => Ok(Some(value)),
|
|
1083
1087
|
Some(other) => Err(DataFusionError::Execution(format!(
|
|
1084
|
-
"{action}
|
|
1088
|
+
"{action} lix_branch expected boolean column '{column_name}', got {other:?}"
|
|
1085
1089
|
))),
|
|
1086
1090
|
}
|
|
1087
1091
|
}
|
|
@@ -1125,7 +1129,7 @@ fn dml_count_batch(schema: SchemaRef, count: u64) -> Result<RecordBatch> {
|
|
|
1125
1129
|
.map_err(DataFusionError::from)
|
|
1126
1130
|
}
|
|
1127
1131
|
|
|
1128
|
-
fn
|
|
1132
|
+
pub(super) fn lix_branch_schema() -> SchemaRef {
|
|
1129
1133
|
Arc::new(Schema::new(vec![
|
|
1130
1134
|
Field::new("id", DataType::Utf8, false),
|
|
1131
1135
|
Field::new("name", DataType::Utf8, false),
|
|
@@ -1134,12 +1138,12 @@ fn lix_version_schema() -> SchemaRef {
|
|
|
1134
1138
|
]))
|
|
1135
1139
|
}
|
|
1136
1140
|
|
|
1137
|
-
fn
|
|
1141
|
+
fn branch_projection_for_scan(projection: Option<&Vec<usize>>) -> Vec<BranchColumn> {
|
|
1138
1142
|
let all_columns = vec![
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
+
BranchColumn::Id,
|
|
1144
|
+
BranchColumn::Name,
|
|
1145
|
+
BranchColumn::Hidden,
|
|
1146
|
+
BranchColumn::CommitId,
|
|
1143
1147
|
];
|
|
1144
1148
|
projection.map_or(all_columns.clone(), |indices| {
|
|
1145
1149
|
indices
|
|
@@ -1156,34 +1160,34 @@ fn projected_schema(schema: &SchemaRef, projection: Option<&Vec<usize>>) -> Sche
|
|
|
1156
1160
|
}
|
|
1157
1161
|
}
|
|
1158
1162
|
|
|
1159
|
-
fn
|
|
1163
|
+
fn branch_record_batch(projection: &[BranchColumn], rows: &[BranchRow]) -> Result<RecordBatch> {
|
|
1160
1164
|
let arrays = projection
|
|
1161
1165
|
.iter()
|
|
1162
1166
|
.map(|column| match column {
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1167
|
+
BranchColumn::Id => string_array(rows.iter().map(|row| Some(row.id.as_str()))),
|
|
1168
|
+
BranchColumn::Name => string_array(rows.iter().map(|row| Some(row.name.as_str()))),
|
|
1169
|
+
BranchColumn::Hidden => Arc::new(BooleanArray::from(
|
|
1166
1170
|
rows.iter().map(|row| row.hidden).collect::<Vec<_>>(),
|
|
1167
1171
|
)) as ArrayRef,
|
|
1168
|
-
|
|
1172
|
+
BranchColumn::CommitId => {
|
|
1169
1173
|
string_array(rows.iter().map(|row| Some(row.commit_id.as_str())))
|
|
1170
1174
|
}
|
|
1171
1175
|
})
|
|
1172
1176
|
.collect::<Vec<_>>();
|
|
1173
|
-
record_batch_with_row_count(
|
|
1174
|
-
DataFusionError::Execution(format!("failed to build
|
|
1177
|
+
record_batch_with_row_count(branch_schema(projection), arrays, rows.len()).map_err(|error| {
|
|
1178
|
+
DataFusionError::Execution(format!("failed to build lix_branch batch: {error}"))
|
|
1175
1179
|
})
|
|
1176
1180
|
}
|
|
1177
1181
|
|
|
1178
|
-
fn
|
|
1182
|
+
fn branch_schema(projection: &[BranchColumn]) -> SchemaRef {
|
|
1179
1183
|
Arc::new(Schema::new(
|
|
1180
1184
|
projection
|
|
1181
1185
|
.iter()
|
|
1182
1186
|
.map(|column| match column {
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
+
BranchColumn::Id => Field::new("id", DataType::Utf8, false),
|
|
1188
|
+
BranchColumn::Name => Field::new("name", DataType::Utf8, false),
|
|
1189
|
+
BranchColumn::Hidden => Field::new("hidden", DataType::Boolean, false),
|
|
1190
|
+
BranchColumn::CommitId => Field::new("commit_id", DataType::Utf8, false),
|
|
1187
1191
|
})
|
|
1188
1192
|
.collect::<Vec<_>>(),
|
|
1189
1193
|
))
|
|
@@ -1194,9 +1198,9 @@ fn string_array<'a>(values: impl Iterator<Item = Option<&'a str>>) -> ArrayRef {
|
|
|
1194
1198
|
}
|
|
1195
1199
|
|
|
1196
1200
|
fn datafusion_error_to_lix_error(error: DataFusionError) -> LixError {
|
|
1197
|
-
|
|
1201
|
+
crate::sql2::error::datafusion_error_to_lix_error(error)
|
|
1198
1202
|
}
|
|
1199
1203
|
|
|
1200
1204
|
fn lix_error_to_datafusion_error(error: LixError) -> DataFusionError {
|
|
1201
|
-
|
|
1205
|
+
crate::sql2::error::lix_error_to_datafusion_error(error)
|
|
1202
1206
|
}
|