quiverdb 0.9.5 → 0.9.6
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/package.json +1 -1
- package/src/composites.ts +22 -15
- package/src/create.ts +8 -10
- package/src/csv.ts +2 -2
- package/src/database.ts +31 -10
- package/src/ffi-helpers.ts +5 -5
- package/src/index.ts +15 -1
- package/src/introspection.ts +4 -7
- package/src/loader.ts +2 -5
- package/src/lua-runner.ts +3 -12
- package/src/metadata.ts +13 -17
- package/src/query.ts +8 -6
- package/src/read.ts +28 -34
- package/src/time-series.ts +163 -26
- package/src/transaction.ts +1 -3
- package/src/types.ts +21 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
package/src/composites.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
import { Database } from "./database.ts";
|
|
2
|
+
import { QuiverError } from "./errors.ts";
|
|
3
|
+
import {
|
|
4
|
+
DATA_TYPE_DATE_TIME,
|
|
5
|
+
DATA_TYPE_FLOAT,
|
|
6
|
+
DATA_TYPE_INTEGER,
|
|
7
|
+
DATA_TYPE_STRING,
|
|
8
|
+
} from "./types.ts";
|
|
2
9
|
|
|
3
10
|
Database.prototype.readScalarsById = function (
|
|
4
11
|
this: Database,
|
|
@@ -10,18 +17,18 @@ Database.prototype.readScalarsById = function (
|
|
|
10
17
|
|
|
11
18
|
for (const attr of attributes) {
|
|
12
19
|
switch (attr.dataType) {
|
|
13
|
-
case
|
|
20
|
+
case DATA_TYPE_INTEGER:
|
|
14
21
|
result[attr.name] = this.readScalarIntegerById(collection, attr.name, id);
|
|
15
22
|
break;
|
|
16
|
-
case
|
|
23
|
+
case DATA_TYPE_FLOAT:
|
|
17
24
|
result[attr.name] = this.readScalarFloatById(collection, attr.name, id);
|
|
18
25
|
break;
|
|
19
|
-
case
|
|
20
|
-
case
|
|
26
|
+
case DATA_TYPE_STRING:
|
|
27
|
+
case DATA_TYPE_DATE_TIME:
|
|
21
28
|
result[attr.name] = this.readScalarStringById(collection, attr.name, id);
|
|
22
29
|
break;
|
|
23
30
|
default:
|
|
24
|
-
throw new
|
|
31
|
+
throw new QuiverError(`Unknown data type ${attr.dataType} for attribute '${attr.name}'`);
|
|
25
32
|
}
|
|
26
33
|
}
|
|
27
34
|
|
|
@@ -39,18 +46,18 @@ Database.prototype.readVectorsById = function (
|
|
|
39
46
|
for (const group of groups) {
|
|
40
47
|
for (const col of group.valueColumns) {
|
|
41
48
|
switch (col.dataType) {
|
|
42
|
-
case
|
|
49
|
+
case DATA_TYPE_INTEGER:
|
|
43
50
|
result[col.name] = this.readVectorIntegersById(collection, col.name, id);
|
|
44
51
|
break;
|
|
45
|
-
case
|
|
52
|
+
case DATA_TYPE_FLOAT:
|
|
46
53
|
result[col.name] = this.readVectorFloatsById(collection, col.name, id);
|
|
47
54
|
break;
|
|
48
|
-
case
|
|
49
|
-
case
|
|
55
|
+
case DATA_TYPE_STRING:
|
|
56
|
+
case DATA_TYPE_DATE_TIME:
|
|
50
57
|
result[col.name] = this.readVectorStringsById(collection, col.name, id);
|
|
51
58
|
break;
|
|
52
59
|
default:
|
|
53
|
-
throw new
|
|
60
|
+
throw new QuiverError(`Unknown data type ${col.dataType} for column '${col.name}'`);
|
|
54
61
|
}
|
|
55
62
|
}
|
|
56
63
|
}
|
|
@@ -69,18 +76,18 @@ Database.prototype.readSetsById = function (
|
|
|
69
76
|
for (const group of groups) {
|
|
70
77
|
for (const col of group.valueColumns) {
|
|
71
78
|
switch (col.dataType) {
|
|
72
|
-
case
|
|
79
|
+
case DATA_TYPE_INTEGER:
|
|
73
80
|
result[col.name] = this.readSetIntegersById(collection, col.name, id);
|
|
74
81
|
break;
|
|
75
|
-
case
|
|
82
|
+
case DATA_TYPE_FLOAT:
|
|
76
83
|
result[col.name] = this.readSetFloatsById(collection, col.name, id);
|
|
77
84
|
break;
|
|
78
|
-
case
|
|
79
|
-
case
|
|
85
|
+
case DATA_TYPE_STRING:
|
|
86
|
+
case DATA_TYPE_DATE_TIME:
|
|
80
87
|
result[col.name] = this.readSetStringsById(collection, col.name, id);
|
|
81
88
|
break;
|
|
82
89
|
default:
|
|
83
|
-
throw new
|
|
90
|
+
throw new QuiverError(`Unknown data type ${col.dataType} for column '${col.name}'`);
|
|
84
91
|
}
|
|
85
92
|
}
|
|
86
93
|
}
|
package/src/create.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ptr } from "bun:ffi";
|
|
2
1
|
import { Database } from "./database.ts";
|
|
3
2
|
import { check, QuiverError } from "./errors.ts";
|
|
4
3
|
import {
|
|
@@ -30,8 +29,8 @@ function setElementArray(
|
|
|
30
29
|
const first = values[0];
|
|
31
30
|
|
|
32
31
|
if (typeof first === "bigint") {
|
|
33
|
-
const arr = allocNativeInt64(
|
|
34
|
-
check(lib.quiver_element_set_array_integer(elemPtr, nameBuf.buf, arr.
|
|
32
|
+
const arr = allocNativeInt64(values as bigint[]);
|
|
33
|
+
check(lib.quiver_element_set_array_integer(elemPtr, nameBuf.buf, arr.buf, values.length));
|
|
35
34
|
return;
|
|
36
35
|
}
|
|
37
36
|
|
|
@@ -39,17 +38,17 @@ function setElementArray(
|
|
|
39
38
|
const allIntegers = (values as number[]).every((v) => Number.isInteger(v));
|
|
40
39
|
if (allIntegers) {
|
|
41
40
|
const arr = allocNativeInt64(values as number[]);
|
|
42
|
-
check(lib.quiver_element_set_array_integer(elemPtr, nameBuf.buf, arr.
|
|
41
|
+
check(lib.quiver_element_set_array_integer(elemPtr, nameBuf.buf, arr.buf, values.length));
|
|
43
42
|
} else {
|
|
44
43
|
const arr = allocNativeFloat64(values as number[]);
|
|
45
|
-
check(lib.quiver_element_set_array_float(elemPtr, nameBuf.buf, arr.
|
|
44
|
+
check(lib.quiver_element_set_array_float(elemPtr, nameBuf.buf, arr.buf, values.length));
|
|
46
45
|
}
|
|
47
46
|
return;
|
|
48
47
|
}
|
|
49
48
|
|
|
50
49
|
if (typeof first === "string") {
|
|
51
50
|
const { table, keepalive: _keepalive } = allocNativeStringArray(values as string[]);
|
|
52
|
-
check(lib.quiver_element_set_array_string(elemPtr, nameBuf.buf, table.
|
|
51
|
+
check(lib.quiver_element_set_array_string(elemPtr, nameBuf.buf, table.buf, values.length));
|
|
53
52
|
return;
|
|
54
53
|
}
|
|
55
54
|
|
|
@@ -101,7 +100,7 @@ Database.prototype.createElement = function (
|
|
|
101
100
|
const handle = this._handle;
|
|
102
101
|
|
|
103
102
|
const outElem = allocPtrOut();
|
|
104
|
-
check(lib.quiver_element_create(outElem.
|
|
103
|
+
check(lib.quiver_element_create(outElem.buf));
|
|
105
104
|
const elemPtr = readPtrOut(outElem);
|
|
106
105
|
|
|
107
106
|
try {
|
|
@@ -111,9 +110,8 @@ Database.prototype.createElement = function (
|
|
|
111
110
|
}
|
|
112
111
|
|
|
113
112
|
const outIdBuf = new Uint8Array(8);
|
|
114
|
-
const outIdPtr = ptr(outIdBuf);
|
|
115
113
|
const collBuf = toCString(collection);
|
|
116
|
-
check(lib.quiver_database_create_element(handle, collBuf.buf, elemPtr,
|
|
114
|
+
check(lib.quiver_database_create_element(handle, collBuf.buf, elemPtr, outIdBuf));
|
|
117
115
|
return Number(new DataView(outIdBuf.buffer).getBigInt64(0, true));
|
|
118
116
|
} finally {
|
|
119
117
|
lib.quiver_element_destroy(elemPtr);
|
|
@@ -130,7 +128,7 @@ Database.prototype.updateElement = function (
|
|
|
130
128
|
const handle = this._handle;
|
|
131
129
|
|
|
132
130
|
const outElem = allocPtrOut();
|
|
133
|
-
check(lib.quiver_element_create(outElem.
|
|
131
|
+
check(lib.quiver_element_create(outElem.buf));
|
|
134
132
|
const elemPtr = readPtrOut(outElem);
|
|
135
133
|
|
|
136
134
|
try {
|
package/src/csv.ts
CHANGED
|
@@ -96,7 +96,7 @@ Database.prototype.exportCsv = function (
|
|
|
96
96
|
const pathBuf = toCString(filePath);
|
|
97
97
|
const [optsBuf, _keepalive] = buildCsvOptionsBuffer(options);
|
|
98
98
|
check(
|
|
99
|
-
lib.quiver_database_export_csv(this._handle, collBuf.buf, grpBuf.buf, pathBuf.buf, optsBuf.
|
|
99
|
+
lib.quiver_database_export_csv(this._handle, collBuf.buf, grpBuf.buf, pathBuf.buf, optsBuf.buf),
|
|
100
100
|
);
|
|
101
101
|
};
|
|
102
102
|
|
|
@@ -113,6 +113,6 @@ Database.prototype.importCsv = function (
|
|
|
113
113
|
const pathBuf = toCString(filePath);
|
|
114
114
|
const [optsBuf, _keepalive] = buildCsvOptionsBuffer(options);
|
|
115
115
|
check(
|
|
116
|
-
lib.quiver_database_import_csv(this._handle, collBuf.buf, grpBuf.buf, pathBuf.buf, optsBuf.
|
|
116
|
+
lib.quiver_database_import_csv(this._handle, collBuf.buf, grpBuf.buf, pathBuf.buf, optsBuf.buf),
|
|
117
117
|
);
|
|
118
118
|
};
|
package/src/database.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { NativePointer } from "./loader.ts";
|
|
|
5
5
|
import { getSymbols } from "./loader.ts";
|
|
6
6
|
import type { GroupMetadata, ScalarMetadata } from "./metadata.ts";
|
|
7
7
|
import type { TimeSeriesData } from "./time-series.ts";
|
|
8
|
-
import type { ElementData, QueryParam } from "./types.ts";
|
|
8
|
+
import type { DatabaseOptions, ElementData, QueryParam } from "./types.ts";
|
|
9
9
|
|
|
10
10
|
export class Database {
|
|
11
11
|
private _ptr: NativePointer;
|
|
@@ -15,41 +15,50 @@ export class Database {
|
|
|
15
15
|
this._ptr = nativePtr;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
static fromSchema(dbPath: string, schemaPath: string): Database {
|
|
18
|
+
static fromSchema(dbPath: string, schemaPath: string, options?: DatabaseOptions): Database {
|
|
19
19
|
const lib = getSymbols();
|
|
20
|
-
const
|
|
20
|
+
const optionsBuf = makeDefaultOptions(options);
|
|
21
21
|
const outDb = allocPtrOut();
|
|
22
22
|
const dbPathBuf = toCString(dbPath);
|
|
23
23
|
const schemaPathBuf = toCString(schemaPath);
|
|
24
24
|
|
|
25
25
|
check(
|
|
26
|
-
lib.quiver_database_from_schema(dbPathBuf.buf, schemaPathBuf.buf,
|
|
26
|
+
lib.quiver_database_from_schema(dbPathBuf.buf, schemaPathBuf.buf, optionsBuf.buf, outDb.buf),
|
|
27
27
|
);
|
|
28
28
|
|
|
29
29
|
return new Database(readPtrOut(outDb));
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
static fromMigrations(
|
|
32
|
+
static fromMigrations(
|
|
33
|
+
dbPath: string,
|
|
34
|
+
migrationsPath: string,
|
|
35
|
+
options?: DatabaseOptions,
|
|
36
|
+
): Database {
|
|
33
37
|
const lib = getSymbols();
|
|
34
|
-
const
|
|
38
|
+
const optionsBuf = makeDefaultOptions(options);
|
|
35
39
|
const outDb = allocPtrOut();
|
|
36
40
|
const dbPathBuf = toCString(dbPath);
|
|
37
41
|
const migrPathBuf = toCString(migrationsPath);
|
|
38
42
|
|
|
39
43
|
check(
|
|
40
|
-
lib.quiver_database_from_migrations(
|
|
44
|
+
lib.quiver_database_from_migrations(
|
|
45
|
+
dbPathBuf.buf,
|
|
46
|
+
migrPathBuf.buf,
|
|
47
|
+
optionsBuf.buf,
|
|
48
|
+
outDb.buf,
|
|
49
|
+
),
|
|
41
50
|
);
|
|
42
51
|
|
|
43
52
|
return new Database(readPtrOut(outDb));
|
|
44
53
|
}
|
|
45
54
|
|
|
46
|
-
static open(dbPath: string): Database {
|
|
55
|
+
static open(dbPath: string, options?: DatabaseOptions): Database {
|
|
47
56
|
const lib = getSymbols();
|
|
48
|
-
const
|
|
57
|
+
const optionsBuf = makeDefaultOptions(options);
|
|
49
58
|
const outDb = allocPtrOut();
|
|
50
59
|
const dbPathBuf = toCString(dbPath);
|
|
51
60
|
|
|
52
|
-
check(lib.quiver_database_open(dbPathBuf.buf,
|
|
61
|
+
check(lib.quiver_database_open(dbPathBuf.buf, optionsBuf.buf, outDb.buf));
|
|
53
62
|
|
|
54
63
|
return new Database(readPtrOut(outDb));
|
|
55
64
|
}
|
|
@@ -130,12 +139,24 @@ export class Database {
|
|
|
130
139
|
|
|
131
140
|
// --- Time series (implemented in time-series.ts) ---
|
|
132
141
|
declare readTimeSeriesGroup: (collection: string, group: string, id: number) => TimeSeriesData;
|
|
142
|
+
declare readTimeSeriesRow: (
|
|
143
|
+
collection: string,
|
|
144
|
+
group: string,
|
|
145
|
+
attribute: string,
|
|
146
|
+
dateTime: string,
|
|
147
|
+
) => (number | string | null)[];
|
|
133
148
|
declare updateTimeSeriesGroup: (
|
|
134
149
|
collection: string,
|
|
135
150
|
group: string,
|
|
136
151
|
id: number,
|
|
137
152
|
data: TimeSeriesData,
|
|
138
153
|
) => void;
|
|
154
|
+
declare addTimeSeriesRow: (
|
|
155
|
+
collection: string,
|
|
156
|
+
group: string,
|
|
157
|
+
id: number,
|
|
158
|
+
row: Record<string, number | bigint | string>,
|
|
159
|
+
) => void;
|
|
139
160
|
declare hasTimeSeriesFiles: (collection: string) => boolean;
|
|
140
161
|
declare listTimeSeriesFilesColumns: (collection: string) => string[];
|
|
141
162
|
declare readTimeSeriesFiles: (collection: string) => Record<string, string | null>;
|
package/src/ffi-helpers.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CString, type Pointer, ptr, read, toArrayBuffer } from "bun:ffi";
|
|
2
|
-
import type
|
|
2
|
+
import { type Allocation, type DatabaseOptions, LOG_LEVEL_INFO } from "./types.ts";
|
|
3
3
|
|
|
4
4
|
const encoder = new TextEncoder();
|
|
5
5
|
|
|
@@ -7,11 +7,11 @@ const encoder = new TextEncoder();
|
|
|
7
7
|
* Construct the 8-byte quiver_database_options_t struct as an Allocation.
|
|
8
8
|
* Layout: offset 0 = int32 read_only (default 0), offset 4 = int32 console_level (default 1 = QUIVER_LOG_INFO).
|
|
9
9
|
*/
|
|
10
|
-
export function makeDefaultOptions(): Allocation {
|
|
10
|
+
export function makeDefaultOptions(options?: DatabaseOptions): Allocation {
|
|
11
11
|
const buf = new Uint8Array(8);
|
|
12
12
|
const dv = new DataView(buf.buffer);
|
|
13
|
-
dv.setInt32(0, 0, true);
|
|
14
|
-
dv.setInt32(4,
|
|
13
|
+
dv.setInt32(0, options?.readOnly ? 1 : 0, true);
|
|
14
|
+
dv.setInt32(4, options?.consoleLevel ?? LOG_LEVEL_INFO, true);
|
|
15
15
|
return { ptr: ptr(buf), buf };
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -102,7 +102,7 @@ export function toCString(str: string): Allocation {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
/** Allocate native memory for an array of int64 values. */
|
|
105
|
-
export function allocNativeInt64(values: number[]): Allocation {
|
|
105
|
+
export function allocNativeInt64(values: (number | bigint)[]): Allocation {
|
|
106
106
|
const buf = new Uint8Array(values.length * 8);
|
|
107
107
|
const dv = new DataView(buf.buffer);
|
|
108
108
|
for (let i = 0; i < values.length; i++) {
|
package/src/index.ts
CHANGED
|
@@ -14,4 +14,18 @@ export { QuiverError } from "./errors.ts";
|
|
|
14
14
|
export { LuaRunner } from "./lua-runner.ts";
|
|
15
15
|
export type { GroupMetadata, ScalarMetadata } from "./metadata.ts";
|
|
16
16
|
export type { TimeSeriesData } from "./time-series.ts";
|
|
17
|
-
export
|
|
17
|
+
export {
|
|
18
|
+
LOG_LEVEL_DEBUG,
|
|
19
|
+
LOG_LEVEL_ERROR,
|
|
20
|
+
LOG_LEVEL_INFO,
|
|
21
|
+
LOG_LEVEL_OFF,
|
|
22
|
+
LOG_LEVEL_WARN,
|
|
23
|
+
} from "./types.ts";
|
|
24
|
+
export type {
|
|
25
|
+
ArrayValue,
|
|
26
|
+
DatabaseOptions,
|
|
27
|
+
ElementData,
|
|
28
|
+
QueryParam,
|
|
29
|
+
ScalarValue,
|
|
30
|
+
Value,
|
|
31
|
+
} from "./types.ts";
|
package/src/introspection.ts
CHANGED
|
@@ -1,29 +1,26 @@
|
|
|
1
|
-
import { ptr } from "bun:ffi";
|
|
2
1
|
import { Database } from "./database.ts";
|
|
3
2
|
import { check } from "./errors.ts";
|
|
4
|
-
import { allocPtrOut, decodeStringFromBuf
|
|
3
|
+
import { allocPtrOut, decodeStringFromBuf } from "./ffi-helpers.ts";
|
|
5
4
|
import { getSymbols } from "./loader.ts";
|
|
6
5
|
|
|
7
6
|
Database.prototype.isHealthy = function (this: Database): boolean {
|
|
8
7
|
const lib = getSymbols();
|
|
9
8
|
const outBuf = new Uint8Array(4);
|
|
10
|
-
|
|
11
|
-
check(lib.quiver_database_is_healthy(this._handle, outPtr));
|
|
9
|
+
check(lib.quiver_database_is_healthy(this._handle, outBuf));
|
|
12
10
|
return new DataView(outBuf.buffer).getInt32(0, true) !== 0;
|
|
13
11
|
};
|
|
14
12
|
|
|
15
13
|
Database.prototype.currentVersion = function (this: Database): number {
|
|
16
14
|
const lib = getSymbols();
|
|
17
15
|
const outBuf = new Uint8Array(8);
|
|
18
|
-
|
|
19
|
-
check(lib.quiver_database_current_version(this._handle, outPtr));
|
|
16
|
+
check(lib.quiver_database_current_version(this._handle, outBuf));
|
|
20
17
|
return Number(new DataView(outBuf.buffer).getBigInt64(0, true));
|
|
21
18
|
};
|
|
22
19
|
|
|
23
20
|
Database.prototype.path = function (this: Database): string {
|
|
24
21
|
const lib = getSymbols();
|
|
25
22
|
const outPath = allocPtrOut();
|
|
26
|
-
check(lib.quiver_database_path(this._handle, outPath.
|
|
23
|
+
check(lib.quiver_database_path(this._handle, outPath.buf));
|
|
27
24
|
return decodeStringFromBuf(outPath);
|
|
28
25
|
};
|
|
29
26
|
|
package/src/loader.ts
CHANGED
|
@@ -13,7 +13,6 @@ const I32 = "i32" as const;
|
|
|
13
13
|
const I64 = "i64" as const;
|
|
14
14
|
const USIZE = "usize" as const;
|
|
15
15
|
const F64 = "f64" as const;
|
|
16
|
-
const V = "void" as const;
|
|
17
16
|
|
|
18
17
|
// Platform constants. `suffix` from bun:ffi is the platform-correct shared
|
|
19
18
|
// library extension ("dll" | "dylib" | "so").
|
|
@@ -30,7 +29,6 @@ export type NativePointer = Pointer | null;
|
|
|
30
29
|
const lifecycleSymbols = {
|
|
31
30
|
quiver_version: { args: [], returns: P },
|
|
32
31
|
quiver_get_last_error: { args: [], returns: P },
|
|
33
|
-
quiver_clear_last_error: { args: [], returns: V },
|
|
34
32
|
// quiver_database_options_default is intentionally omitted: it returns a
|
|
35
33
|
// struct by value, which Bun FFI does not support (oven-sh/bun#6139). It was
|
|
36
34
|
// never called -- makeDefaultOptions() in ffi-helpers.ts builds the options
|
|
@@ -116,6 +114,8 @@ const metadataSymbols = {
|
|
|
116
114
|
|
|
117
115
|
const timeSeriesSymbols = {
|
|
118
116
|
quiver_database_read_time_series_group: { args: [P, BUF, BUF, I64, P, P, P, P, P], returns: I32 },
|
|
117
|
+
quiver_database_read_time_series_row: { args: [P, BUF, BUF, BUF, BUF, P, P, P], returns: I32 },
|
|
118
|
+
quiver_database_add_time_series_row: { args: [P, BUF, BUF, I64, P, P, P, USIZE], returns: I32 },
|
|
119
119
|
quiver_database_update_time_series_group: {
|
|
120
120
|
args: [P, BUF, BUF, I64, P, P, P, USIZE, USIZE],
|
|
121
121
|
returns: I32,
|
|
@@ -149,7 +149,6 @@ const luaSymbols = {
|
|
|
149
149
|
quiver_lua_runner_new: { args: [P, P], returns: I32 },
|
|
150
150
|
quiver_lua_runner_free: { args: [P], returns: I32 },
|
|
151
151
|
quiver_lua_runner_run: { args: [P, BUF], returns: I32 },
|
|
152
|
-
quiver_lua_runner_get_error: { args: [P, P], returns: I32 },
|
|
153
152
|
} as const;
|
|
154
153
|
|
|
155
154
|
// Combined symbol map for dlopen.
|
|
@@ -281,5 +280,3 @@ export function loadLibrary(): QuiverLib {
|
|
|
281
280
|
export function getSymbols() {
|
|
282
281
|
return loadLibrary().symbols;
|
|
283
282
|
}
|
|
284
|
-
|
|
285
|
-
export type Symbols = ReturnType<typeof getSymbols>;
|
package/src/lua-runner.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Database } from "./database.ts";
|
|
2
2
|
import { check, QuiverError } from "./errors.ts";
|
|
3
|
-
import { allocPtrOut,
|
|
3
|
+
import { allocPtrOut, readPtrOut, toCString } from "./ffi-helpers.ts";
|
|
4
4
|
import type { NativePointer } from "./loader.ts";
|
|
5
5
|
import { getSymbols } from "./loader.ts";
|
|
6
6
|
|
|
@@ -13,7 +13,7 @@ export class LuaRunner {
|
|
|
13
13
|
this._db = db;
|
|
14
14
|
const lib = getSymbols();
|
|
15
15
|
const outRunner = allocPtrOut();
|
|
16
|
-
check(lib.quiver_lua_runner_new(db._handle, outRunner.
|
|
16
|
+
check(lib.quiver_lua_runner_new(db._handle, outRunner.buf));
|
|
17
17
|
this._ptr = readPtrOut(outRunner);
|
|
18
18
|
}
|
|
19
19
|
|
|
@@ -21,16 +21,7 @@ export class LuaRunner {
|
|
|
21
21
|
this.ensureOpen();
|
|
22
22
|
const lib = getSymbols();
|
|
23
23
|
const scriptBuf = toCString(script);
|
|
24
|
-
|
|
25
|
-
if (err !== 0) {
|
|
26
|
-
const outError = allocPtrOut();
|
|
27
|
-
const getErr = lib.quiver_lua_runner_get_error(this._ptr, outError.ptr);
|
|
28
|
-
if (getErr === 0 && readPtrOut(outError)) {
|
|
29
|
-
const msg = decodeStringFromBuf(outError);
|
|
30
|
-
if (msg) throw new QuiverError(msg);
|
|
31
|
-
}
|
|
32
|
-
check(err);
|
|
33
|
-
}
|
|
24
|
+
check(lib.quiver_lua_runner_run(this._ptr, scriptBuf.buf));
|
|
34
25
|
}
|
|
35
26
|
|
|
36
27
|
close(): void {
|
package/src/metadata.ts
CHANGED
|
@@ -79,10 +79,9 @@ Database.prototype.getScalarMetadata = function (
|
|
|
79
79
|
const collBuf = toCString(collection);
|
|
80
80
|
const attrBuf = toCString(attribute);
|
|
81
81
|
const outBuf = new Uint8Array(SCALAR_METADATA_SIZE);
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
lib.quiver_database_free_scalar_metadata(outPtr);
|
|
82
|
+
check(lib.quiver_database_get_scalar_metadata(this._handle, collBuf.buf, attrBuf.buf, outBuf));
|
|
83
|
+
const result = readScalarMetadataAt(ptr(outBuf), 0);
|
|
84
|
+
lib.quiver_database_free_scalar_metadata(outBuf);
|
|
86
85
|
return result;
|
|
87
86
|
};
|
|
88
87
|
|
|
@@ -95,10 +94,9 @@ Database.prototype.getVectorMetadata = function (
|
|
|
95
94
|
const collBuf = toCString(collection);
|
|
96
95
|
const groupBuf = toCString(groupName);
|
|
97
96
|
const outBuf = new Uint8Array(GROUP_METADATA_SIZE);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
lib.quiver_database_free_group_metadata(outPtr);
|
|
97
|
+
check(lib.quiver_database_get_vector_metadata(this._handle, collBuf.buf, groupBuf.buf, outBuf));
|
|
98
|
+
const result = readGroupMetadataAt(ptr(outBuf), 0);
|
|
99
|
+
lib.quiver_database_free_group_metadata(outBuf);
|
|
102
100
|
return result;
|
|
103
101
|
};
|
|
104
102
|
|
|
@@ -111,10 +109,9 @@ Database.prototype.getSetMetadata = function (
|
|
|
111
109
|
const collBuf = toCString(collection);
|
|
112
110
|
const groupBuf = toCString(groupName);
|
|
113
111
|
const outBuf = new Uint8Array(GROUP_METADATA_SIZE);
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
lib.quiver_database_free_group_metadata(outPtr);
|
|
112
|
+
check(lib.quiver_database_get_set_metadata(this._handle, collBuf.buf, groupBuf.buf, outBuf));
|
|
113
|
+
const result = readGroupMetadataAt(ptr(outBuf), 0);
|
|
114
|
+
lib.quiver_database_free_group_metadata(outBuf);
|
|
118
115
|
return result;
|
|
119
116
|
};
|
|
120
117
|
|
|
@@ -127,12 +124,11 @@ Database.prototype.getTimeSeriesMetadata = function (
|
|
|
127
124
|
const collBuf = toCString(collection);
|
|
128
125
|
const groupBuf = toCString(groupName);
|
|
129
126
|
const outBuf = new Uint8Array(GROUP_METADATA_SIZE);
|
|
130
|
-
const outPtr = ptr(outBuf);
|
|
131
127
|
check(
|
|
132
|
-
lib.quiver_database_get_time_series_metadata(this._handle, collBuf.buf, groupBuf.buf,
|
|
128
|
+
lib.quiver_database_get_time_series_metadata(this._handle, collBuf.buf, groupBuf.buf, outBuf),
|
|
133
129
|
);
|
|
134
|
-
const result = readGroupMetadataAt(
|
|
135
|
-
lib.quiver_database_free_group_metadata(
|
|
130
|
+
const result = readGroupMetadataAt(ptr(outBuf), 0);
|
|
131
|
+
lib.quiver_database_free_group_metadata(outBuf);
|
|
136
132
|
return result;
|
|
137
133
|
};
|
|
138
134
|
|
|
@@ -148,7 +144,7 @@ function listMetadata<T>(
|
|
|
148
144
|
const collBuf = toCString(collection);
|
|
149
145
|
const outArray = allocPtrOut();
|
|
150
146
|
const outCount = allocUint64Out();
|
|
151
|
-
check((lib as Record<string, Function>)[fn](handle, collBuf.buf, outArray.
|
|
147
|
+
check((lib as Record<string, Function>)[fn](handle, collBuf.buf, outArray.buf, outCount.buf));
|
|
152
148
|
const count = readUint64Out(outCount);
|
|
153
149
|
if (count === 0) return [];
|
|
154
150
|
const arrPtr = readPtrOut(outArray);
|
package/src/query.ts
CHANGED
|
@@ -12,12 +12,14 @@ import {
|
|
|
12
12
|
toCString,
|
|
13
13
|
} from "./ffi-helpers.ts";
|
|
14
14
|
import { getSymbols } from "./loader.ts";
|
|
15
|
-
import
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
import {
|
|
16
|
+
type Allocation,
|
|
17
|
+
DATA_TYPE_FLOAT,
|
|
18
|
+
DATA_TYPE_INTEGER,
|
|
19
|
+
DATA_TYPE_NULL,
|
|
20
|
+
DATA_TYPE_STRING,
|
|
21
|
+
type QueryParam,
|
|
22
|
+
} from "./types.ts";
|
|
21
23
|
|
|
22
24
|
function marshalParams(parameters: QueryParam[]): {
|
|
23
25
|
types: Allocation;
|
package/src/read.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ptr } from "bun:ffi";
|
|
2
1
|
import { Database } from "./database.ts";
|
|
3
2
|
import { check } from "./errors.ts";
|
|
4
3
|
import {
|
|
@@ -33,8 +32,8 @@ Database.prototype.readScalarIntegers = function (
|
|
|
33
32
|
this._handle,
|
|
34
33
|
collBuf.buf,
|
|
35
34
|
attrBuf.buf,
|
|
36
|
-
outValues.
|
|
37
|
-
outCount.
|
|
35
|
+
outValues.buf,
|
|
36
|
+
outCount.buf,
|
|
38
37
|
),
|
|
39
38
|
);
|
|
40
39
|
const count = readUint64Out(outCount);
|
|
@@ -60,8 +59,8 @@ Database.prototype.readScalarFloats = function (
|
|
|
60
59
|
this._handle,
|
|
61
60
|
collBuf.buf,
|
|
62
61
|
attrBuf.buf,
|
|
63
|
-
outValues.
|
|
64
|
-
outCount.
|
|
62
|
+
outValues.buf,
|
|
63
|
+
outCount.buf,
|
|
65
64
|
),
|
|
66
65
|
);
|
|
67
66
|
const count = readUint64Out(outCount);
|
|
@@ -87,8 +86,8 @@ Database.prototype.readScalarStrings = function (
|
|
|
87
86
|
this._handle,
|
|
88
87
|
collBuf.buf,
|
|
89
88
|
attrBuf.buf,
|
|
90
|
-
outValues.
|
|
91
|
-
outCount.
|
|
89
|
+
outValues.buf,
|
|
90
|
+
outCount.buf,
|
|
92
91
|
),
|
|
93
92
|
);
|
|
94
93
|
const count = readUint64Out(outCount);
|
|
@@ -111,17 +110,15 @@ Database.prototype.readScalarIntegerById = function (
|
|
|
111
110
|
const collBuf = toCString(collection);
|
|
112
111
|
const attrBuf = toCString(attribute);
|
|
113
112
|
const outValBuf = new Uint8Array(8);
|
|
114
|
-
const outValPtr = ptr(outValBuf);
|
|
115
113
|
const outHasBuf = new Uint8Array(4);
|
|
116
|
-
const outHasPtr = ptr(outHasBuf);
|
|
117
114
|
check(
|
|
118
115
|
lib.quiver_database_read_scalar_integer_by_id(
|
|
119
116
|
this._handle,
|
|
120
117
|
collBuf.buf,
|
|
121
118
|
attrBuf.buf,
|
|
122
119
|
BigInt(id),
|
|
123
|
-
|
|
124
|
-
|
|
120
|
+
outValBuf,
|
|
121
|
+
outHasBuf,
|
|
125
122
|
),
|
|
126
123
|
);
|
|
127
124
|
if (new DataView(outHasBuf.buffer).getInt32(0, true) === 0) return null;
|
|
@@ -138,17 +135,15 @@ Database.prototype.readScalarFloatById = function (
|
|
|
138
135
|
const collBuf = toCString(collection);
|
|
139
136
|
const attrBuf = toCString(attribute);
|
|
140
137
|
const outValBuf = new Uint8Array(8);
|
|
141
|
-
const outValPtr = ptr(outValBuf);
|
|
142
138
|
const outHasBuf = new Uint8Array(4);
|
|
143
|
-
const outHasPtr = ptr(outHasBuf);
|
|
144
139
|
check(
|
|
145
140
|
lib.quiver_database_read_scalar_float_by_id(
|
|
146
141
|
this._handle,
|
|
147
142
|
collBuf.buf,
|
|
148
143
|
attrBuf.buf,
|
|
149
144
|
BigInt(id),
|
|
150
|
-
|
|
151
|
-
|
|
145
|
+
outValBuf,
|
|
146
|
+
outHasBuf,
|
|
152
147
|
),
|
|
153
148
|
);
|
|
154
149
|
if (new DataView(outHasBuf.buffer).getInt32(0, true) === 0) return null;
|
|
@@ -166,15 +161,14 @@ Database.prototype.readScalarStringById = function (
|
|
|
166
161
|
const attrBuf = toCString(attribute);
|
|
167
162
|
const outValue = allocPtrOut();
|
|
168
163
|
const outHasBuf = new Uint8Array(4);
|
|
169
|
-
const outHasPtr = ptr(outHasBuf);
|
|
170
164
|
check(
|
|
171
165
|
lib.quiver_database_read_scalar_string_by_id(
|
|
172
166
|
this._handle,
|
|
173
167
|
collBuf.buf,
|
|
174
168
|
attrBuf.buf,
|
|
175
169
|
BigInt(id),
|
|
176
|
-
outValue.
|
|
177
|
-
|
|
170
|
+
outValue.buf,
|
|
171
|
+
outHasBuf,
|
|
178
172
|
),
|
|
179
173
|
);
|
|
180
174
|
if (new DataView(outHasBuf.buffer).getInt32(0, true) === 0) return null;
|
|
@@ -190,7 +184,7 @@ Database.prototype.readElementIds = function (this: Database, collection: string
|
|
|
190
184
|
const collBuf = toCString(collection);
|
|
191
185
|
const outIds = allocPtrOut();
|
|
192
186
|
const outCount = allocUint64Out();
|
|
193
|
-
check(lib.quiver_database_read_element_ids(this._handle, collBuf.buf, outIds.
|
|
187
|
+
check(lib.quiver_database_read_element_ids(this._handle, collBuf.buf, outIds.buf, outCount.buf));
|
|
194
188
|
const count = readUint64Out(outCount);
|
|
195
189
|
if (count === 0) return [];
|
|
196
190
|
const arrPtr = readPtrOut(outIds);
|
|
@@ -218,9 +212,9 @@ function readBulkIntegers(
|
|
|
218
212
|
handle,
|
|
219
213
|
collBuf.buf,
|
|
220
214
|
attrBuf.buf,
|
|
221
|
-
outVectors.
|
|
222
|
-
outSizes.
|
|
223
|
-
outCount.
|
|
215
|
+
outVectors.buf,
|
|
216
|
+
outSizes.buf,
|
|
217
|
+
outCount.buf,
|
|
224
218
|
),
|
|
225
219
|
);
|
|
226
220
|
const count = readUint64Out(outCount);
|
|
@@ -254,9 +248,9 @@ function readBulkFloats(
|
|
|
254
248
|
handle,
|
|
255
249
|
collBuf.buf,
|
|
256
250
|
attrBuf.buf,
|
|
257
|
-
outVectors.
|
|
258
|
-
outSizes.
|
|
259
|
-
outCount.
|
|
251
|
+
outVectors.buf,
|
|
252
|
+
outSizes.buf,
|
|
253
|
+
outCount.buf,
|
|
260
254
|
),
|
|
261
255
|
);
|
|
262
256
|
const count = readUint64Out(outCount);
|
|
@@ -290,9 +284,9 @@ function readBulkStrings(
|
|
|
290
284
|
handle,
|
|
291
285
|
collBuf.buf,
|
|
292
286
|
attrBuf.buf,
|
|
293
|
-
outVectors.
|
|
294
|
-
outSizes.
|
|
295
|
-
outCount.
|
|
287
|
+
outVectors.buf,
|
|
288
|
+
outSizes.buf,
|
|
289
|
+
outCount.buf,
|
|
296
290
|
),
|
|
297
291
|
);
|
|
298
292
|
const count = readUint64Out(outCount);
|
|
@@ -408,8 +402,8 @@ function readByIdIntegers(
|
|
|
408
402
|
collBuf.buf,
|
|
409
403
|
attrBuf.buf,
|
|
410
404
|
BigInt(id),
|
|
411
|
-
outValues.
|
|
412
|
-
outCount.
|
|
405
|
+
outValues.buf,
|
|
406
|
+
outCount.buf,
|
|
413
407
|
),
|
|
414
408
|
);
|
|
415
409
|
const count = readUint64Out(outCount);
|
|
@@ -438,8 +432,8 @@ function readByIdFloats(
|
|
|
438
432
|
collBuf.buf,
|
|
439
433
|
attrBuf.buf,
|
|
440
434
|
BigInt(id),
|
|
441
|
-
outValues.
|
|
442
|
-
outCount.
|
|
435
|
+
outValues.buf,
|
|
436
|
+
outCount.buf,
|
|
443
437
|
),
|
|
444
438
|
);
|
|
445
439
|
const count = readUint64Out(outCount);
|
|
@@ -468,8 +462,8 @@ function readByIdStrings(
|
|
|
468
462
|
collBuf.buf,
|
|
469
463
|
attrBuf.buf,
|
|
470
464
|
BigInt(id),
|
|
471
|
-
outValues.
|
|
472
|
-
outCount.
|
|
465
|
+
outValues.buf,
|
|
466
|
+
outCount.buf,
|
|
473
467
|
),
|
|
474
468
|
);
|
|
475
469
|
const count = readUint64Out(outCount);
|
package/src/time-series.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CString, type Pointer, ptr, read, toArrayBuffer } from "bun:ffi";
|
|
2
2
|
import { Database } from "./database.ts";
|
|
3
|
-
import { check } from "./errors.ts";
|
|
3
|
+
import { check, QuiverError } from "./errors.ts";
|
|
4
4
|
import {
|
|
5
5
|
allocNativeFloat64,
|
|
6
6
|
allocNativeInt64,
|
|
@@ -18,15 +18,16 @@ import {
|
|
|
18
18
|
toCString,
|
|
19
19
|
} from "./ffi-helpers.ts";
|
|
20
20
|
import { getSymbols } from "./loader.ts";
|
|
21
|
-
import
|
|
21
|
+
import {
|
|
22
|
+
type Allocation,
|
|
23
|
+
DATA_TYPE_DATE_TIME,
|
|
24
|
+
DATA_TYPE_FLOAT,
|
|
25
|
+
DATA_TYPE_INTEGER,
|
|
26
|
+
DATA_TYPE_STRING,
|
|
27
|
+
} from "./types.ts";
|
|
22
28
|
|
|
23
29
|
export type TimeSeriesData = Record<string, (number | string)[]>;
|
|
24
30
|
|
|
25
|
-
const DATA_TYPE_INTEGER = 0;
|
|
26
|
-
const DATA_TYPE_FLOAT = 1;
|
|
27
|
-
const DATA_TYPE_STRING = 2;
|
|
28
|
-
const DATA_TYPE_DATE_TIME = 3;
|
|
29
|
-
|
|
30
31
|
Database.prototype.readTimeSeriesGroup = function (
|
|
31
32
|
this: Database,
|
|
32
33
|
collection: string,
|
|
@@ -48,11 +49,11 @@ Database.prototype.readTimeSeriesGroup = function (
|
|
|
48
49
|
collBuf.buf,
|
|
49
50
|
grpBuf.buf,
|
|
50
51
|
BigInt(id),
|
|
51
|
-
outNames.
|
|
52
|
-
outTypes.
|
|
53
|
-
outData.
|
|
54
|
-
outColCount.
|
|
55
|
-
outRowCount.
|
|
52
|
+
outNames.buf,
|
|
53
|
+
outTypes.buf,
|
|
54
|
+
outData.buf,
|
|
55
|
+
outColCount.buf,
|
|
56
|
+
outRowCount.buf,
|
|
56
57
|
),
|
|
57
58
|
);
|
|
58
59
|
|
|
@@ -96,6 +97,64 @@ Database.prototype.readTimeSeriesGroup = function (
|
|
|
96
97
|
return result;
|
|
97
98
|
};
|
|
98
99
|
|
|
100
|
+
Database.prototype.readTimeSeriesRow = function (
|
|
101
|
+
this: Database,
|
|
102
|
+
collection: string,
|
|
103
|
+
group: string,
|
|
104
|
+
attribute: string,
|
|
105
|
+
dateTime: string,
|
|
106
|
+
): (number | string | null)[] {
|
|
107
|
+
const lib = getSymbols();
|
|
108
|
+
const collBuf = toCString(collection);
|
|
109
|
+
const grpBuf = toCString(group);
|
|
110
|
+
const attrBuf = toCString(attribute);
|
|
111
|
+
const dtBuf = toCString(dateTime);
|
|
112
|
+
const outDataType = new Uint8Array(4);
|
|
113
|
+
const outValues = allocPtrOut();
|
|
114
|
+
const outCount = allocUint64Out();
|
|
115
|
+
|
|
116
|
+
check(
|
|
117
|
+
lib.quiver_database_read_time_series_row(
|
|
118
|
+
this._handle,
|
|
119
|
+
collBuf.buf,
|
|
120
|
+
grpBuf.buf,
|
|
121
|
+
attrBuf.buf,
|
|
122
|
+
dtBuf.buf,
|
|
123
|
+
outDataType,
|
|
124
|
+
outValues.buf,
|
|
125
|
+
outCount.buf,
|
|
126
|
+
),
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
const count = readUint64Out(outCount);
|
|
130
|
+
const valuesPtr = readPtrOut(outValues);
|
|
131
|
+
if (count === 0 || !valuesPtr) return [];
|
|
132
|
+
|
|
133
|
+
const dataType = new DataView(outDataType.buffer).getInt32(0, true);
|
|
134
|
+
switch (dataType) {
|
|
135
|
+
case DATA_TYPE_INTEGER: {
|
|
136
|
+
const result = decodeInt64Array(valuesPtr, count);
|
|
137
|
+
lib.quiver_database_free_integer_array(valuesPtr);
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
case DATA_TYPE_FLOAT: {
|
|
141
|
+
const result = decodeFloat64Array(valuesPtr, count);
|
|
142
|
+
lib.quiver_database_free_float_array(valuesPtr);
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
default: {
|
|
146
|
+
// STRING or DATE_TIME; NULL entries mark elements with no data
|
|
147
|
+
const result: (string | null)[] = new Array(count);
|
|
148
|
+
for (let i = 0; i < count; i++) {
|
|
149
|
+
const strPtr = read.ptr(valuesPtr as Pointer, i * 8);
|
|
150
|
+
result[i] = strPtr === 0 ? null : new CString(strPtr as Pointer).toString();
|
|
151
|
+
}
|
|
152
|
+
lib.quiver_database_free_string_array(valuesPtr, BigInt(count));
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
99
158
|
Database.prototype.updateTimeSeriesGroup = function (
|
|
100
159
|
this: Database,
|
|
101
160
|
collection: string,
|
|
@@ -127,6 +186,26 @@ Database.prototype.updateTimeSeriesGroup = function (
|
|
|
127
186
|
|
|
128
187
|
const columnCount = entries.length;
|
|
129
188
|
const rowCount = entries[0][1].length;
|
|
189
|
+
|
|
190
|
+
// Validate before marshalling: a jagged column would desync the parallel
|
|
191
|
+
// arrays the C API reads against row_count, and a zero-length column (with
|
|
192
|
+
// columns present) would otherwise marshal a null data pointer that the C API
|
|
193
|
+
// dereferences. Named-but-empty columns are a caller mistake -- pass {} to
|
|
194
|
+
// clear the group instead.
|
|
195
|
+
for (const [name, values] of entries) {
|
|
196
|
+
if (values.length !== rowCount) {
|
|
197
|
+
throw new QuiverError(
|
|
198
|
+
`Cannot updateTimeSeriesGroup: column '${name}' has length ${values.length} but expected ${rowCount}`,
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (rowCount === 0) {
|
|
203
|
+
const names = entries.map(([name]) => name).join(", ");
|
|
204
|
+
throw new QuiverError(
|
|
205
|
+
`Cannot updateTimeSeriesGroup: columns [${names}] contain no rows; pass {} to clear the group`,
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
130
209
|
const keepalive: Allocation[] = [];
|
|
131
210
|
|
|
132
211
|
// Build column names as native string array
|
|
@@ -142,10 +221,7 @@ Database.prototype.updateTimeSeriesGroup = function (
|
|
|
142
221
|
for (let c = 0; c < columnCount; c++) {
|
|
143
222
|
const values = entries[c][1];
|
|
144
223
|
|
|
145
|
-
if (values
|
|
146
|
-
typesDv.setInt32(c * 4, DATA_TYPE_STRING, true);
|
|
147
|
-
dataPtrs.push(null);
|
|
148
|
-
} else if (typeof values[0] === "string") {
|
|
224
|
+
if (typeof values[0] === "string") {
|
|
149
225
|
typesDv.setInt32(c * 4, DATA_TYPE_STRING, true);
|
|
150
226
|
const { table, keepalive: strPtrs } = allocNativeStringArray(values as string[]);
|
|
151
227
|
keepalive.push(table, ...strPtrs);
|
|
@@ -177,15 +253,76 @@ Database.prototype.updateTimeSeriesGroup = function (
|
|
|
177
253
|
collBuf.buf,
|
|
178
254
|
grpBuf.buf,
|
|
179
255
|
BigInt(id),
|
|
180
|
-
namesTable.
|
|
181
|
-
typesAlloc.
|
|
182
|
-
dataTable.
|
|
256
|
+
namesTable.buf,
|
|
257
|
+
typesAlloc.buf,
|
|
258
|
+
dataTable.buf,
|
|
183
259
|
BigInt(columnCount),
|
|
184
260
|
BigInt(rowCount),
|
|
185
261
|
),
|
|
186
262
|
);
|
|
187
263
|
};
|
|
188
264
|
|
|
265
|
+
Database.prototype.addTimeSeriesRow = function (
|
|
266
|
+
this: Database,
|
|
267
|
+
collection: string,
|
|
268
|
+
group: string,
|
|
269
|
+
id: number,
|
|
270
|
+
row: Record<string, number | bigint | string>,
|
|
271
|
+
): void {
|
|
272
|
+
const lib = getSymbols();
|
|
273
|
+
const collBuf = toCString(collection);
|
|
274
|
+
const grpBuf = toCString(group);
|
|
275
|
+
const entries = Object.entries(row);
|
|
276
|
+
const columnCount = entries.length;
|
|
277
|
+
const keepalive: Allocation[] = [];
|
|
278
|
+
|
|
279
|
+
const colNames = entries.map(([name]) => name);
|
|
280
|
+
const { table: namesTable, keepalive: namesPtrs } = allocNativeStringArray(colNames);
|
|
281
|
+
keepalive.push(namesTable, ...namesPtrs);
|
|
282
|
+
|
|
283
|
+
const typesBuf = new Uint8Array(columnCount * 4);
|
|
284
|
+
const typesDv = new DataView(typesBuf.buffer);
|
|
285
|
+
const dataPtrs: (Pointer | null)[] = [];
|
|
286
|
+
|
|
287
|
+
for (let c = 0; c < columnCount; c++) {
|
|
288
|
+
const value = entries[c][1];
|
|
289
|
+
if (typeof value === "string") {
|
|
290
|
+
typesDv.setInt32(c * 4, DATA_TYPE_STRING, true);
|
|
291
|
+
const { table, keepalive: strPtrs } = allocNativeStringArray([value]);
|
|
292
|
+
keepalive.push(table, ...strPtrs);
|
|
293
|
+
dataPtrs.push(table.ptr);
|
|
294
|
+
} else if (typeof value === "bigint" || Number.isInteger(value)) {
|
|
295
|
+
typesDv.setInt32(c * 4, DATA_TYPE_INTEGER, true);
|
|
296
|
+
const p = allocNativeInt64([value]);
|
|
297
|
+
keepalive.push(p);
|
|
298
|
+
dataPtrs.push(p.ptr);
|
|
299
|
+
} else {
|
|
300
|
+
typesDv.setInt32(c * 4, DATA_TYPE_FLOAT, true);
|
|
301
|
+
const p = allocNativeFloat64([value as number]);
|
|
302
|
+
keepalive.push(p);
|
|
303
|
+
dataPtrs.push(p.ptr);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const typesAlloc: Allocation = { ptr: ptr(typesBuf), buf: typesBuf };
|
|
308
|
+
keepalive.push(typesAlloc);
|
|
309
|
+
const dataTable = allocNativePtrTable(dataPtrs);
|
|
310
|
+
keepalive.push(dataTable);
|
|
311
|
+
|
|
312
|
+
check(
|
|
313
|
+
lib.quiver_database_add_time_series_row(
|
|
314
|
+
this._handle,
|
|
315
|
+
collBuf.buf,
|
|
316
|
+
grpBuf.buf,
|
|
317
|
+
BigInt(id),
|
|
318
|
+
namesTable.buf,
|
|
319
|
+
typesAlloc.buf,
|
|
320
|
+
dataTable.buf,
|
|
321
|
+
BigInt(columnCount),
|
|
322
|
+
),
|
|
323
|
+
);
|
|
324
|
+
};
|
|
325
|
+
|
|
189
326
|
Database.prototype.hasTimeSeriesFiles = function (this: Database, collection: string): boolean {
|
|
190
327
|
const lib = getSymbols();
|
|
191
328
|
const collBuf = toCString(collection);
|
|
@@ -206,8 +343,8 @@ Database.prototype.listTimeSeriesFilesColumns = function (
|
|
|
206
343
|
lib.quiver_database_list_time_series_files_columns(
|
|
207
344
|
this._handle,
|
|
208
345
|
collBuf.buf,
|
|
209
|
-
outColumns.
|
|
210
|
-
outCount.
|
|
346
|
+
outColumns.buf,
|
|
347
|
+
outCount.buf,
|
|
211
348
|
),
|
|
212
349
|
);
|
|
213
350
|
const count = readUint64Out(outCount);
|
|
@@ -231,9 +368,9 @@ Database.prototype.readTimeSeriesFiles = function (
|
|
|
231
368
|
lib.quiver_database_read_time_series_files(
|
|
232
369
|
this._handle,
|
|
233
370
|
collBuf.buf,
|
|
234
|
-
outColumns.
|
|
235
|
-
outPaths.
|
|
236
|
-
outCount.
|
|
371
|
+
outColumns.buf,
|
|
372
|
+
outPaths.buf,
|
|
373
|
+
outCount.buf,
|
|
237
374
|
),
|
|
238
375
|
);
|
|
239
376
|
const count = readUint64Out(outCount);
|
|
@@ -283,8 +420,8 @@ Database.prototype.updateTimeSeriesFiles = function (
|
|
|
283
420
|
lib.quiver_database_update_time_series_files(
|
|
284
421
|
this._handle,
|
|
285
422
|
collBuf.buf,
|
|
286
|
-
colsTable.
|
|
287
|
-
pathsTable.
|
|
423
|
+
colsTable.buf,
|
|
424
|
+
pathsTable.buf,
|
|
288
425
|
BigInt(entries.length),
|
|
289
426
|
),
|
|
290
427
|
);
|
package/src/transaction.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ptr } from "bun:ffi";
|
|
2
1
|
import { Database } from "./database.ts";
|
|
3
2
|
import { check } from "./errors.ts";
|
|
4
3
|
import { getSymbols } from "./loader.ts";
|
|
@@ -21,7 +20,6 @@ Database.prototype.rollback = function (this: Database): void {
|
|
|
21
20
|
Database.prototype.inTransaction = function (this: Database): boolean {
|
|
22
21
|
const lib = getSymbols();
|
|
23
22
|
const outBuf = new Uint8Array(4);
|
|
24
|
-
|
|
25
|
-
check(lib.quiver_database_in_transaction(this._handle, outPtr));
|
|
23
|
+
check(lib.quiver_database_in_transaction(this._handle, outBuf));
|
|
26
24
|
return new DataView(outBuf.buffer).getInt32(0, true) !== 0;
|
|
27
25
|
};
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
import type { Pointer } from "bun:ffi";
|
|
2
2
|
|
|
3
|
+
// Mirrors quiver_data_type_t in the C API
|
|
4
|
+
export const DATA_TYPE_INTEGER = 0;
|
|
5
|
+
export const DATA_TYPE_FLOAT = 1;
|
|
6
|
+
export const DATA_TYPE_STRING = 2;
|
|
7
|
+
export const DATA_TYPE_DATE_TIME = 3;
|
|
8
|
+
export const DATA_TYPE_NULL = 4;
|
|
9
|
+
|
|
10
|
+
// Mirrors quiver_log_level_t in the C API
|
|
11
|
+
export const LOG_LEVEL_DEBUG = 0;
|
|
12
|
+
export const LOG_LEVEL_INFO = 1;
|
|
13
|
+
export const LOG_LEVEL_WARN = 2;
|
|
14
|
+
export const LOG_LEVEL_ERROR = 3;
|
|
15
|
+
export const LOG_LEVEL_OFF = 4;
|
|
16
|
+
|
|
17
|
+
/** Options for opening or creating a database. */
|
|
18
|
+
export type DatabaseOptions = {
|
|
19
|
+
readOnly?: boolean;
|
|
20
|
+
/** A LOG_LEVEL_* constant; defaults to LOG_LEVEL_INFO. */
|
|
21
|
+
consoleLevel?: number;
|
|
22
|
+
};
|
|
23
|
+
|
|
3
24
|
export type ScalarValue = number | bigint | string | null;
|
|
4
25
|
export type ArrayValue = number[] | bigint[] | string[];
|
|
5
26
|
export type Value = ScalarValue | ArrayValue;
|