@lix-js/sdk 0.6.0-preview.2 → 0.6.0-preview.3

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.
Files changed (165) hide show
  1. package/SKILL.md +4 -5
  2. package/dist/engine-wasm/wasm/lix_engine.js +1 -1
  3. package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
  4. package/dist/generated/builtin-schemas.d.ts +87 -162
  5. package/dist/generated/builtin-schemas.js +139 -236
  6. package/dist/open-lix.d.ts +1 -1
  7. package/dist-engine-src/src/binary_cas/types.rs +0 -6
  8. package/dist-engine-src/src/catalog/context.rs +412 -0
  9. package/dist-engine-src/src/catalog/mod.rs +10 -0
  10. package/dist-engine-src/src/catalog/schema.rs +4 -0
  11. package/dist-engine-src/src/catalog/snapshot.rs +1114 -0
  12. package/dist-engine-src/src/cel/mod.rs +1 -1
  13. package/dist-engine-src/src/cel/provider.rs +1 -1
  14. package/dist-engine-src/src/commit_graph/context.rs +328 -1015
  15. package/dist-engine-src/src/commit_graph/mod.rs +2 -3
  16. package/dist-engine-src/src/commit_graph/types.rs +7 -43
  17. package/dist-engine-src/src/commit_graph/walker.rs +57 -81
  18. package/dist-engine-src/src/commit_store/codec.rs +887 -0
  19. package/dist-engine-src/src/commit_store/context.rs +944 -0
  20. package/dist-engine-src/src/commit_store/materialization.rs +84 -0
  21. package/dist-engine-src/src/commit_store/mod.rs +16 -0
  22. package/dist-engine-src/src/commit_store/storage.rs +600 -0
  23. package/dist-engine-src/src/commit_store/types.rs +215 -0
  24. package/dist-engine-src/src/common/identity.rs +15 -5
  25. package/dist-engine-src/src/common/json_pointer.rs +67 -0
  26. package/dist-engine-src/src/common/metadata.rs +17 -12
  27. package/dist-engine-src/src/common/mod.rs +5 -5
  28. package/dist-engine-src/src/domain.rs +324 -0
  29. package/dist-engine-src/src/engine.rs +29 -43
  30. package/dist-engine-src/src/entity_identity.rs +238 -118
  31. package/dist-engine-src/src/functions/context.rs +17 -52
  32. package/dist-engine-src/src/functions/deterministic.rs +1 -1
  33. package/dist-engine-src/src/functions/mod.rs +1 -1
  34. package/dist-engine-src/src/functions/provider.rs +4 -4
  35. package/dist-engine-src/src/functions/state.rs +39 -66
  36. package/dist-engine-src/src/functions/types.rs +1 -1
  37. package/dist-engine-src/src/init.rs +204 -151
  38. package/dist-engine-src/src/json_store/context.rs +354 -60
  39. package/dist-engine-src/src/json_store/encoded.rs +6 -6
  40. package/dist-engine-src/src/json_store/mod.rs +4 -1
  41. package/dist-engine-src/src/json_store/store.rs +884 -11
  42. package/dist-engine-src/src/json_store/types.rs +166 -1
  43. package/dist-engine-src/src/lib.rs +10 -9
  44. package/dist-engine-src/src/live_state/context.rs +608 -830
  45. package/dist-engine-src/src/live_state/mod.rs +3 -3
  46. package/dist-engine-src/src/live_state/overlay.rs +7 -7
  47. package/dist-engine-src/src/live_state/reader.rs +5 -5
  48. package/dist-engine-src/src/live_state/types.rs +19 -36
  49. package/dist-engine-src/src/live_state/visibility.rs +19 -14
  50. package/dist-engine-src/src/plugin/archive.rs +3 -6
  51. package/dist-engine-src/src/plugin/install.rs +0 -18
  52. package/dist-engine-src/src/plugin/plugin_manifest.json +0 -1
  53. package/dist-engine-src/src/schema/annotations/defaults.rs +2 -7
  54. package/dist-engine-src/src/schema/builtin/lix_account.json +0 -1
  55. package/dist-engine-src/src/schema/builtin/lix_active_account.json +0 -1
  56. package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +0 -1
  57. package/dist-engine-src/src/schema/builtin/lix_change.json +11 -10
  58. package/dist-engine-src/src/schema/builtin/lix_change_author.json +0 -1
  59. package/dist-engine-src/src/schema/builtin/lix_commit.json +8 -46
  60. package/dist-engine-src/src/schema/builtin/lix_commit_edge.json +29 -22
  61. package/dist-engine-src/src/schema/builtin/lix_directory_descriptor.json +0 -1
  62. package/dist-engine-src/src/schema/builtin/lix_file_descriptor.json +0 -1
  63. package/dist-engine-src/src/schema/builtin/lix_key_value.json +0 -1
  64. package/dist-engine-src/src/schema/builtin/lix_label.json +10 -3
  65. package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +74 -0
  66. package/dist-engine-src/src/schema/builtin/lix_registered_schema.json +2 -8
  67. package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +0 -1
  68. package/dist-engine-src/src/schema/builtin/lix_version_ref.json +0 -1
  69. package/dist-engine-src/src/schema/builtin/mod.rs +10 -59
  70. package/dist-engine-src/src/schema/compatibility.rs +787 -0
  71. package/dist-engine-src/src/schema/definition.json +47 -17
  72. package/dist-engine-src/src/schema/definition.rs +202 -96
  73. package/dist-engine-src/src/schema/key.rs +9 -77
  74. package/dist-engine-src/src/schema/mod.rs +4 -4
  75. package/dist-engine-src/src/schema/tests.rs +133 -92
  76. package/dist-engine-src/src/session/context.rs +40 -42
  77. package/dist-engine-src/src/session/create_version.rs +22 -14
  78. package/dist-engine-src/src/session/execute.rs +45 -14
  79. package/dist-engine-src/src/session/merge/apply.rs +4 -4
  80. package/dist-engine-src/src/session/merge/conflicts.rs +3 -2
  81. package/dist-engine-src/src/session/merge/stats.rs +1 -1
  82. package/dist-engine-src/src/session/merge/version.rs +35 -45
  83. package/dist-engine-src/src/session/mod.rs +4 -2
  84. package/dist-engine-src/src/session/optimization9_sql2_bench.rs +100 -0
  85. package/dist-engine-src/src/session/switch_version.rs +16 -28
  86. package/dist-engine-src/src/sql2/change_provider.rs +14 -20
  87. package/dist-engine-src/src/sql2/classify.rs +61 -26
  88. package/dist-engine-src/src/sql2/context.rs +22 -18
  89. package/dist-engine-src/src/sql2/directory_history_provider.rs +28 -20
  90. package/dist-engine-src/src/sql2/directory_provider.rs +131 -83
  91. package/dist-engine-src/src/sql2/entity_history_provider.rs +10 -14
  92. package/dist-engine-src/src/sql2/entity_provider.rs +680 -169
  93. package/dist-engine-src/src/sql2/error.rs +21 -1
  94. package/dist-engine-src/src/sql2/execute.rs +325 -264
  95. package/dist-engine-src/src/sql2/file_history_provider.rs +29 -21
  96. package/dist-engine-src/src/sql2/file_provider.rs +533 -108
  97. package/dist-engine-src/src/sql2/filesystem_planner.rs +58 -94
  98. package/dist-engine-src/src/sql2/filesystem_visibility.rs +37 -23
  99. package/dist-engine-src/src/sql2/history_projection.rs +3 -27
  100. package/dist-engine-src/src/sql2/history_provider.rs +11 -17
  101. package/dist-engine-src/src/sql2/history_route.rs +22 -8
  102. package/dist-engine-src/src/sql2/lix_state_provider.rs +178 -96
  103. package/dist-engine-src/src/sql2/mod.rs +6 -3
  104. package/dist-engine-src/src/sql2/predicate_typecheck.rs +246 -0
  105. package/dist-engine-src/src/sql2/public_bind/assignment.rs +46 -0
  106. package/dist-engine-src/src/sql2/public_bind/capability.rs +41 -0
  107. package/dist-engine-src/src/sql2/public_bind/dml.rs +166 -0
  108. package/dist-engine-src/src/sql2/public_bind/mod.rs +25 -0
  109. package/dist-engine-src/src/sql2/public_bind/table.rs +168 -0
  110. package/dist-engine-src/src/sql2/read_only.rs +10 -12
  111. package/dist-engine-src/src/sql2/session.rs +7 -10
  112. package/dist-engine-src/src/sql2/udfs/lix_timestamp.rs +76 -0
  113. package/dist-engine-src/src/sql2/udfs/mod.rs +8 -1
  114. package/dist-engine-src/src/sql2/udfs/public_call.rs +211 -0
  115. package/dist-engine-src/src/sql2/version_provider.rs +46 -31
  116. package/dist-engine-src/src/sql2/version_scope.rs +4 -4
  117. package/dist-engine-src/src/storage_bench.rs +1782 -325
  118. package/dist-engine-src/src/test_support.rs +183 -36
  119. package/dist-engine-src/src/tracked_state/by_file_index.rs +20 -24
  120. package/dist-engine-src/src/tracked_state/codec.rs +1519 -181
  121. package/dist-engine-src/src/tracked_state/context.rs +1155 -271
  122. package/dist-engine-src/src/tracked_state/diff.rs +249 -57
  123. package/dist-engine-src/src/tracked_state/materialization.rs +365 -103
  124. package/dist-engine-src/src/tracked_state/materializer.rs +488 -0
  125. package/dist-engine-src/src/tracked_state/merge.rs +37 -19
  126. package/dist-engine-src/src/tracked_state/mod.rs +8 -7
  127. package/dist-engine-src/src/tracked_state/storage.rs +138 -6
  128. package/dist-engine-src/src/tracked_state/tree.rs +695 -252
  129. package/dist-engine-src/src/tracked_state/types.rs +176 -6
  130. package/dist-engine-src/src/transaction/commit.rs +695 -435
  131. package/dist-engine-src/src/transaction/context.rs +551 -310
  132. package/dist-engine-src/src/transaction/live_state_overlay.rs +9 -8
  133. package/dist-engine-src/src/transaction/mod.rs +2 -0
  134. package/dist-engine-src/src/transaction/normalization.rs +311 -447
  135. package/dist-engine-src/src/transaction/prep.rs +37 -0
  136. package/dist-engine-src/src/transaction/schema_resolver.rs +93 -71
  137. package/dist-engine-src/src/transaction/staging.rs +701 -406
  138. package/dist-engine-src/src/transaction/types.rs +231 -122
  139. package/dist-engine-src/src/transaction/validation.rs +2717 -1698
  140. package/dist-engine-src/src/untracked_state/codec.rs +40 -96
  141. package/dist-engine-src/src/untracked_state/context.rs +21 -5
  142. package/dist-engine-src/src/untracked_state/materialization.rs +10 -104
  143. package/dist-engine-src/src/untracked_state/mod.rs +3 -5
  144. package/dist-engine-src/src/untracked_state/storage.rs +105 -57
  145. package/dist-engine-src/src/untracked_state/types.rs +63 -13
  146. package/dist-engine-src/src/version/context.rs +1 -13
  147. package/dist-engine-src/src/version/lifecycle.rs +221 -0
  148. package/dist-engine-src/src/version/mod.rs +3 -2
  149. package/dist-engine-src/src/version/refs.rs +12 -103
  150. package/dist-engine-src/src/version/stage_rows.rs +15 -19
  151. package/package.json +1 -1
  152. package/dist-engine-src/src/changelog/codec.rs +0 -321
  153. package/dist-engine-src/src/changelog/context.rs +0 -92
  154. package/dist-engine-src/src/changelog/materialization.rs +0 -121
  155. package/dist-engine-src/src/changelog/mod.rs +0 -13
  156. package/dist-engine-src/src/changelog/reader.rs +0 -20
  157. package/dist-engine-src/src/changelog/storage.rs +0 -220
  158. package/dist-engine-src/src/changelog/types.rs +0 -38
  159. package/dist-engine-src/src/schema/builtin/lix_change_set.json +0 -18
  160. package/dist-engine-src/src/schema/builtin/lix_change_set_element.json +0 -75
  161. package/dist-engine-src/src/schema/builtin/lix_entity_label.json +0 -63
  162. package/dist-engine-src/src/schema_registry.rs +0 -294
  163. package/dist-engine-src/src/sql2/commit_derived_provider.rs +0 -591
  164. package/dist-engine-src/src/tracked_state/rebuild.rs +0 -771
  165. package/dist-engine-src/src/tracked_state/tree_types.rs +0 -176
@@ -6,20 +6,22 @@ use std::sync::Arc;
6
6
  use serde_json::Value as JsonValue;
7
7
 
8
8
  use crate::binary_cas::{BinaryCasContext, BlobDataReader};
9
- use crate::changelog::ChangelogContext;
9
+ use crate::catalog::CatalogContext;
10
10
  use crate::commit_graph::{CommitGraphContext, CommitGraphReader};
11
+ use crate::commit_store::CommitStoreContext;
11
12
  use crate::entity_identity::EntityIdentity;
12
13
  use crate::functions::FunctionProviderHandle;
13
14
  use crate::json_store::JsonStoreContext;
14
15
  use crate::live_state::{LiveStateContext, LiveStateReader, LiveStateRowRequest};
15
- use crate::schema_registry::SchemaRegistry;
16
- use crate::sql2::{ChangelogQuerySource, SqlChangelogQuerySource, SqlExecutionContext};
16
+ use crate::sql2::{CommitStoreQuerySource, SqlCommitStoreQuerySource, SqlExecutionContext};
17
17
  use crate::storage::{
18
18
  ScopedStorageReader, StorageContext, StorageReadScope, StorageReadTransaction, StorageReader,
19
19
  };
20
20
  use crate::tracked_state::TrackedStateContext;
21
21
  use crate::transaction::{open_transaction, Transaction};
22
- use crate::version::{VersionContext, VersionRefReader};
22
+ use crate::version::{
23
+ VersionContext, VersionLifecycle, VersionOperation, VersionRefReader, VersionReferenceRole,
24
+ };
23
25
  use crate::GLOBAL_VERSION_ID;
24
26
  use crate::{LixError, NullableKeyFilter};
25
27
 
@@ -31,13 +33,13 @@ pub(crate) enum SessionMode {
31
33
  Workspace,
32
34
  }
33
35
 
34
- /// Session-context state for engine2 execution.
36
+ /// Session-context state for engine execution.
35
37
  ///
36
38
  /// A session context pins the active version selector and shared execution
37
39
  /// services. Each call to `execute(...)` projects this state into a read-only
38
40
  /// SQL context or a transaction-owned write context.
39
41
  ///
40
- /// Write transaction invariant: any engine2 operation that may write must enter
42
+ /// Write transaction invariant: any engine operation that may write must enter
41
43
  /// through `SessionContext::with_write_transaction`. Reads that influence writes
42
44
  /// are only available from that transaction capability, not from session-level
43
45
  /// helpers.
@@ -48,9 +50,9 @@ pub struct SessionContext {
48
50
  pub(super) live_state: Arc<LiveStateContext>,
49
51
  pub(super) tracked_state: Arc<TrackedStateContext>,
50
52
  pub(super) binary_cas: Arc<BinaryCasContext>,
51
- pub(super) changelog: Arc<ChangelogContext>,
53
+ pub(super) commit_store: Arc<CommitStoreContext>,
52
54
  pub(super) version_ctx: Arc<VersionContext>,
53
- pub(super) schema_registry: Arc<SchemaRegistry>,
55
+ pub(super) catalog_context: Arc<CatalogContext>,
54
56
  closed: Arc<AtomicBool>,
55
57
  }
56
58
 
@@ -60,9 +62,9 @@ impl SessionContext {
60
62
  live_state: Arc<LiveStateContext>,
61
63
  tracked_state: Arc<TrackedStateContext>,
62
64
  binary_cas: Arc<BinaryCasContext>,
63
- changelog: Arc<ChangelogContext>,
65
+ commit_store: Arc<CommitStoreContext>,
64
66
  version_ctx: Arc<VersionContext>,
65
- schema_registry: Arc<SchemaRegistry>,
67
+ catalog_context: Arc<CatalogContext>,
66
68
  ) -> Result<Self, LixError> {
67
69
  let session = Self::new(
68
70
  SessionMode::Workspace,
@@ -70,9 +72,9 @@ impl SessionContext {
70
72
  live_state,
71
73
  tracked_state,
72
74
  binary_cas,
73
- changelog,
75
+ commit_store,
74
76
  version_ctx,
75
- schema_registry,
77
+ catalog_context,
76
78
  );
77
79
  session.active_version_id().await?;
78
80
  Ok(session)
@@ -84,9 +86,9 @@ impl SessionContext {
84
86
  live_state: Arc<LiveStateContext>,
85
87
  tracked_state: Arc<TrackedStateContext>,
86
88
  binary_cas: Arc<BinaryCasContext>,
87
- changelog: Arc<ChangelogContext>,
89
+ commit_store: Arc<CommitStoreContext>,
88
90
  version_ctx: Arc<VersionContext>,
89
- schema_registry: Arc<SchemaRegistry>,
91
+ catalog_context: Arc<CatalogContext>,
90
92
  ) -> Result<Self, LixError> {
91
93
  Ok(Self::new(
92
94
  SessionMode::Pinned {
@@ -96,9 +98,9 @@ impl SessionContext {
96
98
  live_state,
97
99
  tracked_state,
98
100
  binary_cas,
99
- changelog,
101
+ commit_store,
100
102
  version_ctx,
101
- schema_registry,
103
+ catalog_context,
102
104
  ))
103
105
  }
104
106
 
@@ -108,9 +110,9 @@ impl SessionContext {
108
110
  live_state: Arc<LiveStateContext>,
109
111
  tracked_state: Arc<TrackedStateContext>,
110
112
  binary_cas: Arc<BinaryCasContext>,
111
- changelog: Arc<ChangelogContext>,
113
+ commit_store: Arc<CommitStoreContext>,
112
114
  version_ctx: Arc<VersionContext>,
113
- schema_registry: Arc<SchemaRegistry>,
115
+ catalog_context: Arc<CatalogContext>,
114
116
  ) -> Self {
115
117
  Self::new_with_closed(
116
118
  mode,
@@ -118,9 +120,9 @@ impl SessionContext {
118
120
  live_state,
119
121
  tracked_state,
120
122
  binary_cas,
121
- changelog,
123
+ commit_store,
122
124
  version_ctx,
123
- schema_registry,
125
+ catalog_context,
124
126
  Arc::new(AtomicBool::new(false)),
125
127
  )
126
128
  }
@@ -131,9 +133,9 @@ impl SessionContext {
131
133
  live_state: Arc<LiveStateContext>,
132
134
  tracked_state: Arc<TrackedStateContext>,
133
135
  binary_cas: Arc<BinaryCasContext>,
134
- changelog: Arc<ChangelogContext>,
136
+ commit_store: Arc<CommitStoreContext>,
135
137
  version_ctx: Arc<VersionContext>,
136
- schema_registry: Arc<SchemaRegistry>,
138
+ catalog_context: Arc<CatalogContext>,
137
139
  closed: Arc<AtomicBool>,
138
140
  ) -> Self {
139
141
  Self {
@@ -142,9 +144,9 @@ impl SessionContext {
142
144
  live_state,
143
145
  tracked_state,
144
146
  binary_cas,
145
- changelog,
147
+ commit_store,
146
148
  version_ctx,
147
- schema_registry,
149
+ catalog_context,
148
150
  closed,
149
151
  }
150
152
  }
@@ -256,18 +258,14 @@ impl SessionContext {
256
258
  })?
257
259
  .to_string();
258
260
 
259
- let head = self
260
- .version_ctx
261
- .ref_reader(&mut *reader)
262
- .load_head_commit_id(&version_id)
261
+ let version_ref = self.version_ctx.ref_reader(&mut *reader);
262
+ VersionLifecycle::new(&version_ref)
263
+ .require_existing_ref(
264
+ &version_id,
265
+ VersionOperation::LoadWorkspaceSelector,
266
+ VersionReferenceRole::WorkspaceSelector,
267
+ )
263
268
  .await?;
264
- if head.is_none() {
265
- return Err(LixError::version_not_found(
266
- version_id,
267
- "load_workspace_version_id",
268
- "workspace_selector",
269
- ));
270
- }
271
269
 
272
270
  Ok(version_id)
273
271
  }
@@ -285,9 +283,9 @@ impl SessionContext {
285
283
  Arc::clone(&self.live_state),
286
284
  Arc::clone(&self.tracked_state),
287
285
  Arc::clone(&self.binary_cas),
288
- Arc::clone(&self.changelog),
286
+ Arc::clone(&self.commit_store),
289
287
  Arc::clone(&self.version_ctx),
290
- Arc::clone(&self.schema_registry),
288
+ Arc::clone(&self.catalog_context),
291
289
  )
292
290
  .await?;
293
291
  let mut transaction = opened.transaction;
@@ -321,7 +319,7 @@ pub(super) struct SessionSqlExecutionContext<'a> {
321
319
  ScopedStorageReader<Box<dyn StorageReadTransaction + Send + Sync + 'static>>,
322
320
  pub(super) live_state: Arc<LiveStateContext>,
323
321
  pub(super) binary_cas: Arc<BinaryCasContext>,
324
- pub(super) changelog: Arc<ChangelogContext>,
322
+ pub(super) commit_store: Arc<CommitStoreContext>,
325
323
  pub(super) version_ctx: Arc<VersionContext>,
326
324
  pub(super) visible_schemas: Vec<JsonValue>,
327
325
  pub(super) functions: FunctionProviderHandle,
@@ -336,16 +334,16 @@ impl SqlExecutionContext for SessionSqlExecutionContext<'_> {
336
334
  Arc::new(self.live_state.reader(self.read_store.clone())) as Arc<dyn LiveStateReader>
337
335
  }
338
336
 
339
- fn changelog_query_source(&self) -> SqlChangelogQuerySource {
337
+ fn commit_store_query_source(&self) -> SqlCommitStoreQuerySource {
340
338
  let read_scope = StorageReadScope::new(self.read_store.clone());
341
- ChangelogQuerySource {
342
- changelog_reader: Arc::new(self.changelog.reader(read_scope.store())),
339
+ CommitStoreQuerySource {
340
+ commit_store_reader: Arc::new(self.commit_store.reader(read_scope.store())),
343
341
  json_reader: JsonStoreContext::new().reader(read_scope.store()),
344
342
  }
345
343
  }
346
344
 
347
345
  fn commit_graph(&self) -> Box<dyn CommitGraphReader> {
348
- Box::new(CommitGraphContext::new(ChangelogContext::new()).reader(self.read_store.clone()))
346
+ Box::new(CommitGraphContext::new().reader(self.read_store.clone()))
349
347
  }
350
348
 
351
349
  fn version_ref(&self) -> Arc<dyn VersionRefReader> {
@@ -1,5 +1,8 @@
1
- use crate::transaction::types::{StageWrite, StageWriteMode};
2
- use crate::version::{version_descriptor_stage_row, version_ref_stage_row, VersionRefReader};
1
+ use crate::transaction::types::{TransactionWrite, TransactionWriteMode};
2
+ use crate::version::{
3
+ version_descriptor_stage_row, version_ref_stage_row, VersionLifecycle, VersionOperation,
4
+ VersionReferenceRole,
5
+ };
3
6
  use crate::LixError;
4
7
 
5
8
  use super::context::SessionContext;
@@ -7,7 +10,7 @@ use super::context::SessionContext;
7
10
  /// Options for creating a new version from the session's active version.
8
11
  #[derive(Debug, Clone, PartialEq, Eq)]
9
12
  pub struct CreateVersionOptions {
10
- /// Optional caller-provided version id. If omitted, engine2 generates one.
13
+ /// Optional caller-provided version id. If omitted, engine generates one.
11
14
  pub id: Option<String>,
12
15
  /// User-facing version name.
13
16
  pub name: String,
@@ -41,25 +44,30 @@ impl SessionContext {
41
44
  .id
42
45
  .unwrap_or_else(|| transaction.functions().call_uuid_v7());
43
46
  let source_head = if let Some(from_commit_id) = options.from_commit_id {
47
+ let mut commit_graph = transaction.commit_graph_reader();
48
+ VersionLifecycle::require_existing_commit(
49
+ &mut commit_graph,
50
+ &from_commit_id,
51
+ VersionOperation::CreateVersion,
52
+ VersionReferenceRole::CommitSource,
53
+ )
54
+ .await?;
44
55
  from_commit_id
45
56
  } else {
46
57
  let active_version_id = transaction.active_version_id().to_string();
47
58
  let reader = transaction.version_ref_reader();
48
- reader
49
- .load_head_commit_id(&active_version_id)
59
+ VersionLifecycle::new(&reader)
60
+ .require_existing_commit_id(
61
+ &active_version_id,
62
+ VersionOperation::CreateVersion,
63
+ VersionReferenceRole::Source,
64
+ )
50
65
  .await?
51
- .ok_or_else(|| {
52
- LixError::version_not_found(
53
- active_version_id.clone(),
54
- "create_version",
55
- "source",
56
- )
57
- })?
58
66
  };
59
67
 
60
68
  transaction
61
- .stage_write(StageWrite::Rows {
62
- mode: StageWriteMode::Insert,
69
+ .stage_write(TransactionWrite::Rows {
70
+ mode: TransactionWriteMode::Insert,
63
71
  rows: vec![
64
72
  version_descriptor_stage_row(&version_id, &options.name, false),
65
73
  version_ref_stage_row(&version_id, &source_head),
@@ -1,14 +1,13 @@
1
1
  use std::sync::Arc;
2
2
 
3
3
  use crate::functions::FunctionContext;
4
- use crate::json_store::JsonStoreContext;
5
4
  use crate::sql2;
6
5
  use crate::storage::{StorageReadScope, StorageWriteSet};
7
6
  use crate::{LixError, LixNotice, SqlQueryResult, Value};
8
7
 
9
8
  use super::context::{SessionContext, SessionSqlExecutionContext};
10
9
 
11
- /// Result of executing one SQL statement through engine2.
10
+ /// Result of executing one SQL statement through engine.
12
11
  ///
13
12
  /// Column names live once at the result-set level. Individual rows only own
14
13
  /// values, which keeps the public API row-oriented without copying schema
@@ -251,7 +250,7 @@ fn value_type_error(expected: &str, actual: &Value) -> LixError {
251
250
  )
252
251
  }
253
252
 
254
- /// Borrowed row view with access to the result-set column names.
253
+ /// Zero-copy row view with access to the result-set column names.
255
254
  ///
256
255
  /// This is the ergonomic path for callers that want `row.get("column")`
257
256
  /// without storing column metadata on every owned row.
@@ -300,6 +299,7 @@ impl SessionContext {
300
299
  let kind = sql2::classify_statement(sql)?;
301
300
  if kind == sql2::SqlStatementKind::Write {
302
301
  let sql = sql.to_string();
302
+ let sql_for_error = sql.clone();
303
303
  let params = params.to_vec();
304
304
  return self
305
305
  .with_write_transaction(|transaction| {
@@ -313,7 +313,8 @@ impl SessionContext {
313
313
  Ok(ExecuteResult::from_rows_affected(affected_rows))
314
314
  })
315
315
  })
316
- .await;
316
+ .await
317
+ .map_err(|error| normalize_sql_surface_error(error, &sql_for_error));
317
318
  }
318
319
 
319
320
  let read_scope = StorageReadScope::new(self.storage.begin_read_transaction().await?);
@@ -325,15 +326,15 @@ impl SessionContext {
325
326
  let functions = runtime_functions.provider();
326
327
  let active_version_id = self.active_version_id_from_reader(&mut read_store).await?;
327
328
  let visible_schemas = self
328
- .schema_registry
329
- .visible_schemas(live_state.as_ref(), &active_version_id)
329
+ .catalog_context
330
+ .schema_jsons_for_sql_read_planning(live_state.as_ref(), &active_version_id)
330
331
  .await?;
331
332
  let ctx = SessionSqlExecutionContext {
332
333
  active_version_id: &active_version_id,
333
334
  read_store,
334
335
  live_state: Arc::clone(&self.live_state),
335
336
  binary_cas: Arc::clone(&self.binary_cas),
336
- changelog: Arc::clone(&self.changelog),
337
+ commit_store: Arc::clone(&self.commit_store),
337
338
  version_ctx: Arc::clone(&self.version_ctx),
338
339
  visible_schemas,
339
340
  functions: functions.clone(),
@@ -352,7 +353,7 @@ impl SessionContext {
352
353
  }
353
354
  Err(error) => {
354
355
  let _ = read_scope.rollback().await;
355
- return Err(error);
356
+ return Err(normalize_sql_surface_error(error, sql));
356
357
  }
357
358
  };
358
359
  self.persist_runtime_functions_if_needed(&runtime_functions)
@@ -372,13 +373,8 @@ impl SessionContext {
372
373
  ) -> Result<(), LixError> {
373
374
  let mut transaction = self.storage.begin_write_transaction().await?;
374
375
  let mut writes = StorageWriteSet::new();
375
- let mut json_writer = JsonStoreContext::new().writer();
376
376
  runtime_functions
377
- .stage_persist_if_needed(
378
- &mut self.live_state.writer(transaction.as_mut()),
379
- &mut writes,
380
- &mut json_writer,
381
- )
377
+ .stage_persist_if_needed(&mut writes)
382
378
  .await?;
383
379
  if !writes.is_empty() {
384
380
  writes.apply(&mut transaction.as_mut()).await?;
@@ -387,6 +383,41 @@ impl SessionContext {
387
383
  }
388
384
  }
389
385
 
386
+ fn normalize_sql_surface_error(error: LixError, sql: &str) -> LixError {
387
+ if error.code.starts_with("LIX_ERROR_PATH_") && sql_uses_public_filesystem_path_surface(sql) {
388
+ return LixError {
389
+ code: LixError::CODE_INVALID_PARAM.to_string(),
390
+ ..error
391
+ };
392
+ }
393
+ if error.code == LixError::CODE_INVALID_JSON_PATH
394
+ && error
395
+ .message
396
+ .to_ascii_lowercase()
397
+ .contains("uses variadic path segments")
398
+ {
399
+ return LixError {
400
+ code: LixError::CODE_INVALID_PARAM.to_string(),
401
+ ..error
402
+ };
403
+ }
404
+ if error.code == LixError::CODE_FOREIGN_KEY {
405
+ let lower = error.message.to_ascii_lowercase();
406
+ if lower.contains("schema 'lix_version_ref'") && lower.contains("target 'lix_commit.") {
407
+ return LixError {
408
+ code: LixError::CODE_VERSION_NOT_FOUND.to_string(),
409
+ ..error
410
+ };
411
+ }
412
+ }
413
+ error
414
+ }
415
+
416
+ fn sql_uses_public_filesystem_path_surface(sql: &str) -> bool {
417
+ let lower = sql.to_ascii_lowercase();
418
+ (lower.contains("lix_file") || lower.contains("lix_directory")) && lower.contains("path")
419
+ }
420
+
390
421
  fn affected_rows_from_query_result(result: SqlQueryResult) -> Result<u64, LixError> {
391
422
  let Some(first_row) = result.rows.first() else {
392
423
  return Ok(0);
@@ -1,10 +1,10 @@
1
1
  use crate::tracked_state::TrackedStateMergePlan;
2
- use crate::transaction::types::StageAdoptedChange;
2
+ use crate::transaction::types::TransactionAdoptedChange;
3
3
 
4
4
  pub(crate) fn adopted_changes_from_merge_plan(
5
5
  plan: &TrackedStateMergePlan,
6
6
  target_version_id: &str,
7
- ) -> Vec<StageAdoptedChange> {
7
+ ) -> Vec<TransactionAdoptedChange> {
8
8
  plan.patches
9
9
  .iter()
10
10
  .map(|patch| stage_adopted_change_from_patch(patch, target_version_id))
@@ -14,8 +14,8 @@ pub(crate) fn adopted_changes_from_merge_plan(
14
14
  fn stage_adopted_change_from_patch(
15
15
  patch: &crate::tracked_state::TrackedStateMergePatch,
16
16
  target_version_id: &str,
17
- ) -> StageAdoptedChange {
18
- StageAdoptedChange {
17
+ ) -> TransactionAdoptedChange {
18
+ TransactionAdoptedChange {
19
19
  version_id: target_version_id.to_string(),
20
20
  change_id: patch.change_id().to_string(),
21
21
  projected_row: patch.projected_row().clone(),
@@ -2,12 +2,13 @@ use crate::tracked_state::{
2
2
  TrackedStateDiffEntry, TrackedStateDiffKind, TrackedStateMergeConflict, TrackedStateMergePlan,
3
3
  };
4
4
  use crate::LixError;
5
+ use serde_json::Value as JsonValue;
5
6
 
6
7
  #[derive(Debug, Clone, PartialEq, Eq)]
7
8
  pub(crate) struct MergeConflict {
8
9
  pub(crate) kind: MergeConflictKind,
9
10
  pub(crate) schema_key: String,
10
- pub(crate) entity_id: String,
11
+ pub(crate) entity_id: JsonValue,
11
12
  pub(crate) file_id: Option<String>,
12
13
  pub(crate) target: MergeConflictSide,
13
14
  pub(crate) source: MergeConflictSide,
@@ -42,7 +43,7 @@ fn conflict_from_tracked(conflict: &TrackedStateMergeConflict) -> Result<MergeCo
42
43
  Ok(MergeConflict {
43
44
  kind: MergeConflictKind::SameEntityChanged,
44
45
  schema_key: conflict.identity.schema_key.clone(),
45
- entity_id: conflict.identity.entity_id.as_string()?,
46
+ entity_id: conflict.identity.entity_id.as_json_array_value()?,
46
47
  file_id: conflict.identity.file_id.clone(),
47
48
  target: conflict_side_from_diff_entry(&conflict.target),
48
49
  source: conflict_side_from_diff_entry(&conflict.source),
@@ -36,7 +36,7 @@ pub(crate) fn stats_from_plan(
36
36
  format!(
37
37
  "merge analysis could not find source diff entry for adopted schema '{}' entity '{}'",
38
38
  identity.schema_key,
39
- identity.entity_id.as_string()?
39
+ identity.entity_id.as_json_array_text()?
40
40
  ),
41
41
  ));
42
42
  };
@@ -1,7 +1,7 @@
1
- use serde_json::json;
1
+ use serde_json::{json, Value as JsonValue};
2
2
 
3
- use crate::transaction::types::StageWrite;
4
- use crate::version::VersionRefReader;
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: String,
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 target_head = reader
121
- .load_head_commit_id(&active_version_id)
122
- .await?
123
- .ok_or_else(|| {
124
- LixError::version_not_found(
125
- active_version_id.clone(),
126
- "merge_version_preview",
127
- "target",
128
- )
129
- })?;
130
- let source_head = reader
131
- .load_head_commit_id(&source_version_id)
132
- .await?
133
- .ok_or_else(|| {
134
- LixError::version_not_found(
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 target_head = reader
193
- .load_head_commit_id(&active_version_id)
194
- .await?
195
- .ok_or_else(|| {
196
- LixError::version_not_found(
197
- active_version_id.clone(),
198
- "merge_version",
199
- "target",
200
- )
201
- })?;
202
- let source_head = reader
203
- .load_head_commit_id(&source_version_id)
204
- .await?
205
- .ok_or_else(|| {
206
- LixError::version_not_found(
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(StageWrite::AdoptedChanges {
293
+ .stage_write(TransactionWrite::AdoptedChanges {
304
294
  changes: adopted_changes,
305
295
  })
306
296
  .await?;
@@ -1,7 +1,7 @@
1
- //! Engine2 session boundary.
1
+ //! Engine session boundary.
2
2
  //!
3
3
  //! Transaction invariant:
4
- //! any engine2 operation that may write must enter through
4
+ //! any engine operation that may write must enter through
5
5
  //! `SessionContext::with_write_transaction`. Reads that influence writes are
6
6
  //! only available from the transaction capability. Session APIs must not
7
7
  //! open `Transaction` directly or use session-level read helpers inside write
@@ -11,6 +11,8 @@ mod context;
11
11
  mod create_version;
12
12
  mod execute;
13
13
  mod merge;
14
+ #[cfg(feature = "storage-benches")]
15
+ pub mod optimization9_sql2_bench;
14
16
  mod switch_version;
15
17
 
16
18
  pub use context::SessionContext;