quiverdb 0.10.3 → 0.10.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.
- 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/mod.ts +1 -0
- package/package.json +1 -1
- package/src/database.ts +4 -4
- package/src/group-columns.ts +11 -2
- package/src/lua-api.ts +29 -8
- package/src/time-series.ts +22 -9
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/mod.ts
CHANGED
package/package.json
CHANGED
package/src/database.ts
CHANGED
|
@@ -192,13 +192,13 @@ export class Database {
|
|
|
192
192
|
collection: string,
|
|
193
193
|
group: string,
|
|
194
194
|
id: number,
|
|
195
|
-
data:
|
|
195
|
+
data: GroupColumns,
|
|
196
196
|
) => void;
|
|
197
197
|
declare updateTimeSeriesGroupByLabel: (
|
|
198
198
|
collection: string,
|
|
199
199
|
group: string,
|
|
200
200
|
label: string,
|
|
201
|
-
data:
|
|
201
|
+
data: GroupColumns,
|
|
202
202
|
) => void;
|
|
203
203
|
declare updateVectorGroup: (
|
|
204
204
|
collection: string,
|
|
@@ -228,13 +228,13 @@ export class Database {
|
|
|
228
228
|
collection: string,
|
|
229
229
|
group: string,
|
|
230
230
|
id: number,
|
|
231
|
-
row: Record<string, number | bigint | string>,
|
|
231
|
+
row: Record<string, number | bigint | string | boolean>,
|
|
232
232
|
) => void;
|
|
233
233
|
declare upsertTimeSeriesRowByLabel: (
|
|
234
234
|
collection: string,
|
|
235
235
|
group: string,
|
|
236
236
|
label: string,
|
|
237
|
-
row: Record<string, number | bigint | string>,
|
|
237
|
+
row: Record<string, number | bigint | string | boolean>,
|
|
238
238
|
) => void;
|
|
239
239
|
declare hasTimeSeriesFiles: (collection: string) => boolean;
|
|
240
240
|
declare listTimeSeriesFilesColumns: (collection: string) => string[];
|
package/src/group-columns.ts
CHANGED
|
@@ -11,7 +11,7 @@ import type { NativePointer } from "./loader.ts";
|
|
|
11
11
|
import { DATA_TYPE_FLOAT, DATA_TYPE_INTEGER, DATA_TYPE_STRING, type Allocation } from "./types.ts";
|
|
12
12
|
|
|
13
13
|
/** Column-oriented group payload: one array of cells per column name, `null` for SQL NULL. */
|
|
14
|
-
export type GroupColumns = Record<string, (number | string | null)[]>;
|
|
14
|
+
export type GroupColumns = Record<string, (number | string | boolean | null)[]>;
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* The parallel-array signature every columnar group update C function shares
|
|
@@ -94,7 +94,16 @@ export function updateGroupColumns(
|
|
|
94
94
|
const maskPtrs: (Pointer | null)[] = [];
|
|
95
95
|
|
|
96
96
|
for (let c = 0; c < columnCount; c++) {
|
|
97
|
-
const [colName,
|
|
97
|
+
const [colName, rawValues] = entries[c];
|
|
98
|
+
// SQLite has no boolean type: a boolean is INTEGER 1/0, as in setElementField and
|
|
99
|
+
// marshalParams. Normalizing per cell before the dispatch (rather than adding a boolean
|
|
100
|
+
// branch after it) is what makes a mixed [true, 5] column write 1 and 5 instead of
|
|
101
|
+
// truthiness-mapping every cell, and matches Python's per-cell `int(v)`. A string column is
|
|
102
|
+
// left alone so normalizing cannot change what a mixed ['a', true] column already wrote.
|
|
103
|
+
const isStringColumn = typeof rawValues.find((v) => v !== null) === "string";
|
|
104
|
+
const values = isStringColumn
|
|
105
|
+
? rawValues
|
|
106
|
+
: rawValues.map((v) => (typeof v === "boolean" ? (v ? 1 : 0) : v));
|
|
98
107
|
const first = values.find((v) => v !== null);
|
|
99
108
|
|
|
100
109
|
// Mask via direct indexing — never a DataView, to avoid the documented
|
package/src/lua-api.ts
CHANGED
|
@@ -51,13 +51,25 @@ Lua values map to Quiver column values as follows:
|
|
|
51
51
|
| integer | INTEGER | Also accepted for REAL columns (coerced to real). |
|
|
52
52
|
| number (float) | REAL | A float is rejected for an INTEGER column. |
|
|
53
53
|
| string | TEXT | Also used for \`date_time\` columns (ISO 8601). |
|
|
54
|
+
| boolean | INTEGER 1/0 | SQLite has no boolean type; \`true\` writes 1, \`false\` 0. |
|
|
54
55
|
| \`nil\` | NULL | In query params, file paths, ts rows, relations.|
|
|
55
56
|
| table (1-indexed) | array | Used for vectors/sets and column-oriented data.|
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
A boolean is accepted **wherever an integer is** — element scalars and arrays, query parameters,
|
|
59
|
+
the group writers, and \`upsert_time_series_row\` — so it also reaches a REAL column through the
|
|
60
|
+
usual int-for-REAL coercion. Reading is the asymmetric half: there are no boolean readers in Lua
|
|
61
|
+
(unlike Julia/Dart/Python/JS), so a stored flag comes back as \`0\`/\`1\` from
|
|
62
|
+
\`read_scalar_integers\`. Compare against 0 rather than truth-testing —
|
|
63
|
+
\`read_scalar_integers(c, a)[i] == 1\` — because in Lua a \`nil\` from a NULL cell is *not* equal to
|
|
64
|
+
0 and \`nil ~= 0\` evaluates to \`true\`.
|
|
65
|
+
|
|
66
|
+
The one place a boolean is deliberately refused is \`db:update_relation\`, where the argument is a
|
|
67
|
+
target label and only \`nil\` (or omitting it) may clear the relation.
|
|
68
|
+
|
|
69
|
+
**Unsupported types throw.** Passing a function or a nested table where a scalar is expected raises
|
|
70
|
+
an error rather than silently dropping the value. This applies to element attributes, time-series
|
|
71
|
+
rows, and query parameters. A skipped positional query parameter would shift every later parameter
|
|
72
|
+
and bind NULL to the trailing placeholder, so this is rejected loudly.
|
|
61
73
|
|
|
62
74
|
Dates are plain strings in ISO 8601 format: \`YYYY-MM-DDTHH:MM:SS\`. (Lua keeps a string-based
|
|
63
75
|
datetime surface — there are no DateTime wrapper helpers, unlike Julia/Dart/Python.) The time part
|
|
@@ -368,6 +380,13 @@ db:read_element_by_id(collection, id) -- scalars + vectors + sets mer
|
|
|
368
380
|
\`read_element_by_id\` merges every scalar, vector, and set for the element into a single table.
|
|
369
381
|
Scalar attributes with no value come back as \`nil\`.
|
|
370
382
|
|
|
383
|
+
**Group columns are returned densely, with NULL cells dropped.** \`read_vectors_by_id\` and
|
|
384
|
+
\`read_sets_by_id\` read each column independently, and a column read skips its NULL cells — so two
|
|
385
|
+
columns of the same group are **not** positionally aligned with each other whenever one is
|
|
386
|
+
nullable (e.g. an \`ON DELETE SET NULL\` relation). Do not zip them into rows. There is no
|
|
387
|
+
row-aligned group read in Lua; if you need per-row alignment across a nullable group, do that read
|
|
388
|
+
in the host binding instead.
|
|
389
|
+
|
|
371
390
|
---
|
|
372
391
|
|
|
373
392
|
## Time series
|
|
@@ -681,7 +700,9 @@ and \`unit\` default to \`""\`; \`labels\`, \`dimensions\`, \`dimension_sizes\`,
|
|
|
681
700
|
|
|
682
701
|
## What Lua does *not* expose
|
|
683
702
|
|
|
684
|
-
DateTime wrapper helpers (Lua uses ISO 8601 strings)
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
703
|
+
DateTime wrapper helpers (Lua uses ISO 8601 strings), boolean *reader* helpers (a stored flag reads
|
|
704
|
+
back as \`0\`/\`1\` — writing a boolean is supported), \`_by_id\` single-scalar variants (use the
|
|
705
|
+
composite by-id readers or the bulk readers instead), and the row-aligned whole-group readers the
|
|
706
|
+
other bindings have (hence the null-dropping caveat under composite by-id reads). Everything else
|
|
707
|
+
the native binding exposes — CRUD, reads, time series, metadata, query, CSV, and the
|
|
708
|
+
binary/expression subsystems — is documented above and callable.`;
|
package/src/time-series.ts
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
readUint64Out,
|
|
18
18
|
toCString,
|
|
19
19
|
} from "./ffi-helpers.ts";
|
|
20
|
-
import { updateGroupColumns } from "./group-columns.ts";
|
|
20
|
+
import { type GroupColumns, updateGroupColumns } from "./group-columns.ts";
|
|
21
21
|
import { getSymbols, type NativePointer } from "./loader.ts";
|
|
22
22
|
import {
|
|
23
23
|
type Allocation,
|
|
@@ -187,7 +187,7 @@ Database.prototype.updateTimeSeriesGroup = function (
|
|
|
187
187
|
collection: string,
|
|
188
188
|
group: string,
|
|
189
189
|
id: number,
|
|
190
|
-
data:
|
|
190
|
+
data: GroupColumns,
|
|
191
191
|
): void {
|
|
192
192
|
updateGroupColumns(
|
|
193
193
|
this._handle,
|
|
@@ -206,7 +206,7 @@ Database.prototype.updateTimeSeriesGroupByLabel = function (
|
|
|
206
206
|
collection: string,
|
|
207
207
|
group: string,
|
|
208
208
|
label: string,
|
|
209
|
-
data:
|
|
209
|
+
data: GroupColumns,
|
|
210
210
|
): void {
|
|
211
211
|
updateGroupColumns(
|
|
212
212
|
this._handle,
|
|
@@ -242,11 +242,12 @@ type UpsertRowFn = (
|
|
|
242
242
|
*/
|
|
243
243
|
function upsertRowColumns(
|
|
244
244
|
handle: NativePointer,
|
|
245
|
+
caller: string,
|
|
245
246
|
upsert: UpsertRowFn,
|
|
246
247
|
collection: string,
|
|
247
248
|
group: string,
|
|
248
249
|
key: number | string,
|
|
249
|
-
row: Record<string, number | bigint | string>,
|
|
250
|
+
row: Record<string, number | bigint | string | boolean>,
|
|
250
251
|
): void {
|
|
251
252
|
const collBuf = toCString(collection);
|
|
252
253
|
const grpBuf = toCString(group);
|
|
@@ -264,7 +265,11 @@ function upsertRowColumns(
|
|
|
264
265
|
const dataPtrs: (Pointer | null)[] = [];
|
|
265
266
|
|
|
266
267
|
for (let c = 0; c < columnCount; c++) {
|
|
267
|
-
const
|
|
268
|
+
const [colName, raw] = entries[c];
|
|
269
|
+
// SQLite has no boolean type: a boolean is INTEGER 1/0. Normalized here rather than tested in
|
|
270
|
+
// the INTEGER condition below, because Number.isInteger(true) is false — a boolean otherwise
|
|
271
|
+
// reaches allocNativeFloat64 and lands in the column as FLOAT 1.0, silently the wrong type.
|
|
272
|
+
const value = typeof raw === "boolean" ? (raw ? 1 : 0) : raw;
|
|
268
273
|
if (typeof value === "string") {
|
|
269
274
|
typesDv.setInt32(c * 4, DATA_TYPE_STRING, true);
|
|
270
275
|
const { table, keepalive: strPtrs } = allocNativeStringArray([value]);
|
|
@@ -275,11 +280,17 @@ function upsertRowColumns(
|
|
|
275
280
|
const p = allocNativeInt64([value]);
|
|
276
281
|
keepalive.push(p);
|
|
277
282
|
dataPtrs.push(p.ptr);
|
|
278
|
-
} else {
|
|
283
|
+
} else if (typeof value === "number") {
|
|
279
284
|
typesDv.setInt32(c * 4, DATA_TYPE_FLOAT, true);
|
|
280
|
-
const p = allocNativeFloat64([value
|
|
285
|
+
const p = allocNativeFloat64([value]);
|
|
281
286
|
keepalive.push(p);
|
|
282
287
|
dataPtrs.push(p.ptr);
|
|
288
|
+
} else {
|
|
289
|
+
// Mirrors updateGroupColumns: never let null/undefined/an object fall through to the FLOAT
|
|
290
|
+
// branch, where Number(null) is 0 and anything else is NaN — both written with no error.
|
|
291
|
+
throw new QuiverError(
|
|
292
|
+
`Cannot ${caller}: column '${colName}' has unsupported value type ${typeof value}`,
|
|
293
|
+
);
|
|
283
294
|
}
|
|
284
295
|
}
|
|
285
296
|
|
|
@@ -307,10 +318,11 @@ Database.prototype.upsertTimeSeriesRow = function (
|
|
|
307
318
|
collection: string,
|
|
308
319
|
group: string,
|
|
309
320
|
id: number,
|
|
310
|
-
row: Record<string, number | bigint | string>,
|
|
321
|
+
row: Record<string, number | bigint | string | boolean>,
|
|
311
322
|
): void {
|
|
312
323
|
upsertRowColumns(
|
|
313
324
|
this._handle,
|
|
325
|
+
"upsertTimeSeriesRow",
|
|
314
326
|
getSymbols().quiver_database_upsert_time_series_row,
|
|
315
327
|
collection,
|
|
316
328
|
group,
|
|
@@ -325,10 +337,11 @@ Database.prototype.upsertTimeSeriesRowByLabel = function (
|
|
|
325
337
|
collection: string,
|
|
326
338
|
group: string,
|
|
327
339
|
label: string,
|
|
328
|
-
row: Record<string, number | bigint | string>,
|
|
340
|
+
row: Record<string, number | bigint | string | boolean>,
|
|
329
341
|
): void {
|
|
330
342
|
upsertRowColumns(
|
|
331
343
|
this._handle,
|
|
344
|
+
"upsertTimeSeriesRowByLabel",
|
|
332
345
|
getSymbols().quiver_database_upsert_time_series_row_by_label,
|
|
333
346
|
collection,
|
|
334
347
|
group,
|