@minnowdb/core 0.5.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +3 -2
  2. package/dist/engine/cancellation.d.ts +2 -0
  3. package/dist/engine/cancellation.js +4 -0
  4. package/dist/engine/catalog.d.ts +3 -1
  5. package/dist/engine/catalog.js +1 -0
  6. package/dist/engine/client.d.ts +32 -4
  7. package/dist/engine/client.js +82 -15
  8. package/dist/engine/database.d.ts +23 -14
  9. package/dist/engine/database.js +528 -79
  10. package/dist/engine/defaults.js +11 -0
  11. package/dist/engine/errors.d.ts +13 -0
  12. package/dist/engine/errors.js +22 -0
  13. package/dist/engine/fts.d.ts +2 -15
  14. package/dist/engine/live.d.ts +1 -7
  15. package/dist/engine/live.js +2 -12
  16. package/dist/engine/optimizer.d.ts +7 -0
  17. package/dist/engine/optimizer.js +1349 -76
  18. package/dist/engine/query.d.ts +11 -278
  19. package/dist/engine/query.js +178 -49
  20. package/dist/engine/schema-wire.d.ts +7 -1
  21. package/dist/engine/schema-wire.js +4 -0
  22. package/dist/engine/schema.d.ts +67 -33
  23. package/dist/engine/schema.js +138 -7
  24. package/dist/engine/sql-domains.d.ts +8 -0
  25. package/dist/engine/sql-domains.js +25 -0
  26. package/dist/engine/sql-json.js +22 -3
  27. package/dist/engine/vector.d.ts +2 -2
  28. package/dist/engine/vector.js +369 -43
  29. package/dist/engine/worker-host.js +119 -44
  30. package/dist/plan/index.d.ts +5 -4
  31. package/dist/plan/index.js +3 -3
  32. package/dist/plan/model.d.ts +224 -0
  33. package/dist/plan/model.js +1 -0
  34. package/dist/storage/types.d.ts +7 -0
  35. package/dist/storage/types.js +16 -0
  36. package/dist/transactions/index.d.ts +5 -3
  37. package/dist/transactions/index.js +58 -8
  38. package/dist/worker-protocol/index.d.ts +6 -1
  39. package/dist/worker-protocol/index.js +5 -2
  40. package/package.json +1 -1
  41. package/postgres-feature-profile.json +5 -0
  42. package/sql-feature-matrix.json +89 -21
package/README.md CHANGED
@@ -8,8 +8,9 @@ npm install @minnowdb/core
8
8
  ```
9
9
 
10
10
  - Direct SQL through `MinnowDatabase.query()` and `execute()`.
11
- - Joins, CTEs, window functions, grouping sets, upserts, `RETURNING`, triggers, exact decimals,
12
- JSON/JSONB, zoneless DATE, arrays, enums, sequences, and savepoints.
11
+ - Joins, CTEs, window functions, grouping sets, nested correlated subqueries, subquery-backed
12
+ mutations, upserts, `RETURNING`, triggers, exact decimals, nested JSON/JSONB, stored generated
13
+ columns, zoneless DATE, arrays, enums, sequences, and savepoints.
13
14
  - Compressed column storage, secondary indexes, full-text search, and snapshot reads.
14
15
  - Atomic writes across tabs through IndexedDB or OPFS, strict durability by default, and explicit
15
16
  origin-eviction persistence policy.
@@ -0,0 +1,2 @@
1
+ /** One compact check shared by every bounded query-execution path. */
2
+ export declare function throwIfAborted(signal: AbortSignal | undefined): void;
@@ -0,0 +1,4 @@
1
+ /** One compact check shared by every bounded query-execution path. */
2
+ export function throwIfAborted(signal) {
3
+ signal?.throwIfAborted();
4
+ }
@@ -1,4 +1,4 @@
1
- import { type ColumnDefault, type SecondaryIndexState, type SimpleDataType, type SqlDomain, type TableRecord } from "../storage/types.js";
1
+ import { type ColumnDefault, type ColumnGenerated, type SecondaryIndexState, type SimpleDataType, type SqlDomain, type TableRecord } from "../storage/types.js";
2
2
  /**
3
3
  * The published shape of the catalog: everything a schema tool needs to diff a live database
4
4
  * against a desired schema, without reading engine internals.
@@ -20,6 +20,8 @@ export interface CatalogColumn {
20
20
  readonly nullable: boolean;
21
21
  /** Filled for omitted or SQL DEFAULT insert slots; never applied at read time. */
22
22
  readonly defaultValue?: ColumnDefault;
23
+ /** Stored expression maintained by the engine; callers cannot assign this column. */
24
+ readonly generatedValue?: ColumnGenerated;
23
25
  /** String columns only: the closed set of values writes may draw from. */
24
26
  readonly enumValues?: readonly string[];
25
27
  /** Derived from the default spec, because a planner should not have to decode one. */
@@ -9,6 +9,7 @@ function toCatalogColumn(column) {
9
9
  ...(column.sqlDomain === undefined ? {} : { sqlDomain: structuredClone(column.sqlDomain) }),
10
10
  nullable: column.nullable,
11
11
  ...(column.defaultValue === undefined ? {} : { defaultValue: column.defaultValue }),
12
+ ...(column.generatedValue === undefined ? {} : { generatedValue: column.generatedValue }),
12
13
  ...(column.enumValues === undefined ? {} : { enumValues: [...column.enumValues] }),
13
14
  ...(column.backfill === undefined
14
15
  ? {}
@@ -1,7 +1,7 @@
1
1
  import { type CompactionJobRecord, type GarbageCollectionJobRecord, type StorageIntegrityMode, type StorageIntegrityReport, type StorageStats, type InterruptedSnapshotImport, type InterruptedSnapshotImportAbortResult } from "../storage/types.js";
2
2
  import { type BatchRow, type InsertBatchInput } from "./batch.js";
3
3
  import type { Catalog } from "./catalog.js";
4
- import type { BatchValue, BufferPoolStats, StagedWriteResult, BufferedFlushResult, BufferedWriterOptions, CancelCompactionJobResult, CollectGarbageOptions, CollectGarbageStepOptions, CompactTableOptions, CompactTableResult, CompactTableStepOptions, CompactionJobProgress, CreateTableInput, DatabaseRow, MigrateOptions, DeleteBatchInput, DeleteBatchResult, ExecuteResult, GarbageCollectionProgress, GarbageCollectionResult, MaintenanceStatus, InsertBatchResult, QueryOptions, QueryCursorOptions, QuerySpillCleanupOptions, QuerySpillCleanupResult, ReadTableOptions, RunStatementOptions, SnapshotExportOptions, SnapshotImportOptions, TableDefinition, UpdateBatchInput, UpdateBatchResult, UpsertBatchResult, UpsertOptions, VisibleSegmentPage, VisibleSegmentPageOptions } from "./database.js";
4
+ import type { BatchValue, BufferPoolStats, StagedWriteResult, BufferedFlushResult, BufferedWriterOptions, CancelCompactionJobResult, CollectGarbageOptions, CollectGarbageStepOptions, CompactTableOptions, CompactTableResult, CompactTableStepOptions, CompactionJobProgress, CreateTableInput, DatabaseRow, MigrateOptions, DeleteBatchInput, DeleteBatchResult, ExecuteResult, GarbageCollectionProgress, GarbageCollectionResult, MaintenanceStatus, InsertBatchResult, QueryOptions, QueryExecutionStats, QueryCursorOptions, QuerySpillCleanupOptions, QuerySpillCleanupResult, ReadTableOptions, RunStatementOptions, SnapshotExportOptions, SnapshotImportOptions, TableDefinition, UpdateBatchInput, UpdateBatchResult, UpsertBatchResult, UpsertOptions, VisibleSegmentPage, VisibleSegmentPageOptions } from "./database.js";
5
5
  import type { LiveQueryInput, LiveQueryInvalidation, LiveQueryObserveOptions, LiveQueryStats, LiveQuerySubscribeOptions } from "./live.js";
6
6
  import type { CompiledQuery, CompiledStatement, QueryResult, QueryValue } from "./query.js";
7
7
  import type { AnyTable, SchemaDefinition } from "./schema.js";
@@ -65,6 +65,11 @@ interface EventRoute {
65
65
  onComplete?: () => void;
66
66
  /** Payload shape is the handle's own; only snapshot loads emit these today. */
67
67
  onProgress?: (progress: unknown) => void;
68
+ onStats?: (stats: QueryExecutionStats) => void;
69
+ }
70
+ interface RpcCallControls {
71
+ signal?: AbortSignal | undefined;
72
+ onStats?: ((stats: QueryExecutionStats) => void) | undefined;
68
73
  }
69
74
  export declare class MinnowDatabaseClient {
70
75
  #private;
@@ -72,6 +77,29 @@ export declare class MinnowDatabaseClient {
72
77
  /** Resolves once the worker has opened the store and constructed the database. */
73
78
  ready(): Promise<void>;
74
79
  createTable(input: CreateTableInput): Promise<void>;
80
+ createView(name: string, sql: string, options?: {
81
+ orReplace?: boolean;
82
+ managed?: boolean;
83
+ }): Promise<void>;
84
+ dropView(name: string, options?: {
85
+ ifExists?: boolean;
86
+ }): Promise<boolean>;
87
+ dropColumn(tableName: string, columnName: string, options?: {
88
+ ifExists?: boolean;
89
+ }): Promise<boolean>;
90
+ dropTable(tableName: string, options?: {
91
+ ifExists?: boolean;
92
+ }): Promise<boolean>;
93
+ createIndex(indexName: string, tableName: string, requestedColumns: string | ReadonlyArray<{
94
+ name: string;
95
+ direction: "asc" | "desc";
96
+ }>, options?: {
97
+ unique?: boolean;
98
+ }): Promise<void>;
99
+ dropIndex(indexName: string, options?: {
100
+ ifExists?: boolean;
101
+ }): Promise<boolean>;
102
+ buildFtsIndex(tableName: string, columnName: string): Promise<void>;
75
103
  /** The published catalog; see `MinnowDatabase.introspect()`. */
76
104
  introspect(): Promise<Catalog>;
77
105
  listTables(): Promise<TableDefinition[]>;
@@ -166,6 +194,8 @@ export declare class MinnowDatabaseClient {
166
194
  /** @internal */
167
195
  _invoke(handleId: string, method: string, args: unknown[]): Promise<unknown>;
168
196
  /** @internal */
197
+ _invokeControlled(handleId: string, method: string, args: unknown[], controls: RpcCallControls): Promise<unknown>;
198
+ /** @internal */
169
199
  _routeEvents(handleId: string, route: EventRoute): void;
170
200
  /** @internal */
171
201
  _unrouteEvents(handleId: string): void;
@@ -177,9 +207,7 @@ export declare class MinnowDatabaseClient {
177
207
  /** The scope handed to the client `write()`; mirrors the in-worker WriteSession. */
178
208
  export interface ClientWriteSession {
179
209
  /** Read-your-writes: observes the pre-scope snapshot plus everything staged so far. */
180
- query(sql: string, options?: {
181
- params?: QueryValue[];
182
- }): Promise<QueryResult>;
210
+ query(sql: string, options?: QueryOptions): Promise<QueryResult>;
183
211
  execute(sql: string, params?: readonly QueryValue[]): Promise<ExecuteResult>;
184
212
  insertBatch(tableName: string, input: InsertBatchInput): Promise<StagedWriteResult>;
185
213
  upsertBatch(tableName: string, input: InsertBatchInput): Promise<StagedWriteResult>;
@@ -2,7 +2,7 @@ import { BlockReadBatchTooLargeError, CompactionBacklogError, CompactionJobConfl
2
2
  import { MAX_SNAPSHOT_STREAM_CHUNK_BYTES } from "../storage/snapshot.js";
3
3
  import { parseRpcResponse, MAX_DATABASE_RPC_IN_FLIGHT, protocolVersion, } from "../worker-protocol/index.js";
4
4
  import { toColumnarBatch } from "./batch.js";
5
- import { CompactionJobCancelledError, CompactionMemoryBudgetError, CompactionWriteAmplificationError, MaintenanceBacklogError, MissingKeyError, SqlCompileError, UnknownTableError, UniqueConstraintError, VisibleSegmentCursorStaleError, } from "./errors.js";
5
+ import { CompactionJobCancelledError, CompactionMemoryBudgetError, CompactionWriteAmplificationError, MaintenanceBacklogError, DatabaseReadBacklogError, LiveQueryLimitError, MissingKeyError, SqlCompileError, UnknownTableError, UniqueConstraintError, VisibleSegmentCursorStaleError, } from "./errors.js";
6
6
  import { QueryMemoryBudgetError } from "./memory.js";
7
7
  import { decodeQueryResult } from "./result-wire.js";
8
8
  import { serializeSchema } from "./schema-wire.js";
@@ -36,6 +36,8 @@ const errorRegistry = new Map([
36
36
  CompactionWriteAmplificationError,
37
37
  CompactionJobCancelledError,
38
38
  MaintenanceBacklogError,
39
+ DatabaseReadBacklogError,
40
+ LiveQueryLimitError,
39
41
  SqlCompileError,
40
42
  QueryMemoryBudgetError,
41
43
  VisibleSegmentCursorStaleError,
@@ -142,6 +144,27 @@ export class MinnowDatabaseClient {
142
144
  async createTable(input) {
143
145
  await this.#call("createTable", [input]);
144
146
  }
147
+ async createView(name, sql, options = {}) {
148
+ await this.#call("createView", [name, sql, options]);
149
+ }
150
+ async dropView(name, options = {}) {
151
+ return (await this.#call("dropView", [name, options]));
152
+ }
153
+ async dropColumn(tableName, columnName, options = {}) {
154
+ return (await this.#call("dropColumn", [tableName, columnName, options]));
155
+ }
156
+ async dropTable(tableName, options = {}) {
157
+ return (await this.#call("dropTable", [tableName, options]));
158
+ }
159
+ async createIndex(indexName, tableName, requestedColumns, options = {}) {
160
+ await this.#call("createIndex", [indexName, tableName, requestedColumns, options]);
161
+ }
162
+ async dropIndex(indexName, options = {}) {
163
+ return (await this.#call("dropIndex", [indexName, options]));
164
+ }
165
+ async buildFtsIndex(tableName, columnName) {
166
+ await this.#call("buildFtsIndex", [tableName, columnName]);
167
+ }
145
168
  /** The published catalog; see `MinnowDatabase.introspect()`. */
146
169
  async introspect() {
147
170
  return (await this.#call("introspect", []));
@@ -201,17 +224,17 @@ export class MinnowDatabaseClient {
201
224
  * datetimes) and are rebuilt into row objects here; see `result-wire.ts`.
202
225
  */
203
226
  async query(sql, options) {
204
- return decodeQueryResult(await this.#call("query", options === undefined ? [sql] : [sql, options]));
227
+ const { signal, onStats, ...wireOptions } = options ?? {};
228
+ return decodeQueryResult(await this.#call("query", [sql, wireOptions, onStats !== undefined], { signal, onStats }));
205
229
  }
206
230
  /** Pulls one transferred columnar page at a time, preserving worker backpressure. */
207
231
  queryCursor(sql, options = {}) {
208
232
  const call = this.#call.bind(this);
209
233
  const invoke = this._invoke.bind(this);
234
+ const routeEvents = this._routeEvents.bind(this);
235
+ const unrouteEvents = this._unrouteEvents.bind(this);
210
236
  const handleId = crypto.randomUUID();
211
237
  const { signal, onStats, ...wireOptions } = options;
212
- if (onStats !== undefined) {
213
- throw new TypeError("Query cursor onStats callbacks are not available across a worker");
214
- }
215
238
  async function* batches() {
216
239
  let opened = false;
217
240
  let closing;
@@ -225,9 +248,11 @@ export class MinnowDatabaseClient {
225
248
  void close();
226
249
  };
227
250
  signal?.addEventListener("abort", onAbort, { once: true });
251
+ if (onStats !== undefined)
252
+ routeEvents(handleId, { onStats });
228
253
  try {
229
254
  signal?.throwIfAborted();
230
- await call("queryCursorOpen", [handleId, sql, wireOptions]);
255
+ await call("queryCursorOpen", [handleId, sql, wireOptions, onStats !== undefined]);
231
256
  opened = true;
232
257
  if (signal?.aborted === true) {
233
258
  await close();
@@ -243,6 +268,7 @@ export class MinnowDatabaseClient {
243
268
  finally {
244
269
  signal?.removeEventListener("abort", onAbort);
245
270
  await close();
271
+ unrouteEvents(handleId);
246
272
  }
247
273
  }
248
274
  return batches();
@@ -291,7 +317,10 @@ export class MinnowDatabaseClient {
291
317
  const opened = (await this.#call("writeOpen", []));
292
318
  const stage = (op, tableName, input) => this._invoke(opened.handleId, "stage", [op, tableName, input]);
293
319
  const session = {
294
- query: async (sql, options) => decodeQueryResult(await this._invoke(opened.handleId, "query", [sql, options])),
320
+ query: async (sql, options = {}) => {
321
+ const { signal, onStats, ...wireOptions } = options;
322
+ return decodeQueryResult(await this._invokeControlled(opened.handleId, "query", [sql, wireOptions, onStats !== undefined], { signal, onStats }));
323
+ },
295
324
  execute: (sql, params) => this._invoke(opened.handleId, "execute", params === undefined ? [sql] : [sql, params]),
296
325
  insertBatch: (tableName, input) => stage("insertBatch", tableName, input),
297
326
  upsertBatch: (tableName, input) => stage("upsertBatch", tableName, input),
@@ -502,6 +531,12 @@ export class MinnowDatabaseClient {
502
531
  return this.#post("rpc-call", handleId, method, args);
503
532
  }
504
533
  /** @internal */
534
+ async _invokeControlled(handleId, method, args, controls) {
535
+ if (this.#closed)
536
+ throw new Error("Database client is closed");
537
+ return this.#post("rpc-call", handleId, method, args, undefined, false, controls);
538
+ }
539
+ /** @internal */
505
540
  _routeEvents(handleId, route) {
506
541
  this.#events.set(handleId, route);
507
542
  }
@@ -509,23 +544,49 @@ export class MinnowDatabaseClient {
509
544
  _unrouteEvents(handleId) {
510
545
  this.#events.delete(handleId);
511
546
  }
512
- async #call(method, args) {
547
+ async #call(method, args, controls = {}) {
513
548
  if (this.#closed)
514
549
  throw new Error("Database client is closed");
515
- return this.#post("rpc-call", null, method, args);
550
+ return this.#post("rpc-call", null, method, args, undefined, false, controls);
516
551
  }
517
- async #post(kind, handleId, method, args, transfer, bypassLimit = kind === "rpc-init" || method === "dispose") {
552
+ async #post(kind, handleId, method, args, transfer, bypassLimit = kind === "rpc-init" || method === "dispose", controls = {}) {
518
553
  if (this.#fatal !== undefined)
519
554
  throw this.#fatal;
555
+ controls.signal?.throwIfAborted();
520
556
  if (!bypassLimit && this.#pending.size >= MAX_DATABASE_RPC_IN_FLIGHT) {
521
557
  throw new RangeError(`A database worker connection cannot hold more than ${String(MAX_DATABASE_RPC_IN_FLIGHT)} in-flight requests`);
522
558
  }
523
559
  const requestId = crypto.randomUUID();
524
560
  return new Promise((resolve, reject) => {
525
- this.#pending.set(requestId, { resolve, reject });
526
- this.#transport.postMessage(kind === "rpc-init"
527
- ? { version: protocolVersion, requestId, kind, payload: args[0] }
528
- : { version: protocolVersion, requestId, kind, handleId, method, args }, transfer === undefined ? undefined : { transfer });
561
+ const onAbort = () => {
562
+ try {
563
+ this.#transport.postMessage({ version: protocolVersion, requestId, kind: "rpc-cancel" });
564
+ }
565
+ catch {
566
+ // The original RPC still owns completion. A transport failure also reaches #fail via
567
+ // its error event; throwing from an AbortSignal listener would only be unhandled noise.
568
+ }
569
+ };
570
+ const cleanup = () => {
571
+ controls.signal?.removeEventListener("abort", onAbort);
572
+ if (controls.onStats !== undefined)
573
+ this.#events.delete(requestId);
574
+ };
575
+ controls.signal?.addEventListener("abort", onAbort, { once: true });
576
+ if (controls.onStats !== undefined) {
577
+ this.#events.set(requestId, { onStats: controls.onStats });
578
+ }
579
+ this.#pending.set(requestId, { resolve, reject, cleanup });
580
+ try {
581
+ this.#transport.postMessage(kind === "rpc-init"
582
+ ? { version: protocolVersion, requestId, kind, payload: args[0] }
583
+ : { version: protocolVersion, requestId, kind, handleId, method, args }, transfer === undefined ? undefined : { transfer });
584
+ }
585
+ catch (error) {
586
+ this.#pending.delete(requestId);
587
+ cleanup();
588
+ reject(error instanceof Error ? error : new Error("Database request failed", { cause: error }));
589
+ }
529
590
  });
530
591
  }
531
592
  #receive(message) {
@@ -546,6 +607,9 @@ export class MinnowDatabaseClient {
546
607
  }
547
608
  else if (response.event === "progress")
548
609
  route.onProgress?.(response.payload);
610
+ else if (response.event === "stats") {
611
+ route.onStats?.(response.payload);
612
+ }
549
613
  else if (response.event === "complete") {
550
614
  this.#events.delete(response.handleId);
551
615
  route.onComplete?.();
@@ -556,6 +620,7 @@ export class MinnowDatabaseClient {
556
620
  if (pending === undefined)
557
621
  return;
558
622
  this.#pending.delete(response.requestId);
623
+ pending.cleanup?.();
559
624
  if (response.kind === "rpc-result")
560
625
  pending.resolve(response.result);
561
626
  else
@@ -566,8 +631,10 @@ export class MinnowDatabaseClient {
566
631
  const pending = [...this.#pending.values()];
567
632
  this.#pending.clear();
568
633
  this.#events.clear();
569
- for (const call of pending)
634
+ for (const call of pending) {
635
+ call.cleanup?.();
570
636
  call.reject(error);
637
+ }
571
638
  }
572
639
  }
573
640
  /**
@@ -2,8 +2,9 @@ import { type BatchRow, type BatchValue, type InsertBatchInput } from "./batch.j
2
2
  import { BufferedTableWriter, type BufferedWriterOptions } from "./buffered-writer.js";
3
3
  export { attachLifecycleFlush, BufferedTableWriter, MAX_BUFFERED_WRITER_PENDING_ADDS, type BufferedFlushResult, type BufferedWriterOptions, type LifecycleDocumentTarget, type LifecycleFlushOptions, type LifecycleFlushRequester, type LifecyclePageTarget, } from "./buffered-writer.js";
4
4
  import { CompactionJobCancelledError, CompactionMemoryBudgetError, CompactionWriteAmplificationError, MaintenanceBacklogError, MissingKeyError, SqlCompileError, UnknownTableError, UniqueConstraintError, VisibleSegmentCursorStaleError } from "./errors.js";
5
+ export { DatabaseReadBacklogError } from "./errors.js";
5
6
  import { type Compression } from "../block-format/index.js";
6
- import { type BlockStore, type ColumnDefault, CompactionBacklogError, type CompactionJobRecord, type CompactionJobState, type GarbageCollectionJobRecord, type GarbageCollectionJobState, type SimpleDataType, type SqlDomain, type StorageIntegrityMode, type StorageIntegrityReport, type StorageStats, type InterruptedSnapshotImport, type InterruptedSnapshotImportAbortResult, TableInUseError } from "../storage/types.js";
7
+ import { type BlockStore, type ColumnDefault, type ColumnGenerated, CompactionBacklogError, type CompactionJobRecord, type CompactionJobState, type GarbageCollectionJobRecord, type GarbageCollectionJobState, type SimpleDataType, type SqlDomain, type StorageIntegrityMode, type StorageIntegrityReport, type StorageStats, type InterruptedSnapshotImport, type InterruptedSnapshotImportAbortResult, TableInUseError } from "../storage/types.js";
7
8
  import type { SnapshotExportProgress, SnapshotLoadProgress } from "../storage/snapshot.js";
8
9
  import { type ComparisonOperator, type CompiledQuery, type CompiledStatement, type ForeignKeyDefinition, type QueryResult, type QueryRow, type QueryValue, type UniqueConstraintDefinition } from "./query.js";
9
10
  import { LiveQuerySet, type LiveQuerySetOptions } from "./live.js";
@@ -16,11 +17,6 @@ export declare const MAX_TRANSACTION_SAVEPOINT_BYTES: number;
16
17
  export declare const MAX_DATABASE_PENDING_WRITES = 64;
17
18
  /** Concurrent direct reads retained by one database instance. Reads still execute in parallel. */
18
19
  export declare const MAX_DATABASE_ACTIVE_READS = 256;
19
- export declare class DatabaseReadBacklogError extends Error {
20
- readonly limit: number;
21
- readonly name = "DatabaseReadBacklogError";
22
- constructor(limit?: number);
23
- }
24
20
  export interface ColumnDefinition {
25
21
  name: string;
26
22
  type: SimpleDataType;
@@ -31,6 +27,8 @@ export interface ColumnDefinition {
31
27
  nullable?: boolean;
32
28
  /** Fills omitted or SQL DEFAULT slots at insert time; never applied at read time. */
33
29
  defaultValue?: ColumnDefault;
30
+ /** Stored expression over sibling columns; callers cannot assign this column. */
31
+ generatedValue?: ColumnGenerated;
34
32
  /** String columns only: the closed set of values writes must draw from. */
35
33
  enumValues?: readonly string[];
36
34
  /** What rows written before this column existed read as, instead of NULL. */
@@ -125,6 +123,8 @@ export interface UpdateBatchResult {
125
123
  storedBytes: number;
126
124
  version: number;
127
125
  metrics: WriteMetrics;
126
+ /** Recomputed generated-column vectors in input key order. */
127
+ generatedColumns?: Record<string, BatchValue[]>;
128
128
  }
129
129
  export interface WriteMetrics {
130
130
  logicalBytes: number;
@@ -230,6 +230,11 @@ export interface MaintenanceStatus {
230
230
  } | null;
231
231
  }
232
232
  export interface QueryOptions {
233
+ /**
234
+ * Stops a read between bounded execution or storage batches. An abort never returns a partial
235
+ * result and releases any reader lease and temporary spill owner before the promise rejects.
236
+ */
237
+ readonly signal?: AbortSignal;
233
238
  /**
234
239
  * Called once with what this execution cost, before the result is returned. Additive and
235
240
  * optional: the engine can report its own memory because it reserves before it allocates,
@@ -268,8 +273,6 @@ export interface QueryOptions {
268
273
  export interface QueryCursorOptions extends QueryOptions {
269
274
  /** Maximum rows in one yielded result batch. Defaults to the vector scan batch size. */
270
275
  readonly batchRows?: number;
271
- /** Cancels the scan and releases its snapshot lease. */
272
- readonly signal?: AbortSignal;
273
276
  }
274
277
  export interface DeleteBatchInput {
275
278
  /** Stable ordinary array; do not mutate or expose changing accessors until the write settles. */
@@ -584,26 +587,30 @@ export type ExecuteResult = {
584
587
  } | {
585
588
  kind: "drop-trigger";
586
589
  name: string;
587
- } | {
590
+ } | ({
588
591
  kind: "insert";
589
592
  table: string;
590
593
  rowCount: number;
591
594
  /** Absent when the statement affected no rows (an INSERT ... SELECT of an empty set). */
592
595
  version?: number;
593
- returnedRows?: QueryRow[];
594
- } | {
596
+ } & ReturningExecuteFields) | ({
595
597
  kind: "update";
596
598
  table: string;
597
599
  rowCount: number;
598
600
  version?: number;
599
- returnedRows?: QueryRow[];
600
- } | {
601
+ } & ReturningExecuteFields) | ({
601
602
  kind: "delete";
602
603
  table: string;
603
604
  rowCount: number;
604
605
  version?: number | null;
606
+ } & ReturningExecuteFields);
607
+ interface ReturningExecuteFields {
605
608
  returnedRows?: QueryRow[];
606
- };
609
+ /** RETURNING projection order; present with returnedRows, including for an empty result. */
610
+ returnedColumns?: string[];
611
+ /** Logical domains aligned with returnedColumns. */
612
+ returnedColumnDomains?: Array<SqlDomain | null>;
613
+ }
607
614
  export interface RunStatementOptions {
608
615
  /**
609
616
  * Projects the affected rows back: column names, or "*" for every table column. Inserts echo
@@ -740,6 +747,8 @@ export declare class MinnowDatabase {
740
747
  upsert(tableName: string, row: BatchRow, options?: UpsertOptions): Promise<UpsertBatchResult>;
741
748
  updateBatch(tableName: string, input: UpdateBatchInput): Promise<UpdateBatchResult>;
742
749
  update(tableName: string, key: Exclude<BatchValue, null>, changes: Readonly<Record<string, BatchValue>>): Promise<UpdateBatchResult>;
750
+ /** Deletes one row by the table's unique key. */
751
+ delete(tableName: string, key: Exclude<BatchValue, null>): Promise<DeleteBatchResult>;
743
752
  deleteBatch(tableName: string, input: DeleteBatchInput): Promise<DeleteBatchResult>;
744
753
  bufferedWriter(tableName: string, options?: BufferedWriterOptions): BufferedTableWriter;
745
754
  readTable(tableName: string, versionOrOptions?: number | ReadTableOptions): Promise<DatabaseRow[]>;