@visorcraft/mongreldb 0.18.0
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 +68 -0
- package/index.d.ts +31 -0
- package/index.js +70 -0
- package/mongreldb.linux-x64-gnu.node +0 -0
- package/native.d.ts +426 -0
- package/native.js +323 -0
- package/package.json +33 -0
- package/smoke.mjs +830 -0
package/README.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# mongreldb-node
|
|
2
|
+
|
|
3
|
+
Native Node.js addon for MongrelDB via [NAPI](https://napi.rs) — the
|
|
4
|
+
**better-sqlite3 model**: in-process, no HTTP latency, so the ~6 µs single-row
|
|
5
|
+
write isn't dwarfed by a network round-trip. Exposes a **typed object/method
|
|
6
|
+
interface** (not SQL); TypeScript types are generated at build time.
|
|
7
|
+
|
|
8
|
+
This crate is built **separately** from the Rust workspace (it targets the NAPI
|
|
9
|
+
ABI and needs Node.js tooling). It is excluded from `cargo {test,clippy}
|
|
10
|
+
--workspace`.
|
|
11
|
+
|
|
12
|
+
## Build
|
|
13
|
+
|
|
14
|
+
Requires Node.js ≥ 16 and `@napi-rs/cli`:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
cd crates/mongreldb-node
|
|
18
|
+
npm install
|
|
19
|
+
npm run build # → mongreldb.<platform>.node + index.d.ts
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## API sketch (generated `index.d.ts`)
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
class Database {
|
|
26
|
+
static withPath(path: string): Database
|
|
27
|
+
static open(path: string): Database
|
|
28
|
+
createTable(name: string, schema: SchemaSpec): bigint
|
|
29
|
+
table(name: string): TableHandle
|
|
30
|
+
begin(): Transaction
|
|
31
|
+
sql(sql: string): Promise<Buffer>
|
|
32
|
+
close(): void
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
class TableHandle {
|
|
36
|
+
put(cells: Cell[]): PutResult
|
|
37
|
+
putBatch(rows: Cell[][]): PutResult[]
|
|
38
|
+
bulkLoadTyped(columns: TypedColumn[]): bigint
|
|
39
|
+
commit(): bigint
|
|
40
|
+
flush(): bigint
|
|
41
|
+
count(): bigint // O(1)
|
|
42
|
+
countWhere(conditions: ConditionSpec[]): bigint
|
|
43
|
+
get(rowId: bigint): RowJs | null
|
|
44
|
+
query(conditions: ConditionSpec[]): RowJs[] // hybrid: bitmap ∩ range ∩ FM ∩ HNSW
|
|
45
|
+
queryArrow(conditions: ConditionSpec[]): Buffer
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Hybrid query — the differentiator
|
|
50
|
+
|
|
51
|
+
`query` intersects row-id sets from any combination of the six index types in a
|
|
52
|
+
single in-process call — something no HTTP vector DB or SQL FTS pipeline can do
|
|
53
|
+
in one hop:
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
db.query([
|
|
57
|
+
{ kind: ConditionKind.Ann, columnId: 5, embedding: queryVec, k: 50 },
|
|
58
|
+
{ kind: ConditionKind.FmContains, columnId: 2, text: "rome" },
|
|
59
|
+
{ kind: ConditionKind.BitmapIn, columnId: 3, values: ["eu", "na"] },
|
|
60
|
+
])
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Notes
|
|
64
|
+
|
|
65
|
+
- Row ids / counts / epochs cross the FFI as JS `BigInt` (`u64`), so the full
|
|
66
|
+
64-bit id space is lossless.
|
|
67
|
+
- Most blocking table methods also expose `*Async` Promise variants that run on
|
|
68
|
+
the NAPI blocking pool.
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* Hand-written wrapper around the NAPI-generated native.d.ts binding.
|
|
2
|
+
* Adds a retryable `Database.prototype.transaction` helper and the
|
|
3
|
+
* `ConflictError` class.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export * from './native';
|
|
7
|
+
|
|
8
|
+
/** Retryable write-write conflict. */
|
|
9
|
+
export declare class ConflictError extends Error {
|
|
10
|
+
constructor(message: string);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** Callback used by `Database.prototype.transaction`. */
|
|
14
|
+
export type TransactionCallback = (txn: import('./native').Transaction) => void | Promise<void>;
|
|
15
|
+
|
|
16
|
+
/** Options for `Database.prototype.transaction`. */
|
|
17
|
+
export interface TransactionOptions {
|
|
18
|
+
/** Maximum number of conflict retries before giving up. Default: 3. */
|
|
19
|
+
maxRetries?: number;
|
|
20
|
+
/** Base backoff delay in milliseconds. Default: 2. */
|
|
21
|
+
baseDelayMs?: number;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export declare class Database extends import('./native').Database {
|
|
25
|
+
/**
|
|
26
|
+
* Run `fn(txn)` inside a cross-table transaction, retrying on conflict.
|
|
27
|
+
* `fn` may be sync or async; it must stage operations on `txn` but must not
|
|
28
|
+
* call `commit`/`rollback` itself.
|
|
29
|
+
*/
|
|
30
|
+
transaction(fn: TransactionCallback, opts?: TransactionOptions): Promise<bigint>;
|
|
31
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
/* Hand-written wrapper around the NAPI-generated native.js binding.
|
|
3
|
+
* Adds a retryable `Database.prototype.transaction` helper and exports the
|
|
4
|
+
* `ConflictError` class so callers can distinguish retryable write conflicts.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const native = require('./native.js');
|
|
8
|
+
|
|
9
|
+
/** Retryable write-write conflict. */
|
|
10
|
+
class ConflictError extends Error {
|
|
11
|
+
constructor(message) {
|
|
12
|
+
super(message);
|
|
13
|
+
this.name = 'ConflictError';
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const CONFLICT_RE = /^__CONFLICT__:/;
|
|
18
|
+
|
|
19
|
+
function isConflict(err) {
|
|
20
|
+
return err != null && typeof err.message === 'string' && CONFLICT_RE.test(err.message);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Database wrapper that adds a `transaction(fn, opts?)` retry helper. */
|
|
24
|
+
class Database extends native.Database {
|
|
25
|
+
/**
|
|
26
|
+
* Run `fn(txn)` inside a cross-table transaction, retrying on conflict.
|
|
27
|
+
* `fn` may be sync or async; it must stage operations on `txn` but must not
|
|
28
|
+
* call `commit`/`rollback` itself.
|
|
29
|
+
*/
|
|
30
|
+
transaction(fn, opts = {}) {
|
|
31
|
+
const maxRetries = opts.maxRetries ?? 3;
|
|
32
|
+
const baseDelayMs = opts.baseDelayMs ?? 2;
|
|
33
|
+
|
|
34
|
+
const runOnce = async () => {
|
|
35
|
+
const txn = this.begin();
|
|
36
|
+
try {
|
|
37
|
+
await fn(txn);
|
|
38
|
+
return txn.commit();
|
|
39
|
+
} catch (err) {
|
|
40
|
+
try {
|
|
41
|
+
txn.rollback();
|
|
42
|
+
} catch (_) {
|
|
43
|
+
// ignore rollback errors
|
|
44
|
+
}
|
|
45
|
+
throw err;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const attempt = async (retriesLeft) => {
|
|
50
|
+
try {
|
|
51
|
+
return await runOnce();
|
|
52
|
+
} catch (err) {
|
|
53
|
+
if (retriesLeft > 0 && isConflict(err)) {
|
|
54
|
+
const delay = baseDelayMs * (maxRetries - retriesLeft + 1);
|
|
55
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
56
|
+
return attempt(retriesLeft - 1);
|
|
57
|
+
}
|
|
58
|
+
throw err;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
return attempt(maxRetries);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
module.exports = {
|
|
67
|
+
...native,
|
|
68
|
+
Database,
|
|
69
|
+
ConflictError,
|
|
70
|
+
};
|
|
Binary file
|
package/native.d.ts
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/* auto-generated by NAPI-RS */
|
|
5
|
+
|
|
6
|
+
export const enum ColumnType {
|
|
7
|
+
Bool = 0,
|
|
8
|
+
Int64 = 1,
|
|
9
|
+
Float64 = 2,
|
|
10
|
+
TimestampNanos = 3,
|
|
11
|
+
Date32 = 4,
|
|
12
|
+
Bytes = 5,
|
|
13
|
+
Embedding = 6
|
|
14
|
+
}
|
|
15
|
+
export const enum IndexKindSpec {
|
|
16
|
+
Bitmap = 0,
|
|
17
|
+
FmIndex = 1,
|
|
18
|
+
Ann = 2,
|
|
19
|
+
Sparse = 3,
|
|
20
|
+
MinHash = 4
|
|
21
|
+
}
|
|
22
|
+
export interface ColumnSpec {
|
|
23
|
+
id: number
|
|
24
|
+
name: string
|
|
25
|
+
ty: ColumnType
|
|
26
|
+
primaryKey: boolean
|
|
27
|
+
nullable: boolean
|
|
28
|
+
/** Required when `ty == Embedding`. */
|
|
29
|
+
embeddingDim?: number
|
|
30
|
+
/**
|
|
31
|
+
* Optional default value for schema-evolution back-fill. Currently only
|
|
32
|
+
* validated; applying defaults to existing rows is not yet implemented.
|
|
33
|
+
*/
|
|
34
|
+
defaultValue?: Cell
|
|
35
|
+
/**
|
|
36
|
+
* Engine-managed monotonic identity allocator for an `Int64` primary key.
|
|
37
|
+
* When `true`, the engine assigns the next counter value on insert if the
|
|
38
|
+
* column is omitted/null, and explicit ids advance the counter past them.
|
|
39
|
+
* Mutually exclusive with `nullable`; requires `primary_key` and `Int64`.
|
|
40
|
+
* Defaults to `false` (omitted/null).
|
|
41
|
+
*/
|
|
42
|
+
autoIncrement?: boolean
|
|
43
|
+
/** Encrypt this column's page payload at rest (requires an encrypted db). */
|
|
44
|
+
encrypted?: boolean
|
|
45
|
+
/**
|
|
46
|
+
* Encrypt the column but keep it queryable via deterministic equality
|
|
47
|
+
* tokens / order-preserving encoding (requires an encrypted db).
|
|
48
|
+
*/
|
|
49
|
+
encryptedIndexable?: boolean
|
|
50
|
+
}
|
|
51
|
+
export interface IndexSpec {
|
|
52
|
+
name: string
|
|
53
|
+
columnId: number
|
|
54
|
+
kind: IndexKindSpec
|
|
55
|
+
}
|
|
56
|
+
export interface SchemaSpec {
|
|
57
|
+
columns: Array<ColumnSpec>
|
|
58
|
+
indexes: Array<IndexSpec>
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* A single cell value. Only the field matching the column type is read; the
|
|
62
|
+
* rest are ignored. `bytes` is raw; `text` is UTF-8 (use for `Bytes` columns
|
|
63
|
+
* when the value is a string).
|
|
64
|
+
*/
|
|
65
|
+
export interface Cell {
|
|
66
|
+
columnId: number
|
|
67
|
+
int64?: bigint
|
|
68
|
+
float64?: number
|
|
69
|
+
boolean?: boolean
|
|
70
|
+
text?: string
|
|
71
|
+
bytes?: Buffer
|
|
72
|
+
embedding?: Array<number>
|
|
73
|
+
/**
|
|
74
|
+
* Sparse (SPLADE) token ids, paired with `sparse_weights`; bincoded into a
|
|
75
|
+
* Bytes value for a `Sparse` column on insert.
|
|
76
|
+
*/
|
|
77
|
+
sparseTokens?: Array<number>
|
|
78
|
+
sparseWeights?: Array<number>
|
|
79
|
+
}
|
|
80
|
+
export const enum ConditionKind {
|
|
81
|
+
Pk = 0,
|
|
82
|
+
BitmapEq = 1,
|
|
83
|
+
RangeInt = 2,
|
|
84
|
+
RangeF64 = 3,
|
|
85
|
+
FmContains = 4,
|
|
86
|
+
Ann = 5,
|
|
87
|
+
PkInt64 = 6,
|
|
88
|
+
BitmapIn = 7,
|
|
89
|
+
IsNull = 8,
|
|
90
|
+
IsNotNull = 9,
|
|
91
|
+
FmContainsAll = 10,
|
|
92
|
+
SparseMatch = 11,
|
|
93
|
+
MinHashSimilar = 12
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* One predicate over the shared row-id space. Set the fields appropriate to
|
|
97
|
+
* `kind`; unused fields are ignored. A `query` takes a conjunction (AND) of
|
|
98
|
+
* these — the differentiator no SQL FTS pipeline can match.
|
|
99
|
+
*/
|
|
100
|
+
export interface ConditionSpec {
|
|
101
|
+
kind: ConditionKind
|
|
102
|
+
columnId: number
|
|
103
|
+
int64Lo?: bigint
|
|
104
|
+
int64Hi?: bigint
|
|
105
|
+
float64Lo?: number
|
|
106
|
+
float64Hi?: number
|
|
107
|
+
text?: string
|
|
108
|
+
values?: Array<string>
|
|
109
|
+
embedding?: Array<number>
|
|
110
|
+
k?: number
|
|
111
|
+
/** SparseMatch query token ids (paired with `sparse_weights`). */
|
|
112
|
+
sparseTokens?: Array<number>
|
|
113
|
+
/** SparseMatch query token weights (paired with `sparse_tokens`). */
|
|
114
|
+
sparseWeights?: Array<number>
|
|
115
|
+
}
|
|
116
|
+
export interface RowJs {
|
|
117
|
+
rowId: bigint
|
|
118
|
+
cells: Array<Cell>
|
|
119
|
+
}
|
|
120
|
+
export interface OwnedRowJs {
|
|
121
|
+
cells: Array<Cell>
|
|
122
|
+
}
|
|
123
|
+
export interface UpsertResultJs {
|
|
124
|
+
action: string
|
|
125
|
+
row: OwnedRowJs
|
|
126
|
+
autoInc?: bigint
|
|
127
|
+
}
|
|
128
|
+
export interface RowUpdateJs {
|
|
129
|
+
rowId: bigint
|
|
130
|
+
cells: Array<Cell>
|
|
131
|
+
}
|
|
132
|
+
export interface TxnOpResultJs {
|
|
133
|
+
kind: string
|
|
134
|
+
autoInc?: bigint
|
|
135
|
+
row?: OwnedRowJs
|
|
136
|
+
rows?: Array<OwnedRowJs>
|
|
137
|
+
upsert?: UpsertResultJs
|
|
138
|
+
}
|
|
139
|
+
export interface CommitResultJs {
|
|
140
|
+
epoch: bigint
|
|
141
|
+
results: Array<TxnOpResultJs>
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Result of an insert: the physical row id plus, when the engine allocated
|
|
145
|
+
* it, the `AUTO_INCREMENT` value written into the row.
|
|
146
|
+
*/
|
|
147
|
+
export interface PutResult {
|
|
148
|
+
/** The storage row id (stable physical identity). */
|
|
149
|
+
rowId: bigint
|
|
150
|
+
/**
|
|
151
|
+
* The engine-assigned `AUTO_INCREMENT` value, when the column was omitted
|
|
152
|
+
* or null and the engine filled it. `null` for tables without an
|
|
153
|
+
* auto-increment column, or when the caller supplied an explicit value.
|
|
154
|
+
*/
|
|
155
|
+
autoInc?: bigint
|
|
156
|
+
}
|
|
157
|
+
/** Phase 20.2: a typed column for bulk loading, wrapping JS typed-array data. */
|
|
158
|
+
export interface TypedColumn {
|
|
159
|
+
columnId: number
|
|
160
|
+
ty: ColumnType
|
|
161
|
+
/** Raw data bytes (Int64 = N×8 LE, Float64 = N×8 LE, Bytes = N+1 offsets + values). */
|
|
162
|
+
data: Buffer
|
|
163
|
+
/** Optional validity bitmap (1 byte per row, 1=non-null). */
|
|
164
|
+
validity?: Buffer
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* An open MongrelDB multi-table database. Each table is accessible via
|
|
168
|
+
* `table(name)`; SQL queries via `sql()`.
|
|
169
|
+
*/
|
|
170
|
+
export declare class Database {
|
|
171
|
+
/** Create a fresh database at `path`. */
|
|
172
|
+
static withPath(path: string): Database
|
|
173
|
+
/** Open an existing database from disk. */
|
|
174
|
+
static open(path: string): Database
|
|
175
|
+
/** Create a new table with the given schema. */
|
|
176
|
+
createTable(name: string, schema: SchemaSpec): bigint
|
|
177
|
+
/** Drop a table by name. */
|
|
178
|
+
dropTable(name: string): void
|
|
179
|
+
/**
|
|
180
|
+
* Rename a live table. Fails if `name` does not exist, if `new_name` is
|
|
181
|
+
* empty, or if `new_name` is already in use. A no-op when `name == new_name`.
|
|
182
|
+
*/
|
|
183
|
+
renameTable(name: string, newName: string): void
|
|
184
|
+
/** Get a handle to a table by name for typed put/get/query operations. */
|
|
185
|
+
getTable(name: string): TableHandle
|
|
186
|
+
/** Alias for [`Database::get_table`] matching the spec's `database.table(name)`. */
|
|
187
|
+
table(name: string): TableHandle
|
|
188
|
+
/** Begin a cross-table transaction (stage puts/deletes, then `commit`). */
|
|
189
|
+
begin(): Transaction
|
|
190
|
+
/** The current reader-visible epoch — the database-wide snapshot point. */
|
|
191
|
+
snapshotEpoch(): bigint
|
|
192
|
+
/** List all live table names. */
|
|
193
|
+
tableNames(): Array<string>
|
|
194
|
+
/**
|
|
195
|
+
* Return the column names of a table as it exists in the **database**
|
|
196
|
+
* (not the code-defined schema). Lets migrations check whether a column
|
|
197
|
+
* is already present before calling `add_column`.
|
|
198
|
+
*/
|
|
199
|
+
tableColumns(name: string): Array<string>
|
|
200
|
+
/**
|
|
201
|
+
* Add a column to an existing table. The column must be nullable or supply
|
|
202
|
+
* a default value so existing rows can be evolved safely.
|
|
203
|
+
*/
|
|
204
|
+
addColumn(table: string, column: ColumnSpec): bigint
|
|
205
|
+
/**
|
|
206
|
+
* Alter an existing column's native schema metadata. The source column is
|
|
207
|
+
* selected by `column_name`; the supplied column spec provides the target
|
|
208
|
+
* name, storage type, and flags while the stable engine column id is kept.
|
|
209
|
+
*/
|
|
210
|
+
alterColumn(table: string, columnName: string, column: ColumnSpec): bigint
|
|
211
|
+
/** Verify database integrity. Returns a JSON-string summary. */
|
|
212
|
+
check(): string
|
|
213
|
+
/** Repair/quarantine corrupt tables. Returns a JSON-string summary. */
|
|
214
|
+
doctor(): string
|
|
215
|
+
/** Return the path passed to `withPath` / `open`. */
|
|
216
|
+
directory(): string
|
|
217
|
+
/** Run a cross-table SQL query. Returns Arrow IPC bytes. */
|
|
218
|
+
sql(sql: string): Promise<Buffer>
|
|
219
|
+
/** Flush + release. Optional — the `Database` also drops on GC. */
|
|
220
|
+
close(): void
|
|
221
|
+
/**
|
|
222
|
+
* Create a fresh encrypted database (page-level AES-256-GCM; the database
|
|
223
|
+
* KEK is derived from `passphrase` via Argon2id + HKDF).
|
|
224
|
+
*/
|
|
225
|
+
static createEncrypted(path: string, passphrase: string): Database
|
|
226
|
+
/** Open an existing encrypted database with its passphrase. */
|
|
227
|
+
static openEncrypted(path: string, passphrase: string): Database
|
|
228
|
+
}
|
|
229
|
+
/** A handle to one table inside a [`Database`]. */
|
|
230
|
+
export declare class TableHandle {
|
|
231
|
+
/**
|
|
232
|
+
* Upsert one row. Returns the row id and, when the engine allocated it,
|
|
233
|
+
* the `AUTO_INCREMENT` value.
|
|
234
|
+
*/
|
|
235
|
+
put(cells: Array<Cell>): PutResult
|
|
236
|
+
/** Group-commit this table's pending writes. */
|
|
237
|
+
commit(): bigint
|
|
238
|
+
/** Flush: commit + drain memtable to a sorted run. */
|
|
239
|
+
flush(): bigint
|
|
240
|
+
/** Live row count (O(1)). */
|
|
241
|
+
count(): bigint
|
|
242
|
+
/** Count rows matching a native conjunctive predicate without materializing rows when possible. */
|
|
243
|
+
countWhere(conditions: Array<ConditionSpec>): bigint
|
|
244
|
+
/** Point read by row id. */
|
|
245
|
+
get(rowId: bigint): RowJs | null
|
|
246
|
+
/** Point read by a text primary key. */
|
|
247
|
+
getByPkText(text: string): RowJs | null
|
|
248
|
+
/**
|
|
249
|
+
* Reserve (without inserting) the next `AUTO_INCREMENT` value for this
|
|
250
|
+
* table, advancing the engine's in-memory counter. Returns `null` if the
|
|
251
|
+
* table has no auto-increment column. Used by callers that stage a row with
|
|
252
|
+
* an explicit id inside a transaction; the reservation becomes durable when
|
|
253
|
+
* a row carrying the id commits, and a never-used reservation just leaves a
|
|
254
|
+
* gap. Far cheaper than a Kit-style sequence row — no hot row, no extra
|
|
255
|
+
* commit.
|
|
256
|
+
*/
|
|
257
|
+
reserveAutoInc(): bigint | null
|
|
258
|
+
/** Point read by an Int64 primary key. */
|
|
259
|
+
getByPkInt64(value: bigint): RowJs | null
|
|
260
|
+
/** Delete a row by storage row id. */
|
|
261
|
+
delete(rowId: bigint): void
|
|
262
|
+
/** Truncate all rows in this table. Call `commit()` to make it durable. */
|
|
263
|
+
truncate(): void
|
|
264
|
+
/** Delete the first row matching a text primary key. */
|
|
265
|
+
deleteByPkText(text: string): void
|
|
266
|
+
/** Delete the first row matching an Int64 primary key. */
|
|
267
|
+
deleteByPkInt64(value: bigint): void
|
|
268
|
+
/** Hybrid index query. */
|
|
269
|
+
query(conditions: Array<ConditionSpec>): Array<RowJs>
|
|
270
|
+
/**
|
|
271
|
+
* Read every row of this table visible at commit `epoch` — a point-in-time
|
|
272
|
+
* (MVCC time-travel) read. `epoch` must not exceed the current visible
|
|
273
|
+
* epoch.
|
|
274
|
+
*/
|
|
275
|
+
rowsAtEpoch(epoch: bigint): Array<RowJs>
|
|
276
|
+
/**
|
|
277
|
+
* Reservoir-sampled approximate aggregate (`count`/`sum`/`avg`) with a
|
|
278
|
+
* `z`-score confidence interval. Returns a JSON object, or `null` when the
|
|
279
|
+
* reservoir is empty. `columnId` is required for `sum`/`avg`.
|
|
280
|
+
*/
|
|
281
|
+
approxAggregate(agg: string, columnId: number | undefined | null, z: number): string | null
|
|
282
|
+
/**
|
|
283
|
+
* Incrementally-maintained aggregate (`count`/`sum`/`min`/`max`/`avg`),
|
|
284
|
+
* optionally filtered by pushed-down `conditions`. Returns a JSON object
|
|
285
|
+
* `{value, incremental, delta_rows}`; the value is always exact. The engine
|
|
286
|
+
* caches per `(table, column, agg, conditions)` and folds in only the delta
|
|
287
|
+
* of newly-committed rows once data has spilled to runs.
|
|
288
|
+
*/
|
|
289
|
+
incrementalAggregate(agg: string, columnId: number | undefined | null, conditions: Array<ConditionSpec>): string
|
|
290
|
+
/**
|
|
291
|
+
* Insert a batch of rows in one call. Returns each row's id and, when the
|
|
292
|
+
* engine allocated it, its `AUTO_INCREMENT` value, in order.
|
|
293
|
+
*/
|
|
294
|
+
putBatch(rows: Array<Array<Cell>>): Array<PutResult>
|
|
295
|
+
/**
|
|
296
|
+
* Fastest ingest path: bulk-load typed columns (Int64/Float64/Bool) in one
|
|
297
|
+
* shot, bypassing the per-cell `Value` enum. Returns the commit epoch.
|
|
298
|
+
* Bytes/Embedding columns are not supported here — use `putBatch`.
|
|
299
|
+
*/
|
|
300
|
+
bulkLoadTyped(columns: Array<TypedColumn>): bigint
|
|
301
|
+
/**
|
|
302
|
+
* Hybrid index query returning the matching rows as Arrow IPC bytes
|
|
303
|
+
* (columnar, zero-copy on the JS side). Requires at least one condition —
|
|
304
|
+
* use `Database.sql` for full scans.
|
|
305
|
+
*/
|
|
306
|
+
queryArrow(conditions: Array<ConditionSpec>): Buffer
|
|
307
|
+
putAsync(cells: Array<Cell>): Promise<PutResult>
|
|
308
|
+
commitAsync(): Promise<bigint>
|
|
309
|
+
countAsync(): Promise<bigint>
|
|
310
|
+
countWhereAsync(conditions: Array<ConditionSpec>): Promise<bigint>
|
|
311
|
+
getAsync(rowId: bigint): Promise<RowJs | null>
|
|
312
|
+
queryAsync(conditions: Array<ConditionSpec>): Promise<Array<RowJs>>
|
|
313
|
+
flushAsync(): Promise<bigint>
|
|
314
|
+
queryArrowAsync(conditions: Array<ConditionSpec>): Promise<Buffer>
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* A cross-table transaction (P5.2). Stage puts/deletes across tables; commit
|
|
318
|
+
* atomically. On conflict, `commit` throws a `ConflictError`.
|
|
319
|
+
*/
|
|
320
|
+
export declare class Transaction {
|
|
321
|
+
constructor(db: Database)
|
|
322
|
+
/**
|
|
323
|
+
* Stage a put on `table`. Returns the engine-assigned `AUTO_INCREMENT`
|
|
324
|
+
* value when the table has an auto-increment primary key and the column was
|
|
325
|
+
* omitted or null; returns `null` otherwise (explicit id, or no auto-inc
|
|
326
|
+
* column). The returned value is the id that will be written on commit.
|
|
327
|
+
*/
|
|
328
|
+
put(table: string, cells: Array<Cell>): bigint | null
|
|
329
|
+
/** Stage a delete of `row_id` on `table`. */
|
|
330
|
+
delete(table: string, rowId: bigint): void
|
|
331
|
+
truncate(table: string): void
|
|
332
|
+
upsert(table: string, insertCells: Array<Cell>, updateCells?: Array<Cell> | undefined | null): void
|
|
333
|
+
updateMany(table: string, updates: Array<RowUpdateJs>): void
|
|
334
|
+
deleteMany(table: string, rowIds: Array<bigint>): void
|
|
335
|
+
/**
|
|
336
|
+
* Stage many puts on `table` from a compact little-endian buffer, skipping
|
|
337
|
+
* the per-cell NAPI `Cell` object marshalling that dominates a bulk load.
|
|
338
|
+
* Layout: `u32 rowCount`, then per row `u16 cellCount`, then per cell
|
|
339
|
+
* `u16 columnId`, `u8 tag`, payload — tag 0=null, 1=int64 (i64 LE),
|
|
340
|
+
* 2=float64 (f64 LE), 3=bool (u8), 4=bytes (u32 len + bytes; text is UTF-8).
|
|
341
|
+
* The decoded `(column_id, Value)` pairs are identical to what `put` builds.
|
|
342
|
+
*/
|
|
343
|
+
putPacked(table: string, payload: Buffer): void
|
|
344
|
+
/**
|
|
345
|
+
* Stage many deletes on `table` from a compact buffer of row ids:
|
|
346
|
+
* `u32 count`, then `count` × `u64 LE` row id. One NAPI crossing instead
|
|
347
|
+
* of one per row.
|
|
348
|
+
*/
|
|
349
|
+
deletePacked(table: string, payload: Buffer): void
|
|
350
|
+
/**
|
|
351
|
+
* Commit all staged ops atomically. Returns the commit epoch.
|
|
352
|
+
* Throws `ConflictError` on write-write conflict (retryable).
|
|
353
|
+
*/
|
|
354
|
+
commit(): bigint
|
|
355
|
+
commitReturning(): CommitResultJs
|
|
356
|
+
/**
|
|
357
|
+
* Commit off the JS event loop (the durability fsync runs on the NAPI
|
|
358
|
+
* blocking pool). Throws `ConflictError` on write-write conflict.
|
|
359
|
+
*/
|
|
360
|
+
commitAsync(): Promise<bigint>
|
|
361
|
+
/**
|
|
362
|
+
* Async commit that returns both the committed epoch and the affected row
|
|
363
|
+
* identities, off the JS event loop. Throws `ConflictError` on write-write
|
|
364
|
+
* conflict.
|
|
365
|
+
*/
|
|
366
|
+
commitAsyncReturning(): Promise<CommitResultJs>
|
|
367
|
+
/** Discard all staged ops. */
|
|
368
|
+
rollback(): void
|
|
369
|
+
/**
|
|
370
|
+
* Scope subsequent ops to `table` via a `TxnTable`, so the table name
|
|
371
|
+
* isn't repeated on every `put`/`delete`. Pure sugar over the flat
|
|
372
|
+
* `put(table, …)` / `delete(table, …)` API — the sub-handle stages into
|
|
373
|
+
* THIS transaction, and this transaction's `commit`/`rollback` still drive
|
|
374
|
+
* durability.
|
|
375
|
+
*/
|
|
376
|
+
table(name: string): TxnTable
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* A table-scoped view of a [`Transaction`] (returned by `transaction.table()`).
|
|
380
|
+
* Stages `put`/`delete` for its bound table into the parent transaction; the
|
|
381
|
+
* parent's `commit`/`rollback` still apply.
|
|
382
|
+
*/
|
|
383
|
+
export declare class TxnTable {
|
|
384
|
+
/**
|
|
385
|
+
* Stage a put on this table. Returns the engine-assigned `AUTO_INCREMENT`
|
|
386
|
+
* value when applicable, or `null` otherwise.
|
|
387
|
+
*/
|
|
388
|
+
put(cells: Array<Cell>): bigint | null
|
|
389
|
+
/** Stage a batch of puts on this table. */
|
|
390
|
+
putBatch(rows: Array<Array<Cell>>): void
|
|
391
|
+
/** Stage a delete of `row_id` on this table. */
|
|
392
|
+
delete(rowId: bigint): void
|
|
393
|
+
truncate(): void
|
|
394
|
+
upsert(insertCells: Array<Cell>, updateCells?: Array<Cell> | undefined | null): void
|
|
395
|
+
updateMany(updates: Array<RowUpdateJs>): void
|
|
396
|
+
deleteMany(rowIds: Array<bigint>): void
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Opt-in write micro-batching over one table. Writes are **not durable until
|
|
400
|
+
* flush** — the contract is the opposite of `put()`.
|
|
401
|
+
*/
|
|
402
|
+
export declare class WriteBuffer {
|
|
403
|
+
/** Create a new WriteBuffer over a table. `threshold` rows trigger an auto-flush. */
|
|
404
|
+
constructor(table: TableHandle, threshold?: number | undefined | null)
|
|
405
|
+
/**
|
|
406
|
+
* Buffer a write (not durable until `flush`). Auto-flushes when the
|
|
407
|
+
* threshold is reached, returning the new row id.
|
|
408
|
+
*/
|
|
409
|
+
put(cells: Array<Cell>): bigint | null
|
|
410
|
+
/** Flush all buffered writes (durable after this call). Returns the new epoch. */
|
|
411
|
+
flush(): bigint
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* A daemon-backed database connection (Phase 19.4). Routes put/get/count/
|
|
415
|
+
* query/commit to a `mongreldb-server` instance over HTTP. Multiple Node
|
|
416
|
+
* processes can share one warm cache this way.
|
|
417
|
+
*/
|
|
418
|
+
export declare class RemoteDatabase {
|
|
419
|
+
/** Connect to a `mongreldb-server` at `url` (e.g. `http://127.0.0.1:8453`). */
|
|
420
|
+
constructor(url: string)
|
|
421
|
+
health(): string
|
|
422
|
+
tableNames(): Array<string>
|
|
423
|
+
count(table: string): number
|
|
424
|
+
sql(sql: string): Buffer
|
|
425
|
+
commit(table: string): bigint
|
|
426
|
+
}
|