@lix-js/sdk 0.6.0-preview.4 → 0.6.0-preview.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/README.md +1 -1
  2. package/SKILL.md +65 -64
  3. package/dist/engine-wasm/index.js +4 -4
  4. package/dist/engine-wasm/wasm/lix_engine.d.ts +5 -5
  5. package/dist/engine-wasm/wasm/lix_engine.js +130 -118
  6. package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
  7. package/dist/engine-wasm/wasm/lix_engine.wasm.d.ts +9 -8
  8. package/dist/generated/builtin-schemas.d.ts +69 -69
  9. package/dist/generated/builtin-schemas.js +94 -94
  10. package/dist/open-lix.d.ts +33 -26
  11. package/dist/open-lix.js +10 -10
  12. package/dist/sqlite/index.js +86 -30
  13. package/dist-engine-src/README.md +3 -3
  14. package/dist-engine-src/src/backend/capabilities.rs +67 -0
  15. package/dist-engine-src/src/backend/conformance/baseline.rs +1127 -0
  16. package/dist-engine-src/src/backend/conformance/factory.rs +93 -0
  17. package/dist-engine-src/src/backend/conformance/failure_tests.rs +608 -0
  18. package/dist-engine-src/src/backend/conformance/fixtures.rs +26 -0
  19. package/dist-engine-src/src/backend/conformance/mod.rs +75 -0
  20. package/dist-engine-src/src/backend/conformance/model.rs +28 -0
  21. package/dist-engine-src/src/backend/conformance/model_based.rs +257 -0
  22. package/dist-engine-src/src/backend/conformance/persistence.rs +204 -0
  23. package/dist-engine-src/src/backend/conformance/projection.rs +21 -0
  24. package/dist-engine-src/src/backend/conformance/pushdown.rs +24 -0
  25. package/dist-engine-src/src/backend/conformance/runner.rs +90 -0
  26. package/dist-engine-src/src/backend/conformance/scan.rs +24 -0
  27. package/dist-engine-src/src/backend/conformance/write.rs +16 -0
  28. package/dist-engine-src/src/backend/error.rs +94 -0
  29. package/dist-engine-src/src/backend/in_memory.rs +670 -0
  30. package/dist-engine-src/src/backend/mod.rs +36 -9
  31. package/dist-engine-src/src/backend/predicate.rs +80 -0
  32. package/dist-engine-src/src/backend/traits.rs +260 -0
  33. package/dist-engine-src/src/backend/types.rs +224 -81
  34. package/dist-engine-src/src/binary_cas/context.rs +8 -8
  35. package/dist-engine-src/src/binary_cas/kv.rs +234 -259
  36. package/dist-engine-src/src/{version → branch}/context.rs +12 -12
  37. package/dist-engine-src/src/branch/lifecycle.rs +221 -0
  38. package/dist-engine-src/src/branch/mod.rs +13 -0
  39. package/dist-engine-src/src/branch/refs.rs +321 -0
  40. package/dist-engine-src/src/branch/stage_rows.rs +67 -0
  41. package/dist-engine-src/src/branch/types.rs +21 -0
  42. package/dist-engine-src/src/catalog/context.rs +18 -18
  43. package/dist-engine-src/src/catalog/snapshot.rs +8 -8
  44. package/dist-engine-src/src/changelog/bench_support.rs +785 -0
  45. package/dist-engine-src/src/changelog/change.rs +1 -0
  46. package/dist-engine-src/src/changelog/codec.rs +497 -0
  47. package/dist-engine-src/src/changelog/commit.rs +1 -0
  48. package/dist-engine-src/src/changelog/context.rs +1614 -0
  49. package/dist-engine-src/src/changelog/mod.rs +29 -0
  50. package/dist-engine-src/src/changelog/store.rs +163 -0
  51. package/dist-engine-src/src/changelog/test_support.rs +54 -0
  52. package/dist-engine-src/src/changelog/types.rs +213 -0
  53. package/dist-engine-src/src/commit_graph/context.rs +317 -274
  54. package/dist-engine-src/src/commit_graph/mod.rs +2 -4
  55. package/dist-engine-src/src/commit_graph/types.rs +22 -42
  56. package/dist-engine-src/src/commit_graph/walker.rs +133 -103
  57. package/dist-engine-src/src/common/error.rs +52 -18
  58. package/dist-engine-src/src/common/identity.rs +2 -2
  59. package/dist-engine-src/src/common/mod.rs +1 -1
  60. package/dist-engine-src/src/domain.rs +42 -46
  61. package/dist-engine-src/src/engine.rs +74 -96
  62. package/dist-engine-src/src/{entity_identity.rs → entity_pk.rs} +89 -92
  63. package/dist-engine-src/src/functions/context.rs +56 -52
  64. package/dist-engine-src/src/functions/state.rs +51 -52
  65. package/dist-engine-src/src/init.rs +288 -154
  66. package/dist-engine-src/src/json_store/context.rs +15 -266
  67. package/dist-engine-src/src/json_store/mod.rs +26 -0
  68. package/dist-engine-src/src/json_store/store.rs +103 -718
  69. package/dist-engine-src/src/json_store/types.rs +4 -9
  70. package/dist-engine-src/src/lib.rs +49 -19
  71. package/dist-engine-src/src/live_state/context.rs +654 -790
  72. package/dist-engine-src/src/live_state/mod.rs +9 -3
  73. package/dist-engine-src/src/live_state/overlay.rs +4 -4
  74. package/dist-engine-src/src/live_state/types.rs +30 -21
  75. package/dist-engine-src/src/live_state/visibility.rs +514 -71
  76. package/dist-engine-src/src/plugin/install.rs +48 -48
  77. package/dist-engine-src/src/plugin/manifest.rs +7 -7
  78. package/dist-engine-src/src/plugin/materializer.rs +0 -275
  79. package/dist-engine-src/src/plugin/plugin_manifest.json +4 -3
  80. package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +2 -2
  81. package/dist-engine-src/src/schema/builtin/lix_branch_descriptor.json +34 -0
  82. package/dist-engine-src/src/schema/builtin/lix_branch_ref.json +48 -0
  83. package/dist-engine-src/src/schema/builtin/lix_change.json +3 -3
  84. package/dist-engine-src/src/schema/builtin/lix_commit.json +1 -1
  85. package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +6 -6
  86. package/dist-engine-src/src/schema/builtin/mod.rs +18 -20
  87. package/dist-engine-src/src/schema/compatibility.rs +11 -11
  88. package/dist-engine-src/src/schema/definition.json +2 -2
  89. package/dist-engine-src/src/schema/definition.rs +5 -5
  90. package/dist-engine-src/src/schema/key.rs +3 -3
  91. package/dist-engine-src/src/schema/mod.rs +1 -1
  92. package/dist-engine-src/src/schema/tests.rs +18 -18
  93. package/dist-engine-src/src/session/context.rs +803 -148
  94. package/dist-engine-src/src/session/create_branch.rs +94 -0
  95. package/dist-engine-src/src/session/execute.rs +223 -83
  96. package/dist-engine-src/src/session/merge/analysis.rs +9 -3
  97. package/dist-engine-src/src/session/merge/{version.rs → branch.rs} +119 -129
  98. package/dist-engine-src/src/session/merge/conflicts.rs +2 -2
  99. package/dist-engine-src/src/session/merge/mod.rs +5 -6
  100. package/dist-engine-src/src/session/merge/stats.rs +7 -11
  101. package/dist-engine-src/src/session/mod.rs +15 -12
  102. package/dist-engine-src/src/session/switch_branch.rs +113 -0
  103. package/dist-engine-src/src/session/transaction.rs +495 -14
  104. package/dist-engine-src/src/sql2/{classify.rs → bind/classify.rs} +3 -75
  105. package/dist-engine-src/src/sql2/bind/error.rs +5 -0
  106. package/dist-engine-src/src/sql2/bind/expr.rs +29 -0
  107. package/dist-engine-src/src/sql2/bind/mod.rs +12 -0
  108. package/dist-engine-src/src/sql2/{udfs/public_call.rs → bind/public_udf.rs} +71 -3
  109. package/dist-engine-src/src/sql2/bind/read.rs +65 -0
  110. package/dist-engine-src/src/sql2/bind/statement.rs +2236 -0
  111. package/dist-engine-src/src/sql2/bind/table.rs +273 -0
  112. package/dist-engine-src/src/sql2/bind/write.rs +86 -0
  113. package/dist-engine-src/src/sql2/branch_scope.rs +436 -0
  114. package/dist-engine-src/src/sql2/catalog/capability.rs +20 -0
  115. package/dist-engine-src/src/sql2/catalog/entity_surface.rs +296 -0
  116. package/dist-engine-src/src/sql2/catalog/mod.rs +15 -0
  117. package/dist-engine-src/src/sql2/catalog/registry.rs +556 -0
  118. package/dist-engine-src/src/sql2/catalog/schema.rs +88 -0
  119. package/dist-engine-src/src/sql2/catalog/surface.rs +41 -0
  120. package/dist-engine-src/src/sql2/change_materialization.rs +122 -0
  121. package/dist-engine-src/src/sql2/context.rs +36 -30
  122. package/dist-engine-src/src/sql2/error.rs +1 -1
  123. package/dist-engine-src/src/sql2/exec/bound_public_write.rs +1593 -0
  124. package/dist-engine-src/src/sql2/exec/datafusion.rs +5266 -0
  125. package/dist-engine-src/src/sql2/exec/fast_write.rs +82 -0
  126. package/dist-engine-src/src/sql2/exec/mod.rs +24 -0
  127. package/dist-engine-src/src/sql2/exec/write.rs +661 -0
  128. package/dist-engine-src/src/sql2/filesystem_planner.rs +72 -77
  129. package/dist-engine-src/src/sql2/filesystem_visibility.rs +21 -21
  130. package/dist-engine-src/src/sql2/history_projection.rs +8 -8
  131. package/dist-engine-src/src/sql2/history_route.rs +35 -31
  132. package/dist-engine-src/src/sql2/mod.rs +28 -23
  133. package/dist-engine-src/src/sql2/optimize/datafusion.rs +1 -0
  134. package/dist-engine-src/src/sql2/optimize/mod.rs +2 -0
  135. package/dist-engine-src/src/sql2/optimize/simple_write.rs +116 -0
  136. package/dist-engine-src/src/sql2/parse/mod.rs +69 -0
  137. package/dist-engine-src/src/sql2/parse/normalize.rs +1 -0
  138. package/dist-engine-src/src/sql2/plan/branch_scope.rs +24 -0
  139. package/dist-engine-src/src/sql2/plan/mod.rs +5 -0
  140. package/dist-engine-src/src/sql2/plan/predicate.rs +22 -0
  141. package/dist-engine-src/src/sql2/plan/write.rs +147 -0
  142. package/dist-engine-src/src/sql2/predicate_typecheck.rs +258 -0
  143. package/dist-engine-src/src/sql2/{version_provider.rs → providers/branch.rs} +218 -214
  144. package/dist-engine-src/src/sql2/{change_provider.rs → providers/change.rs} +156 -42
  145. package/dist-engine-src/src/sql2/{directory_provider.rs → providers/directory.rs} +291 -322
  146. package/dist-engine-src/src/sql2/{directory_history_provider.rs → providers/directory_history.rs} +56 -42
  147. package/dist-engine-src/src/sql2/providers/entity.rs +1484 -0
  148. package/dist-engine-src/src/sql2/{entity_history_provider.rs → providers/entity_history.rs} +43 -31
  149. package/dist-engine-src/src/sql2/{file_provider.rs → providers/file.rs} +323 -316
  150. package/dist-engine-src/src/sql2/{file_history_provider.rs → providers/file_history.rs} +60 -46
  151. package/dist-engine-src/src/sql2/{history_provider.rs → providers/history.rs} +46 -32
  152. package/dist-engine-src/src/sql2/{lix_state_provider.rs → providers/lix_state.rs} +359 -329
  153. package/dist-engine-src/src/sql2/providers/mod.rs +508 -0
  154. package/dist-engine-src/src/sql2/read_only.rs +2 -2
  155. package/dist-engine-src/src/sql2/session.rs +47 -96
  156. package/dist-engine-src/src/sql2/storage/constraints.rs +1 -0
  157. package/dist-engine-src/src/sql2/storage/mod.rs +1 -0
  158. package/dist-engine-src/src/sql2/test_support/differential.rs +712 -0
  159. package/dist-engine-src/src/sql2/test_support/generators.rs +354 -0
  160. package/dist-engine-src/src/sql2/test_support/mod.rs +2 -0
  161. package/dist-engine-src/src/sql2/udfs/{lix_active_version_commit_id.rs → lix_active_branch_commit_id.rs} +7 -7
  162. package/dist-engine-src/src/sql2/udfs/mod.rs +3 -6
  163. package/dist-engine-src/src/sql2/write_normalization.rs +45 -22
  164. package/dist-engine-src/src/storage/conformance.rs +399 -0
  165. package/dist-engine-src/src/storage/context.rs +552 -288
  166. package/dist-engine-src/src/storage/mod.rs +48 -10
  167. package/dist-engine-src/src/storage/point.rs +440 -0
  168. package/dist-engine-src/src/storage/read_scope.rs +43 -64
  169. package/dist-engine-src/src/storage/reader.rs +867 -0
  170. package/dist-engine-src/src/storage/scan.rs +784 -0
  171. package/dist-engine-src/src/storage/spaces.rs +236 -0
  172. package/dist-engine-src/src/storage/stats.rs +80 -0
  173. package/dist-engine-src/src/storage/write_set.rs +962 -0
  174. package/dist-engine-src/src/storage_bench.rs +136 -4828
  175. package/dist-engine-src/src/test_support.rs +360 -138
  176. package/dist-engine-src/src/tracked_state/bench_support.rs +394 -0
  177. package/dist-engine-src/src/tracked_state/codec.rs +155 -1057
  178. package/dist-engine-src/src/tracked_state/commit_root_rebuild.rs +358 -0
  179. package/dist-engine-src/src/tracked_state/context.rs +1927 -993
  180. package/dist-engine-src/src/tracked_state/diff.rs +1715 -261
  181. package/dist-engine-src/src/tracked_state/merge.rs +74 -88
  182. package/dist-engine-src/src/tracked_state/mod.rs +19 -16
  183. package/dist-engine-src/src/tracked_state/{materialization.rs → row_materialization.rs} +50 -178
  184. package/dist-engine-src/src/tracked_state/storage.rs +243 -191
  185. package/dist-engine-src/src/tracked_state/tree.rs +247 -371
  186. package/dist-engine-src/src/tracked_state/types.rs +49 -42
  187. package/dist-engine-src/src/transaction/bench_support.rs +407 -0
  188. package/dist-engine-src/src/transaction/commit.rs +821 -713
  189. package/dist-engine-src/src/transaction/context.rs +705 -600
  190. package/dist-engine-src/src/transaction/mod.rs +13 -2
  191. package/dist-engine-src/src/transaction/normalization.rs +63 -76
  192. package/dist-engine-src/src/transaction/prep.rs +13 -13
  193. package/dist-engine-src/src/transaction/schema_resolver.rs +19 -5
  194. package/dist-engine-src/src/transaction/staging.rs +228 -434
  195. package/dist-engine-src/src/transaction/types.rs +41 -98
  196. package/dist-engine-src/src/transaction/validation.rs +382 -446
  197. package/dist-engine-src/src/untracked_state/codec.rs +337 -29
  198. package/dist-engine-src/src/untracked_state/context.rs +7 -7
  199. package/dist-engine-src/src/untracked_state/materialization.rs +2 -2
  200. package/dist-engine-src/src/untracked_state/mod.rs +1 -1
  201. package/dist-engine-src/src/untracked_state/storage.rs +659 -157
  202. package/dist-engine-src/src/untracked_state/types.rs +21 -21
  203. package/package.json +71 -68
  204. package/dist-engine-src/src/backend/kv.rs +0 -358
  205. package/dist-engine-src/src/backend/testing.rs +0 -658
  206. package/dist-engine-src/src/commit_store/codec.rs +0 -887
  207. package/dist-engine-src/src/commit_store/context.rs +0 -944
  208. package/dist-engine-src/src/commit_store/materialization.rs +0 -84
  209. package/dist-engine-src/src/commit_store/mod.rs +0 -16
  210. package/dist-engine-src/src/commit_store/storage.rs +0 -600
  211. package/dist-engine-src/src/commit_store/types.rs +0 -215
  212. package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +0 -34
  213. package/dist-engine-src/src/schema/builtin/lix_version_ref.json +0 -48
  214. package/dist-engine-src/src/session/create_version.rs +0 -88
  215. package/dist-engine-src/src/session/merge/apply.rs +0 -23
  216. package/dist-engine-src/src/session/optimization9_sql2_bench.rs +0 -100
  217. package/dist-engine-src/src/session/switch_version.rs +0 -110
  218. package/dist-engine-src/src/sql2/entity_provider.rs +0 -3211
  219. package/dist-engine-src/src/sql2/execute.rs +0 -3533
  220. package/dist-engine-src/src/sql2/public_bind/assignment.rs +0 -46
  221. package/dist-engine-src/src/sql2/public_bind/capability.rs +0 -41
  222. package/dist-engine-src/src/sql2/public_bind/dml.rs +0 -172
  223. package/dist-engine-src/src/sql2/public_bind/mod.rs +0 -26
  224. package/dist-engine-src/src/sql2/public_bind/table.rs +0 -168
  225. package/dist-engine-src/src/sql2/version_scope.rs +0 -394
  226. package/dist-engine-src/src/storage/types.rs +0 -501
  227. package/dist-engine-src/src/tracked_state/by_file_index.rs +0 -98
  228. package/dist-engine-src/src/tracked_state/materializer.rs +0 -488
  229. package/dist-engine-src/src/transaction/live_state_overlay.rs +0 -35
  230. package/dist-engine-src/src/version/lifecycle.rs +0 -221
  231. package/dist-engine-src/src/version/mod.rs +0 -13
  232. package/dist-engine-src/src/version/refs.rs +0 -330
  233. package/dist-engine-src/src/version/stage_rows.rs +0 -67
  234. package/dist-engine-src/src/version/types.rs +0 -21
@@ -18,38 +18,54 @@ use datafusion::physical_plan::{
18
18
  };
19
19
  use futures_util::stream;
20
20
 
21
- use crate::commit_store::ChangeScanRequest;
21
+ use crate::changelog::{
22
+ ChangeRecord, ChangeScanRequest, ChangelogContext, ChangelogReader, CommitLoadEntry,
23
+ CommitProjection, CommitScanRequest,
24
+ };
22
25
  use crate::serialize_row_metadata;
23
26
  use crate::LixError;
24
27
 
25
- use super::record_batch::record_batch_with_row_count;
26
- use super::result_metadata::json_field;
27
- use super::SqlCommitStoreQuerySource;
28
- use crate::commit_store::{materialize_change, MaterializedChange};
28
+ use crate::sql2::change_materialization::{
29
+ materialize_changelog_change_record, materialize_commit_graph_change, MaterializedChange,
30
+ };
31
+ use crate::sql2::record_batch::record_batch_with_row_count;
32
+ use crate::sql2::result_metadata::json_field;
33
+ use crate::sql2::SqlChangelogQuerySource;
34
+ use crate::storage::StorageRead;
29
35
 
30
- pub(crate) async fn register_lix_change_provider(
36
+ pub(super) async fn register_lix_change_read_provider<S>(
31
37
  session: &datafusion::prelude::SessionContext,
32
- query_source: SqlCommitStoreQuerySource,
33
- ) -> Result<(), LixError> {
38
+ surface_name: &str,
39
+ query_source: SqlChangelogQuerySource<S>,
40
+ ) -> Result<(), LixError>
41
+ where
42
+ S: StorageRead + Clone + Send + Sync + 'static,
43
+ {
34
44
  session
35
- .register_table("lix_change", Arc::new(LixChangeProvider::new(query_source)))
45
+ .register_table(surface_name, Arc::new(LixChangeProvider::new(query_source)))
36
46
  .map_err(datafusion_error_to_lix_error)?;
37
47
  Ok(())
38
48
  }
39
49
 
40
- struct LixChangeProvider {
50
+ /// SQL provider for `lix_change`.
51
+ ///
52
+ /// `lix_change` is the unscoped durable change surface: it scans direct
53
+ /// `changelog.change` records and unions derived `lix_commit` changes from
54
+ /// `changelog.commit`. It does not prove branch reachability. History
55
+ /// providers are the reachability-aware SQL surfaces.
56
+ struct LixChangeProvider<S> {
41
57
  schema: SchemaRef,
42
- query_source: SqlCommitStoreQuerySource,
58
+ query_source: SqlChangelogQuerySource<S>,
43
59
  }
44
60
 
45
- impl std::fmt::Debug for LixChangeProvider {
61
+ impl<S> std::fmt::Debug for LixChangeProvider<S> {
46
62
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47
63
  f.debug_struct("LixChangeProvider").finish()
48
64
  }
49
65
  }
50
66
 
51
- impl LixChangeProvider {
52
- fn new(query_source: SqlCommitStoreQuerySource) -> Self {
67
+ impl<S> LixChangeProvider<S> {
68
+ fn new(query_source: SqlChangelogQuerySource<S>) -> Self {
53
69
  Self {
54
70
  schema: lix_change_schema(),
55
71
  query_source,
@@ -58,7 +74,10 @@ impl LixChangeProvider {
58
74
  }
59
75
 
60
76
  #[async_trait]
61
- impl TableProvider for LixChangeProvider {
77
+ impl<S> TableProvider for LixChangeProvider<S>
78
+ where
79
+ S: StorageRead + Clone + Send + Sync + 'static,
80
+ {
62
81
  fn as_any(&self) -> &dyn Any {
63
82
  self
64
83
  }
@@ -85,35 +104,36 @@ impl TableProvider for LixChangeProvider {
85
104
  &self,
86
105
  _state: &dyn Session,
87
106
  projection: Option<&Vec<usize>>,
88
- _filters: &[Expr],
107
+ filters: &[Expr],
89
108
  limit: Option<usize>,
90
109
  ) -> Result<Arc<dyn ExecutionPlan>> {
110
+ let pushed_limit = if filters.is_empty() { limit } else { None };
91
111
  Ok(Arc::new(LixChangeScanExec::new(
92
112
  self.query_source.clone(),
93
113
  projected_schema(&self.schema, projection),
94
114
  projection.cloned(),
95
- limit,
115
+ pushed_limit,
96
116
  )))
97
117
  }
98
118
  }
99
119
 
100
- struct LixChangeScanExec {
101
- query_source: SqlCommitStoreQuerySource,
120
+ struct LixChangeScanExec<S> {
121
+ query_source: SqlChangelogQuerySource<S>,
102
122
  schema: SchemaRef,
103
123
  projection: Option<Vec<usize>>,
104
124
  limit: Option<usize>,
105
125
  properties: Arc<PlanProperties>,
106
126
  }
107
127
 
108
- impl std::fmt::Debug for LixChangeScanExec {
128
+ impl<S> std::fmt::Debug for LixChangeScanExec<S> {
109
129
  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
110
130
  f.debug_struct("LixChangeScanExec").finish()
111
131
  }
112
132
  }
113
133
 
114
- impl LixChangeScanExec {
134
+ impl<S> LixChangeScanExec<S> {
115
135
  fn new(
116
- query_source: SqlCommitStoreQuerySource,
136
+ query_source: SqlChangelogQuerySource<S>,
117
137
  schema: SchemaRef,
118
138
  projection: Option<Vec<usize>>,
119
139
  limit: Option<usize>,
@@ -134,7 +154,7 @@ impl LixChangeScanExec {
134
154
  }
135
155
  }
136
156
 
137
- impl DisplayAs for LixChangeScanExec {
157
+ impl<S> DisplayAs for LixChangeScanExec<S> {
138
158
  fn fmt_as(&self, t: DisplayFormatType, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
139
159
  match t {
140
160
  DisplayFormatType::Default | DisplayFormatType::Verbose => {
@@ -145,7 +165,10 @@ impl DisplayAs for LixChangeScanExec {
145
165
  }
146
166
  }
147
167
 
148
- impl ExecutionPlan for LixChangeScanExec {
168
+ impl<S> ExecutionPlan for LixChangeScanExec<S>
169
+ where
170
+ S: StorageRead + Clone + Send + Sync + 'static,
171
+ {
149
172
  fn name(&self) -> &str {
150
173
  "LixChangeScanExec"
151
174
  }
@@ -191,18 +214,23 @@ impl ExecutionPlan for LixChangeScanExec {
191
214
  let schema = Arc::clone(&self.schema);
192
215
  let stream = stream::once(async move {
193
216
  let mut json_reader = query_source.json_reader;
194
- let canonical_changes = query_source
195
- .commit_store_reader
196
- .scan_changes(&ChangeScanRequest { limit })
217
+ let canonical_changes = scan_changelog_changes(query_source.store, limit)
197
218
  .await
198
219
  .map_err(lix_error_to_datafusion_error)?;
199
220
  let mut changes = Vec::with_capacity(canonical_changes.len());
200
221
  for change in canonical_changes {
201
- changes.push(
202
- materialize_change(&mut json_reader, change)
203
- .await
204
- .map_err(lix_error_to_datafusion_error)?,
205
- );
222
+ match change {
223
+ LixChangeRow::Direct(change) => changes.push(
224
+ materialize_changelog_change_record(&mut json_reader, change)
225
+ .await
226
+ .map_err(lix_error_to_datafusion_error)?,
227
+ ),
228
+ LixChangeRow::DerivedCommit(change) => changes.push(
229
+ materialize_commit_graph_change(&mut json_reader, change)
230
+ .await
231
+ .map_err(lix_error_to_datafusion_error)?,
232
+ ),
233
+ }
206
234
  }
207
235
  change_record_batch(&projection, &changes)
208
236
  });
@@ -210,10 +238,96 @@ impl ExecutionPlan for LixChangeScanExec {
210
238
  }
211
239
  }
212
240
 
241
+ async fn scan_changelog_changes<S>(
242
+ store: S,
243
+ limit: Option<usize>,
244
+ ) -> Result<Vec<LixChangeRow>, LixError>
245
+ where
246
+ S: StorageRead + Clone + Send + Sync + 'static,
247
+ {
248
+ let mut reader = ChangelogContext::new().reader(store);
249
+ let mut changes = Vec::<LixChangeRow>::new();
250
+ let mut start_after = None::<String>;
251
+ loop {
252
+ let scan = reader
253
+ .scan_changes(ChangeScanRequest {
254
+ start_after: start_after.as_deref(),
255
+ limit: Some(1024),
256
+ })
257
+ .await?;
258
+ changes.extend(scan.entries.into_iter().map(LixChangeRow::Direct));
259
+ let Some(next) = scan.next_start_after else {
260
+ break;
261
+ };
262
+ start_after = Some(next);
263
+ }
264
+ let mut start_after = None::<String>;
265
+ loop {
266
+ let scan = reader
267
+ .scan_commits(CommitScanRequest {
268
+ start_after: start_after.as_deref(),
269
+ limit: Some(1024),
270
+ projection: CommitProjection::Record,
271
+ })
272
+ .await?;
273
+ for entry in scan.entries {
274
+ let CommitLoadEntry::Record(commit) = entry else {
275
+ continue;
276
+ };
277
+ changes.push(LixChangeRow::DerivedCommit(commit_record_canonical_change(
278
+ &commit,
279
+ )));
280
+ }
281
+ let Some(next) = scan.next_start_after else {
282
+ break;
283
+ };
284
+ start_after = Some(next);
285
+ }
286
+ changes.sort_by(|left, right| left.change_id().cmp(right.change_id()));
287
+ if let Some(limit) = limit {
288
+ changes.truncate(limit);
289
+ }
290
+ Ok(changes)
291
+ }
292
+
293
+ enum LixChangeRow {
294
+ Direct(ChangeRecord),
295
+ DerivedCommit(crate::commit_graph::CommitGraphChange),
296
+ }
297
+
298
+ impl LixChangeRow {
299
+ fn change_id(&self) -> &str {
300
+ match self {
301
+ Self::Direct(change) => &change.change_id,
302
+ Self::DerivedCommit(change) => &change.id,
303
+ }
304
+ }
305
+ }
306
+
307
+ fn commit_record_canonical_change(
308
+ commit: &crate::changelog::CommitRecord,
309
+ ) -> crate::commit_graph::CommitGraphChange {
310
+ let snapshot_content = serde_json::to_string(&serde_json::json!({
311
+ "id": commit.commit_id,
312
+ }))
313
+ .expect("lix_commit snapshot serialization should not fail");
314
+ crate::commit_graph::CommitGraphChange {
315
+ id: commit.change_id.clone(),
316
+ entity_pk: crate::entity_pk::EntityPk::single(&commit.commit_id),
317
+ schema_key: "lix_commit".to_string(),
318
+ file_id: None,
319
+ snapshot_ref: Some(crate::json_store::JsonRef::for_content(
320
+ snapshot_content.as_bytes(),
321
+ )),
322
+ metadata_ref: None,
323
+ created_at: commit.created_at.clone(),
324
+ }
325
+ }
326
+
213
327
  #[derive(Debug, Clone, Copy)]
214
328
  enum ChangeColumn {
215
329
  Id,
216
- EntityId,
330
+ EntityPk,
217
331
  SchemaKey,
218
332
  FileId,
219
333
  Metadata,
@@ -221,10 +335,10 @@ enum ChangeColumn {
221
335
  SnapshotContent,
222
336
  }
223
337
 
224
- fn lix_change_schema() -> SchemaRef {
338
+ pub(super) fn lix_change_schema() -> SchemaRef {
225
339
  Arc::new(Schema::new(vec![
226
340
  Field::new("id", DataType::Utf8, false),
227
- json_field("entity_id", false),
341
+ json_field("entity_pk", false),
228
342
  Field::new("schema_key", DataType::Utf8, false),
229
343
  Field::new("file_id", DataType::Utf8, true),
230
344
  json_field("metadata", true),
@@ -236,7 +350,7 @@ fn lix_change_schema() -> SchemaRef {
236
350
  fn change_projection_for_scan(projection: Option<&Vec<usize>>) -> Vec<ChangeColumn> {
237
351
  let all_columns = vec![
238
352
  ChangeColumn::Id,
239
- ChangeColumn::EntityId,
353
+ ChangeColumn::EntityPk,
240
354
  ChangeColumn::SchemaKey,
241
355
  ChangeColumn::FileId,
242
356
  ChangeColumn::Metadata,
@@ -266,14 +380,14 @@ fn change_record_batch(
266
380
  .iter()
267
381
  .map(|column| match column {
268
382
  ChangeColumn::Id => string_array(changes.iter().map(|row| Some(row.id.as_str()))),
269
- ChangeColumn::EntityId => Arc::new(StringArray::from(
383
+ ChangeColumn::EntityPk => Arc::new(StringArray::from(
270
384
  changes
271
385
  .iter()
272
386
  .map(|row| {
273
387
  Some(
274
- row.entity_id
388
+ row.entity_pk
275
389
  .as_json_array_text()
276
- .expect("canonical change entity identity should project"),
390
+ .expect("canonical change entity primary key should project"),
277
391
  )
278
392
  })
279
393
  .collect::<Vec<_>>(),
@@ -307,7 +421,7 @@ fn change_schema(projection: &[ChangeColumn]) -> SchemaRef {
307
421
  .iter()
308
422
  .map(|column| match column {
309
423
  ChangeColumn::Id => Field::new("id", DataType::Utf8, false),
310
- ChangeColumn::EntityId => json_field("entity_id", false),
424
+ ChangeColumn::EntityPk => json_field("entity_pk", false),
311
425
  ChangeColumn::SchemaKey => Field::new("schema_key", DataType::Utf8, false),
312
426
  ChangeColumn::FileId => Field::new("file_id", DataType::Utf8, true),
313
427
  ChangeColumn::Metadata => json_field("metadata", true),
@@ -323,9 +437,9 @@ fn string_array<'a>(values: impl Iterator<Item = Option<&'a str>>) -> ArrayRef {
323
437
  }
324
438
 
325
439
  fn datafusion_error_to_lix_error(error: DataFusionError) -> LixError {
326
- super::error::datafusion_error_to_lix_error(error)
440
+ crate::sql2::error::datafusion_error_to_lix_error(error)
327
441
  }
328
442
 
329
443
  fn lix_error_to_datafusion_error(error: LixError) -> DataFusionError {
330
- super::error::lix_error_to_datafusion_error(error)
444
+ crate::sql2::error::lix_error_to_datafusion_error(error)
331
445
  }