@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
@@ -0,0 +1,508 @@
1
+ use std::sync::Arc;
2
+
3
+ use datafusion::prelude::SessionContext;
4
+
5
+ use crate::LixError;
6
+
7
+ mod branch;
8
+ mod change;
9
+ mod directory;
10
+ mod directory_history;
11
+ mod entity;
12
+ mod entity_history;
13
+ mod file;
14
+ mod file_history;
15
+ mod history;
16
+ mod lix_state;
17
+
18
+ use crate::sql2::catalog::{PublicCatalog, PublicSurfaceKind};
19
+ use crate::sql2::session::SqlWriteSessionOptions;
20
+ use crate::sql2::{SqlExecutionContext, SqlWriteContext};
21
+
22
+ pub(crate) async fn register_read<C>(session: &SessionContext, ctx: &C) -> Result<(), LixError>
23
+ where
24
+ C: SqlExecutionContext + ?Sized,
25
+ {
26
+ let branch_ref = ctx.branch_ref();
27
+ let history_query_source = ctx.history_query_source();
28
+ let changelog_query_source = ctx.changelog_query_source();
29
+ let catalog = PublicCatalog::from_visible_schemas(&ctx.list_visible_schemas()?)?;
30
+ for surface in catalog.surfaces() {
31
+ match &surface.kind {
32
+ PublicSurfaceKind::LixState => {
33
+ lix_state::register_lix_state_active_provider(
34
+ session,
35
+ &surface.name,
36
+ ctx.active_branch_id(),
37
+ ctx.live_state(),
38
+ Arc::clone(&branch_ref),
39
+ )
40
+ .await?;
41
+ }
42
+ PublicSurfaceKind::LixStateByBranch => {
43
+ lix_state::register_lix_state_by_branch_provider(
44
+ session,
45
+ &surface.name,
46
+ ctx.live_state(),
47
+ Arc::clone(&branch_ref),
48
+ )
49
+ .await?;
50
+ }
51
+ PublicSurfaceKind::Branch => {
52
+ branch::register_lix_branch_read_provider(
53
+ session,
54
+ &surface.name,
55
+ ctx.live_state(),
56
+ Arc::clone(&branch_ref),
57
+ )
58
+ .await?;
59
+ }
60
+ PublicSurfaceKind::Change => {
61
+ change::register_lix_change_read_provider(
62
+ session,
63
+ &surface.name,
64
+ changelog_query_source.clone(),
65
+ )
66
+ .await?;
67
+ }
68
+ PublicSurfaceKind::History => {
69
+ history::register_history_provider(
70
+ session,
71
+ &surface.name,
72
+ ctx.commit_graph(),
73
+ history_query_source.clone(),
74
+ )
75
+ .await?;
76
+ }
77
+ PublicSurfaceKind::File => {
78
+ file::register_lix_file_active_provider(
79
+ session,
80
+ &surface.name,
81
+ ctx.active_branch_id(),
82
+ ctx.live_state(),
83
+ Arc::clone(&branch_ref),
84
+ ctx.blob_reader(),
85
+ ctx.functions(),
86
+ )
87
+ .await?;
88
+ }
89
+ PublicSurfaceKind::FileByBranch => {
90
+ file::register_lix_file_by_branch_provider(
91
+ session,
92
+ &surface.name,
93
+ ctx.live_state(),
94
+ Arc::clone(&branch_ref),
95
+ ctx.blob_reader(),
96
+ ctx.functions(),
97
+ )
98
+ .await?;
99
+ }
100
+ PublicSurfaceKind::FileHistory => {
101
+ file_history::register_lix_file_history_surface(
102
+ session,
103
+ &surface.name,
104
+ ctx.commit_graph(),
105
+ history_query_source.clone(),
106
+ ctx.blob_reader(),
107
+ )
108
+ .await?;
109
+ }
110
+ PublicSurfaceKind::Directory => {
111
+ directory::register_lix_directory_active_provider(
112
+ session,
113
+ &surface.name,
114
+ ctx.active_branch_id(),
115
+ ctx.live_state(),
116
+ Arc::clone(&branch_ref),
117
+ ctx.functions(),
118
+ )
119
+ .await?;
120
+ }
121
+ PublicSurfaceKind::DirectoryByBranch => {
122
+ directory::register_lix_directory_by_branch_provider(
123
+ session,
124
+ &surface.name,
125
+ ctx.live_state(),
126
+ Arc::clone(&branch_ref),
127
+ ctx.functions(),
128
+ )
129
+ .await?;
130
+ }
131
+ PublicSurfaceKind::DirectoryHistory => {
132
+ directory_history::register_lix_directory_history_surface(
133
+ session,
134
+ &surface.name,
135
+ ctx.commit_graph(),
136
+ history_query_source.clone(),
137
+ )
138
+ .await?;
139
+ }
140
+ PublicSurfaceKind::EntityBase { .. }
141
+ | PublicSurfaceKind::EntityByBranch { .. }
142
+ | PublicSurfaceKind::EntityHistory { .. } => {}
143
+ }
144
+ }
145
+ entity::register_entity_providers(
146
+ session,
147
+ ctx.active_branch_id(),
148
+ ctx.live_state(),
149
+ Arc::clone(&branch_ref),
150
+ Arc::new(tokio::sync::Mutex::new(ctx.commit_graph())),
151
+ history_query_source,
152
+ &catalog,
153
+ )
154
+ .await?;
155
+
156
+ Ok(())
157
+ }
158
+
159
+ pub(crate) async fn register_write(
160
+ session: &SessionContext,
161
+ write_ctx: SqlWriteContext,
162
+ options: SqlWriteSessionOptions,
163
+ ) -> Result<(), LixError> {
164
+ let catalog = PublicCatalog::from_visible_schemas(&write_ctx.list_visible_schemas()?)?;
165
+ for surface in catalog.surfaces() {
166
+ match &surface.kind {
167
+ PublicSurfaceKind::LixState => {
168
+ replace_registered_table(session, &surface.name)?;
169
+ lix_state::register_lix_state_active_write_provider(
170
+ session,
171
+ &surface.name,
172
+ write_ctx.clone(),
173
+ )
174
+ .await?;
175
+ }
176
+ PublicSurfaceKind::LixStateByBranch => {
177
+ replace_registered_table(session, &surface.name)?;
178
+ lix_state::register_lix_state_by_branch_write_provider(
179
+ session,
180
+ &surface.name,
181
+ write_ctx.clone(),
182
+ )
183
+ .await?;
184
+ }
185
+ PublicSurfaceKind::Branch => {
186
+ replace_registered_table(session, &surface.name)?;
187
+ branch::register_write_provider(session, &surface.name, write_ctx.clone()).await?;
188
+ }
189
+ PublicSurfaceKind::File => {
190
+ replace_registered_table(session, &surface.name)?;
191
+ file::register_active_write_provider(
192
+ session,
193
+ &surface.name,
194
+ write_ctx.clone(),
195
+ options.clone(),
196
+ )
197
+ .await?;
198
+ }
199
+ PublicSurfaceKind::FileByBranch => {
200
+ replace_registered_table(session, &surface.name)?;
201
+ file::register_by_branch_write_provider(
202
+ session,
203
+ &surface.name,
204
+ write_ctx.clone(),
205
+ options.clone(),
206
+ )
207
+ .await?;
208
+ }
209
+ PublicSurfaceKind::Directory => {
210
+ replace_registered_table(session, &surface.name)?;
211
+ directory::register_active_write_provider(
212
+ session,
213
+ &surface.name,
214
+ write_ctx.clone(),
215
+ )
216
+ .await?;
217
+ }
218
+ PublicSurfaceKind::DirectoryByBranch => {
219
+ replace_registered_table(session, &surface.name)?;
220
+ directory::register_by_branch_write_provider(
221
+ session,
222
+ &surface.name,
223
+ write_ctx.clone(),
224
+ )
225
+ .await?;
226
+ }
227
+ PublicSurfaceKind::Change
228
+ | PublicSurfaceKind::History
229
+ | PublicSurfaceKind::FileHistory
230
+ | PublicSurfaceKind::DirectoryHistory => {}
231
+ PublicSurfaceKind::EntityBase { .. }
232
+ | PublicSurfaceKind::EntityByBranch { .. }
233
+ | PublicSurfaceKind::EntityHistory { .. } => {}
234
+ }
235
+ }
236
+ for surface in catalog.surfaces() {
237
+ if matches!(
238
+ surface.kind,
239
+ PublicSurfaceKind::EntityBase { .. } | PublicSurfaceKind::EntityByBranch { .. }
240
+ ) {
241
+ replace_registered_table(session, &surface.name)?;
242
+ }
243
+ }
244
+ entity::register_entity_write_providers(session, write_ctx.clone(), &catalog).await?;
245
+ Ok(())
246
+ }
247
+
248
+ fn replace_registered_table(session: &SessionContext, name: &str) -> Result<(), LixError> {
249
+ match session.deregister_table(name) {
250
+ Ok(_) => Ok(()),
251
+ Err(error) if error.to_string().contains("not found") => Ok(()),
252
+ Err(error) => Err(LixError::new(
253
+ LixError::CODE_UNKNOWN,
254
+ format!("sql2 DataFusion error: {error}"),
255
+ )),
256
+ }
257
+ }
258
+
259
+ #[cfg(test)]
260
+ mod tests {
261
+ use std::sync::Arc;
262
+
263
+ use async_trait::async_trait;
264
+ use serde_json::json;
265
+
266
+ use datafusion::arrow::datatypes::SchemaRef;
267
+ use datafusion::prelude::SessionContext;
268
+
269
+ use crate::branch::{BranchHead, BranchRefReader};
270
+ use crate::commit_graph::{
271
+ CommitGraphChangeHistoryEntry, CommitGraphChangeHistoryRequest, CommitGraphCommit,
272
+ CommitGraphReader, ReachableCommitGraphCommit,
273
+ };
274
+ use crate::json_store::JsonStoreContext;
275
+ use crate::live_state::{
276
+ LiveStateReader, LiveStateRowRequest, LiveStateScanRequest, MaterializedLiveStateRow,
277
+ };
278
+ use crate::sql2::catalog::{derive_entity_surface_spec_from_schema, PublicCatalog};
279
+ use crate::sql2::HistoryQuerySource;
280
+ use crate::storage::{
281
+ InMemoryStorageBackend, InMemoryStorageRead, StorageContext, StorageReadOptions,
282
+ StorageReadScope,
283
+ };
284
+ use crate::LixError;
285
+
286
+ use super::{
287
+ branch, change, directory, directory_history, entity, file, file_history, history,
288
+ lix_state,
289
+ };
290
+
291
+ #[test]
292
+ fn provider_history_schemas_match_catalog_contract_order() {
293
+ let catalog = PublicCatalog::from_visible_schemas(&[]).expect("catalog should build");
294
+
295
+ assert_surface_schema_matches_provider_schema(
296
+ &catalog,
297
+ "lix_state",
298
+ lix_state::lix_state_schema(),
299
+ );
300
+ assert_surface_schema_matches_provider_schema(
301
+ &catalog,
302
+ "lix_state_by_branch",
303
+ lix_state::lix_state_by_branch_schema(),
304
+ );
305
+ assert_surface_schema_matches_provider_schema(
306
+ &catalog,
307
+ "lix_file",
308
+ file::lix_file_schema(),
309
+ );
310
+ assert_surface_schema_matches_provider_schema(
311
+ &catalog,
312
+ "lix_file_by_branch",
313
+ file::lix_file_by_branch_schema(),
314
+ );
315
+ assert_surface_schema_matches_provider_schema(
316
+ &catalog,
317
+ "lix_directory",
318
+ directory::lix_directory_schema(),
319
+ );
320
+ assert_surface_schema_matches_provider_schema(
321
+ &catalog,
322
+ "lix_directory_by_branch",
323
+ directory::lix_directory_by_branch_schema(),
324
+ );
325
+ assert_surface_schema_matches_provider_schema(
326
+ &catalog,
327
+ "lix_branch",
328
+ branch::lix_branch_schema(),
329
+ );
330
+ assert_surface_schema_matches_provider_schema(
331
+ &catalog,
332
+ "lix_change",
333
+ change::lix_change_schema(),
334
+ );
335
+ assert_surface_schema_matches_provider_schema(
336
+ &catalog,
337
+ "lix_state_history",
338
+ history::lix_state_history_schema(),
339
+ );
340
+ assert_surface_schema_matches_provider_schema(
341
+ &catalog,
342
+ "lix_file_history",
343
+ file_history::lix_file_history_schema(),
344
+ );
345
+ assert_surface_schema_matches_provider_schema(
346
+ &catalog,
347
+ "lix_directory_history",
348
+ directory_history::lix_directory_history_schema(),
349
+ );
350
+ }
351
+
352
+ #[tokio::test]
353
+ async fn provider_entity_schemas_match_catalog_contract_order() {
354
+ let schema = json!({
355
+ "x-lix-key": "phase8_entity",
356
+ "x-lix-primary-key": ["/id"],
357
+ "type": "object",
358
+ "properties": {
359
+ "id": { "type": "string" },
360
+ "count": { "type": "integer" },
361
+ "body": { "type": "object" }
362
+ }
363
+ });
364
+ let catalog =
365
+ PublicCatalog::from_visible_schemas(&[schema.clone()]).expect("catalog should build");
366
+ let _spec = derive_entity_surface_spec_from_schema(&schema).expect("schema should derive");
367
+ let session = SessionContext::new();
368
+ entity::register_entity_providers(
369
+ &session,
370
+ "branch-a",
371
+ Arc::new(EmptyLiveStateReader),
372
+ Arc::new(EmptyBranchRefReader),
373
+ Arc::new(tokio::sync::Mutex::new(Box::new(EmptyCommitGraphReader))),
374
+ empty_history_query_source().await,
375
+ &catalog,
376
+ )
377
+ .await
378
+ .expect("entity providers should register");
379
+
380
+ assert_registered_table_schema_matches_catalog(&session, &catalog, "phase8_entity").await;
381
+ assert_registered_table_schema_matches_catalog(
382
+ &session,
383
+ &catalog,
384
+ "phase8_entity_by_branch",
385
+ )
386
+ .await;
387
+ assert_registered_table_schema_matches_catalog(&session, &catalog, "phase8_entity_history")
388
+ .await;
389
+ }
390
+
391
+ async fn assert_registered_table_schema_matches_catalog(
392
+ session: &SessionContext,
393
+ catalog: &PublicCatalog,
394
+ surface_name: &str,
395
+ ) {
396
+ let provider = session
397
+ .table_provider(surface_name)
398
+ .await
399
+ .unwrap_or_else(|error| panic!("{surface_name} provider should load: {error}"));
400
+ assert_surface_schema_matches_provider_schema(catalog, surface_name, provider.schema());
401
+ }
402
+
403
+ fn assert_surface_schema_matches_provider_schema(
404
+ catalog: &PublicCatalog,
405
+ surface_name: &str,
406
+ provider_schema: SchemaRef,
407
+ ) {
408
+ let surface = catalog
409
+ .surface(surface_name)
410
+ .unwrap_or_else(|| panic!("{surface_name} should be in catalog"));
411
+ let catalog_column_names = surface
412
+ .columns
413
+ .iter()
414
+ .map(|column| column.name.as_str())
415
+ .collect::<Vec<_>>();
416
+ let provider_field_names = provider_schema
417
+ .fields()
418
+ .iter()
419
+ .map(|field| field.name().as_str())
420
+ .collect::<Vec<_>>();
421
+ assert_eq!(
422
+ catalog_column_names, provider_field_names,
423
+ "{surface_name} column order"
424
+ );
425
+
426
+ let catalog_schema = catalog
427
+ .surface_schema(surface_name)
428
+ .unwrap_or_else(|| panic!("{surface_name} should be in catalog"));
429
+ assert_eq!(
430
+ catalog_schema.fields(),
431
+ provider_schema.fields(),
432
+ "{surface_name}"
433
+ );
434
+ }
435
+
436
+ async fn empty_history_query_source(
437
+ ) -> crate::sql2::SqlHistoryQuerySource<StorageReadScope<InMemoryStorageRead>> {
438
+ let storage = StorageContext::new(InMemoryStorageBackend::new());
439
+ let read_scope = storage
440
+ .begin_read(StorageReadOptions::default())
441
+ .expect("read should open");
442
+ HistoryQuerySource {
443
+ json_reader: JsonStoreContext::new().reader(read_scope.store()),
444
+ }
445
+ }
446
+
447
+ struct EmptyLiveStateReader;
448
+
449
+ #[async_trait]
450
+ impl LiveStateReader for EmptyLiveStateReader {
451
+ async fn scan_rows(
452
+ &self,
453
+ _request: &LiveStateScanRequest,
454
+ ) -> Result<Vec<MaterializedLiveStateRow>, LixError> {
455
+ Ok(Vec::new())
456
+ }
457
+
458
+ async fn load_row(
459
+ &self,
460
+ _request: &LiveStateRowRequest,
461
+ ) -> Result<Option<MaterializedLiveStateRow>, LixError> {
462
+ Ok(None)
463
+ }
464
+ }
465
+
466
+ struct EmptyBranchRefReader;
467
+
468
+ #[async_trait]
469
+ impl BranchRefReader for EmptyBranchRefReader {
470
+ async fn load_head(&self, branch_id: &str) -> Result<Option<BranchHead>, LixError> {
471
+ Ok(Some(BranchHead {
472
+ branch_id: branch_id.to_string(),
473
+ commit_id: format!("commit-{branch_id}"),
474
+ }))
475
+ }
476
+
477
+ async fn scan_heads(&self) -> Result<Vec<BranchHead>, LixError> {
478
+ Ok(Vec::new())
479
+ }
480
+ }
481
+
482
+ struct EmptyCommitGraphReader;
483
+
484
+ #[async_trait]
485
+ impl CommitGraphReader for EmptyCommitGraphReader {
486
+ async fn load_commit(
487
+ &mut self,
488
+ _commit_id: &str,
489
+ ) -> Result<Option<CommitGraphCommit>, LixError> {
490
+ Ok(None)
491
+ }
492
+
493
+ async fn reachable_commits(
494
+ &mut self,
495
+ _head_commit_id: &str,
496
+ ) -> Result<Vec<ReachableCommitGraphCommit>, LixError> {
497
+ Ok(Vec::new())
498
+ }
499
+
500
+ async fn change_history_from_commit(
501
+ &mut self,
502
+ _start_commit_id: &str,
503
+ _request: &CommitGraphChangeHistoryRequest,
504
+ ) -> Result<Vec<CommitGraphChangeHistoryEntry>, LixError> {
505
+ Ok(Vec::new())
506
+ }
507
+ }
508
+ }
@@ -44,8 +44,8 @@ fn read_only_error(action: &str, schema_key: &str, message: &'static str) -> Dat
44
44
 
45
45
  fn read_only_schema_message(schema_key: &str) -> Option<&'static str> {
46
46
  match schema_key {
47
- "lix_version_descriptor" | "lix_version_ref" => {
48
- Some("Use the writable lix_version surface to create, update, or delete versions.")
47
+ "lix_branch_descriptor" | "lix_branch_ref" => {
48
+ Some("Use the writable lix_branch surface to create, update, or delete branches.")
49
49
  }
50
50
  "lix_file_descriptor" => {
51
51
  Some("Use the writable lix_file surface to create, update, or delete files.")
@@ -1,118 +1,69 @@
1
- use std::sync::Arc;
2
-
3
1
  use datafusion::prelude::{SessionConfig, SessionContext};
2
+ use std::collections::BTreeSet;
4
3
 
5
4
  use crate::LixError;
6
5
 
7
- use super::change_provider::register_lix_change_provider;
8
- use super::directory_history_provider::register_lix_directory_history_provider;
9
- use super::directory_provider::{
10
- register_lix_directory_providers, register_lix_directory_write_providers,
11
- };
12
- use super::entity_provider::{register_entity_providers, register_entity_write_providers};
13
- use super::file_history_provider::register_lix_file_history_provider;
14
- use super::file_provider::{register_lix_file_providers, register_lix_file_write_providers};
15
- use super::history_provider::register_history_providers;
16
- use super::lix_state_provider::{register_lix_state_providers, register_lix_state_write_providers};
6
+ use super::providers;
17
7
  use super::udfs::register_sql2_functions;
18
- use super::version_provider::{register_lix_version_provider, register_lix_version_write_provider};
19
8
  use super::{SqlExecutionContext, SqlWriteContext, SqlWriteExecutionContext};
20
9
 
21
- pub(crate) async fn build_read_session(
22
- ctx: &dyn SqlExecutionContext,
23
- ) -> Result<SessionContext, LixError> {
10
+ pub(crate) async fn build_read_session<C>(ctx: &C) -> Result<SessionContext, LixError>
11
+ where
12
+ C: SqlExecutionContext + ?Sized,
13
+ {
24
14
  let session = new_sql_session_context();
25
- let version_ref = ctx.version_ref();
26
- let active_version_commit_id = version_ref
27
- .load_head(ctx.active_version_id())
15
+ let branch_ref = ctx.branch_ref();
16
+ let active_branch_commit_id = branch_ref
17
+ .load_head(ctx.active_branch_id())
28
18
  .await?
29
19
  .map(|head| head.commit_id);
30
- register_sql2_functions(&session, ctx.functions(), active_version_commit_id);
31
- register_lix_state_providers(
32
- &session,
33
- ctx.active_version_id(),
34
- ctx.live_state(),
35
- Arc::clone(&version_ref),
36
- )
37
- .await?;
38
- register_lix_version_provider(&session, ctx.live_state(), Arc::clone(&version_ref)).await?;
39
- let commit_store_query_source = ctx.commit_store_query_source();
40
- register_lix_change_provider(&session, commit_store_query_source.clone()).await?;
41
- let state_history_commit_graph = ctx.commit_graph();
42
- register_history_providers(
43
- &session,
44
- state_history_commit_graph,
45
- commit_store_query_source.clone(),
46
- )
47
- .await?;
48
- let file_history_commit_graph = ctx.commit_graph();
49
- register_lix_file_history_provider(
50
- &session,
51
- file_history_commit_graph,
52
- commit_store_query_source.clone(),
53
- ctx.blob_reader(),
54
- )
55
- .await?;
56
- let directory_history_commit_graph = ctx.commit_graph();
57
- register_lix_directory_history_provider(
58
- &session,
59
- directory_history_commit_graph,
60
- commit_store_query_source.clone(),
61
- )
62
- .await?;
63
- let entity_commit_graph = Arc::new(tokio::sync::Mutex::new(ctx.commit_graph()));
64
- register_lix_directory_providers(
65
- &session,
66
- ctx.active_version_id(),
67
- ctx.live_state(),
68
- Arc::clone(&version_ref),
69
- ctx.functions(),
70
- )
71
- .await?;
72
- register_lix_file_providers(
73
- &session,
74
- ctx.active_version_id(),
75
- ctx.live_state(),
76
- Arc::clone(&version_ref),
77
- ctx.blob_reader(),
78
- ctx.functions(),
79
- )
80
- .await?;
81
- register_entity_providers(
82
- &session,
83
- ctx.active_version_id(),
84
- ctx.live_state(),
85
- Arc::clone(&version_ref),
86
- entity_commit_graph,
87
- commit_store_query_source,
88
- &ctx.list_visible_schemas()?,
89
- )
90
- .await?;
20
+ register_sql2_functions(&session, ctx.functions(), active_branch_commit_id);
21
+ providers::register_read(&session, ctx).await?;
22
+
23
+ Ok(session)
24
+ }
91
25
 
26
+ pub(crate) async fn build_transaction_read_session<C>(
27
+ read_ctx: &C,
28
+ write_ctx: &mut dyn SqlWriteExecutionContext,
29
+ ) -> Result<SessionContext, LixError>
30
+ where
31
+ C: SqlExecutionContext + ?Sized,
32
+ {
33
+ let session = build_read_session(read_ctx).await?;
34
+ let write_ctx = SqlWriteContext::new(write_ctx);
35
+ providers::register_write(&session, write_ctx, SqlWriteSessionOptions::default()).await?;
92
36
  Ok(session)
93
37
  }
94
38
 
95
- pub(crate) async fn build_write_session(
39
+ #[derive(Clone, Debug, Default)]
40
+ pub(crate) struct SqlWriteSessionOptions {
41
+ pub(crate) omitted_insert_columns: BTreeSet<String>,
42
+ }
43
+
44
+ pub(crate) async fn build_write_session_with_options(
96
45
  ctx: &mut dyn SqlWriteExecutionContext,
46
+ options: SqlWriteSessionOptions,
97
47
  ) -> Result<SessionContext, LixError> {
98
48
  let session = new_sql_session_context();
99
49
  let write_ctx = SqlWriteContext::new(ctx);
100
- let active_version_commit_id = write_ctx
101
- .load_version_head(&write_ctx.active_version_id())
102
- .await?;
103
- register_sql2_functions(&session, write_ctx.functions(), active_version_commit_id);
104
-
105
- register_lix_state_write_providers(&session, write_ctx.clone()).await?;
106
- register_lix_version_write_provider(&session, write_ctx.clone()).await?;
107
-
108
- register_lix_directory_write_providers(&session, write_ctx.clone()).await?;
109
- register_lix_file_write_providers(&session, write_ctx.clone()).await?;
110
- register_entity_write_providers(
50
+ let active_branch_id = write_ctx.active_branch_id();
51
+ let active_branch_commit_id = write_ctx
52
+ .load_branch_head(&active_branch_id)
53
+ .await?
54
+ .ok_or_else(|| {
55
+ LixError::branch_not_found(
56
+ active_branch_id.clone(),
57
+ "build SQL write session",
58
+ "active branch",
59
+ )
60
+ })?;
61
+ register_sql2_functions(
111
62
  &session,
112
- write_ctx.clone(),
113
- &write_ctx.list_visible_schemas()?,
114
- )
115
- .await?;
63
+ write_ctx.functions(),
64
+ Some(active_branch_commit_id),
65
+ );
66
+ providers::register_write(&session, write_ctx, options).await?;
116
67
 
117
68
  Ok(session)
118
69
  }
@@ -0,0 +1 @@
1
+ //! Storage-level write constraints for sql2 plans.
@@ -0,0 +1 @@
1
+ pub(crate) mod constraints;