@clickhouse/client 1.22.0 → 1.23.0-head.c8dc8d8.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 (160) hide show
  1. package/README.md +2 -1
  2. package/dist/client.d.ts +2 -2
  3. package/dist/client.js +3 -3
  4. package/dist/client.js.map +1 -1
  5. package/dist/common/clickhouse_types.d.ts +98 -0
  6. package/dist/common/clickhouse_types.js +30 -0
  7. package/dist/common/clickhouse_types.js.map +1 -0
  8. package/dist/common/client.d.ts +233 -0
  9. package/dist/common/client.js +414 -0
  10. package/dist/common/client.js.map +1 -0
  11. package/dist/common/config.d.ts +234 -0
  12. package/dist/common/config.js +364 -0
  13. package/dist/common/config.js.map +1 -0
  14. package/dist/common/connection.d.ts +124 -0
  15. package/dist/common/connection.js +3 -0
  16. package/dist/common/connection.js.map +1 -0
  17. package/dist/common/data_formatter/format_query_params.d.ts +11 -0
  18. package/dist/common/data_formatter/format_query_params.js +128 -0
  19. package/dist/common/data_formatter/format_query_params.js.map +1 -0
  20. package/dist/common/data_formatter/format_query_settings.d.ts +2 -0
  21. package/dist/common/data_formatter/format_query_settings.js +20 -0
  22. package/dist/common/data_formatter/format_query_settings.js.map +1 -0
  23. package/dist/common/data_formatter/formatter.d.ts +41 -0
  24. package/dist/common/data_formatter/formatter.js +78 -0
  25. package/dist/common/data_formatter/formatter.js.map +1 -0
  26. package/dist/common/data_formatter/index.d.ts +3 -0
  27. package/dist/common/data_formatter/index.js +24 -0
  28. package/dist/common/data_formatter/index.js.map +1 -0
  29. package/dist/common/error/error.d.ts +20 -0
  30. package/dist/common/error/error.js +73 -0
  31. package/dist/common/error/error.js.map +1 -0
  32. package/dist/common/error/index.d.ts +1 -0
  33. package/dist/common/error/index.js +18 -0
  34. package/dist/common/error/index.js.map +1 -0
  35. package/dist/common/index.d.ts +67 -0
  36. package/dist/common/index.js +97 -0
  37. package/dist/common/index.js.map +1 -0
  38. package/dist/common/logger.d.ts +80 -0
  39. package/dist/common/logger.js +154 -0
  40. package/dist/common/logger.js.map +1 -0
  41. package/dist/common/parse/column_types.d.ts +127 -0
  42. package/dist/common/parse/column_types.js +586 -0
  43. package/dist/common/parse/column_types.js.map +1 -0
  44. package/dist/common/parse/index.d.ts +2 -0
  45. package/dist/common/parse/index.js +19 -0
  46. package/dist/common/parse/index.js.map +1 -0
  47. package/dist/common/parse/json_handling.d.ts +19 -0
  48. package/dist/common/parse/json_handling.js +8 -0
  49. package/dist/common/parse/json_handling.js.map +1 -0
  50. package/dist/common/result.d.ts +90 -0
  51. package/dist/common/result.js +3 -0
  52. package/dist/common/result.js.map +1 -0
  53. package/dist/common/settings.d.ts +1990 -0
  54. package/dist/common/settings.js +19 -0
  55. package/dist/common/settings.js.map +1 -0
  56. package/dist/common/tracing.d.ts +146 -0
  57. package/dist/common/tracing.js +76 -0
  58. package/dist/common/tracing.js.map +1 -0
  59. package/dist/common/ts_utils.d.ts +4 -0
  60. package/dist/common/ts_utils.js +3 -0
  61. package/dist/common/ts_utils.js.map +1 -0
  62. package/dist/common/utils/connection.d.ts +21 -0
  63. package/dist/common/utils/connection.js +43 -0
  64. package/dist/common/utils/connection.js.map +1 -0
  65. package/dist/common/utils/index.d.ts +5 -0
  66. package/dist/common/utils/index.js +22 -0
  67. package/dist/common/utils/index.js.map +1 -0
  68. package/dist/common/utils/multipart.d.ts +34 -0
  69. package/dist/common/utils/multipart.js +81 -0
  70. package/dist/common/utils/multipart.js.map +1 -0
  71. package/dist/common/utils/sleep.d.ts +4 -0
  72. package/dist/common/utils/sleep.js +12 -0
  73. package/dist/common/utils/sleep.js.map +1 -0
  74. package/dist/common/utils/stream.d.ts +15 -0
  75. package/dist/common/utils/stream.js +50 -0
  76. package/dist/common/utils/stream.js.map +1 -0
  77. package/dist/common/utils/url.d.ts +20 -0
  78. package/dist/common/utils/url.js +67 -0
  79. package/dist/common/utils/url.js.map +1 -0
  80. package/dist/common/version.d.ts +2 -0
  81. package/dist/common/version.js +4 -0
  82. package/dist/common/version.js.map +1 -0
  83. package/dist/config.d.ts +2 -2
  84. package/dist/config.js +2 -2
  85. package/dist/config.js.map +1 -1
  86. package/dist/connection/compression.d.ts +2 -2
  87. package/dist/connection/compression.js +4 -4
  88. package/dist/connection/compression.js.map +1 -1
  89. package/dist/connection/create_connection.d.ts +1 -1
  90. package/dist/connection/node_base_connection.d.ts +3 -3
  91. package/dist/connection/node_base_connection.js +22 -22
  92. package/dist/connection/node_base_connection.js.map +1 -1
  93. package/dist/connection/node_custom_agent_connection.js +2 -2
  94. package/dist/connection/node_custom_agent_connection.js.map +1 -1
  95. package/dist/connection/node_http_connection.js +2 -2
  96. package/dist/connection/node_http_connection.js.map +1 -1
  97. package/dist/connection/node_https_connection.d.ts +1 -1
  98. package/dist/connection/node_https_connection.js +3 -3
  99. package/dist/connection/node_https_connection.js.map +1 -1
  100. package/dist/connection/socket_pool.d.ts +1 -1
  101. package/dist/connection/socket_pool.js +30 -30
  102. package/dist/connection/socket_pool.js.map +1 -1
  103. package/dist/connection/stream.d.ts +1 -1
  104. package/dist/connection/stream.js +9 -9
  105. package/dist/connection/stream.js.map +1 -1
  106. package/dist/index.d.ts +7 -7
  107. package/dist/index.js +24 -24
  108. package/dist/index.js.map +1 -1
  109. package/dist/result_set.d.ts +1 -1
  110. package/dist/result_set.js +10 -10
  111. package/dist/result_set.js.map +1 -1
  112. package/dist/utils/encoder.d.ts +1 -1
  113. package/dist/utils/encoder.js +5 -5
  114. package/dist/utils/encoder.js.map +1 -1
  115. package/dist/version.d.ts +1 -1
  116. package/dist/version.js +1 -1
  117. package/dist/version.js.map +1 -1
  118. package/package.json +7 -5
  119. package/skills/clickhouse-js-node-rowbinary-parser/EXAMPLES.md +48 -0
  120. package/skills/clickhouse-js-node-rowbinary-parser/README.md +248 -0
  121. package/skills/clickhouse-js-node-rowbinary-parser/SKILL.md +190 -0
  122. package/skills/clickhouse-js-node-rowbinary-parser/case-studies/iot-rowbinary-vs-json.md +83 -0
  123. package/skills/clickhouse-js-node-rowbinary-parser/case-studies/ledger-rowbinary-vs-json.md +103 -0
  124. package/skills/clickhouse-js-node-rowbinary-parser/case-studies/logs-json-wins.md +86 -0
  125. package/skills/clickhouse-js-node-rowbinary-parser/case-studies/wasm-vs-js.md +172 -0
  126. package/skills/clickhouse-js-node-rowbinary-parser/src/aggregateFunction.ts +34 -0
  127. package/skills/clickhouse-js-node-rowbinary-parser/src/bool.ts +10 -0
  128. package/skills/clickhouse-js-node-rowbinary-parser/src/columnar.ts +125 -0
  129. package/skills/clickhouse-js-node-rowbinary-parser/src/composite.ts +181 -0
  130. package/skills/clickhouse-js-node-rowbinary-parser/src/core.ts +77 -0
  131. package/skills/clickhouse-js-node-rowbinary-parser/src/datetime.ts +113 -0
  132. package/skills/clickhouse-js-node-rowbinary-parser/src/decimals.ts +57 -0
  133. package/skills/clickhouse-js-node-rowbinary-parser/src/dynamic.ts +328 -0
  134. package/skills/clickhouse-js-node-rowbinary-parser/src/enums.ts +28 -0
  135. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/carts.ts +71 -0
  136. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/events.ts +51 -0
  137. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/iot.ts +158 -0
  138. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/ledger.ts +98 -0
  139. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/logs.ts +73 -0
  140. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/observability.ts +142 -0
  141. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/orders.ts +65 -0
  142. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/profiles.ts +60 -0
  143. package/skills/clickhouse-js-node-rowbinary-parser/src/examples/telemetry.ts +102 -0
  144. package/skills/clickhouse-js-node-rowbinary-parser/src/floats.ts +32 -0
  145. package/skills/clickhouse-js-node-rowbinary-parser/src/geo.ts +109 -0
  146. package/skills/clickhouse-js-node-rowbinary-parser/src/integers.ts +95 -0
  147. package/skills/clickhouse-js-node-rowbinary-parser/src/interval.ts +54 -0
  148. package/skills/clickhouse-js-node-rowbinary-parser/src/ip.ts +93 -0
  149. package/skills/clickhouse-js-node-rowbinary-parser/src/json.ts +33 -0
  150. package/skills/clickhouse-js-node-rowbinary-parser/src/lowCardinality.ts +18 -0
  151. package/skills/clickhouse-js-node-rowbinary-parser/src/nested.ts +23 -0
  152. package/skills/clickhouse-js-node-rowbinary-parser/src/nothing.ts +29 -0
  153. package/skills/clickhouse-js-node-rowbinary-parser/src/reader.ts +51 -0
  154. package/skills/clickhouse-js-node-rowbinary-parser/src/rows.ts +58 -0
  155. package/skills/clickhouse-js-node-rowbinary-parser/src/simpleAggregateFunction.ts +20 -0
  156. package/skills/clickhouse-js-node-rowbinary-parser/src/stream.ts +276 -0
  157. package/skills/clickhouse-js-node-rowbinary-parser/src/strings.ts +55 -0
  158. package/skills/clickhouse-js-node-rowbinary-parser/src/time.ts +61 -0
  159. package/skills/clickhouse-js-node-rowbinary-parser/src/uuid.ts +153 -0
  160. package/skills/clickhouse-js-node-rowbinary-parser/src/varint.ts +70 -0
@@ -0,0 +1,95 @@
1
+ import { Cursor, advance } from "./core.js";
2
+
3
+ /** Read a single unsigned byte and advance. */
4
+ export function readUInt8(state: Cursor): number {
5
+ return state.buf[advance(state, 1)]!;
6
+ }
7
+
8
+ /** Read an `Int8`: 1 byte, two's-complement signed (-128 .. 127). */
9
+ export function readInt8(state: Cursor): number {
10
+ return state.view.getInt8(advance(state, 1));
11
+ }
12
+
13
+ /** Read a `UInt16`: 2 bytes, little-endian (0 .. 65535). */
14
+ export function readUInt16(state: Cursor): number {
15
+ return state.view.getUint16(advance(state, 2), true);
16
+ }
17
+
18
+ /**
19
+ * Read an `Int16`: 2 bytes, little-endian, two's-complement signed (-32768 ..
20
+ * 32767). `DataView` reads from any offset and decodes explicitly little-endian,
21
+ * so the value never depends on host byte order.
22
+ */
23
+ export function readInt16(state: Cursor): number {
24
+ return state.view.getInt16(advance(state, 2), true);
25
+ }
26
+
27
+ /** Read a `UInt32`: 4 bytes, little-endian (0 .. 4294967295). */
28
+ export function readUInt32(state: Cursor): number {
29
+ return state.view.getUint32(advance(state, 4), true);
30
+ }
31
+
32
+ /** Read an `Int32`: 4 bytes, little-endian, two's-complement signed. */
33
+ export function readInt32(state: Cursor): number {
34
+ return state.view.getInt32(advance(state, 4), true);
35
+ }
36
+
37
+ /**
38
+ * Read a `UInt64`: 8 bytes, little-endian. Returns a `bigint`.
39
+ * SAFE TO TOGGLE: if the values fit in 53 bits, wrap in `Number(...)`.
40
+ */
41
+ export function readUInt64(state: Cursor): bigint {
42
+ return state.view.getBigUint64(advance(state, 8), true);
43
+ }
44
+
45
+ /**
46
+ * Read an `Int64`: 8 bytes, little-endian, two's-complement. Returns a `bigint`
47
+ * (range exceeds `Number.MAX_SAFE_INTEGER`).
48
+ * SAFE TO TOGGLE: if the values fit in 53 bits, wrap in `Number(...)`.
49
+ */
50
+ export function readInt64(state: Cursor): bigint {
51
+ return state.view.getBigInt64(advance(state, 8), true);
52
+ }
53
+
54
+ /** Read a `UInt128`: 16 bytes, little-endian. Always a `bigint`. */
55
+ export function readUInt128(state: Cursor): bigint {
56
+ const start = advance(state, 16);
57
+ const lo = state.view.getBigUint64(start, true);
58
+ const hi = state.view.getBigUint64(start + 8, true);
59
+ return (hi << 64n) + lo;
60
+ }
61
+
62
+ /**
63
+ * Read an `Int128`: 16 bytes, little-endian, two's-complement. Always a
64
+ * `bigint`, composed from the low (unsigned) and high (signed) 64-bit words —
65
+ * reading the high word signed extends the sign across all 128 bits.
66
+ */
67
+ export function readInt128(state: Cursor): bigint {
68
+ const start = advance(state, 16);
69
+ const lo = state.view.getBigUint64(start, true);
70
+ const hi = state.view.getBigInt64(start + 8, true);
71
+ return (hi << 64n) + lo;
72
+ }
73
+
74
+ /** Read a `UInt256`: 32 bytes, little-endian. Always a `bigint`. */
75
+ export function readUInt256(state: Cursor): bigint {
76
+ const start = advance(state, 32);
77
+ const w0 = state.view.getBigUint64(start, true);
78
+ const w1 = state.view.getBigUint64(start + 8, true);
79
+ const w2 = state.view.getBigUint64(start + 16, true);
80
+ const w3 = state.view.getBigUint64(start + 24, true);
81
+ return w0 + (w1 << 64n) + (w2 << 128n) + (w3 << 192n);
82
+ }
83
+
84
+ /**
85
+ * Read an `Int256`: 32 bytes, little-endian, two's-complement. Always a
86
+ * `bigint`. The most-significant 64-bit word is read signed.
87
+ */
88
+ export function readInt256(state: Cursor): bigint {
89
+ const start = advance(state, 32);
90
+ const w0 = state.view.getBigUint64(start, true);
91
+ const w1 = state.view.getBigUint64(start + 8, true);
92
+ const w2 = state.view.getBigUint64(start + 16, true);
93
+ const w3 = state.view.getBigInt64(start + 24, true);
94
+ return (w3 << 192n) + (w2 << 128n) + (w1 << 64n) + w0;
95
+ }
@@ -0,0 +1,54 @@
1
+ import { Cursor } from "./core.js";
2
+ import { readInt64 } from "./integers.js";
3
+
4
+ /** The 11 `Interval` units, in ClickHouse's ascending order. */
5
+ export type IntervalUnit =
6
+ | "Nanosecond"
7
+ | "Microsecond"
8
+ | "Millisecond"
9
+ | "Second"
10
+ | "Minute"
11
+ | "Hour"
12
+ | "Day"
13
+ | "Week"
14
+ | "Month"
15
+ | "Quarter"
16
+ | "Year";
17
+
18
+ /**
19
+ * `Interval` units indexed by the kind byte the binary type encoding writes
20
+ * after the `0x22` tag (`0x00` = Nanosecond ... `0x0a` = Year). Exported because
21
+ * the `Dynamic` reader needs it to decode an `Interval` nested in a `Dynamic`.
22
+ */
23
+ export const INTERVAL_UNITS: readonly IntervalUnit[] = [
24
+ "Nanosecond",
25
+ "Microsecond",
26
+ "Millisecond",
27
+ "Second",
28
+ "Minute",
29
+ "Hour",
30
+ "Day",
31
+ "Week",
32
+ "Month",
33
+ "Quarter",
34
+ "Year",
35
+ ];
36
+
37
+ /**
38
+ * An `Interval` decoded where the unit is carried IN the wire (inside a
39
+ * `Dynamic`): the signed `Int64` count plus its unit. A standalone `Interval*`
40
+ * column has no unit byte — there, use {@link readInterval} and take the unit
41
+ * from the column type instead.
42
+ */
43
+ export type IntervalValue = readonly [count: bigint, unit: IntervalUnit];
44
+
45
+ /**
46
+ * Read an `Interval` — any of `IntervalNanosecond` ... `IntervalYear`: a signed
47
+ * `Int64` count of the unit. The unit is in the type name, not the bytes, and
48
+ * all 11 interval types share this exact wire, so this one reader covers them
49
+ * all; the caller knows the unit from the column type. Returns a `bigint`; wrap
50
+ * in `Number(...)` if the counts are known to fit in 53 bits.
51
+ */
52
+ export function readInterval(state: Cursor): bigint {
53
+ return readInt64(state);
54
+ }
@@ -0,0 +1,93 @@
1
+ import { Cursor, advance } from "./core.js";
2
+
3
+ /**
4
+ * Read an `IPv4`: stored as a 4-byte little-endian `UInt32`. Returns the raw
5
+ * 32-bit value (the little-endian load already orders the octets); pass it to
6
+ * {@link formatIPv4} for the dotted-quad string.
7
+ */
8
+ export function readIPv4(state: Cursor): number {
9
+ return state.view.getUint32(advance(state, 4), true);
10
+ }
11
+
12
+ /**
13
+ * Read an `IPv6`: 16 bytes in network (big-endian) order. Returns the raw bytes
14
+ * as a zero-copy view; pass them to {@link formatIPv6} for the canonical string.
15
+ *
16
+ * The view shares memory with the response buffer, so keeping it alive pins the
17
+ * whole response chunk in memory. If the value must outlive the row/response,
18
+ * copy it with `Buffer.from(...)`.
19
+ */
20
+ export function readIPv6(state: Cursor): Buffer {
21
+ const start = advance(state, 16);
22
+ return state.buf.subarray(start, start + 16);
23
+ }
24
+
25
+ /**
26
+ * Format an `IPv4` (the raw 32-bit value from {@link readIPv4}) as a dotted-quad
27
+ * string. Kept aside so the hot read path can skip building a string when the
28
+ * numeric value is all the caller needs.
29
+ */
30
+ export function formatIPv4(value: number): string {
31
+ return `${(value >>> 24) & 0xff}.${(value >>> 16) & 0xff}.${(value >>> 8) & 0xff}.${value & 0xff}`;
32
+ }
33
+
34
+ /**
35
+ * Join groups `[from, to)` as colon-separated lowercase hex, by concatenating
36
+ * into a string in a loop. Benchmarks faster than `slice().map().join(":")`,
37
+ * which allocates an intermediate array. Returns `""` for an empty range.
38
+ */
39
+ function joinGroupsHex(g: number[], from: number, to: number): string {
40
+ if (from >= to) return "";
41
+ let s = g[from]!.toString(16);
42
+ for (let i = from + 1; i < to; i++) s += ":" + g[i]!.toString(16);
43
+ return s;
44
+ }
45
+
46
+ /**
47
+ * Format an `IPv6` (the raw 16 bytes from {@link readIPv6}) as the canonical
48
+ * RFC 5952 string: lowercase, no leading zeros, the longest run of zero groups
49
+ * (>= 2) collapsed to `::` (leftmost on a tie), and the `::ffff:a.b.c.d` form
50
+ * for IPv4-mapped addresses (matching ClickHouse).
51
+ *
52
+ * Kept aside from the read so the hot path only formats when a string is
53
+ * actually needed.
54
+ */
55
+ export function formatIPv6(b: Buffer): string {
56
+ // IPv4-mapped (::ffff:a.b.c.d): first 10 bytes zero, then 0xffff.
57
+ let mapped = b[10] === 0xff && b[11] === 0xff;
58
+ for (let i = 0; mapped && i < 10; i++) {
59
+ if (b[i] !== 0) mapped = false;
60
+ }
61
+ if (mapped) {
62
+ return `::ffff:${b[12]}.${b[13]}.${b[14]}.${b[15]}`;
63
+ }
64
+
65
+ // Eight 16-bit groups, big-endian.
66
+ const g: number[] = [];
67
+ for (let i = 0; i < 8; i++) {
68
+ g.push((b[2 * i]! << 8) | b[2 * i + 1]!);
69
+ }
70
+
71
+ // Longest run of >= 2 zero groups becomes "::" (leftmost wins on a tie).
72
+ let bestStart = -1;
73
+ let bestLen = 0;
74
+ let curStart = -1;
75
+ let curLen = 0;
76
+ for (let i = 0; i < 8; i++) {
77
+ if (g[i] === 0) {
78
+ if (curStart < 0) curStart = i;
79
+ curLen++;
80
+ if (curLen > bestLen) {
81
+ bestLen = curLen;
82
+ bestStart = curStart;
83
+ }
84
+ } else {
85
+ curStart = -1;
86
+ curLen = 0;
87
+ }
88
+ }
89
+ if (bestLen < 2) {
90
+ return joinGroupsHex(g, 0, 8);
91
+ }
92
+ return `${joinGroupsHex(g, 0, bestStart)}::${joinGroupsHex(g, bestStart + bestLen, 8)}`;
93
+ }
@@ -0,0 +1,33 @@
1
+ import { Cursor } from "./core.js";
2
+ import { readUVarint } from "./varint.js";
3
+ import { readString } from "./strings.js";
4
+ import { readDynamic } from "./dynamic.js";
5
+
6
+ /**
7
+ * Read a `JSON` value. ClickHouse's `JSON` is NOT JSON text and NOT BSON — it is
8
+ * a list of (path, value) pairs built on the same machinery as `Dynamic`:
9
+ *
10
+ * <varuint pathCount> then pathCount x ( <String path> <Dynamic value> )
11
+ *
12
+ * Nested objects are FLATTENED to dotted paths (`{a:{b:2}}` -> path `"a.b"`), and
13
+ * each leaf value is a self-describing `Dynamic`, so this just loops
14
+ * {@link readString} + {@link readDynamic}. Returns a `Map` keyed by the flat
15
+ * dotted path. Path order on the wire is not significant.
16
+ *
17
+ * GOTCHA: a null-valued path is NOT stored at all — `{"a":null}` serializes as
18
+ * zero paths, identical to `{}`. JSON arrays come back as `Array(Nullable(T))`.
19
+ *
20
+ * LIMITATION — typed paths only. This reads a plain `JSON` column, where every
21
+ * path is dynamic (tagged). A `JSON(a T, ...)` with DECLARED typed paths
22
+ * serializes those paths' values WITHOUT a type tag, so they cannot be decoded
23
+ * without the schema; read each typed path with its known `T` reader instead.
24
+ */
25
+ export function readJSON(state: Cursor): Map<string, unknown> {
26
+ const n = readUVarint(state);
27
+ const out = new Map<string, unknown>();
28
+ for (let i = 0; i < n; i++) {
29
+ const path = readString(state);
30
+ out.set(path, readDynamic(state));
31
+ }
32
+ return out;
33
+ }
@@ -0,0 +1,18 @@
1
+ import { type Reader } from "./core.js";
2
+
3
+ /**
4
+ * `LowCardinality(T)` is TRANSPARENT in RowBinary: it is encoded byte-for-byte
5
+ * the same as `T`, with NO dictionary/index layer. (The dictionary encoding
6
+ * exists only in the Native format — do not look for it here.) So there is
7
+ * nothing to decode at this level: use `T`'s own reader directly.
8
+ *
9
+ * This identity combinator exists only to document that, and to let a generated
10
+ * parser name the wrapper at the call site if it wants the type to read
11
+ * literally — it returns the inner reader unchanged:
12
+ *
13
+ * readLowCardinality(readString) === readString
14
+ *
15
+ * Prefer just calling the inner reader.
16
+ */
17
+ export const readLowCardinality = <T>(readValue: Reader<T>): Reader<T> =>
18
+ readValue;
@@ -0,0 +1,23 @@
1
+ import { readArray, readTupleNamed } from "./composite.js";
2
+ import { type Reader } from "./core.js";
3
+
4
+ /**
5
+ * `Nested(a T1, b T2, …)` has NO wire format of its own:
6
+ * - `flatten_nested = 1` (the default): the column expands into separate
7
+ * columns `a Array(T1)`, `b Array(T2)`, … — decode each with `readArray`.
8
+ * - `flatten_nested = 0`: the column is `Array(Tuple(a T1, b T2, …))` — decode
9
+ * with `readArray` + `readTupleNamed`.
10
+ *
11
+ * Either way it reuses existing readers; there is no dedicated Nested wire. This
12
+ * thin alias just composes the two for the `flatten_nested = 0` shape, as
13
+ * documentation that "Nested === Array(Tuple(...))":
14
+ *
15
+ * readNested({ a: readUInt8, b: readString })
16
+ * === readArray(readTupleNamed({ a: readUInt8, b: readString }))
17
+ *
18
+ * When generating code, prefer inlining (monomorphize the array + tuple) over
19
+ * this generic composition.
20
+ */
21
+ export const readNested = <T extends Record<string, unknown>>(fields: {
22
+ [K in keyof T]: Reader<T[K]>;
23
+ }): Reader<T[]> => readArray(readTupleNamed(fields));
@@ -0,0 +1,29 @@
1
+ import { type Reader } from "./core.js";
2
+
3
+ /**
4
+ * `Nothing` is the empty type: it has NO values and occupies ZERO bytes. It is
5
+ * never a column on its own (you cannot materialize a value of it) — it only
6
+ * appears wrapped, as the inferred element of an untyped literal:
7
+ *
8
+ * [] -> Array(Nothing) -> always the empty array (varint length 0x00)
9
+ * NULL -> Nullable(Nothing) -> always NULL (lone flag byte 0x01)
10
+ *
11
+ * So a `Nothing` value is NEVER read: `readArray`'s element reader and
12
+ * `readNullable`'s inner reader are not called in those cases (the array is
13
+ * empty / the value is NULL). There is nothing to decode.
14
+ *
15
+ * Wire this in as the inner reader to make that invariant loud: it throws if it
16
+ * is ever actually invoked, which would mean a `Nothing` reader was placed where
17
+ * a real element/inner type was expected.
18
+ *
19
+ * readArray(readNothing) // [] — readNothing never runs
20
+ * readNullable(readNothing) // null — readNothing never runs
21
+ */
22
+ export const readNothing: Reader<never> = () => {
23
+ throw new Error(
24
+ "RowBinary: Nothing is zero-width and is never decoded — it only appears as " +
25
+ "an empty Array(Nothing) or a NULL Nullable(Nothing), where the inner reader " +
26
+ "is not called. Reaching here means a Nothing reader was wired where a real " +
27
+ "element/inner type was expected.",
28
+ );
29
+ };
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Barrel re-export of the RowBinary reader, split by type family into the
3
+ * sibling modules. Import from here for everything in one place, or from a
4
+ * specific module (e.g. `./integers.js`, `./strings.js`) to pull in only the
5
+ * sub-parsers a given result actually needs — the latter is what a generated
6
+ * parser should do, copying just the modules its column types require.
7
+ *
8
+ * - core — Cursor, Reader<T>, advance, NeedMoreData
9
+ * - varint — readUVarint
10
+ * - integers — readUInt8..readUInt256, readInt8..readInt256
11
+ * - bool / enums / floats
12
+ * - decimals — DecimalValue, formatDecimal, readDecimal32..256
13
+ * - strings — readString, readFixedString, readFixedStringBytes
14
+ * - uuid — readUUID(+BigInt/HiLo), formatUUID(+Table)
15
+ * - ip — readIPv4/6, formatIPv4/6
16
+ * - datetime / time / interval
17
+ * - composite — readArray/Map/Tuple/TupleNamed/Nullable/Variant/QBit
18
+ * - rows — readRows
19
+ * - geo — Point, readPoint/Ring/LineString/Polygon/MultiLineString/MultiPolygon/Geometry
20
+ * - dynamic — readDynamic, readDynamicType
21
+ * - json — readJSON
22
+ * - stream — streamRowBatches, coalesceChunks
23
+ * - transparent / special wrappers (mostly documentation; see each file):
24
+ * lowCardinality (readLowCardinality), simpleAggregateFunction
25
+ * (readSimpleAggregateFunction), nested (readNested), nothing (readNothing),
26
+ * aggregateFunction (readAggregateFunction)
27
+ */
28
+ export * from "./core.js";
29
+ export * from "./varint.js";
30
+ export * from "./integers.js";
31
+ export * from "./bool.js";
32
+ export * from "./enums.js";
33
+ export * from "./floats.js";
34
+ export * from "./decimals.js";
35
+ export * from "./strings.js";
36
+ export * from "./uuid.js";
37
+ export * from "./ip.js";
38
+ export * from "./datetime.js";
39
+ export * from "./time.js";
40
+ export * from "./interval.js";
41
+ export * from "./composite.js";
42
+ export * from "./rows.js";
43
+ export * from "./geo.js";
44
+ export * from "./dynamic.js";
45
+ export * from "./json.js";
46
+ export * from "./stream.js";
47
+ export * from "./lowCardinality.js";
48
+ export * from "./simpleAggregateFunction.js";
49
+ export * from "./nested.js";
50
+ export * from "./nothing.js";
51
+ export * from "./aggregateFunction.js";
@@ -0,0 +1,58 @@
1
+ import { NeedMoreData, type Reader } from "./core.js";
2
+
3
+ /**
4
+ * Drive `readRow` over every row of a plain `RowBinary` result into an array.
5
+ * Curried: `readRows(readRow)` returns a `Reader<T[]>`. Rows are concatenated on
6
+ * the wire with no count, length prefix, or delimiter, so the result is exhausted
7
+ * only when the cursor reaches the buffer end.
8
+ *
9
+ * `readRow` must consume EXACTLY one row's bytes — a byte short or long compounds
10
+ * across rows and the cursor overshoots or never lands on `buf.length`. Returns
11
+ * `[]` for an empty buffer. When generating code, inline the per-column reads
12
+ * into the loop body:
13
+ *
14
+ * function readRowsUser(s) {
15
+ * const out = [];
16
+ * while (s.pos < s.buf.length) {
17
+ * out.push({ id: readUInt64(s), name: readString(s) });
18
+ * }
19
+ * return out;
20
+ * }
21
+ *
22
+ * STREAMING (partial trailing row): a chunk of a still-arriving response may end
23
+ * mid-row. `pos` is committed only AFTER a row reads cleanly, so when a row
24
+ * starves and `readRow` throws {@link NeedMoreData}, this catches it, rewinds
25
+ * `pos` to the last complete row boundary, and returns the rows so far — never a
26
+ * half-built row. The cursor is left at the straddling row, a commit point the
27
+ * driver carries forward:
28
+ *
29
+ * const drive = readRows(readRow);
30
+ * let committed = 0;
31
+ * for (const chunk of chunks) { // chunk = growing prefix
32
+ * const s = new Cursor(chunk);
33
+ * s.pos = committed;
34
+ * emit(drive(s)); // complete rows in this chunk
35
+ * committed = s.pos; // start of the straddling row
36
+ * }
37
+ *
38
+ * On a complete buffer no read starves, so the catch never runs. Errors other
39
+ * than {@link NeedMoreData} are real decode faults and propagate. See also
40
+ * `streamRowBatches`, the async driver built on this.
41
+ */
42
+ export function readRows<T>(readRow: Reader<T>): Reader<T[]> {
43
+ return (state) => {
44
+ const out: T[] = [];
45
+ let committed = state.pos;
46
+ try {
47
+ while (state.pos < state.buf.length) {
48
+ const row = readRow(state);
49
+ committed = state.pos; // row read cleanly — advance the commit point
50
+ out.push(row);
51
+ }
52
+ } catch (e) {
53
+ if (e !== NeedMoreData) throw e;
54
+ state.pos = committed; // drop the partial trailing row; resume next chunk
55
+ }
56
+ return out;
57
+ };
58
+ }
@@ -0,0 +1,20 @@
1
+ import { type Reader } from "./core.js";
2
+
3
+ /**
4
+ * `SimpleAggregateFunction(func, T)` is TRANSPARENT in RowBinary: the column
5
+ * already holds a finished value of the underlying type `T` (the partial
6
+ * aggregate of a "simple" function — sum / min / max / groupArrayArray / … — is
7
+ * just a value of `T`), so it is encoded byte-for-byte the same as `T`. Decode
8
+ * the inner `T` directly.
9
+ *
10
+ * Do NOT confuse it with `AggregateFunction(func, T)`, whose value is an opaque
11
+ * serialized aggregation STATE with a function-specific binary layout — see
12
+ * `./aggregateFunction.js`.
13
+ *
14
+ * Identity combinator, documentation only:
15
+ *
16
+ * readSimpleAggregateFunction(readUInt64) === readUInt64
17
+ */
18
+ export const readSimpleAggregateFunction = <T>(
19
+ readValue: Reader<T>,
20
+ ): Reader<T> => readValue;