@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.
Files changed (270) hide show
  1. package/README.md +23 -32
  2. package/dist/block-format/block.d.ts +32 -13
  3. package/dist/block-format/block.js +179 -55
  4. package/dist/block-format/checksum.d.ts +2 -1
  5. package/dist/block-format/checksum.js +5 -2
  6. package/dist/block-format/codecs.d.ts +7 -2
  7. package/dist/block-format/codecs.js +53 -12
  8. package/dist/block-format/column.d.ts +3 -2
  9. package/dist/block-format/column.js +96 -30
  10. package/dist/block-format/index.d.ts +2 -2
  11. package/dist/block-format/index.js +2 -2
  12. package/dist/block-format/physical.d.ts +8 -2
  13. package/dist/block-format/physical.js +14 -6
  14. package/dist/block-format/types.d.ts +7 -3
  15. package/dist/block-format/types.js +0 -1
  16. package/dist/block-format/unicode.d.ts +11 -0
  17. package/dist/block-format/unicode.js +46 -0
  18. package/dist/date-value.d.ts +15 -0
  19. package/dist/date-value.js +64 -0
  20. package/dist/engine/artifact-cache.d.ts +2 -1
  21. package/dist/engine/artifact-cache.js +5 -1
  22. package/dist/engine/batch.d.ts +11 -3
  23. package/dist/engine/batch.js +17 -7
  24. package/dist/engine/buffered-writer.d.ts +2 -1
  25. package/dist/engine/buffered-writer.js +34 -9
  26. package/dist/engine/cache-limits.d.ts +25 -0
  27. package/dist/engine/cache-limits.js +25 -0
  28. package/dist/engine/catalog.d.ts +24 -5
  29. package/dist/engine/catalog.js +34 -7
  30. package/dist/engine/client.d.ts +29 -7
  31. package/dist/engine/client.js +216 -40
  32. package/dist/engine/database.d.ts +224 -39
  33. package/dist/engine/database.js +7475 -1539
  34. package/dist/engine/defaults.d.ts +4 -8
  35. package/dist/engine/defaults.js +46 -22
  36. package/dist/engine/errors.d.ts +19 -1
  37. package/dist/engine/errors.js +32 -2
  38. package/dist/engine/fts.d.ts +0 -6
  39. package/dist/engine/fts.js +41 -14
  40. package/dist/engine/group-index.d.ts +0 -1
  41. package/dist/engine/group-index.js +6 -11
  42. package/dist/engine/index.d.ts +16 -10
  43. package/dist/engine/index.js +12 -9
  44. package/dist/engine/join-index.d.ts +0 -1
  45. package/dist/engine/join-index.js +2 -2
  46. package/dist/engine/keyed-live.d.ts +57 -0
  47. package/dist/engine/keyed-live.js +226 -0
  48. package/dist/engine/live-api.d.ts +4 -0
  49. package/dist/engine/live-api.js +4 -0
  50. package/dist/engine/live.d.ts +43 -26
  51. package/dist/engine/live.js +504 -126
  52. package/dist/engine/memory.d.ts +2 -1
  53. package/dist/engine/memory.js +3 -2
  54. package/dist/engine/optimizer.d.ts +0 -1
  55. package/dist/engine/optimizer.js +262 -27
  56. package/dist/engine/query-api.d.ts +3 -0
  57. package/dist/engine/query-api.js +3 -0
  58. package/dist/engine/query-cache.d.ts +1 -2
  59. package/dist/engine/query-cache.js +7 -5
  60. package/dist/engine/query.d.ts +134 -29
  61. package/dist/engine/query.js +1668 -372
  62. package/dist/engine/result-wire.d.ts +0 -1
  63. package/dist/engine/result-wire.js +2 -2
  64. package/dist/engine/schema-wire.d.ts +6 -3
  65. package/dist/engine/schema-wire.js +40 -34
  66. package/dist/engine/schema.d.ts +156 -80
  67. package/dist/engine/schema.js +570 -108
  68. package/dist/engine/sort-keys.d.ts +4 -4
  69. package/dist/engine/sort-keys.js +44 -29
  70. package/dist/engine/sql-domains.d.ts +31 -0
  71. package/dist/engine/sql-domains.js +585 -0
  72. package/dist/engine/sql-driver.d.ts +19 -0
  73. package/dist/engine/sql-driver.js +1 -0
  74. package/dist/engine/sql-json.d.ts +7 -9
  75. package/dist/engine/sql-json.js +75 -15
  76. package/dist/engine/sql-semantics.d.ts +8 -3
  77. package/dist/engine/sql-semantics.js +458 -30
  78. package/dist/engine/typed-live.d.ts +67 -0
  79. package/dist/engine/typed-live.js +349 -0
  80. package/dist/engine/vector.d.ts +12 -2
  81. package/dist/engine/vector.js +635 -119
  82. package/dist/engine/worker-host.d.ts +9 -2
  83. package/dist/engine/worker-host.js +620 -152
  84. package/dist/engine/worker.d.ts +0 -1
  85. package/dist/engine/worker.js +3 -3
  86. package/dist/engine/write-block-planner.d.ts +18 -0
  87. package/dist/engine/write-block-planner.js +112 -0
  88. package/dist/index.d.ts +0 -1
  89. package/dist/index.js +0 -1
  90. package/dist/plan/index.d.ts +3 -4
  91. package/dist/plan/index.js +3 -4
  92. package/dist/storage/index.d.ts +1 -1
  93. package/dist/storage/index.js +1 -1
  94. package/dist/storage/indexeddb.d.ts +99 -51
  95. package/dist/storage/indexeddb.js +13448 -2660
  96. package/dist/storage/memory.d.ts +64 -57
  97. package/dist/storage/memory.js +1042 -128
  98. package/dist/storage/opfs/files.d.ts +18 -7
  99. package/dist/storage/opfs/files.js +115 -28
  100. package/dist/storage/opfs/index.d.ts +1 -1
  101. package/dist/storage/opfs/index.js +1 -1
  102. package/dist/storage/opfs/leader.d.ts +409 -75
  103. package/dist/storage/opfs/leader.js +4621 -650
  104. package/dist/storage/opfs/rpc.d.ts +15 -3
  105. package/dist/storage/opfs/rpc.js +224 -2
  106. package/dist/storage/opfs/snapshot-ledger.d.ts +40 -0
  107. package/dist/storage/opfs/snapshot-ledger.js +281 -0
  108. package/dist/storage/opfs/store.d.ts +33 -99
  109. package/dist/storage/opfs/store.js +453 -364
  110. package/dist/storage/persistence.d.ts +37 -0
  111. package/dist/storage/persistence.js +78 -0
  112. package/dist/storage/snapshot-stream.d.ts +24 -0
  113. package/dist/storage/snapshot-stream.js +897 -0
  114. package/dist/storage/snapshot.d.ts +9 -85
  115. package/dist/storage/snapshot.js +33 -265
  116. package/dist/storage/toolkit/extents.d.ts +41 -7
  117. package/dist/storage/toolkit/extents.js +402 -39
  118. package/dist/storage/toolkit/index.d.ts +4 -5
  119. package/dist/storage/toolkit/index.js +28 -4
  120. package/dist/storage/toolkit/record-core.d.ts +182 -55
  121. package/dist/storage/toolkit/record-core.js +6158 -1331
  122. package/dist/storage/toolkit/sync-file.d.ts +10 -1
  123. package/dist/storage/toolkit/sync-file.js +50 -2
  124. package/dist/storage/toolkit/wal.d.ts +23 -5
  125. package/dist/storage/toolkit/wal.js +89 -27
  126. package/dist/storage/toolkit/wire.d.ts +15 -2
  127. package/dist/storage/toolkit/wire.js +199 -10
  128. package/dist/storage/types.d.ts +1439 -204
  129. package/dist/storage/types.js +1745 -141
  130. package/dist/testing/block-store-conformance.d.ts +0 -1
  131. package/dist/testing/block-store-conformance.js +1009 -119
  132. package/dist/testing/index.d.ts +46 -26
  133. package/dist/testing/index.js +112 -57
  134. package/dist/testing/opfs-shim.d.ts +13 -3
  135. package/dist/testing/opfs-shim.js +40 -6
  136. package/dist/testing/simulator.d.ts +97 -0
  137. package/dist/testing/simulator.js +591 -0
  138. package/dist/testing/sqllogictest.d.ts +89 -0
  139. package/dist/testing/sqllogictest.js +434 -0
  140. package/dist/transactions/index.d.ts +92 -16
  141. package/dist/transactions/index.js +1074 -236
  142. package/dist/worker-protocol/index.d.ts +3 -2
  143. package/dist/worker-protocol/index.js +2 -5
  144. package/package.json +53 -3
  145. package/postgres-feature-profile.json +223 -0
  146. package/sql-feature-matrix.json +172 -252
  147. package/dist/block-format/block.d.ts.map +0 -1
  148. package/dist/block-format/block.js.map +0 -1
  149. package/dist/block-format/checksum.d.ts.map +0 -1
  150. package/dist/block-format/checksum.js.map +0 -1
  151. package/dist/block-format/codecs.d.ts.map +0 -1
  152. package/dist/block-format/codecs.js.map +0 -1
  153. package/dist/block-format/column.d.ts.map +0 -1
  154. package/dist/block-format/column.js.map +0 -1
  155. package/dist/block-format/index.d.ts.map +0 -1
  156. package/dist/block-format/index.js.map +0 -1
  157. package/dist/block-format/physical.d.ts.map +0 -1
  158. package/dist/block-format/physical.js.map +0 -1
  159. package/dist/block-format/types.d.ts.map +0 -1
  160. package/dist/block-format/types.js.map +0 -1
  161. package/dist/engine/artifact-cache.d.ts.map +0 -1
  162. package/dist/engine/artifact-cache.js.map +0 -1
  163. package/dist/engine/batch.d.ts.map +0 -1
  164. package/dist/engine/batch.js.map +0 -1
  165. package/dist/engine/buffered-writer.d.ts.map +0 -1
  166. package/dist/engine/buffered-writer.js.map +0 -1
  167. package/dist/engine/catalog.d.ts.map +0 -1
  168. package/dist/engine/catalog.js.map +0 -1
  169. package/dist/engine/client.d.ts.map +0 -1
  170. package/dist/engine/client.js.map +0 -1
  171. package/dist/engine/coordinator.d.ts +0 -17
  172. package/dist/engine/coordinator.d.ts.map +0 -1
  173. package/dist/engine/coordinator.js +0 -60
  174. package/dist/engine/coordinator.js.map +0 -1
  175. package/dist/engine/database.d.ts.map +0 -1
  176. package/dist/engine/database.js.map +0 -1
  177. package/dist/engine/defaults.d.ts.map +0 -1
  178. package/dist/engine/defaults.js.map +0 -1
  179. package/dist/engine/errors.d.ts.map +0 -1
  180. package/dist/engine/errors.js.map +0 -1
  181. package/dist/engine/fts.d.ts.map +0 -1
  182. package/dist/engine/fts.js.map +0 -1
  183. package/dist/engine/group-index.d.ts.map +0 -1
  184. package/dist/engine/group-index.js.map +0 -1
  185. package/dist/engine/index.d.ts.map +0 -1
  186. package/dist/engine/index.js.map +0 -1
  187. package/dist/engine/join-index.d.ts.map +0 -1
  188. package/dist/engine/join-index.js.map +0 -1
  189. package/dist/engine/live.d.ts.map +0 -1
  190. package/dist/engine/live.js.map +0 -1
  191. package/dist/engine/memory.d.ts.map +0 -1
  192. package/dist/engine/memory.js.map +0 -1
  193. package/dist/engine/optimizer.d.ts.map +0 -1
  194. package/dist/engine/optimizer.js.map +0 -1
  195. package/dist/engine/query-cache.d.ts.map +0 -1
  196. package/dist/engine/query-cache.js.map +0 -1
  197. package/dist/engine/query.d.ts.map +0 -1
  198. package/dist/engine/query.js.map +0 -1
  199. package/dist/engine/result-wire.d.ts.map +0 -1
  200. package/dist/engine/result-wire.js.map +0 -1
  201. package/dist/engine/schema-wire.d.ts.map +0 -1
  202. package/dist/engine/schema-wire.js.map +0 -1
  203. package/dist/engine/schema.d.ts.map +0 -1
  204. package/dist/engine/schema.js.map +0 -1
  205. package/dist/engine/sort-keys.d.ts.map +0 -1
  206. package/dist/engine/sort-keys.js.map +0 -1
  207. package/dist/engine/sql-json.d.ts.map +0 -1
  208. package/dist/engine/sql-json.js.map +0 -1
  209. package/dist/engine/sql-semantics.d.ts.map +0 -1
  210. package/dist/engine/sql-semantics.js.map +0 -1
  211. package/dist/engine/vector.d.ts.map +0 -1
  212. package/dist/engine/vector.js.map +0 -1
  213. package/dist/engine/worker-host.d.ts.map +0 -1
  214. package/dist/engine/worker-host.js.map +0 -1
  215. package/dist/engine/worker.d.ts.map +0 -1
  216. package/dist/engine/worker.js.map +0 -1
  217. package/dist/index.d.ts.map +0 -1
  218. package/dist/index.js.map +0 -1
  219. package/dist/plan/index.d.ts.map +0 -1
  220. package/dist/plan/index.js.map +0 -1
  221. package/dist/storage/fixture-shape.d.ts +0 -42
  222. package/dist/storage/fixture-shape.d.ts.map +0 -1
  223. package/dist/storage/fixture-shape.js +0 -146
  224. package/dist/storage/fixture-shape.js.map +0 -1
  225. package/dist/storage/index.d.ts.map +0 -1
  226. package/dist/storage/index.js.map +0 -1
  227. package/dist/storage/indexeddb.d.ts.map +0 -1
  228. package/dist/storage/indexeddb.js.map +0 -1
  229. package/dist/storage/memory.d.ts.map +0 -1
  230. package/dist/storage/memory.js.map +0 -1
  231. package/dist/storage/opfs/files.d.ts.map +0 -1
  232. package/dist/storage/opfs/files.js.map +0 -1
  233. package/dist/storage/opfs/index.d.ts.map +0 -1
  234. package/dist/storage/opfs/index.js.map +0 -1
  235. package/dist/storage/opfs/leader.d.ts.map +0 -1
  236. package/dist/storage/opfs/leader.js.map +0 -1
  237. package/dist/storage/opfs/rpc.d.ts.map +0 -1
  238. package/dist/storage/opfs/rpc.js.map +0 -1
  239. package/dist/storage/opfs/store.d.ts.map +0 -1
  240. package/dist/storage/opfs/store.js.map +0 -1
  241. package/dist/storage/snapshot.d.ts.map +0 -1
  242. package/dist/storage/snapshot.js.map +0 -1
  243. package/dist/storage/toolkit/extents.d.ts.map +0 -1
  244. package/dist/storage/toolkit/extents.js.map +0 -1
  245. package/dist/storage/toolkit/index.d.ts.map +0 -1
  246. package/dist/storage/toolkit/index.js.map +0 -1
  247. package/dist/storage/toolkit/record-core.d.ts.map +0 -1
  248. package/dist/storage/toolkit/record-core.js.map +0 -1
  249. package/dist/storage/toolkit/sync-file.d.ts.map +0 -1
  250. package/dist/storage/toolkit/sync-file.js.map +0 -1
  251. package/dist/storage/toolkit/wal.d.ts.map +0 -1
  252. package/dist/storage/toolkit/wal.js.map +0 -1
  253. package/dist/storage/toolkit/wire.d.ts.map +0 -1
  254. package/dist/storage/toolkit/wire.js.map +0 -1
  255. package/dist/storage/types.d.ts.map +0 -1
  256. package/dist/storage/types.js.map +0 -1
  257. package/dist/testing/block-store-conformance.d.ts.map +0 -1
  258. package/dist/testing/block-store-conformance.js.map +0 -1
  259. package/dist/testing/index.d.ts.map +0 -1
  260. package/dist/testing/index.js.map +0 -1
  261. package/dist/testing/opfs-shim.d.ts.map +0 -1
  262. package/dist/testing/opfs-shim.js.map +0 -1
  263. package/dist/testing/seeds.d.ts +0 -11
  264. package/dist/testing/seeds.d.ts.map +0 -1
  265. package/dist/testing/seeds.js +0 -50
  266. package/dist/testing/seeds.js.map +0 -1
  267. package/dist/transactions/index.d.ts.map +0 -1
  268. package/dist/transactions/index.js.map +0 -1
  269. package/dist/worker-protocol/index.d.ts.map +0 -1
  270. 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
- return Promise.resolve(bytes);
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 [, result] = await Promise.all([
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
- return result;
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
- await reader.cancel(boundErrorMessage);
69
- throw new Error(boundErrorMessage);
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
- return transform(bytes, new CompressionStream("gzip"), maximumOutputBytes, "Gzip payload exceeds compression bound");
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
- //# sourceMappingURL=column.d.ts.map
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
- const validity = new Uint8Array(bitmapLength(rowCount));
21
- let nullCount = 0;
22
- for (let index = 0; index < rowCount; index += 1) {
23
- const value = input.values[index];
24
- if (value === undefined)
25
- throw new TypeError("Column values cannot be undefined");
26
- if (value !== null)
27
- setBit(validity, index);
28
- else
29
- nullCount += 1;
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
- if (input.values[index] === true)
36
- setBit(values, index);
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 === null || value === undefined)
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 === null || value === undefined)
109
+ if (value === undefined)
110
+ throw new TypeError("Column values cannot be undefined");
111
+ if (value === null) {
112
+ nullCount += 1;
69
113
  continue;
70
- const milliseconds = value.getTime();
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
- // Every value UTF-8-encodes once, directly into a shared worst-case scratch (three bytes
85
- // per UTF-16 code unit bounds any UTF-8 expansion) instead of allocating a throwaway
86
- // buffer per string and copying it into place afterwards.
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
- const content = new Uint8Array(capacity);
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 !== null && value !== undefined) {
99
- offset += textEncoder.encodeInto(value, content.subarray(offset)).written;
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 * from "./column.js";
4
+ export { decodeColumn, encodeColumn } from "./column.js";
5
5
  export * from "./physical.js";
6
6
  export * from "./types.js";
7
- //# sourceMappingURL=index.d.ts.map
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 * from "./column.js";
4
+ export { decodeColumn, encodeColumn } from "./column.js";
5
5
  export * from "./physical.js";
6
6
  export * from "./types.js";
7
- //# sourceMappingURL=index.js.map
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 a version-zero physical column. */
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
- //# sourceMappingURL=physical.d.ts.map
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 a version-zero physical column. */
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
- if (rowCount > 0xffffffff)
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 > 0xffffffff)
408
- throw new RangeError("Too many rows in one physical column");
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 version-zero
50
- * column encoding documented in `docs/BLOCK_FORMAT.md`.
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
@@ -1,2 +1 @@
1
1
  export const logicalTypes = ["boolean", "number", "string", "datetime"];
2
- //# sourceMappingURL=types.js.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
@@ -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. Columns left out are written as null, so nullable columns can be omitted. */
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
- /** The columnar form: one array per column, all of the same length, aligned by index. */
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