@based/db 0.0.8 → 0.0.9

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 (132) hide show
  1. package/README.md +425 -8
  2. package/dist/lib/darwin_aarch64/include/selva/db.h +12 -3
  3. package/dist/lib/darwin_aarch64/include/selva/fields.h +22 -11
  4. package/dist/lib/darwin_aarch64/include/selva/history.h +49 -0
  5. package/dist/lib/darwin_aarch64/include/selva/hll.h +21 -0
  6. package/dist/lib/darwin_aarch64/include/selva/sort.h +14 -0
  7. package/dist/lib/darwin_aarch64/include/selva/types.h +9 -2
  8. package/dist/lib/darwin_aarch64/include/selva/vector.h +22 -1
  9. package/dist/lib/darwin_aarch64/include/selva/xxhash64.h +23 -0
  10. package/dist/lib/darwin_aarch64/libnode-v20.11.1.node +0 -0
  11. package/dist/lib/darwin_aarch64/libnode-v20.18.1.node +0 -0
  12. package/dist/lib/darwin_aarch64/libnode-v22.13.0.node +0 -0
  13. package/dist/lib/darwin_aarch64/libnode-v22.8.0.node +0 -0
  14. package/dist/lib/darwin_aarch64/libselva.dylib +0 -0
  15. package/dist/lib/linux_aarch64/include/selva/db.h +12 -3
  16. package/dist/lib/linux_aarch64/include/selva/fields.h +22 -11
  17. package/dist/lib/linux_aarch64/include/selva/history.h +49 -0
  18. package/dist/lib/linux_aarch64/include/selva/hll.h +21 -0
  19. package/dist/lib/linux_aarch64/include/selva/sort.h +14 -0
  20. package/dist/lib/linux_aarch64/include/selva/types.h +9 -2
  21. package/dist/lib/linux_aarch64/include/selva/vector.h +22 -1
  22. package/dist/lib/linux_aarch64/include/selva/xxhash64.h +23 -0
  23. package/dist/lib/linux_aarch64/libnode-v20.11.1.node +0 -0
  24. package/dist/lib/linux_aarch64/libnode-v20.18.1.node +0 -0
  25. package/dist/lib/linux_aarch64/libnode-v22.13.0.node +0 -0
  26. package/dist/lib/linux_aarch64/libselva.so +0 -0
  27. package/dist/lib/linux_x86_64/include/selva/db.h +12 -3
  28. package/dist/lib/linux_x86_64/include/selva/fields.h +22 -11
  29. package/dist/lib/linux_x86_64/include/selva/history.h +49 -0
  30. package/dist/lib/linux_x86_64/include/selva/hll.h +21 -0
  31. package/dist/lib/linux_x86_64/include/selva/sort.h +14 -0
  32. package/dist/lib/linux_x86_64/include/selva/types.h +9 -2
  33. package/dist/lib/linux_x86_64/include/selva/vector.h +22 -1
  34. package/dist/lib/linux_x86_64/include/selva/xxhash64.h +23 -0
  35. package/dist/lib/linux_x86_64/libnode-v20.11.1.node +0 -0
  36. package/dist/lib/linux_x86_64/libnode-v20.18.1.node +0 -0
  37. package/dist/lib/linux_x86_64/libnode-v22.13.0.node +0 -0
  38. package/dist/lib/linux_x86_64/libselva.so +0 -0
  39. package/dist/src/client/bitWise.js +21 -1
  40. package/dist/src/client/index.d.ts +11 -5
  41. package/dist/src/client/index.js +57 -11
  42. package/dist/src/client/modify/ModifyRes.d.ts +4 -1
  43. package/dist/src/client/modify/ModifyRes.js +8 -1
  44. package/dist/src/client/modify/alias.js +3 -3
  45. package/dist/src/client/modify/binary.js +5 -2
  46. package/dist/src/client/modify/cardinality.d.ts +4 -0
  47. package/dist/src/client/modify/cardinality.js +50 -0
  48. package/dist/src/client/modify/create copy.d.ts +5 -0
  49. package/dist/src/client/modify/create copy.js +112 -0
  50. package/dist/src/client/modify/create.d.ts +2 -1
  51. package/dist/src/client/modify/create.js +11 -7
  52. package/dist/src/client/modify/delete.d.ts +2 -0
  53. package/dist/src/client/modify/delete.js +37 -0
  54. package/dist/src/client/modify/expire.d.ts +3 -0
  55. package/dist/src/client/modify/expire.js +25 -0
  56. package/dist/src/client/modify/fixed.js +11 -1
  57. package/dist/src/client/modify/index.d.ts +1 -1
  58. package/dist/src/client/modify/index.js +1 -1
  59. package/dist/src/client/modify/json.d.ts +4 -0
  60. package/dist/src/client/modify/json.js +5 -0
  61. package/dist/src/client/modify/modify.js +11 -7
  62. package/dist/src/client/modify/references/edge.js +21 -6
  63. package/dist/src/client/modify/references/reference.js +2 -2
  64. package/dist/src/client/modify/references/references.d.ts +0 -1
  65. package/dist/src/client/modify/references/references.js +4 -4
  66. package/dist/src/client/modify/remove.d.ts +1 -2
  67. package/dist/src/client/modify/remove.js +9 -6
  68. package/dist/src/client/modify/setCursor.d.ts +1 -1
  69. package/dist/src/client/modify/setCursor.js +4 -1
  70. package/dist/src/client/modify/string.js +2 -2
  71. package/dist/src/client/modify/text.d.ts +2 -1
  72. package/dist/src/client/modify/text.js +13 -7
  73. package/dist/src/client/modify/types.d.ts +8 -1
  74. package/dist/src/client/modify/types.js +1 -0
  75. package/dist/src/client/modify/update.d.ts +2 -1
  76. package/dist/src/client/modify/update.js +9 -5
  77. package/dist/src/client/modify/upsert.d.ts +2 -1
  78. package/dist/src/client/modify/upsert.js +3 -3
  79. package/dist/src/client/modify/vector copy.d.ts +4 -0
  80. package/dist/src/client/modify/vector copy.js +46 -0
  81. package/dist/src/client/modify/vector.js +6 -4
  82. package/dist/src/client/query/BasedDbQuery.d.ts +4 -3
  83. package/dist/src/client/query/BasedDbQuery.js +39 -16
  84. package/dist/src/client/query/BasedIterable.js +3 -3
  85. package/dist/src/client/query/filter/FilterBranch.d.ts +2 -2
  86. package/dist/src/client/query/filter/FilterBranch.js +2 -2
  87. package/dist/src/client/query/filter/createFixedFilterBuffer.d.ts +3 -2
  88. package/dist/src/client/query/filter/createFixedFilterBuffer.js +14 -11
  89. package/dist/src/client/query/filter/createReferenceFilter.d.ts +2 -1
  90. package/dist/src/client/query/filter/createReferenceFilter.js +6 -5
  91. package/dist/src/client/query/filter/createVariableFilterBuffer.d.ts +2 -1
  92. package/dist/src/client/query/filter/createVariableFilterBuffer.js +61 -30
  93. package/dist/src/client/query/filter/filter.d.ts +2 -2
  94. package/dist/src/client/query/filter/filter.js +23 -21
  95. package/dist/src/client/query/filter/parseFilterValue.js +9 -64
  96. package/dist/src/client/query/filter/primitiveFilter.js +7 -11
  97. package/dist/src/client/query/filter/toBuffer.js +5 -7
  98. package/dist/src/client/query/filter/types.d.ts +51 -2
  99. package/dist/src/client/query/filter/types.js +114 -0
  100. package/dist/src/client/query/include/props.d.ts +2 -0
  101. package/dist/src/client/query/include/props.js +25 -6
  102. package/dist/src/client/query/include/toBuffer.js +21 -1
  103. package/dist/src/client/query/include/walk.js +17 -2
  104. package/dist/src/client/query/queryDef.js +1 -0
  105. package/dist/src/client/query/read/read.js +85 -21
  106. package/dist/src/client/query/search/index.d.ts +2 -0
  107. package/dist/src/client/query/search/index.js +79 -23
  108. package/dist/src/client/query/subscription/index.js +2 -2
  109. package/dist/src/client/query/subscription/markers.d.ts +1 -1
  110. package/dist/src/client/query/subscription/markers.js +2 -2
  111. package/dist/src/client/query/toBuffer.js +0 -4
  112. package/dist/src/client/query/types.d.ts +10 -0
  113. package/dist/src/client/query/validation.d.ts +3 -2
  114. package/dist/src/client/query/validation.js +17 -2
  115. package/dist/src/client/timestamp.d.ts +1 -0
  116. package/dist/src/client/timestamp.js +68 -0
  117. package/dist/src/client/xxHash64.d.ts +1 -0
  118. package/dist/src/client/xxHash64.js +5 -0
  119. package/dist/src/index.d.ts +4 -1
  120. package/dist/src/index.js +13 -3
  121. package/dist/src/native.d.ts +1 -0
  122. package/dist/src/native.js +4 -1
  123. package/dist/src/server/csmt/tree.js +12 -2
  124. package/dist/src/server/index.d.ts +12 -4
  125. package/dist/src/server/index.js +63 -17
  126. package/dist/src/server/migrate/worker.js +3 -3
  127. package/dist/src/server/schema/selvaBuffer.js +20 -11
  128. package/dist/src/server/schema/typeDef.d.ts +2 -2
  129. package/dist/src/server/schema/typeDef.js +14 -5
  130. package/dist/src/server/schema/types.d.ts +7 -2
  131. package/dist/src/server/schema/types.js +6 -3
  132. package/package.json +1 -1
package/README.md CHANGED
@@ -1,4 +1,16 @@
1
- #Based-db
1
+ # BasedDb
2
+
3
+ BasedDb is a powerful database solution that supports various data types, references, edges, and operations. It also offers concurrency handling, client-server architecture support, and more.
4
+
5
+ ## Features
6
+
7
+ - Schema definition and management
8
+ - Data creation, querying, updating, and deletion
9
+ - Support for strings, numbers, booleans, binaries, aliases, enums, and cardinality
10
+ - Edges and references for advanced data modeling
11
+ - Concurrency support for high-load scenarios
12
+ - Client-server design for distributed systems
13
+ - Checksum, analytics, and expiration features
2
14
 
3
15
  ## Install
4
16
 
@@ -9,7 +21,7 @@
9
21
  - zig 0.13.0
10
22
  - npm & node.js, v20.11.1 or newer
11
23
 
12
- ```
24
+ ```bash
13
25
  npm i
14
26
  npm run get-napi // only need this the first time
15
27
  npm run build
@@ -18,26 +30,431 @@ npm run build
18
30
  ## Running tests
19
31
 
20
32
  Run all tests + ldb + build c, zig and js
21
- `npm run test`
33
+
34
+ ```bash
35
+ npm run test
36
+ ```
22
37
 
23
38
  Run specific test file - does substring matching
24
- `npm run test -- range.js`
39
+
40
+ ```bash
41
+ npm run test -- range.js
42
+ ```
25
43
 
26
44
  Run specific test file & run specific test
27
- `npm run test -- range.js:range`
45
+
46
+ ```bash
47
+ npm run test -- range.js:range
48
+ ```
28
49
 
29
50
  Different flavours of test
30
51
 
31
52
  Only builds zig
32
- `npm run test-zig`
53
+
54
+ ```bash
55
+ npm run test-zig
56
+ ```
33
57
 
34
58
  Builds nothing only runs tests
35
- `npm run test-fast`
36
59
 
37
- ## Getting started
60
+ ```bash
61
+ npm run test-fast
62
+ ```
63
+
64
+ ## Getting Started
65
+
66
+ To get started with BasedDb, follow these steps:
67
+
68
+ 1. Install the package
69
+ 2. Define your schema
70
+ 3. Start the database
71
+ 4. Perform operations like create, query, update, and delete
38
72
 
39
73
  ```ts
40
74
  const db = new BasedDb({
41
75
  path: '/persistent-file-path',
42
76
  })
43
77
  ```
78
+
79
+ ## Schema Definition
80
+
81
+ Define your schema using the `putSchema` method. Here is an example:
82
+
83
+ ```typescript
84
+ await db.putSchema({
85
+ types: {
86
+ user: {
87
+ name: 'string',
88
+ age: 'number',
89
+ email: 'alias',
90
+ isNice: 'boolean',
91
+ roles: ['admin', 'editor', 'viewer'],
92
+ file: 'binary',
93
+ bestFriend: {
94
+ ref: 'user',
95
+ prop: 'bestFriend',
96
+ },
97
+ friends: {
98
+ items: {
99
+ ref: 'user',
100
+ prop: 'friends',
101
+ },
102
+ },
103
+ },
104
+ article: {
105
+ body: 'string',
106
+ myUniqueValuesCount: 'cardinality',
107
+ contributors: {
108
+ type: 'references',
109
+ items: {
110
+ ref: 'user',
111
+ prop: 'articles',
112
+ $role: ['writer', 'editor'],
113
+ },
114
+ },
115
+ },
116
+ page: {
117
+ name: 'string',
118
+ clients: {
119
+ items: {
120
+ ref: '_client',
121
+ prop: 'pages',
122
+ $viewers: 'uint8',
123
+ },
124
+ },
125
+ activeViewers: {
126
+ type: 'uint32',
127
+ path: 'clients.$viewers.#sum',
128
+ history: {
129
+ interval: 'second',
130
+ },
131
+ },
132
+ },
133
+ _client: {
134
+ name: 'string',
135
+ },
136
+ },
137
+ })
138
+ ```
139
+
140
+ ## Data Operations
141
+
142
+ ### Create
143
+
144
+ Create new records using the `create` method:
145
+
146
+ ```typescript
147
+ const userId = await db.create('user', {
148
+ name: 'youzi',
149
+ email: 'youzi@example.com',
150
+ isNice: true,
151
+ roles: 'admin',
152
+ })
153
+ ```
154
+
155
+ ### Query & Filters
156
+
157
+ Query records using the `query` method:
158
+
159
+ ```typescript
160
+ const results = await db
161
+ .query('user')
162
+ .filter('isNice', '=', true)
163
+ .filter('name', '=', 'youzi')
164
+ .get()
165
+ .toObject()
166
+ ```
167
+
168
+ ### Update
169
+
170
+ Update records using the `update` method:
171
+
172
+ ```typescript
173
+ await db.update('user', userId, {
174
+ roles: 'editor',
175
+ })
176
+ ```
177
+
178
+ ### Delete
179
+
180
+ Delete records using the `delete` method:
181
+
182
+ ```typescript
183
+ await db.delete('user', userId)
184
+ ```
185
+
186
+ ## Advanced Features
187
+
188
+ ### Copy
189
+
190
+ Copy records with transformations:
191
+
192
+ ```typescript
193
+ await db.copy('edition', editionId, {
194
+ copiedByYouzi: true,
195
+ versionOf({ id }) {
196
+ return id
197
+ },
198
+ name({ name }) {
199
+ return name + ' (edition copy)'
200
+ },
201
+ sequences({ sequences }) {
202
+ return sequences.map(({ id }) => {
203
+ return db.copy('sequence', id, {
204
+ copiedByYouzi: true,
205
+ name({ name }) {
206
+ return name + ' (sequence copy)'
207
+ },
208
+ pages({ pages }) {
209
+ return pages.map(({ id }) =>
210
+ db.copy('page', id, {
211
+ copiedByYouzi: true,
212
+ name({ name }) {
213
+ return name + ' (page copy)'
214
+ },
215
+ }),
216
+ )
217
+ },
218
+ })
219
+ })
220
+ },
221
+ })
222
+ ```
223
+
224
+ ### Concurrency
225
+
226
+ Concurrent write and read operations are supported. The example below shows multiple concurrent queries and creates. Handle concurrency carefully to avoid conflicts:
227
+
228
+ ```typescript
229
+ let id = 0
230
+ let queries = 0
231
+ let refs = []
232
+ let timer = setTimeout(() => {
233
+ timer = null
234
+ }, 5e3)
235
+
236
+ const query = async () => {
237
+ queries++
238
+ try {
239
+ await db.query('user').include('friends').range(0, 1000_000).get()
240
+ } catch (e) {
241
+ console.error('err:', e)
242
+ }
243
+ queries--
244
+ }
245
+
246
+ while (timer) {
247
+ let i = 100
248
+ while (i--) {
249
+ query()
250
+ }
251
+ while (timer && queries) {
252
+ db.create('user', {
253
+ friends: refs,
254
+ })
255
+ refs.push(++id)
256
+ await db.drain()
257
+ await setTimeoutAsync()
258
+ }
259
+ }
260
+
261
+ clearTimeout(timer)
262
+ ```
263
+
264
+ ### Client-Server
265
+
266
+ Set up a client-server architecture:
267
+
268
+ ```typescript
269
+ const server = new DbServer({
270
+ path: t.tmp,
271
+ onSchemaChange(schema) {
272
+ client1.putLocalSchema(schema)
273
+ client2.putLocalSchema(schema)
274
+ },
275
+ })
276
+
277
+ await server.start({ clean: true })
278
+
279
+ const hooks: DbClientHooks = {
280
+ async putSchema(schema, fromStart, transformFns) {
281
+ return server.putSchema(schema, fromStart, transformFns)
282
+ },
283
+ async flushModify(buf) {
284
+ const offsets = server.modify(buf)
285
+ return { offsets }
286
+ },
287
+ async getQueryBuf(buf) {
288
+ return server.getQueryBuf(buf)
289
+ },
290
+ }
291
+
292
+ const client1 = new DbClient({ hooks })
293
+ const client2 = new DbClient({ hooks })
294
+
295
+ await client1.putSchema({
296
+ types: {
297
+ user: {
298
+ name: 'string',
299
+ },
300
+ },
301
+ })
302
+
303
+ const youzi = await client1.create('user', { name: 'youzi' })
304
+ const jamez = await client1.create('user', { name: 'jamez' })
305
+
306
+ deepEqual(await client1.query('user').get().toObject(), [
307
+ { id: 1, name: 'youzi' },
308
+ { id: 2, name: 'jamez' },
309
+ ])
310
+ ```
311
+
312
+ ### Checksum
313
+
314
+ Include checksum in queries:
315
+
316
+ ```typescript
317
+ await db.query('article').include('*', '_checksum')
318
+ ```
319
+
320
+ ### Cardinality
321
+
322
+ Use cardinality for unique value counts:
323
+
324
+ ```typescript
325
+ await db.putSchema({
326
+ types: {
327
+ article: {
328
+ myUniqueValuesCount: 'cardinality',
329
+ },
330
+ },
331
+ })
332
+
333
+ const myArticle = await db.create('article', {
334
+ myUniqueValuesCount: 'myCoolValue',
335
+ })
336
+ ```
337
+
338
+ ### Boolean
339
+
340
+ Handle boolean properties:
341
+
342
+ ```typescript
343
+ await db.putSchema({
344
+ types: {
345
+ user: {
346
+ props: {
347
+ isNice: 'boolean',
348
+ },
349
+ },
350
+ },
351
+ })
352
+
353
+ db.create('user', {})
354
+ db.create('user', { isNice: true })
355
+ db.create('user', { isNice: false })
356
+
357
+ await db.drain()
358
+
359
+ deepEqual((await db.query('user').get()).toObject(), [
360
+ { id: 1, isNice: false },
361
+ { id: 2, isNice: true },
362
+ { id: 3, isNice: false },
363
+ ])
364
+ ```
365
+
366
+ ### Binary
367
+
368
+ Handle binary data:
369
+
370
+ ```typescript
371
+ await db.putSchema({
372
+ types: {
373
+ user: {
374
+ props: {
375
+ file: { type: 'binary' },
376
+ },
377
+ },
378
+ },
379
+ })
380
+
381
+ db.create('user', {
382
+ file: new Uint32Array([1, 2, 3, 4]),
383
+ })
384
+
385
+ await db.drain()
386
+
387
+ deepEqual((await db.query('user').get()).toObject(), [
388
+ {
389
+ id: 1,
390
+ file: new Uint8Array(new Uint32Array([1, 2, 3, 4]).buffer),
391
+ },
392
+ ])
393
+ ```
394
+
395
+ ### Analytics
396
+
397
+ Perform analytics on data:
398
+
399
+ ```typescript
400
+ await db.putSchema({
401
+ types: {
402
+ page: {
403
+ name: 'string',
404
+ clients: {
405
+ items: {
406
+ ref: '_client',
407
+ prop: 'pages',
408
+ $viewers: 'uint8',
409
+ },
410
+ },
411
+ activeViewers: {
412
+ type: 'uint32',
413
+ path: 'clients.$viewers.#sum',
414
+ history: {
415
+ interval: 'second',
416
+ },
417
+ },
418
+ },
419
+ },
420
+ })
421
+
422
+ const client = await db.create('_client', {})
423
+ const page = await db.create('page', {
424
+ clients: [
425
+ {
426
+ id: client,
427
+ $viewers: { increment: 1 },
428
+ },
429
+ ],
430
+ })
431
+ ```
432
+
433
+ ### Alias
434
+
435
+ Use aliases for properties:
436
+
437
+ ```typescript
438
+ await db.putSchema({
439
+ types: {
440
+ user: {
441
+ props: {
442
+ externalId: 'alias',
443
+ potato: 'string',
444
+ },
445
+ },
446
+ },
447
+ })
448
+
449
+ const user1 = db.create('user', {
450
+ externalId: 'cool',
451
+ })
452
+
453
+ await db.drain()
454
+
455
+ deepEqual((await db.query('user', user1).get()).toObject(), {
456
+ id: 1,
457
+ externalId: 'cool',
458
+ potato: '',
459
+ })
460
+ ```
@@ -107,6 +107,15 @@ enum SelvaFieldType selva_get_fs_type(const struct SelvaFieldSchema *fs);
107
107
  SELVA_EXPORT
108
108
  const struct EdgeFieldConstraint *selva_get_edge_field_constraint(const struct SelvaFieldSchema *fs) __attribute__((nonnull));
109
109
 
110
+ SELVA_EXPORT
111
+ const struct SelvaFieldsSchema *selva_get_edge_field_fields_schema(struct SelvaDb *db, const struct EdgeFieldConstraint *efc);
112
+
113
+ SELVA_EXPORT
114
+ void selva_expire_node(struct SelvaDb *db, node_type_t type, node_id_t node_id, int64_t ts);
115
+
116
+ SELVA_EXPORT
117
+ void selva_db_expire_tick(struct SelvaDb *db, int64_t now);
118
+
110
119
  /**
111
120
  * Delete a node.
112
121
  */
@@ -216,13 +225,13 @@ node_id_t selva_get_node_id(const struct SelvaNode *node) __attribute__((nonnull
216
225
  * @param tmp_hash_state is only used for computation and it's reset before use.
217
226
  */
218
227
  SELVA_EXPORT
219
- selva_hash128_t selva_node_hash_update(struct SelvaTypeEntry *type, struct SelvaNode *node, struct XXH3_state_s *tmp_hash_state);
228
+ selva_hash128_t selva_node_hash_update(struct SelvaDb *db, struct SelvaTypeEntry *type, struct SelvaNode *node, struct XXH3_state_s *tmp_hash_state);
220
229
 
221
230
  SELVA_EXPORT
222
- selva_hash128_t selva_node_hash_update2(struct SelvaTypeEntry *type, struct SelvaNode *node);
231
+ selva_hash128_t selva_node_hash_update2(struct SelvaDb *db, struct SelvaTypeEntry *type, struct SelvaNode *node);
223
232
 
224
233
  SELVA_EXPORT
225
- selva_hash128_t selva_node_hash_range(struct SelvaTypeEntry *type, node_id_t start, node_id_t end) __attribute__((nonnull));
234
+ selva_hash128_t selva_node_hash_range(struct SelvaDb *db, struct SelvaTypeEntry *type, node_id_t start, node_id_t end) __attribute__((nonnull));
226
235
 
227
236
  /**
228
237
  * @}
@@ -87,6 +87,7 @@ struct SelvaFieldsAny {
87
87
  struct SelvaNodeWeakReferences weak_references; /*!< SELVA_FIELD_TYPE_WEAK_REFERENCES */
88
88
  struct SelvaMicroBuffer *smb; /*!< SELVA_FIELD_TYPE_MICRO_BUFFER */
89
89
  #endif
90
+ // HyperLogLogPlusPlus cardinality; /*!< SELVA_FIELD_TYPE_HLL */
90
91
  };
91
92
  };
92
93
 
@@ -137,6 +138,17 @@ int selva_fields_get_mutable_string(
137
138
  struct selva_string **s)
138
139
  __attribute__((access(write_only, 4)));
139
140
 
141
+ /*
142
+ * TODO prefix with selva_
143
+ * TODO Document diff to get_mutable_string
144
+ */
145
+ SELVA_EXPORT
146
+ struct selva_string *fields_ensure_string(
147
+ struct SelvaDb *db,
148
+ struct SelvaNode *node,
149
+ const struct SelvaFieldSchema *fs,
150
+ size_t initial_len);
151
+
140
152
  SELVA_EXPORT
141
153
  int selva_fields_reference_set(
142
154
  struct SelvaDb *db,
@@ -204,6 +216,7 @@ int selva_fields_references_swap(
204
216
 
205
217
  SELVA_EXPORT
206
218
  int selva_fields_set_reference_meta(
219
+ struct SelvaDb *db,
207
220
  struct SelvaNode *node,
208
221
  struct SelvaNodeReference *ref,
209
222
  const struct EdgeFieldConstraint *efc,
@@ -212,6 +225,7 @@ int selva_fields_set_reference_meta(
212
225
 
213
226
  SELVA_EXPORT
214
227
  int selva_fields_get_reference_meta_mutable_string(
228
+ struct SelvaDb *db,
215
229
  struct SelvaNode *node,
216
230
  struct SelvaNodeReference *ref,
217
231
  const struct EdgeFieldConstraint *efc,
@@ -283,6 +297,12 @@ struct SelvaNode *selva_fields_resolve_weak_reference(
283
297
  const struct SelvaFieldSchema *fs,
284
298
  const struct SelvaNodeWeakReference *weak_ref);
285
299
 
300
+ SELVA_EXPORT
301
+ struct selva_string *selva_fields_get_selva_string2(struct SelvaFields *fields, const struct SelvaFieldSchema *fs);
302
+
303
+ SELVA_EXPORT
304
+ struct selva_string *selva_fields_get_selva_string(struct SelvaNode *node, const struct SelvaFieldSchema *fs);
305
+
286
306
  SELVA_EXPORT
287
307
  struct SelvaFieldsPointer selva_fields_get_raw2(struct SelvaFields *fields, const struct SelvaFieldSchema *fs)
288
308
  __attribute__((nonnull));
@@ -319,20 +339,11 @@ void selva_fields_init(const struct SelvaFieldsSchema *schema, struct SelvaField
319
339
  SELVA_EXPORT
320
340
  void selva_fields_destroy(struct SelvaDb *db, struct SelvaNode *node);
321
341
 
322
- SELVA_EXPORT
323
- int selva_fields_get_string_crc(const struct SelvaNode *node, const struct SelvaFieldSchema *fs, uint32_t *crc);
324
-
325
- SELVA_EXPORT
326
- int selva_fields_get_string_crc2(const struct SelvaFields *fields, const struct SelvaFieldSchema *fs, uint32_t *crc);
327
-
328
342
  SELVA_EXPORT
329
343
  int selva_fields_get_text_crc(const struct SelvaNode *node, const struct SelvaFieldSchema *fs, enum selva_lang_code lang, uint32_t *crc);
330
344
 
331
345
  SELVA_EXPORT
332
- int selva_fields_get_text_crc2(const struct SelvaFields *fields, const struct SelvaFieldSchema *fs, enum selva_lang_code lang, uint32_t *crc);
333
-
334
- SELVA_EXPORT
335
- void selva_fields_hash_update(struct XXH3_state_s *hash_state, const struct SelvaFieldsSchema *schema, const struct SelvaFields *fields);
346
+ void selva_fields_hash_update(struct XXH3_state_s *hash_state, struct SelvaDb *db, const struct SelvaFieldsSchema *schema, const struct SelvaFields *fields);
336
347
 
337
348
  SELVA_EXPORT
338
- selva_hash128_t selva_fields_hash(const struct SelvaFieldsSchema *schema, const struct SelvaFields *fields);
349
+ selva_hash128_t selva_fields_hash(struct SelvaDb *db, const struct SelvaFieldsSchema *schema, const struct SelvaFields *fields);
@@ -0,0 +1,49 @@
1
+ /*
2
+ * Copyright (c) 2025 SAULX
3
+ * SPDX-License-Identifier: MIT
4
+ */
5
+ #pragma once
6
+
7
+ #include <stddef.h>
8
+ #include <stdint.h>
9
+ #include "selva/types.h"
10
+ #include "selva/_export.h"
11
+
12
+ struct selva_history;
13
+
14
+ struct selva_history_event {
15
+ int64_t ts;
16
+ node_id_t node_id;
17
+ uint32_t crc;
18
+ } __packed __attribute__((aligned(4)));
19
+
20
+ static_assert(alignof(struct selva_history_event) == alignof(uint32_t));
21
+
22
+ SELVA_EXPORT
23
+ int selva_history_init(const char *pathname, size_t bsize, struct selva_history **hist_out);
24
+
25
+ SELVA_EXPORT
26
+ void selva_history_destroy(struct selva_history *hist);
27
+
28
+ SELVA_EXPORT
29
+ void selva_history_append(struct selva_history *hist, int64_t ts, node_id_t node_id, void *buf);
30
+
31
+ SELVA_EXPORT
32
+ void selva_history_fsync(struct selva_history *hist);
33
+
34
+ /**
35
+ * Find a range.
36
+ * The returned buffer must be freed with selva_history_free_range().
37
+ */
38
+ SELVA_EXPORT
39
+ uint32_t *selva_history_find_range(struct selva_history *hist, int64_t from, int64_t to, size_t *size_out);
40
+
41
+ /**
42
+ * Find a range.
43
+ * The returned buffer must be freed with selva_history_free_range().
44
+ */
45
+ SELVA_EXPORT
46
+ uint32_t *selva_history_find_range_node(struct selva_history *hist, int64_t from, int64_t to, node_id_t node_id, size_t *size_out);
47
+
48
+ SELVA_EXPORT
49
+ void selva_history_free_range(uint32_t *range);
@@ -0,0 +1,21 @@
1
+ #ifndef UTIL_HLL_H
2
+ #define UTIL_HLL_H
3
+
4
+ #include <stdlib.h>
5
+ #include <stdint.h>
6
+ #include "selva/_export.h"
7
+ #include "selva_string.h"
8
+ #include <stdbool.h>
9
+ #include "cdefs.h"
10
+
11
+
12
+ SELVA_EXPORT
13
+ void hll_init(struct selva_string *hllss, uint8_t precision, bool is_sparse);
14
+ SELVA_EXPORT
15
+ void hll_add(struct selva_string *hllss, uint64_t element);
16
+ SELVA_EXPORT
17
+ double hll_count(struct selva_string *hllss);
18
+ SELVA_EXPORT
19
+ struct selva_string hll_array_union(struct selva_string *hll_array, size_t count);
20
+
21
+ #endif
@@ -30,6 +30,8 @@ enum SelvaSortOrder {
30
30
  SELVA_SORT_ORDER_NONE = 0,
31
31
  SELVA_SORT_ORDER_I64_ASC,
32
32
  SELVA_SORT_ORDER_I64_DESC,
33
+ SELVA_SORT_ORDER_FLOAT_ASC,
34
+ SELVA_SORT_ORDER_FLOAT_DESC,
33
35
  SELVA_SORT_ORDER_DOUBLE_ASC,
34
36
  SELVA_SORT_ORDER_DOUBLE_DESC,
35
37
  SELVA_SORT_ORDER_BUFFER_ASC,
@@ -58,6 +60,9 @@ void selva_sort_insert(struct SelvaSortCtx *ctx, const void *p);
58
60
  SELVA_EXPORT
59
61
  void selva_sort_insert_i64(struct SelvaSortCtx *ctx, int64_t v, const void *p);
60
62
 
63
+ SELVA_EXPORT
64
+ void selva_sort_insert_float(struct SelvaSortCtx *ctx, float f, const void *p);
65
+
61
66
  SELVA_EXPORT
62
67
  void selva_sort_insert_double(struct SelvaSortCtx *ctx, double d, const void *p);
63
68
 
@@ -73,6 +78,9 @@ void selva_sort_remove(struct SelvaSortCtx *ctx, const void *p);
73
78
  SELVA_EXPORT
74
79
  void selva_sort_remove_i64(struct SelvaSortCtx *ctx, int64_t v, const void *p);
75
80
 
81
+ SELVA_EXPORT
82
+ void selva_sort_remove_float(struct SelvaSortCtx *ctx, float f, const void *p);
83
+
76
84
  SELVA_EXPORT
77
85
  void selva_sort_remove_double(struct SelvaSortCtx *ctx, double d, const void *p);
78
86
 
@@ -100,6 +108,12 @@ void *selva_sort_foreach_i64(struct SelvaSortCtx *ctx, int64_t *v);
100
108
  SELVA_EXPORT
101
109
  void *selva_sort_foreach_i64_reverse(struct SelvaSortCtx *ctx, int64_t *v);
102
110
 
111
+ SELVA_EXPORT
112
+ void *selva_sort_foreach_float(struct SelvaSortCtx *ctx, float *f);
113
+
114
+ SELVA_EXPORT
115
+ void *selva_sort_foreach_float_reverse(struct SelvaSortCtx *ctx, float *f);
116
+
103
117
  SELVA_EXPORT
104
118
  void *selva_sort_foreach_double(struct SelvaSortCtx *ctx, double *d);
105
119
 
@@ -55,14 +55,19 @@ enum SelvaFieldType {
55
55
 
56
56
  struct EdgeFieldConstraint {
57
57
  enum EdgeFieldConstraintFlag {
58
+ EDGE_FIELD_CONSTRAINT_FLAG_DEPENDENT = 0x01,
58
59
  /**
59
60
  * Skip saving this field while dumping.
60
61
  */
61
- EDGE_FIELD_CONSTRAINT_FLAG_SKIP_DUMP = 0x80,
62
+ EDGE_FIELD_CONSTRAINT_FLAG_SKIP_DUMP = 0x80,
62
63
  } __packed flags;
63
64
  field_t inverse_field;
64
65
  node_type_t dst_node_type;
65
- struct SelvaFieldsSchema *fields_schema;
66
+ /**
67
+ * Don't use directly!
68
+ * Use: `selva_get_edge_field_fields_schema()`
69
+ */
70
+ struct SelvaFieldsSchema *_fields_schema;
66
71
  };
67
72
 
68
73
  struct SelvaFieldSchema {
@@ -92,7 +97,9 @@ struct SelvaFieldsSchema {
92
97
  };
93
98
 
94
99
  struct SelvaNodeSchema {
100
+ size_t nr_aliases; /*!< Number of alias fields in this type. */
95
101
  struct SelvaFieldsSchema fields_schema;
102
+ /* Nothing must be put after this line. */
96
103
  };
97
104
 
98
105
  struct SelvaAlias;