@minnowdb/core 0.2.1 → 0.4.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 +23 -32
- package/dist/block-format/block.d.ts +32 -13
- package/dist/block-format/block.js +179 -55
- package/dist/block-format/checksum.d.ts +2 -1
- package/dist/block-format/checksum.js +5 -2
- package/dist/block-format/codecs.d.ts +7 -2
- package/dist/block-format/codecs.js +53 -12
- package/dist/block-format/column.d.ts +3 -2
- package/dist/block-format/column.js +96 -30
- package/dist/block-format/index.d.ts +2 -2
- package/dist/block-format/index.js +2 -2
- package/dist/block-format/physical.d.ts +8 -2
- package/dist/block-format/physical.js +14 -6
- package/dist/block-format/types.d.ts +7 -3
- package/dist/block-format/types.js +0 -1
- package/dist/block-format/unicode.d.ts +11 -0
- package/dist/block-format/unicode.js +46 -0
- package/dist/date-value.d.ts +15 -0
- package/dist/date-value.js +64 -0
- package/dist/engine/artifact-cache.d.ts +2 -1
- package/dist/engine/artifact-cache.js +5 -1
- package/dist/engine/batch.d.ts +11 -3
- package/dist/engine/batch.js +17 -7
- package/dist/engine/buffered-writer.d.ts +2 -1
- package/dist/engine/buffered-writer.js +34 -9
- package/dist/engine/cache-limits.d.ts +25 -0
- package/dist/engine/cache-limits.js +25 -0
- package/dist/engine/catalog.d.ts +24 -5
- package/dist/engine/catalog.js +34 -7
- package/dist/engine/client.d.ts +29 -7
- package/dist/engine/client.js +216 -40
- package/dist/engine/database.d.ts +224 -39
- package/dist/engine/database.js +7475 -1539
- package/dist/engine/defaults.d.ts +4 -8
- package/dist/engine/defaults.js +46 -22
- package/dist/engine/errors.d.ts +19 -1
- package/dist/engine/errors.js +32 -2
- package/dist/engine/fts.d.ts +0 -6
- package/dist/engine/fts.js +41 -14
- package/dist/engine/group-index.d.ts +0 -1
- package/dist/engine/group-index.js +6 -11
- package/dist/engine/index.d.ts +16 -10
- package/dist/engine/index.js +12 -9
- package/dist/engine/join-index.d.ts +0 -1
- package/dist/engine/join-index.js +2 -2
- package/dist/engine/keyed-live.d.ts +57 -0
- package/dist/engine/keyed-live.js +226 -0
- package/dist/engine/live-api.d.ts +4 -0
- package/dist/engine/live-api.js +4 -0
- package/dist/engine/live.d.ts +43 -26
- package/dist/engine/live.js +504 -126
- package/dist/engine/memory.d.ts +2 -1
- package/dist/engine/memory.js +3 -2
- package/dist/engine/optimizer.d.ts +0 -1
- package/dist/engine/optimizer.js +262 -27
- package/dist/engine/query-api.d.ts +3 -0
- package/dist/engine/query-api.js +3 -0
- package/dist/engine/query-cache.d.ts +1 -2
- package/dist/engine/query-cache.js +7 -5
- package/dist/engine/query.d.ts +134 -29
- package/dist/engine/query.js +1668 -372
- package/dist/engine/result-wire.d.ts +0 -1
- package/dist/engine/result-wire.js +2 -2
- package/dist/engine/schema-wire.d.ts +6 -3
- package/dist/engine/schema-wire.js +40 -34
- package/dist/engine/schema.d.ts +156 -80
- package/dist/engine/schema.js +570 -108
- package/dist/engine/sort-keys.d.ts +4 -4
- package/dist/engine/sort-keys.js +44 -29
- package/dist/engine/sql-domains.d.ts +31 -0
- package/dist/engine/sql-domains.js +585 -0
- package/dist/engine/sql-driver.d.ts +19 -0
- package/dist/engine/sql-driver.js +1 -0
- package/dist/engine/sql-json.d.ts +7 -9
- package/dist/engine/sql-json.js +75 -15
- package/dist/engine/sql-semantics.d.ts +8 -3
- package/dist/engine/sql-semantics.js +458 -30
- package/dist/engine/typed-live.d.ts +67 -0
- package/dist/engine/typed-live.js +349 -0
- package/dist/engine/vector.d.ts +12 -2
- package/dist/engine/vector.js +635 -119
- package/dist/engine/worker-host.d.ts +9 -2
- package/dist/engine/worker-host.js +620 -152
- package/dist/engine/worker.d.ts +0 -1
- package/dist/engine/worker.js +3 -3
- package/dist/engine/write-block-planner.d.ts +18 -0
- package/dist/engine/write-block-planner.js +112 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/plan/index.d.ts +3 -4
- package/dist/plan/index.js +3 -4
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.js +1 -1
- package/dist/storage/indexeddb.d.ts +99 -51
- package/dist/storage/indexeddb.js +13448 -2660
- package/dist/storage/memory.d.ts +64 -57
- package/dist/storage/memory.js +1042 -128
- package/dist/storage/opfs/files.d.ts +18 -7
- package/dist/storage/opfs/files.js +115 -28
- package/dist/storage/opfs/index.d.ts +1 -1
- package/dist/storage/opfs/index.js +1 -1
- package/dist/storage/opfs/leader.d.ts +409 -75
- package/dist/storage/opfs/leader.js +4621 -650
- package/dist/storage/opfs/rpc.d.ts +15 -3
- package/dist/storage/opfs/rpc.js +224 -2
- package/dist/storage/opfs/snapshot-ledger.d.ts +40 -0
- package/dist/storage/opfs/snapshot-ledger.js +281 -0
- package/dist/storage/opfs/store.d.ts +33 -99
- package/dist/storage/opfs/store.js +453 -364
- package/dist/storage/persistence.d.ts +37 -0
- package/dist/storage/persistence.js +78 -0
- package/dist/storage/snapshot-stream.d.ts +24 -0
- package/dist/storage/snapshot-stream.js +897 -0
- package/dist/storage/snapshot.d.ts +9 -85
- package/dist/storage/snapshot.js +33 -265
- package/dist/storage/toolkit/extents.d.ts +41 -7
- package/dist/storage/toolkit/extents.js +402 -39
- package/dist/storage/toolkit/index.d.ts +4 -5
- package/dist/storage/toolkit/index.js +28 -4
- package/dist/storage/toolkit/record-core.d.ts +182 -55
- package/dist/storage/toolkit/record-core.js +6158 -1331
- package/dist/storage/toolkit/sync-file.d.ts +10 -1
- package/dist/storage/toolkit/sync-file.js +50 -2
- package/dist/storage/toolkit/wal.d.ts +23 -5
- package/dist/storage/toolkit/wal.js +89 -27
- package/dist/storage/toolkit/wire.d.ts +15 -2
- package/dist/storage/toolkit/wire.js +199 -10
- package/dist/storage/types.d.ts +1439 -204
- package/dist/storage/types.js +1745 -141
- package/dist/testing/block-store-conformance.d.ts +0 -1
- package/dist/testing/block-store-conformance.js +1009 -119
- package/dist/testing/index.d.ts +46 -26
- package/dist/testing/index.js +112 -57
- package/dist/testing/opfs-shim.d.ts +13 -3
- package/dist/testing/opfs-shim.js +40 -6
- package/dist/testing/simulator.d.ts +97 -0
- package/dist/testing/simulator.js +591 -0
- package/dist/testing/sqllogictest.d.ts +89 -0
- package/dist/testing/sqllogictest.js +434 -0
- package/dist/transactions/index.d.ts +92 -16
- package/dist/transactions/index.js +1074 -236
- package/dist/worker-protocol/index.d.ts +3 -2
- package/dist/worker-protocol/index.js +2 -5
- package/package.json +53 -3
- package/postgres-feature-profile.json +223 -0
- package/sql-feature-matrix.json +172 -252
- package/dist/block-format/block.d.ts.map +0 -1
- package/dist/block-format/block.js.map +0 -1
- package/dist/block-format/checksum.d.ts.map +0 -1
- package/dist/block-format/checksum.js.map +0 -1
- package/dist/block-format/codecs.d.ts.map +0 -1
- package/dist/block-format/codecs.js.map +0 -1
- package/dist/block-format/column.d.ts.map +0 -1
- package/dist/block-format/column.js.map +0 -1
- package/dist/block-format/index.d.ts.map +0 -1
- package/dist/block-format/index.js.map +0 -1
- package/dist/block-format/physical.d.ts.map +0 -1
- package/dist/block-format/physical.js.map +0 -1
- package/dist/block-format/types.d.ts.map +0 -1
- package/dist/block-format/types.js.map +0 -1
- package/dist/engine/artifact-cache.d.ts.map +0 -1
- package/dist/engine/artifact-cache.js.map +0 -1
- package/dist/engine/batch.d.ts.map +0 -1
- package/dist/engine/batch.js.map +0 -1
- package/dist/engine/buffered-writer.d.ts.map +0 -1
- package/dist/engine/buffered-writer.js.map +0 -1
- package/dist/engine/catalog.d.ts.map +0 -1
- package/dist/engine/catalog.js.map +0 -1
- package/dist/engine/client.d.ts.map +0 -1
- package/dist/engine/client.js.map +0 -1
- package/dist/engine/coordinator.d.ts +0 -17
- package/dist/engine/coordinator.d.ts.map +0 -1
- package/dist/engine/coordinator.js +0 -60
- package/dist/engine/coordinator.js.map +0 -1
- package/dist/engine/database.d.ts.map +0 -1
- package/dist/engine/database.js.map +0 -1
- package/dist/engine/defaults.d.ts.map +0 -1
- package/dist/engine/defaults.js.map +0 -1
- package/dist/engine/errors.d.ts.map +0 -1
- package/dist/engine/errors.js.map +0 -1
- package/dist/engine/fts.d.ts.map +0 -1
- package/dist/engine/fts.js.map +0 -1
- package/dist/engine/group-index.d.ts.map +0 -1
- package/dist/engine/group-index.js.map +0 -1
- package/dist/engine/index.d.ts.map +0 -1
- package/dist/engine/index.js.map +0 -1
- package/dist/engine/join-index.d.ts.map +0 -1
- package/dist/engine/join-index.js.map +0 -1
- package/dist/engine/live.d.ts.map +0 -1
- package/dist/engine/live.js.map +0 -1
- package/dist/engine/memory.d.ts.map +0 -1
- package/dist/engine/memory.js.map +0 -1
- package/dist/engine/optimizer.d.ts.map +0 -1
- package/dist/engine/optimizer.js.map +0 -1
- package/dist/engine/query-cache.d.ts.map +0 -1
- package/dist/engine/query-cache.js.map +0 -1
- package/dist/engine/query.d.ts.map +0 -1
- package/dist/engine/query.js.map +0 -1
- package/dist/engine/result-wire.d.ts.map +0 -1
- package/dist/engine/result-wire.js.map +0 -1
- package/dist/engine/schema-wire.d.ts.map +0 -1
- package/dist/engine/schema-wire.js.map +0 -1
- package/dist/engine/schema.d.ts.map +0 -1
- package/dist/engine/schema.js.map +0 -1
- package/dist/engine/sort-keys.d.ts.map +0 -1
- package/dist/engine/sort-keys.js.map +0 -1
- package/dist/engine/sql-json.d.ts.map +0 -1
- package/dist/engine/sql-json.js.map +0 -1
- package/dist/engine/sql-semantics.d.ts.map +0 -1
- package/dist/engine/sql-semantics.js.map +0 -1
- package/dist/engine/vector.d.ts.map +0 -1
- package/dist/engine/vector.js.map +0 -1
- package/dist/engine/worker-host.d.ts.map +0 -1
- package/dist/engine/worker-host.js.map +0 -1
- package/dist/engine/worker.d.ts.map +0 -1
- package/dist/engine/worker.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/plan/index.d.ts.map +0 -1
- package/dist/plan/index.js.map +0 -1
- package/dist/storage/fixture-shape.d.ts +0 -42
- package/dist/storage/fixture-shape.d.ts.map +0 -1
- package/dist/storage/fixture-shape.js +0 -146
- package/dist/storage/fixture-shape.js.map +0 -1
- package/dist/storage/index.d.ts.map +0 -1
- package/dist/storage/index.js.map +0 -1
- package/dist/storage/indexeddb.d.ts.map +0 -1
- package/dist/storage/indexeddb.js.map +0 -1
- package/dist/storage/memory.d.ts.map +0 -1
- package/dist/storage/memory.js.map +0 -1
- package/dist/storage/opfs/files.d.ts.map +0 -1
- package/dist/storage/opfs/files.js.map +0 -1
- package/dist/storage/opfs/index.d.ts.map +0 -1
- package/dist/storage/opfs/index.js.map +0 -1
- package/dist/storage/opfs/leader.d.ts.map +0 -1
- package/dist/storage/opfs/leader.js.map +0 -1
- package/dist/storage/opfs/rpc.d.ts.map +0 -1
- package/dist/storage/opfs/rpc.js.map +0 -1
- package/dist/storage/opfs/store.d.ts.map +0 -1
- package/dist/storage/opfs/store.js.map +0 -1
- package/dist/storage/snapshot.d.ts.map +0 -1
- package/dist/storage/snapshot.js.map +0 -1
- package/dist/storage/toolkit/extents.d.ts.map +0 -1
- package/dist/storage/toolkit/extents.js.map +0 -1
- package/dist/storage/toolkit/index.d.ts.map +0 -1
- package/dist/storage/toolkit/index.js.map +0 -1
- package/dist/storage/toolkit/record-core.d.ts.map +0 -1
- package/dist/storage/toolkit/record-core.js.map +0 -1
- package/dist/storage/toolkit/sync-file.d.ts.map +0 -1
- package/dist/storage/toolkit/sync-file.js.map +0 -1
- package/dist/storage/toolkit/wal.d.ts.map +0 -1
- package/dist/storage/toolkit/wal.js.map +0 -1
- package/dist/storage/toolkit/wire.d.ts.map +0 -1
- package/dist/storage/toolkit/wire.js.map +0 -1
- package/dist/storage/types.d.ts.map +0 -1
- package/dist/storage/types.js.map +0 -1
- package/dist/testing/block-store-conformance.d.ts.map +0 -1
- package/dist/testing/block-store-conformance.js.map +0 -1
- package/dist/testing/index.d.ts.map +0 -1
- package/dist/testing/index.js.map +0 -1
- package/dist/testing/opfs-shim.d.ts.map +0 -1
- package/dist/testing/opfs-shim.js.map +0 -1
- package/dist/testing/seeds.d.ts +0 -11
- package/dist/testing/seeds.d.ts.map +0 -1
- package/dist/testing/seeds.js +0 -50
- package/dist/testing/seeds.js.map +0 -1
- package/dist/transactions/index.d.ts.map +0 -1
- package/dist/transactions/index.js.map +0 -1
- package/dist/worker-protocol/index.d.ts.map +0 -1
- package/dist/worker-protocol/index.js.map +0 -1
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/** A caller's explicit compressed-output ceiling was reached before an output join/allocation. */
|
|
2
|
+
export class CompressionOutputLimitError extends RangeError {
|
|
3
|
+
byteLength;
|
|
4
|
+
maximumOutputLength;
|
|
5
|
+
constructor(byteLength, maximumOutputLength) {
|
|
6
|
+
super("Compressed payload exceeds caller output ceiling");
|
|
7
|
+
this.byteLength = byteLength;
|
|
8
|
+
this.maximumOutputLength = maximumOutputLength;
|
|
9
|
+
this.name = "CompressionOutputLimitError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
1
12
|
/**
|
|
2
13
|
* The raw codec returns its input view unchanged in both directions: callers treat compressed
|
|
3
14
|
* and decompressed payloads as read-only (encode copies the payload into the block envelope,
|
|
@@ -7,8 +18,14 @@
|
|
|
7
18
|
*/
|
|
8
19
|
export const rawCodec = {
|
|
9
20
|
id: "raw",
|
|
10
|
-
compress(bytes) {
|
|
11
|
-
|
|
21
|
+
async compress(bytes, maximumOutputLength) {
|
|
22
|
+
if (maximumOutputLength !== undefined) {
|
|
23
|
+
assertCallerOutputLength(maximumOutputLength);
|
|
24
|
+
if (bytes.byteLength > maximumOutputLength) {
|
|
25
|
+
throw new CompressionOutputLimitError(bytes.byteLength, maximumOutputLength);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return bytes;
|
|
12
29
|
},
|
|
13
30
|
decompress(bytes, expectedLength) {
|
|
14
31
|
if (bytes.byteLength !== expectedLength)
|
|
@@ -43,19 +60,25 @@ export function getCompressionMemoryBound(compression, inputLength) {
|
|
|
43
60
|
}
|
|
44
61
|
}
|
|
45
62
|
}
|
|
46
|
-
async function transform(bytes, stream, maximumOutputLength = Number.POSITIVE_INFINITY, boundErrorMessage = "Decompressed payload exceeds declared length") {
|
|
63
|
+
async function transform(bytes, stream, maximumOutputLength = Number.POSITIVE_INFINITY, boundErrorMessage = "Decompressed payload exceeds declared length", outputLimitError) {
|
|
47
64
|
const write = (async () => {
|
|
48
65
|
const writer = stream.writable.getWriter();
|
|
49
66
|
await writer.write(new Uint8Array(bytes));
|
|
50
67
|
await writer.close();
|
|
51
68
|
})();
|
|
52
|
-
const [,
|
|
69
|
+
const [writeResult, readResult] = await Promise.allSettled([
|
|
53
70
|
write,
|
|
54
|
-
readBounded(stream.readable, maximumOutputLength, boundErrorMessage),
|
|
71
|
+
readBounded(stream.readable, maximumOutputLength, boundErrorMessage, outputLimitError),
|
|
55
72
|
]);
|
|
56
|
-
|
|
73
|
+
// A reader-side bound failure intentionally cancels the writer. Preserve that precise error
|
|
74
|
+
// instead of racing it against the writer rejection caused by the cancellation.
|
|
75
|
+
if (readResult.status === "rejected")
|
|
76
|
+
throw readResult.reason;
|
|
77
|
+
if (writeResult.status === "rejected")
|
|
78
|
+
throw writeResult.reason;
|
|
79
|
+
return readResult.value;
|
|
57
80
|
}
|
|
58
|
-
async function readBounded(readable, maximumLength, boundErrorMessage) {
|
|
81
|
+
async function readBounded(readable, maximumLength, boundErrorMessage, outputLimitError) {
|
|
59
82
|
const reader = readable.getReader();
|
|
60
83
|
const chunks = [];
|
|
61
84
|
let length = 0;
|
|
@@ -65,8 +88,14 @@ async function readBounded(readable, maximumLength, boundErrorMessage) {
|
|
|
65
88
|
break;
|
|
66
89
|
length += value.byteLength;
|
|
67
90
|
if (length > maximumLength) {
|
|
68
|
-
|
|
69
|
-
|
|
91
|
+
const error = outputLimitError?.(length) ?? new Error(boundErrorMessage);
|
|
92
|
+
try {
|
|
93
|
+
await reader.cancel(error);
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// Cancellation is cleanup. The deterministic bound error remains the operation result.
|
|
97
|
+
}
|
|
98
|
+
throw error;
|
|
70
99
|
}
|
|
71
100
|
chunks.push(value);
|
|
72
101
|
}
|
|
@@ -80,9 +109,17 @@ async function readBounded(readable, maximumLength, boundErrorMessage) {
|
|
|
80
109
|
}
|
|
81
110
|
export const gzipCodec = {
|
|
82
111
|
id: "gzip",
|
|
83
|
-
async compress(bytes) {
|
|
112
|
+
async compress(bytes, maximumOutputLength) {
|
|
84
113
|
const { maximumOutputBytes } = getCompressionMemoryBound("gzip", bytes.byteLength);
|
|
85
|
-
|
|
114
|
+
if (maximumOutputLength !== undefined)
|
|
115
|
+
assertCallerOutputLength(maximumOutputLength);
|
|
116
|
+
const outputLimit = Math.min(maximumOutputBytes, maximumOutputLength ?? maximumOutputBytes);
|
|
117
|
+
const callerLimited = outputLimit < maximumOutputBytes;
|
|
118
|
+
return transform(bytes, new CompressionStream("gzip"), outputLimit, callerLimited
|
|
119
|
+
? "Compressed payload exceeds caller output ceiling"
|
|
120
|
+
: "Gzip payload exceeds compression bound", callerLimited
|
|
121
|
+
? (byteLength) => new CompressionOutputLimitError(byteLength, outputLimit)
|
|
122
|
+
: undefined);
|
|
86
123
|
},
|
|
87
124
|
async decompress(bytes, expectedLength) {
|
|
88
125
|
const output = await transform(bytes, new DecompressionStream("gzip"), expectedLength);
|
|
@@ -91,6 +128,11 @@ export const gzipCodec = {
|
|
|
91
128
|
return output;
|
|
92
129
|
},
|
|
93
130
|
};
|
|
131
|
+
function assertCallerOutputLength(value) {
|
|
132
|
+
if (!Number.isSafeInteger(value) || value < 0) {
|
|
133
|
+
throw new RangeError("Invalid compression output ceiling");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
94
136
|
export function getCodec(id) {
|
|
95
137
|
switch (id) {
|
|
96
138
|
case "raw":
|
|
@@ -99,4 +141,3 @@ export function getCodec(id) {
|
|
|
99
141
|
return gzipCodec;
|
|
100
142
|
}
|
|
101
143
|
}
|
|
102
|
-
//# sourceMappingURL=codecs.js.map
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type { BlockMetadata, ColumnInput, DecodedColumn, LogicalType } from "./types.js";
|
|
1
|
+
import type { BlockMetadata, ColumnInput, DecodedColumn, LogicalType, ValidatedPhysicalColumn } from "./types.js";
|
|
2
2
|
export declare function encodeColumn(input: ColumnInput): {
|
|
3
3
|
bytes: Uint8Array;
|
|
4
4
|
metadata: BlockMetadata;
|
|
5
5
|
nullCount: number;
|
|
6
6
|
};
|
|
7
7
|
export declare function decodeColumn<T extends LogicalType>(type: T, bytes: Uint8Array, rowCount: number): DecodedColumn<T>;
|
|
8
|
-
|
|
8
|
+
/** Package-internal row materialization after the physical payload was already validated. */
|
|
9
|
+
export declare function decodeValidatedColumn<T extends LogicalType>(column: ValidatedPhysicalColumn<T>): DecodedColumn<T>;
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { dateMilliseconds } from "../date-value.js";
|
|
2
|
+
import { physicalColumnByteLength, validatePhysicalColumn } from "./physical.js";
|
|
3
|
+
import { wellFormedUtf8ByteLength } from "./unicode.js";
|
|
1
4
|
const textEncoder = new TextEncoder();
|
|
2
5
|
const textDecoder = new TextDecoder("utf-8", { fatal: true });
|
|
3
6
|
// The on-disk format is little-endian; bulk Float64 writes use platform order when they match.
|
|
@@ -17,37 +20,74 @@ export function encodeColumn(input) {
|
|
|
17
20
|
// the validity bitmap from the value payload and persist a corrupt block. A hole reads as
|
|
18
21
|
// undefined and is rejected like any other non-value.
|
|
19
22
|
const rowCount = input.values.length;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
// Validate the fixed portion before allocation. Its format-level row cap bounds the largest
|
|
24
|
+
// fixed-width allocation to about 8 MiB, so boolean, number, and datetime columns validate and
|
|
25
|
+
// encode each accessor value in one pass. Reading them twice would both waste a full scan and
|
|
26
|
+
// introduce a needless time-of-check/time-of-use boundary for accessor-backed inputs.
|
|
27
|
+
physicalColumnByteLength(input.type, rowCount);
|
|
28
|
+
let stringContentByteLength = 0;
|
|
29
|
+
if (input.type === "string") {
|
|
30
|
+
// Variable-width output still needs an exact sizing pass before allocation. The encode pass
|
|
31
|
+
// below revalidates the local value it writes, so a changing accessor cannot smuggle invalid
|
|
32
|
+
// UTF-16 or make offsets disagree with the content buffer.
|
|
33
|
+
for (let index = 0; index < rowCount; index += 1) {
|
|
34
|
+
const value = input.values[index];
|
|
35
|
+
if (value === undefined)
|
|
36
|
+
throw new TypeError("Column values cannot be undefined");
|
|
37
|
+
if (value !== null) {
|
|
38
|
+
if (typeof value !== "string") {
|
|
39
|
+
throw new TypeError("String columns accept only strings or null");
|
|
40
|
+
}
|
|
41
|
+
stringContentByteLength += wellFormedUtf8ByteLength(value);
|
|
42
|
+
if (!Number.isSafeInteger(stringContentByteLength)) {
|
|
43
|
+
throw new RangeError("Invalid string content byte length");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
30
47
|
}
|
|
48
|
+
physicalColumnByteLength(input.type, rowCount, stringContentByteLength);
|
|
49
|
+
const validity = new Uint8Array(bitmapLength(rowCount));
|
|
31
50
|
switch (input.type) {
|
|
32
51
|
case "boolean": {
|
|
33
52
|
const values = new Uint8Array(bitmapLength(rowCount));
|
|
53
|
+
let nullCount = 0;
|
|
34
54
|
for (let index = 0; index < rowCount; index += 1) {
|
|
35
|
-
|
|
36
|
-
|
|
55
|
+
const value = input.values[index];
|
|
56
|
+
if (value === undefined)
|
|
57
|
+
throw new TypeError("Column values cannot be undefined");
|
|
58
|
+
if (value !== null && typeof value !== "boolean") {
|
|
59
|
+
throw new TypeError("Boolean columns accept only booleans or null");
|
|
60
|
+
}
|
|
61
|
+
if (value === null)
|
|
62
|
+
nullCount += 1;
|
|
63
|
+
else {
|
|
64
|
+
setBit(validity, index);
|
|
65
|
+
if (value)
|
|
66
|
+
setBit(values, index);
|
|
67
|
+
}
|
|
37
68
|
}
|
|
38
69
|
return { bytes: join(validity, values), metadata: {}, nullCount };
|
|
39
70
|
}
|
|
40
71
|
case "number": {
|
|
41
72
|
const values = new Float64Array(rowCount);
|
|
42
73
|
const view = PLATFORM_LITTLE_ENDIAN ? undefined : new DataView(values.buffer);
|
|
74
|
+
let nullCount = 0;
|
|
43
75
|
let min = Number.POSITIVE_INFINITY;
|
|
44
76
|
let max = Number.NEGATIVE_INFINITY;
|
|
45
77
|
for (let index = 0; index < rowCount; index += 1) {
|
|
46
78
|
const value = input.values[index];
|
|
47
|
-
if (value ===
|
|
79
|
+
if (value === undefined)
|
|
80
|
+
throw new TypeError("Column values cannot be undefined");
|
|
81
|
+
if (value === null) {
|
|
82
|
+
nullCount += 1;
|
|
48
83
|
continue;
|
|
84
|
+
}
|
|
85
|
+
if (typeof value !== "number") {
|
|
86
|
+
throw new TypeError("Number columns accept only numbers or null");
|
|
87
|
+
}
|
|
49
88
|
if (!Number.isFinite(value))
|
|
50
89
|
throw new TypeError("Number values must be finite");
|
|
90
|
+
setBit(validity, index);
|
|
51
91
|
if (view === undefined)
|
|
52
92
|
values[index] = value;
|
|
53
93
|
else
|
|
@@ -61,15 +101,24 @@ export function encodeColumn(input) {
|
|
|
61
101
|
case "datetime": {
|
|
62
102
|
const values = new Float64Array(rowCount);
|
|
63
103
|
const view = PLATFORM_LITTLE_ENDIAN ? undefined : new DataView(values.buffer);
|
|
104
|
+
let nullCount = 0;
|
|
64
105
|
let min = Number.POSITIVE_INFINITY;
|
|
65
106
|
let max = Number.NEGATIVE_INFINITY;
|
|
66
107
|
for (let index = 0; index < rowCount; index += 1) {
|
|
67
108
|
const value = input.values[index];
|
|
68
|
-
if (value ===
|
|
109
|
+
if (value === undefined)
|
|
110
|
+
throw new TypeError("Column values cannot be undefined");
|
|
111
|
+
if (value === null) {
|
|
112
|
+
nullCount += 1;
|
|
69
113
|
continue;
|
|
70
|
-
|
|
114
|
+
}
|
|
115
|
+
if (!(value instanceof Date)) {
|
|
116
|
+
throw new TypeError("Datetime columns accept only Date objects or null");
|
|
117
|
+
}
|
|
118
|
+
const milliseconds = dateMilliseconds(value);
|
|
71
119
|
if (!Number.isFinite(milliseconds))
|
|
72
120
|
throw new TypeError("Datetime values must be valid Dates");
|
|
121
|
+
setBit(validity, index);
|
|
73
122
|
if (view === undefined)
|
|
74
123
|
values[index] = milliseconds;
|
|
75
124
|
else
|
|
@@ -81,25 +130,40 @@ export function encodeColumn(input) {
|
|
|
81
130
|
return { bytes: join(validity, new Uint8Array(values.buffer)), metadata, nullCount };
|
|
82
131
|
}
|
|
83
132
|
case "string": {
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
let capacity = 0;
|
|
88
|
-
for (let index = 0; index < rowCount; index += 1) {
|
|
89
|
-
const value = input.values[index];
|
|
90
|
-
if (value !== null && value !== undefined)
|
|
91
|
-
capacity += value.length * 3;
|
|
92
|
-
}
|
|
133
|
+
// Measure exactly without allocating, both to reject lossy unpaired surrogates and to avoid
|
|
134
|
+
// the former 3x worst-case scratch for ASCII-heavy data. The complete 64 MiB format bound is
|
|
135
|
+
// checked before the content or offset arrays are allocated.
|
|
93
136
|
const offsets = new Uint32Array(rowCount + 1);
|
|
94
|
-
|
|
137
|
+
// Some native encodeInto implementations stop at an internal chunk boundary when the
|
|
138
|
+
// destination has exactly two or three bytes left, even though the final code point fits.
|
|
139
|
+
// Three bytes of non-persisted tail room keeps the native fast path reliable; the returned
|
|
140
|
+
// physical payload still contains exactly `contentByteLength` content bytes.
|
|
141
|
+
const content = new Uint8Array(stringContentByteLength + 3);
|
|
95
142
|
let offset = 0;
|
|
143
|
+
let nullCount = 0;
|
|
96
144
|
for (let index = 0; index < rowCount; index += 1) {
|
|
97
145
|
const value = input.values[index];
|
|
98
|
-
if (value
|
|
99
|
-
|
|
146
|
+
if (value === undefined)
|
|
147
|
+
throw new TypeError("Column values cannot be undefined");
|
|
148
|
+
if (value === null)
|
|
149
|
+
nullCount += 1;
|
|
150
|
+
else {
|
|
151
|
+
if (typeof value !== "string") {
|
|
152
|
+
throw new TypeError("String columns accept only strings or null");
|
|
153
|
+
}
|
|
154
|
+
const localByteLength = wellFormedUtf8ByteLength(value);
|
|
155
|
+
setBit(validity, index);
|
|
156
|
+
const result = textEncoder.encodeInto(value, content.subarray(offset));
|
|
157
|
+
if (result.read !== value.length)
|
|
158
|
+
throw new Error("UTF-8 output sizing mismatch");
|
|
159
|
+
if (result.written !== localByteLength)
|
|
160
|
+
throw new Error("UTF-8 output sizing mismatch");
|
|
161
|
+
offset += result.written;
|
|
100
162
|
}
|
|
101
163
|
offsets[index + 1] = offset;
|
|
102
164
|
}
|
|
165
|
+
if (offset !== stringContentByteLength)
|
|
166
|
+
throw new Error("UTF-8 output sizing mismatch");
|
|
103
167
|
return {
|
|
104
168
|
bytes: join(validity, new Uint8Array(offsets.buffer), content.subarray(0, offset)),
|
|
105
169
|
metadata: {},
|
|
@@ -109,9 +173,12 @@ export function encodeColumn(input) {
|
|
|
109
173
|
}
|
|
110
174
|
}
|
|
111
175
|
export function decodeColumn(type, bytes, rowCount) {
|
|
176
|
+
return decodeValidatedColumn(validatePhysicalColumn({ type, bytes, rowCount }));
|
|
177
|
+
}
|
|
178
|
+
/** Package-internal row materialization after the physical payload was already validated. */
|
|
179
|
+
export function decodeValidatedColumn(column) {
|
|
180
|
+
const { type, bytes, rowCount } = column;
|
|
112
181
|
const validityLength = bitmapLength(rowCount);
|
|
113
|
-
if (bytes.byteLength < validityLength)
|
|
114
|
-
throw new Error("Truncated validity bitmap");
|
|
115
182
|
const validity = bytes.subarray(0, validityLength);
|
|
116
183
|
const payload = bytes.subarray(validityLength);
|
|
117
184
|
const values = [];
|
|
@@ -163,4 +230,3 @@ function join(...parts) {
|
|
|
163
230
|
}
|
|
164
231
|
return output;
|
|
165
232
|
}
|
|
166
|
-
//# sourceMappingURL=column.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from "./block.js";
|
|
2
2
|
export * from "./checksum.js";
|
|
3
3
|
export * from "./codecs.js";
|
|
4
|
-
export
|
|
4
|
+
export { decodeColumn, encodeColumn } from "./column.js";
|
|
5
5
|
export * from "./physical.js";
|
|
6
6
|
export * from "./types.js";
|
|
7
|
-
|
|
7
|
+
export * from "./unicode.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export * from "./block.js";
|
|
2
2
|
export * from "./checksum.js";
|
|
3
3
|
export * from "./codecs.js";
|
|
4
|
-
export
|
|
4
|
+
export { decodeColumn, encodeColumn } from "./column.js";
|
|
5
5
|
export * from "./physical.js";
|
|
6
6
|
export * from "./types.js";
|
|
7
|
-
|
|
7
|
+
export * from "./unicode.js";
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import type { LogicalType, PhysicalColumnMeasurement, PhysicalColumnPayload, PhysicalColumnRange, ValidatedPhysicalColumn } from "./types.js";
|
|
2
2
|
export declare const MAX_PHYSICAL_COLUMN_BYTE_LENGTH: number;
|
|
3
|
+
/**
|
|
4
|
+
* Hard row ceiling for one physical block. Bitmap columns otherwise fit 268 million rows under
|
|
5
|
+
* the byte limit, which would require an unsafe decoded JS array even for a valid block.
|
|
6
|
+
*/
|
|
7
|
+
export declare const MAX_BLOCK_ROW_COUNT = 1048576;
|
|
3
8
|
export declare function physicalBitmapByteLength(rowCount: number): number;
|
|
4
|
-
/** Returns the exact encoded byte length for
|
|
9
|
+
/** Returns the exact encoded byte length for the canonical v2 physical column. */
|
|
5
10
|
export declare function physicalColumnByteLength(type: LogicalType, rowCount: number, stringContentByteLength?: number): number;
|
|
6
11
|
/**
|
|
7
12
|
* Validates a physical payload without copying its bytes or materializing row
|
|
@@ -17,4 +22,5 @@ export declare function measurePhysicalColumnRanges<T extends LogicalType>(type:
|
|
|
17
22
|
export declare function buildPhysicalColumnFromRanges<T extends LogicalType>(type: T, ranges: ReadonlyArray<PhysicalColumnRange<T>>): ValidatedPhysicalColumn<T>;
|
|
18
23
|
export declare function slicePhysicalColumn<T extends LogicalType>(column: PhysicalColumnPayload<T>, start: number, end: number): ValidatedPhysicalColumn<T>;
|
|
19
24
|
export declare function concatenatePhysicalColumns<T extends LogicalType>(type: T, columns: ReadonlyArray<PhysicalColumnPayload<T>>): ValidatedPhysicalColumn<T>;
|
|
20
|
-
|
|
25
|
+
/** Validates the shared persisted-block row ceiling without allocating a physical payload. */
|
|
26
|
+
export declare function assertBlockRowCount(rowCount: number): void;
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
export const MAX_PHYSICAL_COLUMN_BYTE_LENGTH = 64 * 1024 * 1024;
|
|
2
|
+
/**
|
|
3
|
+
* Hard row ceiling for one physical block. Bitmap columns otherwise fit 268 million rows under
|
|
4
|
+
* the byte limit, which would require an unsafe decoded JS array even for a valid block.
|
|
5
|
+
*/
|
|
6
|
+
export const MAX_BLOCK_ROW_COUNT = 1_048_576;
|
|
2
7
|
const MAX_DATETIME_MILLISECONDS = 8_640_000_000_000_000;
|
|
3
8
|
export function physicalBitmapByteLength(rowCount) {
|
|
4
9
|
assertRowCount(rowCount);
|
|
5
10
|
return Math.ceil(rowCount / 8);
|
|
6
11
|
}
|
|
7
|
-
/** Returns the exact encoded byte length for
|
|
12
|
+
/** Returns the exact encoded byte length for the canonical v2 physical column. */
|
|
8
13
|
export function physicalColumnByteLength(type, rowCount, stringContentByteLength = 0) {
|
|
9
14
|
assertLogicalType(type);
|
|
10
15
|
const validityByteLength = physicalBitmapByteLength(rowCount);
|
|
@@ -254,8 +259,7 @@ function preparePhysicalColumn(type, ranges) {
|
|
|
254
259
|
}
|
|
255
260
|
const rangeRowCount = range.end - range.start;
|
|
256
261
|
rowCount = checkedAdd(rowCount, rangeRowCount, "row count");
|
|
257
|
-
|
|
258
|
-
throw new RangeError("Too many rows in one physical column");
|
|
262
|
+
assertBlockRowCount(rowCount);
|
|
259
263
|
const sourceValidityLength = physicalBitmapByteLength(column.rowCount);
|
|
260
264
|
const sourceValidity = column.bytes.subarray(0, sourceValidityLength);
|
|
261
265
|
if (type === "string") {
|
|
@@ -404,8 +408,13 @@ function assertContinuation(bytes, index, end) {
|
|
|
404
408
|
}
|
|
405
409
|
function assertRowCount(rowCount) {
|
|
406
410
|
assertNonnegativeSafeInteger(rowCount, "row count");
|
|
407
|
-
if (rowCount >
|
|
408
|
-
throw new RangeError("
|
|
411
|
+
if (rowCount > MAX_BLOCK_ROW_COUNT) {
|
|
412
|
+
throw new RangeError("Physical column exceeds maximum row count");
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
/** Validates the shared persisted-block row ceiling without allocating a physical payload. */
|
|
416
|
+
export function assertBlockRowCount(rowCount) {
|
|
417
|
+
assertRowCount(rowCount);
|
|
409
418
|
}
|
|
410
419
|
function assertLogicalType(type) {
|
|
411
420
|
if (type !== "boolean" && type !== "number" && type !== "string" && type !== "datetime") {
|
|
@@ -436,4 +445,3 @@ function checkedMultiply(left, right, name) {
|
|
|
436
445
|
}
|
|
437
446
|
return left * right;
|
|
438
447
|
}
|
|
439
|
-
//# sourceMappingURL=physical.js.map
|
|
@@ -30,13 +30,18 @@ export interface BlockMetadata {
|
|
|
30
30
|
}
|
|
31
31
|
export interface BlockDescription {
|
|
32
32
|
formatVersion: number;
|
|
33
|
+
headerLength: number;
|
|
34
|
+
metadataLength: number;
|
|
33
35
|
type: LogicalType;
|
|
34
36
|
compression: Compression;
|
|
35
37
|
rowCount: number;
|
|
36
38
|
nullCount: number;
|
|
37
39
|
encodedLength: number;
|
|
38
40
|
storedLength: number;
|
|
41
|
+
/** CRC32 of the uncompressed physical column bytes. */
|
|
39
42
|
checksum: number;
|
|
43
|
+
/** CRC32 of the stored payload bytes, independently verifiable without decompression. */
|
|
44
|
+
storedChecksum: number;
|
|
40
45
|
metadata: BlockMetadata;
|
|
41
46
|
}
|
|
42
47
|
export interface DecodedBlock<T extends LogicalType = LogicalType> {
|
|
@@ -46,8 +51,8 @@ export interface DecodedBlock<T extends LogicalType = LogicalType> {
|
|
|
46
51
|
column: DecodedColumn<T>;
|
|
47
52
|
}
|
|
48
53
|
/**
|
|
49
|
-
* An uncompressed physical column payload. `bytes` uses the
|
|
50
|
-
*
|
|
54
|
+
* An uncompressed physical column payload. `bytes` uses the canonical v2 column encoding
|
|
55
|
+
* documented in `apps/site/content/docs/reference/architecture.mdx`.
|
|
51
56
|
*/
|
|
52
57
|
export interface PhysicalColumnPayload<T extends LogicalType = LogicalType> {
|
|
53
58
|
type: T;
|
|
@@ -90,4 +95,3 @@ export interface DecodedPhysicalBlock<T extends LogicalType = LogicalType> {
|
|
|
90
95
|
column: ValidatedPhysicalColumn<T>;
|
|
91
96
|
}
|
|
92
97
|
export {};
|
|
93
|
-
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the exact UTF-8 byte length of a well-formed JavaScript string without allocating.
|
|
3
|
+
*
|
|
4
|
+
* UTF-8 cannot represent isolated UTF-16 surrogate code units. `TextEncoder` silently replaces
|
|
5
|
+
* them with U+FFFD, which would make persistence lossy and can collapse distinct index keys.
|
|
6
|
+
* Minnow rejects those strings instead, so every accepted string has one exact UTF-8 encoding
|
|
7
|
+
* and round-trips byte-for-byte through the block format.
|
|
8
|
+
*/
|
|
9
|
+
export declare function wellFormedUtf8ByteLength(value: string, context?: string): number;
|
|
10
|
+
/** Rejects strings that cannot round-trip exactly through UTF-8 persistence. */
|
|
11
|
+
export declare function assertWellFormedString(value: string, context?: string): void;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the exact UTF-8 byte length of a well-formed JavaScript string without allocating.
|
|
3
|
+
*
|
|
4
|
+
* UTF-8 cannot represent isolated UTF-16 surrogate code units. `TextEncoder` silently replaces
|
|
5
|
+
* them with U+FFFD, which would make persistence lossy and can collapse distinct index keys.
|
|
6
|
+
* Minnow rejects those strings instead, so every accepted string has one exact UTF-8 encoding
|
|
7
|
+
* and round-trips byte-for-byte through the block format.
|
|
8
|
+
*/
|
|
9
|
+
export function wellFormedUtf8ByteLength(value, context = "String value") {
|
|
10
|
+
return measureWellFormedUtf8(value, context);
|
|
11
|
+
}
|
|
12
|
+
/** Rejects strings that cannot round-trip exactly through UTF-8 persistence. */
|
|
13
|
+
export function assertWellFormedString(value, context = "String value") {
|
|
14
|
+
wellFormedUtf8ByteLength(value, context);
|
|
15
|
+
}
|
|
16
|
+
function measureWellFormedUtf8(value, context) {
|
|
17
|
+
if (typeof value !== "string")
|
|
18
|
+
throw new TypeError(`${context} must be a string`);
|
|
19
|
+
let byteLength = 0;
|
|
20
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
21
|
+
const code = value.charCodeAt(index);
|
|
22
|
+
if (code <= 0x7f) {
|
|
23
|
+
byteLength += 1;
|
|
24
|
+
}
|
|
25
|
+
else if (code <= 0x7ff) {
|
|
26
|
+
byteLength += 2;
|
|
27
|
+
}
|
|
28
|
+
else if (code >= 0xd800 && code <= 0xdbff) {
|
|
29
|
+
const low = index + 1 < value.length ? value.charCodeAt(index + 1) : 0;
|
|
30
|
+
if (low < 0xdc00 || low > 0xdfff)
|
|
31
|
+
throw unpairedSurrogate(context, index);
|
|
32
|
+
byteLength += 4;
|
|
33
|
+
index += 1;
|
|
34
|
+
}
|
|
35
|
+
else if (code >= 0xdc00 && code <= 0xdfff) {
|
|
36
|
+
throw unpairedSurrogate(context, index);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
byteLength += 3;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return byteLength;
|
|
43
|
+
}
|
|
44
|
+
function unpairedSurrogate(context, index) {
|
|
45
|
+
return new TypeError(`${context} contains an unpaired surrogate at UTF-16 index ${String(index)}`);
|
|
46
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Returns a Date's internal millisecond value without invoking an instance override. */
|
|
2
|
+
export declare function dateMilliseconds(value: Date): number;
|
|
3
|
+
/** Copies a Date by its internal value without invoking instance methods. */
|
|
4
|
+
export declare function copyDate(value: Date): Date;
|
|
5
|
+
/** Formats a Date's internal value without invoking an instance override. */
|
|
6
|
+
export declare function dateIsoString(value: Date): string;
|
|
7
|
+
export declare function dateUtcFullYear(value: Date): number;
|
|
8
|
+
export declare function dateUtcMonth(value: Date): number;
|
|
9
|
+
export declare function dateUtcDate(value: Date): number;
|
|
10
|
+
export declare function dateUtcDay(value: Date): number;
|
|
11
|
+
export declare function dateUtcHours(value: Date): number;
|
|
12
|
+
export declare function dateUtcMinutes(value: Date): number;
|
|
13
|
+
export declare function dateUtcSeconds(value: Date): number;
|
|
14
|
+
export declare function setDateUtcDate(value: Date, day: number): number;
|
|
15
|
+
export declare function setDateUtcMonth(value: Date, month: number): number;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Capture the intrinsic once. A Date instance may shadow `getTime`; persistence, indexes, and
|
|
2
|
+
// comparisons must all observe its internal [[DateValue]], not caller-controlled method code.
|
|
3
|
+
// Capturing the intrinsic is the point: later Date.prototype mutations must not change values.
|
|
4
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
5
|
+
const intrinsicDateGetTime = Date.prototype.getTime;
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method -- See the getTime capture above.
|
|
7
|
+
const intrinsicDateToISOString = Date.prototype.toISOString;
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method -- Captured for the same reason.
|
|
9
|
+
const intrinsicDateGetUtcFullYear = Date.prototype.getUTCFullYear;
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method -- Captured for the same reason.
|
|
11
|
+
const intrinsicDateGetUtcMonth = Date.prototype.getUTCMonth;
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method -- Captured for the same reason.
|
|
13
|
+
const intrinsicDateGetUtcDate = Date.prototype.getUTCDate;
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method -- Captured for the same reason.
|
|
15
|
+
const intrinsicDateGetUtcDay = Date.prototype.getUTCDay;
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method -- Captured for the same reason.
|
|
17
|
+
const intrinsicDateGetUtcHours = Date.prototype.getUTCHours;
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method -- Captured for the same reason.
|
|
19
|
+
const intrinsicDateGetUtcMinutes = Date.prototype.getUTCMinutes;
|
|
20
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method -- Captured for the same reason.
|
|
21
|
+
const intrinsicDateGetUtcSeconds = Date.prototype.getUTCSeconds;
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method -- Captured for the same reason.
|
|
23
|
+
const intrinsicDateSetUtcDate = Date.prototype.setUTCDate;
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method -- Captured for the same reason.
|
|
25
|
+
const intrinsicDateSetUtcMonth = Date.prototype.setUTCMonth;
|
|
26
|
+
/** Returns a Date's internal millisecond value without invoking an instance override. */
|
|
27
|
+
export function dateMilliseconds(value) {
|
|
28
|
+
return intrinsicDateGetTime.call(value);
|
|
29
|
+
}
|
|
30
|
+
/** Copies a Date by its internal value without invoking instance methods. */
|
|
31
|
+
export function copyDate(value) {
|
|
32
|
+
return new Date(dateMilliseconds(value));
|
|
33
|
+
}
|
|
34
|
+
/** Formats a Date's internal value without invoking an instance override. */
|
|
35
|
+
export function dateIsoString(value) {
|
|
36
|
+
return intrinsicDateToISOString.call(value);
|
|
37
|
+
}
|
|
38
|
+
export function dateUtcFullYear(value) {
|
|
39
|
+
return intrinsicDateGetUtcFullYear.call(value);
|
|
40
|
+
}
|
|
41
|
+
export function dateUtcMonth(value) {
|
|
42
|
+
return intrinsicDateGetUtcMonth.call(value);
|
|
43
|
+
}
|
|
44
|
+
export function dateUtcDate(value) {
|
|
45
|
+
return intrinsicDateGetUtcDate.call(value);
|
|
46
|
+
}
|
|
47
|
+
export function dateUtcDay(value) {
|
|
48
|
+
return intrinsicDateGetUtcDay.call(value);
|
|
49
|
+
}
|
|
50
|
+
export function dateUtcHours(value) {
|
|
51
|
+
return intrinsicDateGetUtcHours.call(value);
|
|
52
|
+
}
|
|
53
|
+
export function dateUtcMinutes(value) {
|
|
54
|
+
return intrinsicDateGetUtcMinutes.call(value);
|
|
55
|
+
}
|
|
56
|
+
export function dateUtcSeconds(value) {
|
|
57
|
+
return intrinsicDateGetUtcSeconds.call(value);
|
|
58
|
+
}
|
|
59
|
+
export function setDateUtcDate(value, day) {
|
|
60
|
+
return intrinsicDateSetUtcDate.call(value, day);
|
|
61
|
+
}
|
|
62
|
+
export function setDateUtcMonth(value, month) {
|
|
63
|
+
return intrinsicDateSetUtcMonth.call(value, month);
|
|
64
|
+
}
|
|
@@ -17,6 +17,7 @@ export declare class ArtifactCache {
|
|
|
17
17
|
get enabled(): boolean;
|
|
18
18
|
get(key: string): unknown;
|
|
19
19
|
put(key: string, payload: unknown, bytes: number): void;
|
|
20
|
+
/** Releases every retained payload while preserving lifetime counters for final diagnostics. */
|
|
21
|
+
clear(): void;
|
|
20
22
|
stats(): ArtifactCacheStats;
|
|
21
23
|
}
|
|
22
|
-
//# sourceMappingURL=artifact-cache.d.ts.map
|
|
@@ -54,6 +54,11 @@ export class ArtifactCache {
|
|
|
54
54
|
this.#evictions += 1;
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
+
/** Releases every retained payload while preserving lifetime counters for final diagnostics. */
|
|
58
|
+
clear() {
|
|
59
|
+
this.#entries.clear();
|
|
60
|
+
this.#usedBytes = 0;
|
|
61
|
+
}
|
|
57
62
|
stats() {
|
|
58
63
|
return {
|
|
59
64
|
limitBytes: this.#limitBytes,
|
|
@@ -65,4 +70,3 @@ export class ArtifactCache {
|
|
|
65
70
|
};
|
|
66
71
|
}
|
|
67
72
|
}
|
|
68
|
-
//# sourceMappingURL=artifact-cache.js.map
|
package/dist/engine/batch.d.ts
CHANGED
|
@@ -8,11 +8,20 @@
|
|
|
8
8
|
*/
|
|
9
9
|
/** A value a column can hold. */
|
|
10
10
|
export type BatchValue = boolean | number | string | Date | null;
|
|
11
|
-
/** One row.
|
|
11
|
+
/** One row. A missing property is SQL omission; an explicit `null` remains SQL NULL. */
|
|
12
12
|
export type BatchRow = Readonly<Record<string, BatchValue>>;
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* The columnar form: one ordinary readonly array per column, all of the same length and aligned by
|
|
15
|
+
* index. The engine reads these arrays without copying while the asynchronous write is active;
|
|
16
|
+
* callers must not mutate them or use changing accessor/proxy values until the write settles.
|
|
17
|
+
*/
|
|
14
18
|
export interface ColumnarBatch {
|
|
15
19
|
columns: Readonly<Record<string, readonly BatchValue[]>>;
|
|
20
|
+
/**
|
|
21
|
+
* Per-row SQL omission markers. A true slot asks the engine to use the column default (or NULL
|
|
22
|
+
* when no default exists), without conflating that request with an explicit NULL value.
|
|
23
|
+
*/
|
|
24
|
+
omitted?: Readonly<Record<string, readonly boolean[]>>;
|
|
16
25
|
/**
|
|
17
26
|
* The batch's row count when no column carries it — a pivot of rows whose every column is
|
|
18
27
|
* default-generated produces an empty column map, and the count would otherwise be lost
|
|
@@ -25,4 +34,3 @@ export type InsertBatchInput = readonly BatchRow[] | ColumnarBatch;
|
|
|
25
34
|
export declare function isColumnarBatch(input: InsertBatchInput): input is ColumnarBatch;
|
|
26
35
|
/** Pivots rows into the engine's columnar form; a columnar batch passes straight through. */
|
|
27
36
|
export declare function toColumnarBatch(input: InsertBatchInput): ColumnarBatch;
|
|
28
|
-
//# sourceMappingURL=batch.d.ts.map
|