quiverdb 0.10.1 → 0.10.2
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.
- package/README.md +2 -0
- package/libs/linux-x86_64/libquiver.so +0 -0
- package/libs/linux-x86_64/libquiver.so.0 +0 -0
- package/libs/linux-x86_64/libquiver_c.so +0 -0
- package/libs/macos-aarch64/libquiver.0.dylib +0 -0
- package/libs/macos-aarch64/libquiver_c.dylib +0 -0
- package/libs/windows-x86_64/libquiver.dll +0 -0
- package/libs/windows-x86_64/libquiver_c.dll +0 -0
- package/package.json +1 -1
- package/src/create.ts +77 -0
- package/src/database.ts +26 -0
- package/src/group-columns.ts +9 -7
- package/src/loader.ts +18 -0
- package/src/lua-api.ts +26 -1
- package/src/time-series.ts +83 -7
package/README.md
CHANGED
|
@@ -71,6 +71,8 @@ bun run example.ts
|
|
|
71
71
|
- `createElement(collection, data)` -- Create element, returns numeric ID
|
|
72
72
|
- `updateElement(collection, id, data)` -- Update element by ID
|
|
73
73
|
- `deleteElement(collection, id)` -- Delete element by ID
|
|
74
|
+
- `updateElementByLabel(collection, label, data)` -- Update element by label
|
|
75
|
+
- `deleteElementByLabel(collection, label)` -- Delete element by label
|
|
74
76
|
|
|
75
77
|
### Read (bulk)
|
|
76
78
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
package/src/create.ts
CHANGED
|
@@ -148,12 +148,51 @@ Database.prototype.updateElement = function (
|
|
|
148
148
|
}
|
|
149
149
|
};
|
|
150
150
|
|
|
151
|
+
/** Label-addressed counterpart of updateElement. */
|
|
152
|
+
Database.prototype.updateElementByLabel = function (
|
|
153
|
+
this: Database,
|
|
154
|
+
collection: string,
|
|
155
|
+
label: string,
|
|
156
|
+
data: ElementData,
|
|
157
|
+
): void {
|
|
158
|
+
const lib = getSymbols();
|
|
159
|
+
const handle = this._handle;
|
|
160
|
+
|
|
161
|
+
const outElem = allocPtrOut();
|
|
162
|
+
check(lib.quiver_element_create(outElem.buf));
|
|
163
|
+
const elemPtr = readPtrOut(outElem);
|
|
164
|
+
|
|
165
|
+
try {
|
|
166
|
+
for (const [key, value] of Object.entries(data)) {
|
|
167
|
+
if (value === undefined) continue;
|
|
168
|
+
setElementField(lib, elemPtr, key, value);
|
|
169
|
+
}
|
|
170
|
+
const collBuf = toCString(collection);
|
|
171
|
+
const labelBuf = toCString(label);
|
|
172
|
+
check(lib.quiver_database_update_element_by_label(handle, collBuf.buf, labelBuf.buf, elemPtr));
|
|
173
|
+
} finally {
|
|
174
|
+
lib.quiver_element_destroy(elemPtr);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
|
|
151
178
|
Database.prototype.deleteElement = function (this: Database, collection: string, id: number): void {
|
|
152
179
|
const lib = getSymbols();
|
|
153
180
|
const collBuf = toCString(collection);
|
|
154
181
|
check(lib.quiver_database_delete_element(this._handle, collBuf.buf, BigInt(id)));
|
|
155
182
|
};
|
|
156
183
|
|
|
184
|
+
/** Label-addressed counterpart of deleteElement. */
|
|
185
|
+
Database.prototype.deleteElementByLabel = function (
|
|
186
|
+
this: Database,
|
|
187
|
+
collection: string,
|
|
188
|
+
label: string,
|
|
189
|
+
): void {
|
|
190
|
+
const lib = getSymbols();
|
|
191
|
+
const collBuf = toCString(collection);
|
|
192
|
+
const labelBuf = toCString(label);
|
|
193
|
+
check(lib.quiver_database_delete_element_by_label(this._handle, collBuf.buf, labelBuf.buf));
|
|
194
|
+
};
|
|
195
|
+
|
|
157
196
|
/**
|
|
158
197
|
* Replace all of an element's rows in one *named* vector group, from column arrays keyed by name.
|
|
159
198
|
*
|
|
@@ -180,6 +219,25 @@ Database.prototype.updateVectorGroup = function (
|
|
|
180
219
|
);
|
|
181
220
|
};
|
|
182
221
|
|
|
222
|
+
/** Label-addressed counterpart of updateVectorGroup. */
|
|
223
|
+
Database.prototype.updateVectorGroupByLabel = function (
|
|
224
|
+
this: Database,
|
|
225
|
+
collection: string,
|
|
226
|
+
group: string,
|
|
227
|
+
label: string,
|
|
228
|
+
data: GroupColumns,
|
|
229
|
+
): void {
|
|
230
|
+
updateGroupColumns(
|
|
231
|
+
this._handle,
|
|
232
|
+
"updateVectorGroupByLabel",
|
|
233
|
+
getSymbols().quiver_database_update_vector_group_by_label,
|
|
234
|
+
collection,
|
|
235
|
+
group,
|
|
236
|
+
label,
|
|
237
|
+
data,
|
|
238
|
+
);
|
|
239
|
+
};
|
|
240
|
+
|
|
183
241
|
/** Set-group counterpart of updateVectorGroup. */
|
|
184
242
|
Database.prototype.updateSetGroup = function (
|
|
185
243
|
this: Database,
|
|
@@ -198,3 +256,22 @@ Database.prototype.updateSetGroup = function (
|
|
|
198
256
|
data,
|
|
199
257
|
);
|
|
200
258
|
};
|
|
259
|
+
|
|
260
|
+
/** Label-addressed counterpart of updateSetGroup. */
|
|
261
|
+
Database.prototype.updateSetGroupByLabel = function (
|
|
262
|
+
this: Database,
|
|
263
|
+
collection: string,
|
|
264
|
+
group: string,
|
|
265
|
+
label: string,
|
|
266
|
+
data: GroupColumns,
|
|
267
|
+
): void {
|
|
268
|
+
updateGroupColumns(
|
|
269
|
+
this._handle,
|
|
270
|
+
"updateSetGroupByLabel",
|
|
271
|
+
getSymbols().quiver_database_update_set_group_by_label,
|
|
272
|
+
collection,
|
|
273
|
+
group,
|
|
274
|
+
label,
|
|
275
|
+
data,
|
|
276
|
+
);
|
|
277
|
+
};
|
package/src/database.ts
CHANGED
|
@@ -86,7 +86,9 @@ export class Database {
|
|
|
86
86
|
// --- Element CRUD (implemented in create.ts) ---
|
|
87
87
|
declare createElement: (collection: string, data: ElementData) => number;
|
|
88
88
|
declare updateElement: (collection: string, id: number, data: ElementData) => void;
|
|
89
|
+
declare updateElementByLabel: (collection: string, label: string, data: ElementData) => void;
|
|
89
90
|
declare deleteElement: (collection: string, id: number) => void;
|
|
91
|
+
declare deleteElementByLabel: (collection: string, label: string) => void;
|
|
90
92
|
|
|
91
93
|
// --- Reads (implemented in read.ts) ---
|
|
92
94
|
declare readScalarIntegers: (collection: string, attribute: string) => (number | null)[];
|
|
@@ -156,24 +158,48 @@ export class Database {
|
|
|
156
158
|
id: number,
|
|
157
159
|
data: TimeSeriesData,
|
|
158
160
|
) => void;
|
|
161
|
+
declare updateTimeSeriesGroupByLabel: (
|
|
162
|
+
collection: string,
|
|
163
|
+
group: string,
|
|
164
|
+
label: string,
|
|
165
|
+
data: TimeSeriesData,
|
|
166
|
+
) => void;
|
|
159
167
|
declare updateVectorGroup: (
|
|
160
168
|
collection: string,
|
|
161
169
|
group: string,
|
|
162
170
|
id: number,
|
|
163
171
|
data: GroupColumns,
|
|
164
172
|
) => void;
|
|
173
|
+
declare updateVectorGroupByLabel: (
|
|
174
|
+
collection: string,
|
|
175
|
+
group: string,
|
|
176
|
+
label: string,
|
|
177
|
+
data: GroupColumns,
|
|
178
|
+
) => void;
|
|
165
179
|
declare updateSetGroup: (
|
|
166
180
|
collection: string,
|
|
167
181
|
group: string,
|
|
168
182
|
id: number,
|
|
169
183
|
data: GroupColumns,
|
|
170
184
|
) => void;
|
|
185
|
+
declare updateSetGroupByLabel: (
|
|
186
|
+
collection: string,
|
|
187
|
+
group: string,
|
|
188
|
+
label: string,
|
|
189
|
+
data: GroupColumns,
|
|
190
|
+
) => void;
|
|
171
191
|
declare upsertTimeSeriesRow: (
|
|
172
192
|
collection: string,
|
|
173
193
|
group: string,
|
|
174
194
|
id: number,
|
|
175
195
|
row: Record<string, number | bigint | string>,
|
|
176
196
|
) => void;
|
|
197
|
+
declare upsertTimeSeriesRowByLabel: (
|
|
198
|
+
collection: string,
|
|
199
|
+
group: string,
|
|
200
|
+
label: string,
|
|
201
|
+
row: Record<string, number | bigint | string>,
|
|
202
|
+
) => void;
|
|
177
203
|
declare hasTimeSeriesFiles: (collection: string) => boolean;
|
|
178
204
|
declare listTimeSeriesFilesColumns: (collection: string) => string[];
|
|
179
205
|
declare readTimeSeriesFiles: (collection: string) => Record<string, string | null>;
|
package/src/group-columns.ts
CHANGED
|
@@ -15,13 +15,14 @@ export type GroupColumns = Record<string, (number | string | null)[]>;
|
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* The parallel-array signature every columnar group update C function shares
|
|
18
|
-
* (quiver_database_update_{time_series,vector,set}_group).
|
|
18
|
+
* (quiver_database_update_{time_series,vector,set}_group and their _by_label forms). The 4th
|
|
19
|
+
* argument addresses the element: an id for the by-id forms, a NUL-terminated label otherwise.
|
|
19
20
|
*/
|
|
20
21
|
type ColumnUpdateFn = (
|
|
21
22
|
db: NativePointer,
|
|
22
23
|
collection: Uint8Array,
|
|
23
24
|
group: Uint8Array,
|
|
24
|
-
|
|
25
|
+
key: bigint | Uint8Array,
|
|
25
26
|
names: Uint8Array | null,
|
|
26
27
|
types: Uint8Array | null,
|
|
27
28
|
data: Uint8Array | null,
|
|
@@ -32,8 +33,8 @@ type ColumnUpdateFn = (
|
|
|
32
33
|
|
|
33
34
|
/**
|
|
34
35
|
* Marshal a column-oriented payload and forward it to one of the columnar group update C
|
|
35
|
-
* functions. Shared by updateTimeSeriesGroup / updateVectorGroup / updateSetGroup
|
|
36
|
-
* differ only in which C entry point they call.
|
|
36
|
+
* functions. Shared by updateTimeSeriesGroup / updateVectorGroup / updateSetGroup and their
|
|
37
|
+
* _by_label counterparts: they differ only in which C entry point they call.
|
|
37
38
|
*
|
|
38
39
|
* Pass `{}` (no columns) to clear the group.
|
|
39
40
|
*/
|
|
@@ -43,15 +44,16 @@ export function updateGroupColumns(
|
|
|
43
44
|
update: ColumnUpdateFn,
|
|
44
45
|
collection: string,
|
|
45
46
|
group: string,
|
|
46
|
-
|
|
47
|
+
key: number | string,
|
|
47
48
|
data: GroupColumns,
|
|
48
49
|
): void {
|
|
49
50
|
const collBuf = toCString(collection);
|
|
50
51
|
const grpBuf = toCString(group);
|
|
52
|
+
const keyArg = typeof key === "string" ? toCString(key).buf : BigInt(key);
|
|
51
53
|
const entries = Object.entries(data);
|
|
52
54
|
|
|
53
55
|
if (entries.length === 0) {
|
|
54
|
-
check(update(handle, collBuf.buf, grpBuf.buf,
|
|
56
|
+
check(update(handle, collBuf.buf, grpBuf.buf, keyArg, null, null, null, null, 0n, 0n));
|
|
55
57
|
return;
|
|
56
58
|
}
|
|
57
59
|
|
|
@@ -149,7 +151,7 @@ export function updateGroupColumns(
|
|
|
149
151
|
handle,
|
|
150
152
|
collBuf.buf,
|
|
151
153
|
grpBuf.buf,
|
|
152
|
-
|
|
154
|
+
keyArg,
|
|
153
155
|
namesTable.buf,
|
|
154
156
|
typesAlloc.buf,
|
|
155
157
|
dataTable.buf,
|
package/src/loader.ts
CHANGED
|
@@ -58,7 +58,9 @@ const elementSymbols = {
|
|
|
58
58
|
const crudSymbols = {
|
|
59
59
|
quiver_database_create_element: { args: [P, BUF, P, P], returns: I32 },
|
|
60
60
|
quiver_database_update_element: { args: [P, BUF, I64, P], returns: I32 },
|
|
61
|
+
quiver_database_update_element_by_label: { args: [P, BUF, BUF, P], returns: I32 },
|
|
61
62
|
quiver_database_delete_element: { args: [P, BUF, I64], returns: I32 },
|
|
63
|
+
quiver_database_delete_element_by_label: { args: [P, BUF, BUF], returns: I32 },
|
|
62
64
|
} as const;
|
|
63
65
|
|
|
64
66
|
const readSymbols = {
|
|
@@ -131,18 +133,34 @@ const timeSeriesSymbols = {
|
|
|
131
133
|
args: [P, BUF, BUF, I64, P, P, P, USIZE],
|
|
132
134
|
returns: I32,
|
|
133
135
|
},
|
|
136
|
+
quiver_database_upsert_time_series_row_by_label: {
|
|
137
|
+
args: [P, BUF, BUF, BUF, P, P, P, USIZE],
|
|
138
|
+
returns: I32,
|
|
139
|
+
},
|
|
134
140
|
quiver_database_update_time_series_group: {
|
|
135
141
|
args: [P, BUF, BUF, I64, P, P, P, P, USIZE, USIZE],
|
|
136
142
|
returns: I32,
|
|
137
143
|
},
|
|
144
|
+
quiver_database_update_time_series_group_by_label: {
|
|
145
|
+
args: [P, BUF, BUF, BUF, P, P, P, P, USIZE, USIZE],
|
|
146
|
+
returns: I32,
|
|
147
|
+
},
|
|
138
148
|
quiver_database_update_vector_group: {
|
|
139
149
|
args: [P, BUF, BUF, I64, P, P, P, P, USIZE, USIZE],
|
|
140
150
|
returns: I32,
|
|
141
151
|
},
|
|
152
|
+
quiver_database_update_vector_group_by_label: {
|
|
153
|
+
args: [P, BUF, BUF, BUF, P, P, P, P, USIZE, USIZE],
|
|
154
|
+
returns: I32,
|
|
155
|
+
},
|
|
142
156
|
quiver_database_update_set_group: {
|
|
143
157
|
args: [P, BUF, BUF, I64, P, P, P, P, USIZE, USIZE],
|
|
144
158
|
returns: I32,
|
|
145
159
|
},
|
|
160
|
+
quiver_database_update_set_group_by_label: {
|
|
161
|
+
args: [P, BUF, BUF, BUF, P, P, P, P, USIZE, USIZE],
|
|
162
|
+
returns: I32,
|
|
163
|
+
},
|
|
146
164
|
quiver_database_free_time_series_data: { args: [P, P, P, P, USIZE, USIZE], returns: I32 },
|
|
147
165
|
quiver_database_has_time_series_files: { args: [P, BUF, P], returns: I32 },
|
|
148
166
|
quiver_database_list_time_series_files_columns: { args: [P, BUF, P, P], returns: I32 },
|
package/src/lua-api.ts
CHANGED
|
@@ -212,7 +212,9 @@ Rules worth knowing:
|
|
|
212
212
|
\`\`\`lua
|
|
213
213
|
local id = db:create_element(collection, element_table) -- returns new integer id
|
|
214
214
|
db:update_element(collection, id, element_table)
|
|
215
|
+
db:update_element_by_label(collection, label, element_table) -- same update, addressed by label
|
|
215
216
|
db:delete_element(collection, id)
|
|
217
|
+
db:delete_element_by_label(collection, label) -- same delete, addressed by label
|
|
216
218
|
\`\`\`
|
|
217
219
|
|
|
218
220
|
The element table holds scalar attributes as \`key = value\`, and vector/set attributes as
|
|
@@ -238,6 +240,13 @@ Notes:
|
|
|
238
240
|
- **\`update_element\` / \`delete_element\` require an existing id.** Targeting an id that does not
|
|
239
241
|
exist throws \`Element not found: <id> in collection '<collection>'\` (no silent no-op). Use
|
|
240
242
|
\`read_element_ids\` to get valid ids.
|
|
243
|
+
- **\`update_element_by_label\` / \`delete_element_by_label\` require an existing label**, unique
|
|
244
|
+
*per collection*, not per database — one naming an element of another collection does not
|
|
245
|
+
resolve. A miss throws \`Element not found: label '<label>' in collection '<collection>'\` and
|
|
246
|
+
changes nothing. Passing \`label = "New name"\` in the element table renames the element, after
|
|
247
|
+
which only the new label resolves. Because the label form delegates to the id form, failures
|
|
248
|
+
that validate the *element* (an empty table, a type mismatch) report
|
|
249
|
+
\`Cannot update_element: ...\`.
|
|
241
250
|
- **Empty arrays are skipped.** An attribute whose value is \`{}\` writes no vector/set (the element
|
|
242
251
|
type can't be inferred from an empty array), so it is silently dropped.
|
|
243
252
|
- **No \`nil\` scalar attributes.** In Lua a key set to \`nil\` is dropped from the table, so
|
|
@@ -295,6 +304,9 @@ db:update_vector_group("Child", "refs", id, { parent_ref = { 1, 2, 3 } })
|
|
|
295
304
|
db:update_set_group("Child", "parents", id, { parent_ref = { 1, 2 } })
|
|
296
305
|
|
|
297
306
|
db:update_vector_group("Child", "refs", id, {}) -- clears the group
|
|
307
|
+
|
|
308
|
+
db:update_vector_group_by_label("Child", "refs", "Child 1", { parent_ref = { 1, 2 } })
|
|
309
|
+
db:update_set_group_by_label("Child", "parents", "Child 1", { parent_ref = { 1, 2 } })
|
|
298
310
|
\`\`\`
|
|
299
311
|
|
|
300
312
|
Use these instead of routing a group's columns through \`update_element\` whenever a column name is
|
|
@@ -311,7 +323,8 @@ Rules:
|
|
|
311
323
|
are rejected if passed.
|
|
312
324
|
- **Foreign-key columns accept a label string** and resolve it to the referenced id, exactly as in
|
|
313
325
|
\`create_element\` / \`update_element\`.
|
|
314
|
-
- The element id must exist, same as \`update_element\` / \`delete_element
|
|
326
|
+
- The element id must exist, same as \`update_element\` / \`delete_element\`; the \`_by_label\` form
|
|
327
|
+
takes a label in its place, with \`update_element_by_label\`'s resolution and miss semantics.
|
|
315
328
|
|
|
316
329
|
---
|
|
317
330
|
|
|
@@ -372,6 +385,8 @@ db:update_time_series_group("Items", "data", id, {
|
|
|
372
385
|
})
|
|
373
386
|
|
|
374
387
|
db:update_time_series_group("Items", "data", id, {}) -- clears the group
|
|
388
|
+
|
|
389
|
+
db:update_time_series_group_by_label("Items", "data", "Item 1", { date_time = { "2024-01-01T00:00:00" }, value = { 10.5 } })
|
|
375
390
|
\`\`\`
|
|
376
391
|
|
|
377
392
|
A read-modify-write looks like this:
|
|
@@ -401,6 +416,8 @@ column names). Each value of the top-level table must be an **array**, not a sca
|
|
|
401
416
|
table {} to clear the group\`) — only a bare \`{}\` clears.
|
|
402
417
|
- Integer values are accepted for REAL columns (converted on insert). Booleans, functions, and
|
|
403
418
|
other unsupported Lua types throw \`column '...' has unsupported Lua type\`.
|
|
419
|
+
- The element id must exist; the \`_by_label\` form takes a label in its place, with
|
|
420
|
+
\`update_element_by_label\`'s resolution and miss semantics. Every rule above applies to both.
|
|
404
421
|
|
|
405
422
|
### Append/upsert a single row (\`upsert_time_series_row\` — ROW-oriented, the one exception)
|
|
406
423
|
|
|
@@ -412,8 +429,16 @@ db:upsert_time_series_row("Items", "data", id, {
|
|
|
412
429
|
date_time = "2024-01-04T00:00:00",
|
|
413
430
|
value = 40.0,
|
|
414
431
|
})
|
|
432
|
+
|
|
433
|
+
db:upsert_time_series_row_by_label("Items", "data", "Item 1", {
|
|
434
|
+
date_time = "2024-01-04T00:00:00",
|
|
435
|
+
value = 40.0,
|
|
436
|
+
})
|
|
415
437
|
\`\`\`
|
|
416
438
|
|
|
439
|
+
The element id must exist; the \`_by_label\` form takes a label in its place, with
|
|
440
|
+
\`update_element_by_label\`'s resolution and miss semantics.
|
|
441
|
+
|
|
417
442
|
---
|
|
418
443
|
|
|
419
444
|
## Time series files
|
package/src/time-series.ts
CHANGED
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
toCString,
|
|
19
19
|
} from "./ffi-helpers.ts";
|
|
20
20
|
import { updateGroupColumns } from "./group-columns.ts";
|
|
21
|
-
import { getSymbols } from "./loader.ts";
|
|
21
|
+
import { getSymbols, type NativePointer } from "./loader.ts";
|
|
22
22
|
import {
|
|
23
23
|
type Allocation,
|
|
24
24
|
DATA_TYPE_DATE_TIME,
|
|
@@ -200,16 +200,57 @@ Database.prototype.updateTimeSeriesGroup = function (
|
|
|
200
200
|
);
|
|
201
201
|
};
|
|
202
202
|
|
|
203
|
-
|
|
203
|
+
/** Label-addressed counterpart of updateTimeSeriesGroup. */
|
|
204
|
+
Database.prototype.updateTimeSeriesGroupByLabel = function (
|
|
204
205
|
this: Database,
|
|
205
206
|
collection: string,
|
|
206
207
|
group: string,
|
|
207
|
-
|
|
208
|
+
label: string,
|
|
209
|
+
data: TimeSeriesData,
|
|
210
|
+
): void {
|
|
211
|
+
updateGroupColumns(
|
|
212
|
+
this._handle,
|
|
213
|
+
"updateTimeSeriesGroupByLabel",
|
|
214
|
+
getSymbols().quiver_database_update_time_series_group_by_label,
|
|
215
|
+
collection,
|
|
216
|
+
group,
|
|
217
|
+
label,
|
|
218
|
+
data,
|
|
219
|
+
);
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* The parallel-array signature both row-oriented time-series upsert C functions share
|
|
224
|
+
* (quiver_database_upsert_time_series_row and its _by_label form). `key` is an id for the by-id
|
|
225
|
+
* form, a NUL-terminated label otherwise.
|
|
226
|
+
*/
|
|
227
|
+
type UpsertRowFn = (
|
|
228
|
+
db: NativePointer,
|
|
229
|
+
collection: Uint8Array,
|
|
230
|
+
group: Uint8Array,
|
|
231
|
+
key: bigint | Uint8Array,
|
|
232
|
+
names: Uint8Array | null,
|
|
233
|
+
types: Uint8Array | null,
|
|
234
|
+
data: Uint8Array | null,
|
|
235
|
+
columnCount: bigint,
|
|
236
|
+
) => number;
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Marshal a single row of scalars and forward it to one of the row-oriented time-series upsert
|
|
240
|
+
* C functions. Shared by upsertTimeSeriesRow / upsertTimeSeriesRowByLabel: they differ only in
|
|
241
|
+
* which C entry point they call and whether `key` is an id or a label.
|
|
242
|
+
*/
|
|
243
|
+
function upsertRowColumns(
|
|
244
|
+
handle: NativePointer,
|
|
245
|
+
upsert: UpsertRowFn,
|
|
246
|
+
collection: string,
|
|
247
|
+
group: string,
|
|
248
|
+
key: number | string,
|
|
208
249
|
row: Record<string, number | bigint | string>,
|
|
209
250
|
): void {
|
|
210
|
-
const lib = getSymbols();
|
|
211
251
|
const collBuf = toCString(collection);
|
|
212
252
|
const grpBuf = toCString(group);
|
|
253
|
+
const keyArg = typeof key === "string" ? toCString(key).buf : BigInt(key);
|
|
213
254
|
const entries = Object.entries(row);
|
|
214
255
|
const columnCount = entries.length;
|
|
215
256
|
const keepalive: Allocation[] = [];
|
|
@@ -248,17 +289,52 @@ Database.prototype.upsertTimeSeriesRow = function (
|
|
|
248
289
|
keepalive.push(dataTable);
|
|
249
290
|
|
|
250
291
|
check(
|
|
251
|
-
|
|
252
|
-
|
|
292
|
+
upsert(
|
|
293
|
+
handle,
|
|
253
294
|
collBuf.buf,
|
|
254
295
|
grpBuf.buf,
|
|
255
|
-
|
|
296
|
+
keyArg,
|
|
256
297
|
namesTable.buf,
|
|
257
298
|
typesAlloc.buf,
|
|
258
299
|
dataTable.buf,
|
|
259
300
|
BigInt(columnCount),
|
|
260
301
|
),
|
|
261
302
|
);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
Database.prototype.upsertTimeSeriesRow = function (
|
|
306
|
+
this: Database,
|
|
307
|
+
collection: string,
|
|
308
|
+
group: string,
|
|
309
|
+
id: number,
|
|
310
|
+
row: Record<string, number | bigint | string>,
|
|
311
|
+
): void {
|
|
312
|
+
upsertRowColumns(
|
|
313
|
+
this._handle,
|
|
314
|
+
getSymbols().quiver_database_upsert_time_series_row,
|
|
315
|
+
collection,
|
|
316
|
+
group,
|
|
317
|
+
id,
|
|
318
|
+
row,
|
|
319
|
+
);
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
/** Label-addressed counterpart of upsertTimeSeriesRow. */
|
|
323
|
+
Database.prototype.upsertTimeSeriesRowByLabel = function (
|
|
324
|
+
this: Database,
|
|
325
|
+
collection: string,
|
|
326
|
+
group: string,
|
|
327
|
+
label: string,
|
|
328
|
+
row: Record<string, number | bigint | string>,
|
|
329
|
+
): void {
|
|
330
|
+
upsertRowColumns(
|
|
331
|
+
this._handle,
|
|
332
|
+
getSymbols().quiver_database_upsert_time_series_row_by_label,
|
|
333
|
+
collection,
|
|
334
|
+
group,
|
|
335
|
+
label,
|
|
336
|
+
row,
|
|
337
|
+
);
|
|
262
338
|
};
|
|
263
339
|
|
|
264
340
|
Database.prototype.hasTimeSeriesFiles = function (this: Database, collection: string): boolean {
|