@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
@@ -46,6 +46,7 @@ function initializeDatabase(db) {
46
46
  class BetterSqlite3Backend {
47
47
  #db;
48
48
  #registryKey;
49
+ #transactionMode = null;
49
50
  #closed = false;
50
51
  constructor(db, registryKey) {
51
52
  this.#db = db;
@@ -53,19 +54,28 @@ class BetterSqlite3Backend {
53
54
  }
54
55
  beginReadTransaction() {
55
56
  this.#ensureOpen();
56
- if (this.#db.inTransaction) {
57
- throw new Error("cannot open nested Lix backend transaction");
58
- }
59
- this.#db.exec("BEGIN DEFERRED");
60
- return new BetterSqlite3Transaction(this.#db);
57
+ return new BetterSqlite3Transaction(this.#db, {
58
+ ownsTransaction: false,
59
+ writable: false,
60
+ });
61
61
  }
62
62
  beginWriteTransaction() {
63
63
  this.#ensureOpen();
64
64
  if (this.#db.inTransaction) {
65
- throw new Error("cannot open nested Lix backend transaction");
65
+ return new BetterSqlite3Transaction(this.#db, {
66
+ ownsTransaction: false,
67
+ writable: true,
68
+ });
66
69
  }
67
70
  this.#db.exec("BEGIN IMMEDIATE");
68
- return new BetterSqlite3Transaction(this.#db);
71
+ this.#transactionMode = "write";
72
+ return new BetterSqlite3Transaction(this.#db, {
73
+ ownsTransaction: true,
74
+ writable: true,
75
+ onClose: () => {
76
+ this.#transactionMode = null;
77
+ },
78
+ });
69
79
  }
70
80
  close() {
71
81
  if (this.#closed)
@@ -88,9 +98,15 @@ class BetterSqlite3Backend {
88
98
  }
89
99
  class BetterSqlite3Transaction {
90
100
  #db;
101
+ #ownsTransaction;
102
+ #writable;
103
+ #onClose;
91
104
  #closed = false;
92
- constructor(db) {
105
+ constructor(db, options) {
93
106
  this.#db = db;
107
+ this.#ownsTransaction = options.ownsTransaction;
108
+ this.#writable = options.writable;
109
+ this.#onClose = options.onClose;
94
110
  }
95
111
  getValues(request) {
96
112
  this.#ensureOpen();
@@ -127,34 +143,59 @@ class BetterSqlite3Transaction {
127
143
  }
128
144
  writeKvBatch(batch) {
129
145
  this.#ensureOpen();
146
+ if (!this.#writable) {
147
+ throw new Error("Lix backend transaction is read-only");
148
+ }
130
149
  const stats = {
131
150
  puts: 0,
132
151
  deletes: 0,
152
+ deleteRanges: 0,
133
153
  bytesWritten: 0,
134
154
  };
135
155
  for (const group of batch.groups) {
136
- for (const put of group.puts) {
137
- stats.puts += 1;
138
- stats.bytesWritten += put.key.length + put.value.length;
139
- kvPut(this.#db, group.namespace, put.key, put.value);
140
- }
141
- for (const key of group.deletes) {
142
- stats.deletes += 1;
143
- stats.bytesWritten += key.length;
144
- kvDelete(this.#db, group.namespace, key);
156
+ for (const op of group.ops) {
157
+ if (op.kind === "put") {
158
+ stats.puts += 1;
159
+ stats.bytesWritten += op.key.length + op.value.length;
160
+ kvPut(this.#db, group.namespace, op.key, op.value);
161
+ }
162
+ else if (op.kind === "delete") {
163
+ stats.deletes += 1;
164
+ stats.bytesWritten += op.key.length;
165
+ kvDelete(this.#db, group.namespace, op.key);
166
+ }
167
+ else {
168
+ stats.deleteRanges += 1;
169
+ stats.bytesWritten += deleteRangeBytes(op.range);
170
+ kvDeleteRange(this.#db, group.namespace, op.range);
171
+ }
145
172
  }
146
173
  }
147
174
  return stats;
148
175
  }
149
176
  commit() {
150
177
  this.#ensureOpen();
151
- this.#db.exec("COMMIT");
152
- this.#closed = true;
178
+ try {
179
+ if (this.#ownsTransaction) {
180
+ this.#db.exec("COMMIT");
181
+ }
182
+ }
183
+ finally {
184
+ this.#closed = true;
185
+ this.#onClose?.();
186
+ }
153
187
  }
154
188
  rollback() {
155
189
  this.#ensureOpen();
156
- this.#db.exec("ROLLBACK");
157
- this.#closed = true;
190
+ try {
191
+ if (this.#ownsTransaction) {
192
+ this.#db.exec("ROLLBACK");
193
+ }
194
+ }
195
+ finally {
196
+ this.#closed = true;
197
+ this.#onClose?.();
198
+ }
158
199
  }
159
200
  #ensureOpen() {
160
201
  if (this.#closed) {
@@ -185,9 +226,7 @@ function scanPage(db, request) {
185
226
  const pagePairs = pairs.slice(0, request.limit);
186
227
  return {
187
228
  pairs: pagePairs,
188
- resumeAfter: hasMore
189
- ? (pagePairs.at(-1)?.key ?? null)
190
- : null,
229
+ resumeAfter: hasMore ? (pagePairs.at(-1)?.key ?? null) : null,
191
230
  };
192
231
  }
193
232
  function kvGet(db, namespace, key) {
@@ -207,9 +246,16 @@ function kvPut(db, namespace, key, value) {
207
246
  function kvDelete(db, namespace, key) {
208
247
  db.prepare("DELETE FROM lix_kv WHERE namespace = ? AND key = ?").run(namespace, sqliteBytes(key));
209
248
  }
249
+ function kvDeleteRange(db, namespace, range) {
250
+ const { clauses, params } = rangeClauses(namespace, range);
251
+ db.prepare(`DELETE FROM lix_kv WHERE ${clauses.join(" AND ")}`).run(...params);
252
+ }
210
253
  function kvScan(db, namespace, range, limit) {
211
254
  const { sql, params } = scanQuery(namespace, range, limit);
212
- return db.prepare(sql).all(...params).map((row) => {
255
+ return db
256
+ .prepare(sql)
257
+ .all(...params)
258
+ .map((row) => {
213
259
  if (!isObject(row) || !("key" in row) || !("value" in row)) {
214
260
  throw new Error("invalid lix_kv scan row");
215
261
  }
@@ -220,6 +266,15 @@ function kvScan(db, namespace, range, limit) {
220
266
  });
221
267
  }
222
268
  function scanQuery(namespace, range, limit) {
269
+ const { clauses, params } = rangeClauses(namespace, range);
270
+ let sql = `SELECT key, value FROM lix_kv WHERE ${clauses.join(" AND ")} ORDER BY key`;
271
+ if (limit != null) {
272
+ sql += " LIMIT ?";
273
+ params.push(limit);
274
+ }
275
+ return { sql, params };
276
+ }
277
+ function rangeClauses(namespace, range) {
223
278
  const params = [namespace];
224
279
  const clauses = ["namespace = ?"];
225
280
  if (range.kind === "prefix") {
@@ -235,12 +290,13 @@ function scanQuery(namespace, range, limit) {
235
290
  clauses.push("key >= ?", "key < ?");
236
291
  params.push(sqliteBytes(range.start), sqliteBytes(range.end));
237
292
  }
238
- let sql = `SELECT key, value FROM lix_kv WHERE ${clauses.join(" AND ")} ORDER BY key`;
239
- if (limit != null) {
240
- sql += " LIMIT ?";
241
- params.push(limit);
293
+ return { clauses, params };
294
+ }
295
+ function deleteRangeBytes(range) {
296
+ if (range.kind === "prefix") {
297
+ return range.prefix.length;
242
298
  }
243
- return { sql, params };
299
+ return range.start.length + range.end.length;
244
300
  }
245
301
  function compareBytes(left, right) {
246
302
  const length = Math.min(left.length, right.length);
@@ -8,9 +8,9 @@ Agents should inspect these files when SDK behavior is unclear instead of relyin
8
8
 
9
9
  Useful entry points:
10
10
 
11
- - `src/sql2/entity_provider.rs` - registered schema SQL surfaces
12
- - `src/sql2/change_provider.rs` - `lix_change` projection
13
- - `src/sql2/version_provider.rs` - writable `lix_version` surface
11
+ - `src/sql2/providers/entity.rs` - registered schema SQL surfaces
12
+ - `src/sql2/providers/change.rs` - `lix_change` projection
13
+ - `src/sql2/providers/branch.rs` - writable `lix_branch` surface
14
14
  - `src/transaction/validation.rs` - primary-key, unique, foreign-key, and shape validation
15
15
  - `src/schema/definition.json` - Lix schema-definition meta-schema
16
16
  - `src/schema/builtin/` - built-in schema definitions
@@ -0,0 +1,67 @@
1
+ use crate::backend::PredicateSupportLevel;
2
+
3
+ #[derive(Clone, Debug)]
4
+ pub struct BackendCapabilities {
5
+ pub profile: BackendProfile,
6
+ pub projection: ProjectionCapabilities,
7
+ pub scan: ScanCapabilities,
8
+ pub write: WriteCapabilities,
9
+ pub pushdown: PushdownCapabilities,
10
+ }
11
+
12
+ #[derive(Clone, Copy, Debug, PartialEq, Eq)]
13
+ pub enum BackendProfile {
14
+ /// Ordered byte keys, coherent read views, batched point reads,
15
+ /// chunked forward scans, and atomic write commit.
16
+ V0 { write_concurrency: WriteConcurrency },
17
+ }
18
+
19
+ #[derive(Clone, Copy, Debug, PartialEq, Eq)]
20
+ pub enum WriteConcurrency {
21
+ SingleWriter,
22
+ ConcurrentWithConflictDetection,
23
+ ConcurrentWithoutConflictDetection,
24
+ }
25
+
26
+ #[derive(Clone, Debug, Default)]
27
+ pub struct ProjectionCapabilities {
28
+ pub header: bool,
29
+ pub refs: bool,
30
+ pub header_and_refs: bool,
31
+ pub payload: bool,
32
+ }
33
+
34
+ #[derive(Clone, Debug, Default)]
35
+ pub struct ScanCapabilities {
36
+ pub native_prefix_scan: bool,
37
+ pub reverse: bool,
38
+ pub limit_bytes: bool,
39
+ pub long_lived_cursors: bool,
40
+ pub parallel_partitions: bool,
41
+ }
42
+
43
+ #[derive(Clone, Debug, Default)]
44
+ pub struct WriteCapabilities {
45
+ pub preconditions: bool,
46
+ pub idempotent_commit: bool,
47
+ }
48
+
49
+ #[derive(Clone, Debug, Default)]
50
+ pub struct PushdownCapabilities {
51
+ pub key: PredicateSupportLevel,
52
+ pub header: PredicateSupportLevel,
53
+ pub refs: PredicateSupportLevel,
54
+ pub object_pruning: PredicateSupportLevel,
55
+ }
56
+
57
+ impl BackendCapabilities {
58
+ pub fn v0(write_concurrency: WriteConcurrency) -> Self {
59
+ Self {
60
+ profile: BackendProfile::V0 { write_concurrency },
61
+ projection: ProjectionCapabilities::default(),
62
+ scan: ScanCapabilities::default(),
63
+ write: WriteCapabilities::default(),
64
+ pushdown: PushdownCapabilities::default(),
65
+ }
66
+ }
67
+ }