@lix-js/sdk 0.6.0-preview.2 → 0.6.0-preview.4
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/SKILL.md +46 -8
- package/dist/engine-wasm/wasm/lix_engine.d.ts +25 -1
- package/dist/engine-wasm/wasm/lix_engine.js +60 -2
- package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
- package/dist/engine-wasm/wasm/lix_engine.wasm.d.ts +5 -0
- package/dist/generated/builtin-schemas.d.ts +87 -162
- package/dist/generated/builtin-schemas.js +139 -236
- package/dist/open-lix.d.ts +10 -3
- package/dist/open-lix.js +39 -0
- package/dist-engine-src/src/binary_cas/types.rs +0 -6
- package/dist-engine-src/src/catalog/context.rs +412 -0
- package/dist-engine-src/src/catalog/mod.rs +10 -0
- package/dist-engine-src/src/catalog/schema.rs +4 -0
- package/dist-engine-src/src/catalog/snapshot.rs +1114 -0
- package/dist-engine-src/src/cel/mod.rs +1 -1
- package/dist-engine-src/src/cel/provider.rs +1 -1
- package/dist-engine-src/src/commit_graph/context.rs +328 -1015
- package/dist-engine-src/src/commit_graph/mod.rs +2 -3
- package/dist-engine-src/src/commit_graph/types.rs +7 -43
- package/dist-engine-src/src/commit_graph/walker.rs +57 -81
- package/dist-engine-src/src/commit_store/codec.rs +887 -0
- package/dist-engine-src/src/commit_store/context.rs +944 -0
- package/dist-engine-src/src/commit_store/materialization.rs +84 -0
- package/dist-engine-src/src/commit_store/mod.rs +16 -0
- package/dist-engine-src/src/commit_store/storage.rs +600 -0
- package/dist-engine-src/src/commit_store/types.rs +215 -0
- package/dist-engine-src/src/common/identity.rs +15 -5
- package/dist-engine-src/src/common/json_pointer.rs +67 -0
- package/dist-engine-src/src/common/metadata.rs +17 -12
- package/dist-engine-src/src/common/mod.rs +5 -5
- package/dist-engine-src/src/domain.rs +324 -0
- package/dist-engine-src/src/engine.rs +29 -43
- package/dist-engine-src/src/entity_identity.rs +238 -118
- package/dist-engine-src/src/functions/context.rs +17 -52
- package/dist-engine-src/src/functions/deterministic.rs +1 -1
- package/dist-engine-src/src/functions/mod.rs +1 -1
- package/dist-engine-src/src/functions/provider.rs +4 -4
- package/dist-engine-src/src/functions/state.rs +39 -66
- package/dist-engine-src/src/functions/types.rs +1 -1
- package/dist-engine-src/src/init.rs +204 -151
- package/dist-engine-src/src/json_store/context.rs +354 -60
- package/dist-engine-src/src/json_store/encoded.rs +6 -6
- package/dist-engine-src/src/json_store/mod.rs +4 -1
- package/dist-engine-src/src/json_store/store.rs +884 -11
- package/dist-engine-src/src/json_store/types.rs +166 -1
- package/dist-engine-src/src/lib.rs +11 -10
- package/dist-engine-src/src/live_state/context.rs +608 -830
- package/dist-engine-src/src/live_state/mod.rs +3 -3
- package/dist-engine-src/src/live_state/overlay.rs +7 -7
- package/dist-engine-src/src/live_state/reader.rs +5 -5
- package/dist-engine-src/src/live_state/types.rs +19 -36
- package/dist-engine-src/src/live_state/visibility.rs +19 -14
- package/dist-engine-src/src/plugin/archive.rs +3 -6
- package/dist-engine-src/src/plugin/install.rs +0 -18
- package/dist-engine-src/src/plugin/plugin_manifest.json +0 -1
- package/dist-engine-src/src/schema/annotations/defaults.rs +2 -7
- package/dist-engine-src/src/schema/builtin/lix_account.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_active_account.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_change.json +11 -10
- package/dist-engine-src/src/schema/builtin/lix_change_author.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_commit.json +8 -46
- package/dist-engine-src/src/schema/builtin/lix_commit_edge.json +29 -22
- package/dist-engine-src/src/schema/builtin/lix_directory_descriptor.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_file_descriptor.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_key_value.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_label.json +10 -3
- package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +74 -0
- package/dist-engine-src/src/schema/builtin/lix_registered_schema.json +2 -8
- package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_version_ref.json +0 -1
- package/dist-engine-src/src/schema/builtin/mod.rs +10 -59
- package/dist-engine-src/src/schema/compatibility.rs +787 -0
- package/dist-engine-src/src/schema/definition.json +47 -17
- package/dist-engine-src/src/schema/definition.rs +202 -96
- package/dist-engine-src/src/schema/key.rs +9 -77
- package/dist-engine-src/src/schema/mod.rs +4 -4
- package/dist-engine-src/src/schema/tests.rs +133 -92
- package/dist-engine-src/src/session/context.rs +86 -48
- package/dist-engine-src/src/session/create_version.rs +22 -14
- package/dist-engine-src/src/session/execute.rs +117 -23
- package/dist-engine-src/src/session/merge/apply.rs +4 -4
- package/dist-engine-src/src/session/merge/conflicts.rs +3 -2
- package/dist-engine-src/src/session/merge/stats.rs +1 -1
- package/dist-engine-src/src/session/merge/version.rs +35 -45
- package/dist-engine-src/src/session/mod.rs +9 -7
- package/dist-engine-src/src/session/optimization9_sql2_bench.rs +100 -0
- package/dist-engine-src/src/session/switch_version.rs +17 -28
- package/dist-engine-src/src/session/transaction.rs +76 -0
- package/dist-engine-src/src/sql2/change_provider.rs +14 -20
- package/dist-engine-src/src/sql2/classify.rs +75 -48
- package/dist-engine-src/src/sql2/context.rs +22 -18
- package/dist-engine-src/src/sql2/directory_history_provider.rs +28 -20
- package/dist-engine-src/src/sql2/directory_provider.rs +131 -83
- package/dist-engine-src/src/sql2/entity_history_provider.rs +10 -14
- package/dist-engine-src/src/sql2/entity_provider.rs +680 -169
- package/dist-engine-src/src/sql2/error.rs +24 -5
- package/dist-engine-src/src/sql2/execute.rs +426 -272
- package/dist-engine-src/src/sql2/file_history_provider.rs +29 -21
- package/dist-engine-src/src/sql2/file_provider.rs +533 -108
- package/dist-engine-src/src/sql2/filesystem_planner.rs +58 -94
- package/dist-engine-src/src/sql2/filesystem_visibility.rs +37 -23
- package/dist-engine-src/src/sql2/history_projection.rs +3 -27
- package/dist-engine-src/src/sql2/history_provider.rs +11 -17
- package/dist-engine-src/src/sql2/history_route.rs +22 -8
- package/dist-engine-src/src/sql2/lix_state_provider.rs +178 -96
- package/dist-engine-src/src/sql2/mod.rs +8 -4
- package/dist-engine-src/src/sql2/predicate_typecheck.rs +246 -0
- package/dist-engine-src/src/sql2/public_bind/assignment.rs +46 -0
- package/dist-engine-src/src/sql2/public_bind/capability.rs +41 -0
- package/dist-engine-src/src/sql2/public_bind/dml.rs +172 -0
- package/dist-engine-src/src/sql2/public_bind/mod.rs +26 -0
- package/dist-engine-src/src/sql2/public_bind/table.rs +168 -0
- package/dist-engine-src/src/sql2/read_only.rs +10 -12
- package/dist-engine-src/src/sql2/session.rs +7 -10
- package/dist-engine-src/src/sql2/udfs/lix_timestamp.rs +76 -0
- package/dist-engine-src/src/sql2/udfs/mod.rs +8 -1
- package/dist-engine-src/src/sql2/udfs/public_call.rs +238 -0
- package/dist-engine-src/src/sql2/version_provider.rs +46 -31
- package/dist-engine-src/src/sql2/version_scope.rs +4 -4
- package/dist-engine-src/src/storage_bench.rs +1782 -325
- package/dist-engine-src/src/test_support.rs +183 -36
- package/dist-engine-src/src/tracked_state/by_file_index.rs +20 -24
- package/dist-engine-src/src/tracked_state/codec.rs +1519 -181
- package/dist-engine-src/src/tracked_state/context.rs +1155 -271
- package/dist-engine-src/src/tracked_state/diff.rs +249 -57
- package/dist-engine-src/src/tracked_state/materialization.rs +365 -103
- package/dist-engine-src/src/tracked_state/materializer.rs +488 -0
- package/dist-engine-src/src/tracked_state/merge.rs +37 -19
- package/dist-engine-src/src/tracked_state/mod.rs +8 -7
- package/dist-engine-src/src/tracked_state/storage.rs +138 -6
- package/dist-engine-src/src/tracked_state/tree.rs +695 -252
- package/dist-engine-src/src/tracked_state/types.rs +176 -6
- package/dist-engine-src/src/transaction/commit.rs +695 -435
- package/dist-engine-src/src/transaction/context.rs +551 -310
- package/dist-engine-src/src/transaction/live_state_overlay.rs +9 -8
- package/dist-engine-src/src/transaction/mod.rs +2 -0
- package/dist-engine-src/src/transaction/normalization.rs +311 -447
- package/dist-engine-src/src/transaction/prep.rs +37 -0
- package/dist-engine-src/src/transaction/schema_resolver.rs +93 -71
- package/dist-engine-src/src/transaction/staging.rs +701 -406
- package/dist-engine-src/src/transaction/types.rs +231 -122
- package/dist-engine-src/src/transaction/validation.rs +2717 -1698
- package/dist-engine-src/src/untracked_state/codec.rs +40 -96
- package/dist-engine-src/src/untracked_state/context.rs +21 -5
- package/dist-engine-src/src/untracked_state/materialization.rs +10 -104
- package/dist-engine-src/src/untracked_state/mod.rs +3 -5
- package/dist-engine-src/src/untracked_state/storage.rs +105 -57
- package/dist-engine-src/src/untracked_state/types.rs +63 -13
- package/dist-engine-src/src/version/context.rs +1 -13
- package/dist-engine-src/src/version/lifecycle.rs +221 -0
- package/dist-engine-src/src/version/mod.rs +3 -2
- package/dist-engine-src/src/version/refs.rs +12 -103
- package/dist-engine-src/src/version/stage_rows.rs +15 -19
- package/package.json +1 -1
- package/dist-engine-src/src/changelog/codec.rs +0 -321
- package/dist-engine-src/src/changelog/context.rs +0 -92
- package/dist-engine-src/src/changelog/materialization.rs +0 -121
- package/dist-engine-src/src/changelog/mod.rs +0 -13
- package/dist-engine-src/src/changelog/reader.rs +0 -20
- package/dist-engine-src/src/changelog/storage.rs +0 -220
- package/dist-engine-src/src/changelog/types.rs +0 -38
- package/dist-engine-src/src/schema/builtin/lix_change_set.json +0 -18
- package/dist-engine-src/src/schema/builtin/lix_change_set_element.json +0 -75
- package/dist-engine-src/src/schema/builtin/lix_entity_label.json +0 -63
- package/dist-engine-src/src/schema_registry.rs +0 -294
- package/dist-engine-src/src/sql2/commit_derived_provider.rs +0 -591
- package/dist-engine-src/src/tracked_state/rebuild.rs +0 -771
- package/dist-engine-src/src/tracked_state/tree_types.rs +0 -176
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
use serde_json::json;
|
|
1
|
+
use serde_json::{json, Value as JsonValue};
|
|
2
2
|
|
|
3
|
-
use crate::transaction::types::
|
|
4
|
-
use crate::version::
|
|
3
|
+
use crate::transaction::types::TransactionWrite;
|
|
4
|
+
use crate::version::{VersionLifecycle, VersionOperation, VersionReferenceRole};
|
|
5
5
|
use crate::LixError;
|
|
6
6
|
|
|
7
7
|
use super::analysis::{analyze, MergeCommits, MergeOutcome};
|
|
@@ -67,7 +67,7 @@ pub struct MergeVersionPreview {
|
|
|
67
67
|
pub struct MergeConflict {
|
|
68
68
|
pub kind: MergeConflictKind,
|
|
69
69
|
pub schema_key: String,
|
|
70
|
-
pub entity_id:
|
|
70
|
+
pub entity_id: JsonValue,
|
|
71
71
|
pub file_id: Option<String>,
|
|
72
72
|
pub target: MergeConflictSide,
|
|
73
73
|
pub source: MergeConflictSide,
|
|
@@ -117,26 +117,21 @@ impl SessionContext {
|
|
|
117
117
|
|
|
118
118
|
let (target_head, source_head) = {
|
|
119
119
|
let reader = transaction.version_ref_reader();
|
|
120
|
-
let
|
|
121
|
-
|
|
122
|
-
.
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
source_version_id.clone(),
|
|
136
|
-
"merge_version_preview",
|
|
137
|
-
"source",
|
|
138
|
-
)
|
|
139
|
-
})?;
|
|
120
|
+
let lifecycle = VersionLifecycle::new(&reader);
|
|
121
|
+
let target_head = lifecycle
|
|
122
|
+
.require_existing_commit_id(
|
|
123
|
+
&active_version_id,
|
|
124
|
+
VersionOperation::MergeVersionPreview,
|
|
125
|
+
VersionReferenceRole::Target,
|
|
126
|
+
)
|
|
127
|
+
.await?;
|
|
128
|
+
let source_head = lifecycle
|
|
129
|
+
.require_existing_commit_id(
|
|
130
|
+
&source_version_id,
|
|
131
|
+
VersionOperation::MergeVersionPreview,
|
|
132
|
+
VersionReferenceRole::Source,
|
|
133
|
+
)
|
|
134
|
+
.await?;
|
|
140
135
|
(target_head, source_head)
|
|
141
136
|
};
|
|
142
137
|
|
|
@@ -189,26 +184,21 @@ impl SessionContext {
|
|
|
189
184
|
|
|
190
185
|
let (target_head, source_head) = {
|
|
191
186
|
let reader = transaction.version_ref_reader();
|
|
192
|
-
let
|
|
193
|
-
|
|
194
|
-
.
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
source_version_id.clone(),
|
|
208
|
-
"merge_version",
|
|
209
|
-
"source",
|
|
210
|
-
)
|
|
211
|
-
})?;
|
|
187
|
+
let lifecycle = VersionLifecycle::new(&reader);
|
|
188
|
+
let target_head = lifecycle
|
|
189
|
+
.require_existing_commit_id(
|
|
190
|
+
&active_version_id,
|
|
191
|
+
VersionOperation::MergeVersion,
|
|
192
|
+
VersionReferenceRole::Target,
|
|
193
|
+
)
|
|
194
|
+
.await?;
|
|
195
|
+
let source_head = lifecycle
|
|
196
|
+
.require_existing_commit_id(
|
|
197
|
+
&source_version_id,
|
|
198
|
+
VersionOperation::MergeVersion,
|
|
199
|
+
VersionReferenceRole::Source,
|
|
200
|
+
)
|
|
201
|
+
.await?;
|
|
212
202
|
(target_head, source_head)
|
|
213
203
|
};
|
|
214
204
|
|
|
@@ -300,7 +290,7 @@ impl SessionContext {
|
|
|
300
290
|
}
|
|
301
291
|
|
|
302
292
|
transaction
|
|
303
|
-
.stage_write(
|
|
293
|
+
.stage_write(TransactionWrite::AdoptedChanges {
|
|
304
294
|
changes: adopted_changes,
|
|
305
295
|
})
|
|
306
296
|
.await?;
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
//!
|
|
1
|
+
//! Engine session boundary.
|
|
2
2
|
//!
|
|
3
|
-
//! Transaction invariant:
|
|
4
|
-
//!
|
|
5
|
-
//!
|
|
6
|
-
//!
|
|
7
|
-
//! open `Transaction` directly or use session-level read helpers inside write
|
|
8
|
-
//! flows.
|
|
3
|
+
//! Transaction invariant: a session has one execution lease. Parent-handle
|
|
4
|
+
//! calls use it for implicit single-statement execution; explicit transactions
|
|
5
|
+
//! hold it until commit or rollback. Session APIs must not open `Transaction`
|
|
6
|
+
//! directly or use session-level read helpers inside write flows.
|
|
9
7
|
|
|
10
8
|
mod context;
|
|
11
9
|
mod create_version;
|
|
12
10
|
mod execute;
|
|
13
11
|
mod merge;
|
|
12
|
+
#[cfg(feature = "storage-benches")]
|
|
13
|
+
pub mod optimization9_sql2_bench;
|
|
14
14
|
mod switch_version;
|
|
15
|
+
mod transaction;
|
|
15
16
|
|
|
16
17
|
pub use context::SessionContext;
|
|
17
18
|
pub(crate) use context::{SessionMode, WORKSPACE_VERSION_KEY};
|
|
@@ -23,3 +24,4 @@ pub use merge::{
|
|
|
23
24
|
MergeVersionReceipt,
|
|
24
25
|
};
|
|
25
26
|
pub use switch_version::{SwitchVersionOptions, SwitchVersionReceipt};
|
|
27
|
+
pub use transaction::SessionTransaction;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
use crate::functions::FunctionContext;
|
|
2
|
+
use crate::session::context::{SessionContext, SessionSqlExecutionContext};
|
|
3
|
+
use crate::sql2::{self, SqlLogicalPlan};
|
|
4
|
+
use crate::storage::StorageReadScope;
|
|
5
|
+
use crate::transaction::open_transaction;
|
|
6
|
+
use crate::{LixError, SqlQueryResult, Value};
|
|
7
|
+
|
|
8
|
+
/// Opaque read plan used by the Optimization 9 SQL2 diagnostic benchmark.
|
|
9
|
+
///
|
|
10
|
+
/// This module is gated behind `storage-benches` and exists only to split SQL2
|
|
11
|
+
/// planning cost from SQL2 execution cost without widening the normal session
|
|
12
|
+
/// API.
|
|
13
|
+
pub struct PreparedReadPlan {
|
|
14
|
+
plan: SqlLogicalPlan,
|
|
15
|
+
read_scope:
|
|
16
|
+
StorageReadScope<Box<dyn crate::storage::StorageReadTransaction + Send + Sync + 'static>>,
|
|
17
|
+
runtime_functions: FunctionContext,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
pub async fn plan_read_only(session: &SessionContext, sql: &str) -> Result<(), LixError> {
|
|
21
|
+
let prepared = prepare_read_plan(session, sql).await?;
|
|
22
|
+
drop(prepared.plan);
|
|
23
|
+
drop(prepared.runtime_functions);
|
|
24
|
+
prepared.read_scope.rollback().await
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
pub async fn plan_write_only(session: &SessionContext, sql: &str) -> Result<(), LixError> {
|
|
28
|
+
session.ensure_open()?;
|
|
29
|
+
let opened = open_transaction(
|
|
30
|
+
&session.mode,
|
|
31
|
+
session.storage.clone(),
|
|
32
|
+
std::sync::Arc::clone(&session.live_state),
|
|
33
|
+
std::sync::Arc::clone(&session.tracked_state),
|
|
34
|
+
std::sync::Arc::clone(&session.binary_cas),
|
|
35
|
+
std::sync::Arc::clone(&session.commit_store),
|
|
36
|
+
std::sync::Arc::clone(&session.version_ctx),
|
|
37
|
+
std::sync::Arc::clone(&session.catalog_context),
|
|
38
|
+
)
|
|
39
|
+
.await?;
|
|
40
|
+
let mut transaction = opened.transaction;
|
|
41
|
+
let runtime_functions = opened.runtime_functions;
|
|
42
|
+
let plan = sql2::create_write_logical_plan(&mut transaction, sql).await?;
|
|
43
|
+
drop(plan);
|
|
44
|
+
drop(runtime_functions);
|
|
45
|
+
transaction.rollback().await
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
pub async fn prepare_read_plan(
|
|
49
|
+
session: &SessionContext,
|
|
50
|
+
sql: &str,
|
|
51
|
+
) -> Result<PreparedReadPlan, LixError> {
|
|
52
|
+
session.ensure_open()?;
|
|
53
|
+
let read_scope = StorageReadScope::new(session.storage.begin_read_transaction().await?);
|
|
54
|
+
let mut read_store = read_scope.store();
|
|
55
|
+
let live_state: std::sync::Arc<dyn crate::live_state::LiveStateReader> =
|
|
56
|
+
std::sync::Arc::new(session.live_state.reader(read_store.clone()));
|
|
57
|
+
let runtime_functions = FunctionContext::prepare(live_state.as_ref()).await?;
|
|
58
|
+
let functions = runtime_functions.provider();
|
|
59
|
+
let active_version_id = session
|
|
60
|
+
.active_version_id_from_reader(&mut read_store)
|
|
61
|
+
.await?;
|
|
62
|
+
let visible_schemas = session
|
|
63
|
+
.catalog_context
|
|
64
|
+
.schema_jsons_for_sql_read_planning(live_state.as_ref(), &active_version_id)
|
|
65
|
+
.await?;
|
|
66
|
+
let ctx = SessionSqlExecutionContext {
|
|
67
|
+
active_version_id: &active_version_id,
|
|
68
|
+
read_store,
|
|
69
|
+
live_state: std::sync::Arc::clone(&session.live_state),
|
|
70
|
+
binary_cas: std::sync::Arc::clone(&session.binary_cas),
|
|
71
|
+
commit_store: std::sync::Arc::clone(&session.commit_store),
|
|
72
|
+
version_ctx: std::sync::Arc::clone(&session.version_ctx),
|
|
73
|
+
visible_schemas,
|
|
74
|
+
functions: functions.clone(),
|
|
75
|
+
};
|
|
76
|
+
let plan = sql2::create_logical_plan(&ctx, sql).await?;
|
|
77
|
+
drop(ctx);
|
|
78
|
+
drop(live_state);
|
|
79
|
+
|
|
80
|
+
Ok(PreparedReadPlan {
|
|
81
|
+
plan,
|
|
82
|
+
read_scope,
|
|
83
|
+
runtime_functions,
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
pub async fn execute_read_plan(
|
|
88
|
+
prepared: PreparedReadPlan,
|
|
89
|
+
params: &[Value],
|
|
90
|
+
) -> Result<SqlQueryResult, LixError> {
|
|
91
|
+
let PreparedReadPlan {
|
|
92
|
+
plan,
|
|
93
|
+
read_scope,
|
|
94
|
+
runtime_functions,
|
|
95
|
+
} = prepared;
|
|
96
|
+
let result = sql2::execute_logical_plan(plan, params).await;
|
|
97
|
+
read_scope.rollback().await?;
|
|
98
|
+
drop(runtime_functions);
|
|
99
|
+
result
|
|
100
|
+
}
|
|
@@ -2,15 +2,14 @@ use std::sync::Arc;
|
|
|
2
2
|
|
|
3
3
|
use serde_json::json;
|
|
4
4
|
|
|
5
|
-
use crate::transaction::types::
|
|
6
|
-
use crate::version::
|
|
5
|
+
use crate::transaction::types::{TransactionJson, TransactionWriteRow};
|
|
6
|
+
use crate::version::{VersionLifecycle, VersionOperation, VersionReferenceRole};
|
|
7
7
|
use crate::LixError;
|
|
8
8
|
use crate::GLOBAL_VERSION_ID;
|
|
9
9
|
|
|
10
10
|
use super::context::{SessionContext, SessionMode, WORKSPACE_VERSION_KEY};
|
|
11
11
|
|
|
12
12
|
const KEY_VALUE_SCHEMA_KEY: &str = "lix_key_value";
|
|
13
|
-
const KEY_VALUE_SCHEMA_VERSION: &str = "1";
|
|
14
13
|
|
|
15
14
|
/// Options for switching a session to another version.
|
|
16
15
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
@@ -40,17 +39,16 @@ impl SessionContext {
|
|
|
40
39
|
let next_mode = self
|
|
41
40
|
.with_write_transaction(|transaction| {
|
|
42
41
|
Box::pin(async move {
|
|
43
|
-
|
|
42
|
+
{
|
|
44
43
|
let reader = transaction.version_ref_reader();
|
|
45
|
-
|
|
44
|
+
VersionLifecycle::new(&reader)
|
|
45
|
+
.require_existing_commit_id(
|
|
46
|
+
&version_id,
|
|
47
|
+
VersionOperation::SwitchVersion,
|
|
48
|
+
VersionReferenceRole::Target,
|
|
49
|
+
)
|
|
50
|
+
.await?
|
|
46
51
|
};
|
|
47
|
-
if head.is_none() {
|
|
48
|
-
return Err(LixError::version_not_found(
|
|
49
|
-
version_id.clone(),
|
|
50
|
-
"switch_version",
|
|
51
|
-
"target",
|
|
52
|
-
));
|
|
53
|
-
}
|
|
54
52
|
|
|
55
53
|
match current_mode {
|
|
56
54
|
SessionMode::Pinned { .. } => Ok(SessionMode::Pinned {
|
|
@@ -73,10 +71,11 @@ impl SessionContext {
|
|
|
73
71
|
Arc::clone(&self.live_state),
|
|
74
72
|
Arc::clone(&self.tracked_state),
|
|
75
73
|
Arc::clone(&self.binary_cas),
|
|
76
|
-
Arc::clone(&self.
|
|
74
|
+
Arc::clone(&self.commit_store),
|
|
77
75
|
Arc::clone(&self.version_ctx),
|
|
78
|
-
Arc::clone(&self.
|
|
76
|
+
Arc::clone(&self.catalog_context),
|
|
79
77
|
self.closed_flag(),
|
|
78
|
+
self.active_transaction_flag(),
|
|
80
79
|
);
|
|
81
80
|
Ok((
|
|
82
81
|
session,
|
|
@@ -87,20 +86,19 @@ impl SessionContext {
|
|
|
87
86
|
}
|
|
88
87
|
}
|
|
89
88
|
|
|
90
|
-
fn workspace_version_stage_row(version_id: &str) -> Result<
|
|
91
|
-
Ok(
|
|
89
|
+
fn workspace_version_stage_row(version_id: &str) -> Result<TransactionWriteRow, LixError> {
|
|
90
|
+
Ok(TransactionWriteRow {
|
|
92
91
|
entity_id: Some(crate::entity_identity::EntityIdentity::single(
|
|
93
92
|
WORKSPACE_VERSION_KEY,
|
|
94
93
|
)),
|
|
95
94
|
schema_key: KEY_VALUE_SCHEMA_KEY.to_string(),
|
|
96
95
|
file_id: None,
|
|
97
|
-
|
|
96
|
+
snapshot: Some(TransactionJson::from_value_unchecked(json!({
|
|
98
97
|
"key": WORKSPACE_VERSION_KEY,
|
|
99
98
|
"value": version_id,
|
|
100
|
-
}))
|
|
99
|
+
}))),
|
|
101
100
|
metadata: None,
|
|
102
101
|
origin: None,
|
|
103
|
-
schema_version: KEY_VALUE_SCHEMA_VERSION.to_string(),
|
|
104
102
|
created_at: None,
|
|
105
103
|
updated_at: None,
|
|
106
104
|
global: true,
|
|
@@ -110,12 +108,3 @@ fn workspace_version_stage_row(version_id: &str) -> Result<StageRow, LixError> {
|
|
|
110
108
|
version_id: GLOBAL_VERSION_ID.to_string(),
|
|
111
109
|
})
|
|
112
110
|
}
|
|
113
|
-
|
|
114
|
-
fn encode_snapshot(value: serde_json::Value) -> Result<String, LixError> {
|
|
115
|
-
serde_json::to_string(&value).map_err(|error| {
|
|
116
|
-
LixError::new(
|
|
117
|
-
"LIX_ERROR_UNKNOWN",
|
|
118
|
-
format!("engine2 switch_version snapshot serialization failed: {error}"),
|
|
119
|
-
)
|
|
120
|
-
})
|
|
121
|
-
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
use std::sync::Arc;
|
|
2
|
+
|
|
3
|
+
use crate::functions::FunctionContext;
|
|
4
|
+
use crate::transaction::{open_transaction, Transaction};
|
|
5
|
+
use crate::LixError;
|
|
6
|
+
|
|
7
|
+
use super::context::SessionTransactionGuard;
|
|
8
|
+
use super::SessionContext;
|
|
9
|
+
|
|
10
|
+
pub struct SessionTransaction {
|
|
11
|
+
pub(super) transaction: Option<Transaction>,
|
|
12
|
+
pub(super) runtime_functions: FunctionContext,
|
|
13
|
+
_transaction_guard: SessionTransactionGuard,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
impl SessionContext {
|
|
17
|
+
pub async fn begin_transaction(&self) -> Result<SessionTransaction, LixError> {
|
|
18
|
+
self.ensure_open()?;
|
|
19
|
+
let transaction_guard = self.reserve_session_transaction()?;
|
|
20
|
+
let opened = match open_transaction(
|
|
21
|
+
&self.mode,
|
|
22
|
+
self.storage.clone(),
|
|
23
|
+
Arc::clone(&self.live_state),
|
|
24
|
+
Arc::clone(&self.tracked_state),
|
|
25
|
+
Arc::clone(&self.binary_cas),
|
|
26
|
+
Arc::clone(&self.commit_store),
|
|
27
|
+
Arc::clone(&self.version_ctx),
|
|
28
|
+
Arc::clone(&self.catalog_context),
|
|
29
|
+
)
|
|
30
|
+
.await
|
|
31
|
+
{
|
|
32
|
+
Ok(opened) => opened,
|
|
33
|
+
Err(error) => {
|
|
34
|
+
return Err(error);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
Ok(SessionTransaction {
|
|
38
|
+
transaction: Some(opened.transaction),
|
|
39
|
+
runtime_functions: opened.runtime_functions,
|
|
40
|
+
_transaction_guard: transaction_guard,
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
impl SessionTransaction {
|
|
46
|
+
pub(super) fn transaction_mut(&mut self) -> Result<&mut Transaction, LixError> {
|
|
47
|
+
self.transaction
|
|
48
|
+
.as_mut()
|
|
49
|
+
.ok_or_else(|| transaction_state_error("Lix transaction is closed"))
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
pub async fn commit(mut self) -> Result<(), LixError> {
|
|
53
|
+
let transaction = self
|
|
54
|
+
.transaction
|
|
55
|
+
.take()
|
|
56
|
+
.ok_or_else(|| transaction_state_error("Lix transaction is closed"))?;
|
|
57
|
+
let result = transaction
|
|
58
|
+
.commit(&self.runtime_functions)
|
|
59
|
+
.await
|
|
60
|
+
.map(|_| ());
|
|
61
|
+
result
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
pub async fn rollback(mut self) -> Result<(), LixError> {
|
|
65
|
+
let transaction = self
|
|
66
|
+
.transaction
|
|
67
|
+
.take()
|
|
68
|
+
.ok_or_else(|| transaction_state_error("Lix transaction is closed"))?;
|
|
69
|
+
let result = transaction.rollback().await;
|
|
70
|
+
result
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
pub(crate) fn transaction_state_error(message: impl Into<String>) -> LixError {
|
|
75
|
+
LixError::new("LIX_INVALID_TRANSACTION_STATE", message)
|
|
76
|
+
}
|
|
@@ -18,17 +18,18 @@ use datafusion::physical_plan::{
|
|
|
18
18
|
};
|
|
19
19
|
use futures_util::stream;
|
|
20
20
|
|
|
21
|
-
use crate::
|
|
21
|
+
use crate::commit_store::ChangeScanRequest;
|
|
22
22
|
use crate::serialize_row_metadata;
|
|
23
23
|
use crate::LixError;
|
|
24
24
|
|
|
25
25
|
use super::record_batch::record_batch_with_row_count;
|
|
26
26
|
use super::result_metadata::json_field;
|
|
27
|
-
use super::
|
|
27
|
+
use super::SqlCommitStoreQuerySource;
|
|
28
|
+
use crate::commit_store::{materialize_change, MaterializedChange};
|
|
28
29
|
|
|
29
30
|
pub(crate) async fn register_lix_change_provider(
|
|
30
31
|
session: &datafusion::prelude::SessionContext,
|
|
31
|
-
query_source:
|
|
32
|
+
query_source: SqlCommitStoreQuerySource,
|
|
32
33
|
) -> Result<(), LixError> {
|
|
33
34
|
session
|
|
34
35
|
.register_table("lix_change", Arc::new(LixChangeProvider::new(query_source)))
|
|
@@ -38,7 +39,7 @@ pub(crate) async fn register_lix_change_provider(
|
|
|
38
39
|
|
|
39
40
|
struct LixChangeProvider {
|
|
40
41
|
schema: SchemaRef,
|
|
41
|
-
query_source:
|
|
42
|
+
query_source: SqlCommitStoreQuerySource,
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
impl std::fmt::Debug for LixChangeProvider {
|
|
@@ -48,7 +49,7 @@ impl std::fmt::Debug for LixChangeProvider {
|
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
impl LixChangeProvider {
|
|
51
|
-
fn new(query_source:
|
|
52
|
+
fn new(query_source: SqlCommitStoreQuerySource) -> Self {
|
|
52
53
|
Self {
|
|
53
54
|
schema: lix_change_schema(),
|
|
54
55
|
query_source,
|
|
@@ -97,7 +98,7 @@ impl TableProvider for LixChangeProvider {
|
|
|
97
98
|
}
|
|
98
99
|
|
|
99
100
|
struct LixChangeScanExec {
|
|
100
|
-
query_source:
|
|
101
|
+
query_source: SqlCommitStoreQuerySource,
|
|
101
102
|
schema: SchemaRef,
|
|
102
103
|
projection: Option<Vec<usize>>,
|
|
103
104
|
limit: Option<usize>,
|
|
@@ -112,7 +113,7 @@ impl std::fmt::Debug for LixChangeScanExec {
|
|
|
112
113
|
|
|
113
114
|
impl LixChangeScanExec {
|
|
114
115
|
fn new(
|
|
115
|
-
query_source:
|
|
116
|
+
query_source: SqlCommitStoreQuerySource,
|
|
116
117
|
schema: SchemaRef,
|
|
117
118
|
projection: Option<Vec<usize>>,
|
|
118
119
|
limit: Option<usize>,
|
|
@@ -191,8 +192,8 @@ impl ExecutionPlan for LixChangeScanExec {
|
|
|
191
192
|
let stream = stream::once(async move {
|
|
192
193
|
let mut json_reader = query_source.json_reader;
|
|
193
194
|
let canonical_changes = query_source
|
|
194
|
-
.
|
|
195
|
-
.scan_changes(&
|
|
195
|
+
.commit_store_reader
|
|
196
|
+
.scan_changes(&ChangeScanRequest { limit })
|
|
196
197
|
.await
|
|
197
198
|
.map_err(lix_error_to_datafusion_error)?;
|
|
198
199
|
let mut changes = Vec::with_capacity(canonical_changes.len());
|
|
@@ -214,7 +215,6 @@ enum ChangeColumn {
|
|
|
214
215
|
Id,
|
|
215
216
|
EntityId,
|
|
216
217
|
SchemaKey,
|
|
217
|
-
SchemaVersion,
|
|
218
218
|
FileId,
|
|
219
219
|
Metadata,
|
|
220
220
|
CreatedAt,
|
|
@@ -224,9 +224,8 @@ enum ChangeColumn {
|
|
|
224
224
|
fn lix_change_schema() -> SchemaRef {
|
|
225
225
|
Arc::new(Schema::new(vec![
|
|
226
226
|
Field::new("id", DataType::Utf8, false),
|
|
227
|
-
|
|
227
|
+
json_field("entity_id", false),
|
|
228
228
|
Field::new("schema_key", DataType::Utf8, false),
|
|
229
|
-
Field::new("schema_version", DataType::Utf8, false),
|
|
230
229
|
Field::new("file_id", DataType::Utf8, true),
|
|
231
230
|
json_field("metadata", true),
|
|
232
231
|
Field::new("created_at", DataType::Utf8, false),
|
|
@@ -239,7 +238,6 @@ fn change_projection_for_scan(projection: Option<&Vec<usize>>) -> Vec<ChangeColu
|
|
|
239
238
|
ChangeColumn::Id,
|
|
240
239
|
ChangeColumn::EntityId,
|
|
241
240
|
ChangeColumn::SchemaKey,
|
|
242
|
-
ChangeColumn::SchemaVersion,
|
|
243
241
|
ChangeColumn::FileId,
|
|
244
242
|
ChangeColumn::Metadata,
|
|
245
243
|
ChangeColumn::CreatedAt,
|
|
@@ -262,7 +260,7 @@ fn projected_schema(schema: &SchemaRef, projection: Option<&Vec<usize>>) -> Sche
|
|
|
262
260
|
|
|
263
261
|
fn change_record_batch(
|
|
264
262
|
projection: &[ChangeColumn],
|
|
265
|
-
changes: &[
|
|
263
|
+
changes: &[MaterializedChange],
|
|
266
264
|
) -> Result<RecordBatch> {
|
|
267
265
|
let arrays = projection
|
|
268
266
|
.iter()
|
|
@@ -274,7 +272,7 @@ fn change_record_batch(
|
|
|
274
272
|
.map(|row| {
|
|
275
273
|
Some(
|
|
276
274
|
row.entity_id
|
|
277
|
-
.
|
|
275
|
+
.as_json_array_text()
|
|
278
276
|
.expect("canonical change entity identity should project"),
|
|
279
277
|
)
|
|
280
278
|
})
|
|
@@ -283,9 +281,6 @@ fn change_record_batch(
|
|
|
283
281
|
ChangeColumn::SchemaKey => {
|
|
284
282
|
string_array(changes.iter().map(|row| Some(row.schema_key.as_str())))
|
|
285
283
|
}
|
|
286
|
-
ChangeColumn::SchemaVersion => {
|
|
287
|
-
string_array(changes.iter().map(|row| Some(row.schema_version.as_str())))
|
|
288
|
-
}
|
|
289
284
|
ChangeColumn::FileId => string_array(changes.iter().map(|row| row.file_id.as_deref())),
|
|
290
285
|
ChangeColumn::Metadata => Arc::new(StringArray::from(
|
|
291
286
|
changes
|
|
@@ -312,9 +307,8 @@ fn change_schema(projection: &[ChangeColumn]) -> SchemaRef {
|
|
|
312
307
|
.iter()
|
|
313
308
|
.map(|column| match column {
|
|
314
309
|
ChangeColumn::Id => Field::new("id", DataType::Utf8, false),
|
|
315
|
-
ChangeColumn::EntityId =>
|
|
310
|
+
ChangeColumn::EntityId => json_field("entity_id", false),
|
|
316
311
|
ChangeColumn::SchemaKey => Field::new("schema_key", DataType::Utf8, false),
|
|
317
|
-
ChangeColumn::SchemaVersion => Field::new("schema_version", DataType::Utf8, false),
|
|
318
312
|
ChangeColumn::FileId => Field::new("file_id", DataType::Utf8, true),
|
|
319
313
|
ChangeColumn::Metadata => json_field("metadata", true),
|
|
320
314
|
ChangeColumn::CreatedAt => Field::new("created_at", DataType::Utf8, false),
|