@clickhouse/client 0.0.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 (105) hide show
  1. package/LICENSE +203 -0
  2. package/README.md +636 -0
  3. package/dist/clickhouse_types.d.ts +17 -0
  4. package/dist/clickhouse_types.js +3 -0
  5. package/dist/clickhouse_types.js.map +1 -0
  6. package/dist/client.d.ts +56 -0
  7. package/dist/client.js +180 -0
  8. package/dist/client.js.map +1 -0
  9. package/dist/connection/adapter/base_http_adapter.d.ts +33 -0
  10. package/dist/connection/adapter/base_http_adapter.js +257 -0
  11. package/dist/connection/adapter/base_http_adapter.js.map +1 -0
  12. package/dist/connection/adapter/http_adapter.d.ts +10 -0
  13. package/dist/connection/adapter/http_adapter.js +27 -0
  14. package/dist/connection/adapter/http_adapter.js.map +1 -0
  15. package/dist/connection/adapter/http_search_params.d.ts +9 -0
  16. package/dist/connection/adapter/http_search_params.js +36 -0
  17. package/dist/connection/adapter/http_search_params.js.map +1 -0
  18. package/dist/connection/adapter/https_adapter.d.ts +10 -0
  19. package/dist/connection/adapter/https_adapter.js +27 -0
  20. package/dist/connection/adapter/https_adapter.js.map +1 -0
  21. package/dist/connection/adapter/index.d.ts +2 -0
  22. package/dist/connection/adapter/index.js +8 -0
  23. package/dist/connection/adapter/index.js.map +1 -0
  24. package/dist/connection/adapter/transform_url.d.ts +5 -0
  25. package/dist/connection/adapter/transform_url.js +15 -0
  26. package/dist/connection/adapter/transform_url.js.map +1 -0
  27. package/dist/connection/connection.d.ts +34 -0
  28. package/dist/connection/connection.js +17 -0
  29. package/dist/connection/connection.js.map +1 -0
  30. package/dist/connection/index.d.ts +1 -0
  31. package/dist/connection/index.js +18 -0
  32. package/dist/connection/index.js.map +1 -0
  33. package/dist/data_formatter/format_query_params.d.ts +1 -0
  34. package/dist/data_formatter/format_query_params.js +61 -0
  35. package/dist/data_formatter/format_query_params.js.map +1 -0
  36. package/dist/data_formatter/format_query_settings.d.ts +2 -0
  37. package/dist/data_formatter/format_query_settings.js +21 -0
  38. package/dist/data_formatter/format_query_settings.js.map +1 -0
  39. package/dist/data_formatter/formatter.d.ts +23 -0
  40. package/dist/data_formatter/formatter.js +81 -0
  41. package/dist/data_formatter/formatter.js.map +1 -0
  42. package/dist/data_formatter/index.d.ts +3 -0
  43. package/dist/data_formatter/index.js +23 -0
  44. package/dist/data_formatter/index.js.map +1 -0
  45. package/dist/error/index.d.ts +1 -0
  46. package/dist/error/index.js +18 -0
  47. package/dist/error/index.js.map +1 -0
  48. package/dist/error/parse_error.d.ts +12 -0
  49. package/dist/error/parse_error.js +39 -0
  50. package/dist/error/parse_error.js.map +1 -0
  51. package/dist/index.d.ts +15 -0
  52. package/dist/index.js +14 -0
  53. package/dist/index.js.map +1 -0
  54. package/dist/logger.d.ts +8 -0
  55. package/dist/logger.js +35 -0
  56. package/dist/logger.js.map +1 -0
  57. package/dist/rows.d.ts +50 -0
  58. package/dist/rows.js +114 -0
  59. package/dist/rows.js.map +1 -0
  60. package/dist/schema/common.d.ts +8 -0
  61. package/dist/schema/common.js +3 -0
  62. package/dist/schema/common.js.map +1 -0
  63. package/dist/schema/compact.d.ts +3 -0
  64. package/dist/schema/compact.js +24 -0
  65. package/dist/schema/compact.js.map +1 -0
  66. package/dist/schema/engines.d.ts +40 -0
  67. package/dist/schema/engines.js +61 -0
  68. package/dist/schema/engines.js.map +1 -0
  69. package/dist/schema/index.d.ts +7 -0
  70. package/dist/schema/index.js +24 -0
  71. package/dist/schema/index.js.map +1 -0
  72. package/dist/schema/query_formatter.d.ts +9 -0
  73. package/dist/schema/query_formatter.js +48 -0
  74. package/dist/schema/query_formatter.js.map +1 -0
  75. package/dist/schema/result.d.ts +13 -0
  76. package/dist/schema/result.js +3 -0
  77. package/dist/schema/result.js.map +1 -0
  78. package/dist/schema/schema.d.ts +6 -0
  79. package/dist/schema/schema.js +20 -0
  80. package/dist/schema/schema.js.map +1 -0
  81. package/dist/schema/stream.d.ts +11 -0
  82. package/dist/schema/stream.js +25 -0
  83. package/dist/schema/stream.js.map +1 -0
  84. package/dist/schema/table.d.ts +44 -0
  85. package/dist/schema/table.js +70 -0
  86. package/dist/schema/table.js.map +1 -0
  87. package/dist/schema/types.d.ts +201 -0
  88. package/dist/schema/types.js +268 -0
  89. package/dist/schema/types.js.map +1 -0
  90. package/dist/schema/where.d.ts +8 -0
  91. package/dist/schema/where.js +43 -0
  92. package/dist/schema/where.js.map +1 -0
  93. package/dist/settings.d.ts +1453 -0
  94. package/dist/settings.js +28 -0
  95. package/dist/settings.js.map +1 -0
  96. package/dist/utils/index.d.ts +2 -0
  97. package/dist/utils/index.js +19 -0
  98. package/dist/utils/index.js.map +1 -0
  99. package/dist/utils/stream.d.ts +5 -0
  100. package/dist/utils/stream.js +32 -0
  101. package/dist/utils/stream.js.map +1 -0
  102. package/dist/utils/string.d.ts +1 -0
  103. package/dist/utils/string.js +9 -0
  104. package/dist/utils/string.js.map +1 -0
  105. package/package.json +63 -0
package/README.md ADDED
@@ -0,0 +1,636 @@
1
+ <p align="center">
2
+ <img src=".static/logo.png" width="200px" align="center">
3
+ <h1 align="center">ClickHouse Node.JS client</h1>
4
+ </p>
5
+ <br/>
6
+ <p align="center">
7
+ <a href="https://github.com/ClickHouse/clickhouse-js/actions/workflows/run-tests.yml">
8
+ <img src="https://github.com/ClickHouse/clickhouse-js/actions/workflows/run-tests.yml/badge.svg?branch=main">
9
+ </a>
10
+ </p>
11
+
12
+ ## Introduction
13
+
14
+ Official Node.js client for [ClickHouse](https://clickhouse.com/), written purely in TypeScript, thoroughly tested with actual ClickHouse versions.
15
+
16
+ It is focused on data streaming for both inserts and selects using standard [Node.js Streaming API](https://nodejs.org/docs/latest-v14.x/api/stream.html).
17
+
18
+ ## Compatibility
19
+
20
+ The client is tested with the following ClickHouse and Node.js versions:
21
+
22
+ | Node.js | ClickHouse | Status |
23
+ |---------|------------|--------|
24
+ | 14.x | 22.8 | ✔ |
25
+ | 16.x | 22.8 | ✔ |
26
+ | 18.x | 22.8 | ✔ |
27
+ | 14.x | 22.9 | ✔ |
28
+ | 16.x | 22.9 | ✔ |
29
+ | 18.x | 22.9 | ✔ |
30
+
31
+ ## Connection
32
+
33
+ Currently, only HTTP(s) protocol is supported.
34
+
35
+ A very basic connection to a single local ClickHouse instance with default settings (for example, if it is running as a Docker container as described in the [contribution guide](./CONTRIBUTING.md)):
36
+
37
+ ```ts
38
+ import { createClient } from '@clickhouse/client'
39
+
40
+ const client = createClient()
41
+ ```
42
+
43
+ Basic HTTPS connection:
44
+
45
+ ```ts
46
+ import { createClient } from '@clickhouse/client'
47
+
48
+ const client = createClient({
49
+ host: `https://<YOUR_CLICKHOUSE_HOST>:8443`,
50
+ password: '<YOUR_CLICKHOUSE_PASSWORD>',
51
+ database: '<YOUR_CLICKHOUSE_DATABASE>',
52
+ })
53
+ ```
54
+
55
+ Using custom ClickHouse settings and forced HTTP compression (GZIP) for both request and response:
56
+
57
+ ```ts
58
+ import { createClient } from '@clickhouse/client'
59
+
60
+ const client = createClient({
61
+ host: `https://<YOUR_CLICKHOUSE_HOST>:8443`,
62
+ password: '<YOUR_CLICKHOUSE_PASSWORD>',
63
+ database: '<YOUR_CLICKHOUSE_DATABASE>',
64
+ compression: {
65
+ request: true,
66
+ response: true,
67
+ },
68
+ clickhouse_settings: {
69
+ insert_quorum: '2',
70
+ },
71
+ })
72
+ ```
73
+
74
+ Closing the connection:
75
+
76
+ ```ts
77
+ await client.close()
78
+ ```
79
+
80
+ ### Connection settings overview
81
+
82
+ See [ClickHouseClientConfigOptions](https://github.com/ClickHouse/clickhouse-js/blob/60c484a3492420baed4b4c6c33cc0845262285e7/src/client.ts#L13-L35)
83
+
84
+ ```ts
85
+ export interface ClickHouseClientConfigOptions {
86
+ // a valid URL, for example, https://myclickhouseserver.org:8123
87
+ // if unset, defaults to http://localhost:8123
88
+ host?: string
89
+
90
+ // milliseconds, default 10_000
91
+ connect_timeout?: number
92
+
93
+ // milliseconds, default 300_000
94
+ request_timeout?: number
95
+
96
+ // For HTTP protocol, the connection pool has infinite size by default
97
+ // it can be overriden with this setting
98
+ max_open_connections?: number
99
+
100
+ // HTTP compression settings. Uses GZIP.
101
+ // For more details, see https://clickhouse.com/docs/en/interfaces/http/#compression
102
+ compression?: {
103
+ // enabled by default - the server will compress the data it sends to you in the response
104
+ response?: boolean
105
+ // disabled by default - the server will decompress the data which you pass in the request
106
+ request?: boolean
107
+ }
108
+
109
+ // if not set, 'default' is used
110
+ username?: string
111
+
112
+ // if not set, an empty password is used
113
+ password?: string
114
+
115
+ // used to identify the connection on the server side, if not set, uses 'clickhouse-js'
116
+ application?: string
117
+
118
+ // if not set, 'default' is used
119
+ database?: string
120
+
121
+ // additional settings to send with every query, such as `date_time_input_format` or `insert_quorum`
122
+ // see https://clickhouse.com/docs/en/operations/settings/settings/
123
+ // typings should support most of the options listed there
124
+ clickhouse_settings?: ClickHouseSettings
125
+
126
+ // logger settings
127
+ log?: {
128
+ // disabled by default, can be enabled using this setting
129
+ enable?: boolean
130
+ // use it to override default clickhouse-js logger with your own implementation
131
+ LoggerClass?: new (enabled: boolean) => Logger
132
+ }
133
+ }
134
+ ```
135
+
136
+ See also:
137
+
138
+ - [ClickHouseSettings](https://github.com/ClickHouse/clickhouse-js/blob/730b1b2516e2d47dc9a32b1d8d0b8ba8ceb95ead/src/settings.ts#L10-L1201)
139
+
140
+ - [Logger](https://github.com/ClickHouse/clickhouse-js/blob/ebdcab7a5d00d53bbbe46cce45c14bbcfda93f0c/src/logger.ts)
141
+
142
+ ## Supported formats
143
+
144
+ | Format | Input (array) | Input (stream) | Output (JSON) | Output (text) |
145
+ |--------------------------------------------|---------------|----------------|---------------|---------------|
146
+ | JSON | ❌ | ❌ | ✔️ | ✔️ |
147
+ | JSONEachRow | ✔️ | ✔️ | ✔️ | ✔️ |
148
+ | JSONStringsEachRow | ✔️ | ✔️ | ✔️ | ✔️ |
149
+ | JSONCompactEachRow | ✔️ | ✔️ | ✔️ | ✔️ |
150
+ | JSONCompactStringsEachRow | ✔️ | ✔️ | ✔️ | ✔️ |
151
+ | JSONCompactEachRowWithNames | ✔️ | ✔️ | ✔️ | ✔️ |
152
+ | JSONCompactEachRowWithNamesAndTypes | ✔️ | ✔️ | ✔️ | ✔️ |
153
+ | JSONCompactStringsEachRowWithNames | ✔️ | ✔️ | ✔️ | ✔️ |
154
+ | JSONCompactStringsEachRowWithNamesAndTypes | ✔️ | ✔️ | ✔️ | ✔️ |
155
+ | CSV | ❌ | ✔️ | ❌ | ✔️ |
156
+ | CSVWithNames | ❌ | ✔️ | ❌ | ✔️ |
157
+ | CSVWithNamesAndTypes | ❌ | ✔️ | ❌ | ✔️ |
158
+ | TabSeparated | ❌ | ✔️ | ❌ | ✔️ |
159
+ | TabSeparatedRaw | ❌ | ✔️ | ❌ | ✔️ |
160
+ | TabSeparatedWithNames | ❌ | ✔️ | ❌ | ✔️ |
161
+ | TabSeparatedWithNamesAndTypes | ❌ | ✔️ | ❌ | ✔️ |
162
+ | CustomSeparated | ❌ | ✔️ | ❌ | ✔️ |
163
+ | CustomSeparatedWithNames | ❌ | ✔️ | ❌ | ✔️ |
164
+ | CustomSeparatedWithNamesAndTypes | ❌ | ✔️ | ❌ | ✔️ |
165
+
166
+ The entire list of ClickHouse input and output formats is available [here](https://clickhouse.com/docs/en/interfaces/formats).
167
+
168
+ ## Supported ClickHouse data types
169
+
170
+ | Type | Status | JS type |
171
+ |----------------|----------------|---------------------------------------|
172
+ | UInt8/16/32 | ✔️ | number |
173
+ | UInt64/128/256 | ✔️❗- see below | string |
174
+ | Int8/16/32 | ✔️ | number |
175
+ | Int64/128/256 | ✔️❗- see below | string |
176
+ | Float32/64 | ✔️ | number |
177
+ | Decimal | ✔️❗- see below | number |
178
+ | Boolean | ✔️ | boolean |
179
+ | String | ✔️ | string |
180
+ | FixedString | ✔️ | string |
181
+ | UUID | ✔️ | string |
182
+ | Date32/64 | ✔️❗- see below | string |
183
+ | DateTime32/64 | ✔️❗- see below | string |
184
+ | Enum | ✔️ | string |
185
+ | LowCardinality | ✔️ | string |
186
+ | Array(T) | ✔️ | Array\<JS type for T> |
187
+ | JSON | ✔️ | object |
188
+ | Nested | ❌ | - |
189
+ | Tuple | ✔️ | Tuple |
190
+ | Nullable(T) | ✔️ | JS type for T or null |
191
+ | IPv4 | ✔️ | string |
192
+ | IPv6 | ✔️ | string |
193
+ | Point | ✔️ | [ number, number ] |
194
+ | Ring | ✔️ | Array\<Point> |
195
+ | Polygon | ✔️ | Array\<Ring> |
196
+ | MultiPolygon | ✔️ | Array\<Polygon> |
197
+ | Map(K, V) | ✔️ | Record\<JS type for K, JS type for V> |
198
+
199
+ The entire list of supported ClickHouse formats is available [here](https://clickhouse.com/docs/en/sql-reference/data-types/).
200
+
201
+ ### Date* / DateTime* types caveats:
202
+
203
+ Since we use data streaming for inserts without the `VALUES` clause (which does additional type conversion), Date\* type columns can be only inserted as strings and not as Unix time epoch. It can be possibly changed with the future ClickHouse database releases. Please refer to the corresponding [integration tests](https://github.com/ClickHouse/clickhouse-js/blob/ba387d7f4ce375a60982ac2d99cb47391cf76cec/__tests__/integration/date_time.test.ts) for more examples.
204
+
205
+ ### Decimal\* types caveats:
206
+
207
+ Since we do not use `VALUES` clause and there is no additional type conversion, it is not possible to insert Decimal* type columns as strings, only as numbers. This is a suboptimal approach as it might end in float precision loss. Thus, it is recommended to avoid JSON* formats when using Decimals as of now. Consider TabSeparated* / CSV* / CustomSeparated\* formats families for that kind of workflows. Please refer to the [data types tests](https://github.com/ClickHouse/clickhouse-js/blob/c1b70c82f525c39edb3ca1ee05cb5e6b43dba5b3/__tests__/integration/data_types.test.ts#L98-L131) for more concrete examples on how to avoid precision loss.
208
+
209
+ ### NB: Int64, Int128, Int256, UInt64, UInt128, UInt256
210
+
211
+ Though the server can accept it as a number, it is by default returned as a string in JSON\* family output formats to avoid integer overflow as max values for these types are bigger than `Number.MAX_SAFE_INTEGER`.
212
+
213
+ This behavior, however, can be modified with [`output_format_json_quote_64bit_integers` setting](https://clickhouse.com/docs/en/operations/settings/settings/#output_format_json_quote_64bit_integers).
214
+
215
+ ## ClickHouse client API overview
216
+
217
+ ### Query
218
+
219
+ Used for most statements that can have a response, such as `SELECT`, or for sending DDLs such as `CREATE TABLE`. For data insertion, please consider using the dedicated method `insert` which is described next.
220
+
221
+ ```ts
222
+ interface QueryParams {
223
+ // Query to execute that might return some data
224
+ // IMPORTANT: do not specify the FORMAT clause here
225
+ // use `format` param instead.
226
+ query: string
227
+ // Desired OUTPUT data format to be appended the query as ` FORMAT $format`
228
+ // It is extracted to the separate param
229
+ // as we may need to apply some additional request logic
230
+ // based on the desired format
231
+ format?: DataFormat
232
+ // ClickHouse settings that can be applied on query level, such as `date_time_input_format`
233
+ clickhouse_settings?: ClickHouseSettings
234
+ // See https://clickhouse.com/docs/en/interfaces/http/#cli-queries-with-parameters for more details
235
+ // IMPORTANT: that you should not prefix it with `param_` here, client will do that for you
236
+ query_params?: Record<string, unknown>
237
+ // A query can be aborted using this standard AbortSignal instance
238
+ // Please refer to the usage examples for more details
239
+ abort_signal?: AbortSignal
240
+ }
241
+
242
+ class ClickHouseClient {
243
+ query(params: QueryParams): Promise<Rows> {}
244
+ // ...
245
+ }
246
+ ```
247
+
248
+ #### Rows response abstraction
249
+
250
+ Provides several convenience methods for data processing in your application.
251
+
252
+ ```ts
253
+ class Rows {
254
+ // Consume the entire stream and get the contents as a string
255
+ // Can be used with any DataFormat
256
+ // Should be called only once
257
+ text(): Promise<string> {}
258
+ // Consume the entire stream and get the contents as a JS object
259
+ // Can be used only with JSON formats
260
+ // Should be called only once
261
+ json<T>(): Promise<T> {}
262
+ // Returns a readable stream of Row instances for responses that can be streamed (i.e. all except JSON)
263
+ // Should be called only once
264
+ // NB: if called for the second time, the second stream will be just empty
265
+ stream(): Stream.Readable {}
266
+ }
267
+
268
+ class Row {
269
+ // Get the content of the row as plain string
270
+ text(): string {}
271
+ // Get the content of the row as a JS object
272
+ json<T>(): T {}
273
+ }
274
+ ```
275
+
276
+ ### Insert
277
+
278
+ Primary method for data insertion. It can work with both `Stream.Readable` (all formats except `JSON`) and plain `Array<T>` (`JSON*` family formats only). It is recommended to avoid arrays in case of large inserts to reduce application memory consumption, and consider streaming for most of the use cases.
279
+
280
+ Should be awaited, but it does not return anything.
281
+
282
+ ```ts
283
+ interface InsertParams<T> {
284
+ // Table name to insert the data into
285
+ table: string
286
+ // Stream.Readable will work for all formats except JSON
287
+ // Array will work only for JSON* formats
288
+ values: ReadonlyArray<T> | Stream.Readable
289
+ // Desired INPUT data format to be appended the statement as ` FORMAT $format`
290
+ // It is extracted to the separate param
291
+ // as we may need to apply some additional request logic
292
+ // based on the desired format
293
+ format?: DataFormat
294
+ // ClickHouse settings that can be applied on statement level, such as `insert_quorum`
295
+ clickhouse_settings?: ClickHouseSettings
296
+ // See https://clickhouse.com/docs/en/interfaces/http/#cli-queries-with-parameters for more details
297
+ // IMPORTANT: that you should not prefix it with `param_` here, client will do that for you
298
+ query_params?: Record<string, unknown>
299
+ // A query can be aborted using this standard AbortSignal instance
300
+ // Please refer to the usage examples for more details
301
+ abort_signal?: AbortSignal
302
+ }
303
+
304
+ class ClickHouseClient {
305
+ insert(params: InsertParams): Promise<void> {}
306
+ // ...
307
+ }
308
+ ```
309
+
310
+ ### Exec
311
+
312
+ Can be used for statements that do not have any output, when format clause is not applicable, or when you are not interested in the response at all. An example of such statement can be `CREATE TABLE` or `ALTER TABLE`.
313
+
314
+ Should be awaited.
315
+
316
+ Optionally, it returns a readable stream that can be consumed on the application side if you need it for some reason. But in that case you might consider using `query` instead.
317
+
318
+ ```ts
319
+ interface ExecParams {
320
+ // Statement to execute
321
+ query: string
322
+ // ClickHouse settings that can be applied on query level, such as `date_time_input_format`
323
+ clickhouse_settings?: ClickHouseSettings
324
+ // See https://clickhouse.com/docs/en/interfaces/http/#cli-queries-with-parameters for more details
325
+ // IMPORTANT: that you should not prefix it with `param_` here, client will do that for you
326
+ query_params?: Record<string, unknown>
327
+ // A query can be aborted using this standard AbortSignal instance
328
+ // Please refer to the usage examples for more details
329
+ abort_signal?: AbortSignal
330
+ }
331
+
332
+ class ClickHouseClient {
333
+ exec(params: ExecParams): Promise<Stream.Readable> {}
334
+ // ...
335
+ }
336
+ ```
337
+
338
+ ### Ping
339
+
340
+ Might be useful to check the connectivity to the ClickHouse server. Returns `true` if server can be reached. Can throw a standard Node.js Error such as `ECONNREFUSED`.
341
+
342
+ ```ts
343
+ class ClickHouseClient {
344
+ ping(): Promise<boolean> {}
345
+ // ...
346
+ }
347
+ ```
348
+
349
+ ### Close
350
+
351
+ Use it in your application graceful shutdown handler, as it properly closes all the open connections.
352
+
353
+ ```ts
354
+ class ClickHouseClient {
355
+ close(): Promise<void> {}
356
+ // ...
357
+ }
358
+ ```
359
+
360
+ ## Usage examples
361
+
362
+ ### Create a table (single node)
363
+
364
+ ```ts
365
+ await client.exec({
366
+ query: `
367
+ CREATE TABLE foobar
368
+ (id UInt64, name String)
369
+ ENGINE MergeTree()
370
+ ORDER BY (id)
371
+ `,
372
+ })
373
+ ```
374
+
375
+ ### Create a table (local cluster)
376
+
377
+ ```ts
378
+ await client.exec({
379
+ query: `
380
+ CREATE TABLE foobar ON CLUSTER '{cluster}'
381
+ (id UInt64, name String)
382
+ ENGINE ReplicatedMergeTree(
383
+ '/clickhouse/{cluster}/tables/{database}/{table}/{shard}',
384
+ '{replica}'
385
+ )
386
+ ORDER BY (id)
387
+ `,
388
+ // Recommended for cluster usage to avoid situations
389
+ // where a query processing error occurred after the response code
390
+ // and HTTP headers were sent to the client.
391
+ // See https://clickhouse.com/docs/en/interfaces/http/#response-buffering
392
+ clickhouse_settings: {
393
+ wait_end_of_query: 1,
394
+ },
395
+ })
396
+ ```
397
+
398
+ ### Create a table (ClickHouse cloud)
399
+
400
+ Note that `ENGINE` and `ON CLUSTER` clauses can be omitted entirely here.
401
+
402
+ ClickHouse cloud will automatically use `ReplicatedMergeTree` with appropriate settings in this case.
403
+
404
+ ```ts
405
+ await client.exec({
406
+ query: `
407
+ CREATE TABLE foobar
408
+ (id UInt64, name String)
409
+ ORDER BY (id)
410
+ `,
411
+ // Recommended for cluster usage to avoid situations
412
+ // where a query processing error occurred after the response code
413
+ // and HTTP headers were sent to the client.
414
+ // See https://clickhouse.com/docs/en/interfaces/http/#response-buffering
415
+ clickhouse_settings: {
416
+ wait_end_of_query: 1,
417
+ },
418
+ })
419
+ ```
420
+
421
+ ### Insert with array input (JSON\* family formats only)
422
+
423
+ ```ts
424
+ await client.insert({
425
+ table: tableName,
426
+ // structure should match the desired format, JSONEachRow in this example
427
+ values: [
428
+ { id: 42, name: 'foo' },
429
+ { id: 42, name: 'bar' },
430
+ ],
431
+ format: 'JSONEachRow',
432
+ })
433
+ ```
434
+
435
+ ### Insert with stream input (any format except JSON, stream is created out of an array)
436
+
437
+ ```ts
438
+ await client.insert({
439
+ table: tableName,
440
+ // structure should match the desired format, JSONCompactEachRow in this example
441
+ values: Stream.Readable.from([
442
+ [42, 'foo'],
443
+ [42, 'bar'],
444
+ ]),
445
+ format: 'JSONCompactEachRow',
446
+ })
447
+ ```
448
+
449
+ ### Insert with stream input (any format except JSON, flowing stream)
450
+
451
+ ```ts
452
+ const stream = new Stream.Readable({
453
+ objectMode: true, // required for JSON* family formats
454
+ read() {
455
+ /* stub */
456
+ },
457
+ })
458
+ // ... your (async) code pushing the values into the stream...
459
+ await client.insert({
460
+ table: tableName,
461
+ values: stream,
462
+ format: 'JSONEachRow', // or any other desired JSON* format
463
+ })
464
+ // close the stream when finished by pushing a null value there
465
+ stream.push(null)
466
+ ```
467
+
468
+ ### Insert with stream input ("raw" formats like CSV* / TabSeparated* / CustomSeparated\*, stream is created out of an array)
469
+
470
+ ```ts
471
+ await client.insert({
472
+ table: tableName,
473
+ // structure should match the desired format, TabSeparated in this example
474
+ values: Stream.Readable.from(['42,foobar'], {
475
+ objectMode: false, // required for "raw" family formats
476
+ }),
477
+ format: 'TabSeparated', // or any other desired "raw" format
478
+ })
479
+ ```
480
+
481
+ ### Insert with stream input ("raw" formats like CSV* / TabSeparated* / CustomSeparated\*, flowing stream)
482
+
483
+ ```ts
484
+ const stream = new Stream.Readable({
485
+ objectMode: false, // required for "raw" family formats
486
+ read() {
487
+ /* stub */
488
+ },
489
+ })
490
+ // ... your (async) code pushing the values into the stream...
491
+ await client.insert({
492
+ table: tableName,
493
+ values: stream,
494
+ format: 'TabSeparated', // or any other desired "raw" format
495
+ })
496
+ // close the stream when finished by pushing a null value there
497
+ stream.push(null)
498
+ ```
499
+
500
+ ### Inserting a file (for example, CSV)
501
+
502
+ ```ts
503
+ const filename = Path.resolve(process.cwd(), 'path/to/file.csv')
504
+ await client.insert({
505
+ table: tableName,
506
+ values: Fs.createReadStream(filename),
507
+ format: 'CSVWithNames',
508
+ })
509
+ ```
510
+
511
+ See also:
512
+
513
+ - [NDJSON file streaming example](https://github.com/ClickHouse/clickhouse-js/blob/60c484a3492420baed4b4c6c33cc0845262285e7/examples/streaming/stream_ndjson.ts)
514
+ - [Memory leaks test using Brown University benchmarks files](https://github.com/ClickHouse/clickhouse-js/blob/60c484a3492420baed4b4c6c33cc0845262285e7/benchmarks/leaks/memory_leak_brown.ts#L72-L80)
515
+
516
+ ### Selecting the data as JSON using a JSON\* family format
517
+
518
+ ```ts
519
+ const rows = await client.query({
520
+ query: 'SELECT number FROM system.numbers LIMIT 5',
521
+ format: 'JSONCompactEachRow',
522
+ })
523
+ const result = await rows.json()
524
+ // result is [['0'], ['1'], ['2'], ['3'], ['4']]
525
+ ```
526
+
527
+ ### Selecting the data as JSON including response metadata
528
+
529
+ ```ts
530
+ const rows = await client.query({
531
+ query: 'SELECT number FROM system.numbers LIMIT 2',
532
+ format: 'JSON',
533
+ })
534
+ const result = await rows.json<ResponseJSON<{ number: string }>>()
535
+
536
+ /* result will look like
537
+
538
+ {
539
+ "meta": [ { "name": "number", "type": "UInt64" } ],
540
+ "data": [ { "number": "0"}, { "number": "1" } ],
541
+ "rows": 2,
542
+ "rows_before_limit_at_least": 2,
543
+ "statistics": {
544
+ "elapsed": 0.00013129,
545
+ "rows_read": 2,
546
+ "bytes_read": 16
547
+ }
548
+ }
549
+
550
+ */
551
+ ```
552
+
553
+ ### Selecting the data as text
554
+
555
+ ```ts
556
+ const rows = await client.query({
557
+ query: `SELECT number FROM system.numbers LIMIT 2`,
558
+ format: 'CSV',
559
+ })
560
+ const result = await rows.text()
561
+ // result is now '0\n1\n'
562
+ ```
563
+
564
+ ### Selecting the data as a stream
565
+
566
+ ```ts
567
+ const rows = await client.query({
568
+ query: `SELECT * from ${tableName}`,
569
+ format: 'JSONCompactEachRow',
570
+ })
571
+ for await (const row of rows.stream()) {
572
+ const data = (row as Row).json()
573
+ // ... your code processing the data here
574
+ }
575
+ ```
576
+
577
+ ### Query with parameter binding
578
+
579
+ ```ts
580
+ const rows = await client.query({
581
+ query: 'SELECT plus({val1: Int32}, {val2: Int32})',
582
+ format: 'CSV',
583
+ query_params: {
584
+ val1: 10,
585
+ val2: 20,
586
+ },
587
+ })
588
+ const result = await rows.text()
589
+ // result is '30\n'
590
+ ```
591
+
592
+ ### Query with custom ClickHouse settings
593
+
594
+ ```ts
595
+ await client.insert({
596
+ table: tableName,
597
+ values: [
598
+ { id: 42, name: 'foo' },
599
+ { id: 42, name: 'bar' },
600
+ ],
601
+ format: 'JSONEachRow',
602
+ clickhouse_settings: { insert_quorum: '2' },
603
+ })
604
+ ```
605
+
606
+ ### Abort query
607
+
608
+ ```ts
609
+ import { AbortController } from 'node-abort-controller'
610
+
611
+ const controller = new AbortController()
612
+ const selectPromise = client.query({
613
+ query: 'SELECT sleep(3)',
614
+ format: 'CSV',
615
+ abort_signal: controller.signal as AbortSignal,
616
+ })
617
+ controller.abort()
618
+ // selectPromise is now rejected with "The request was aborted" message
619
+ ```
620
+
621
+ ## Known limitations
622
+
623
+ - Browser usage is not supported.
624
+ - There are no data mappers for the result sets, so only language primitives are used.
625
+ - There are some [Decimal* and Date* / DateTime\* data types caveats](#date--datetime-types-caveats).
626
+ - Nested data type is currently not officially supported.
627
+
628
+ ## Tips for performance optimizations
629
+
630
+ - To reduce application memory consumption, consider using streams for large inserts when applicable.
631
+ - Node.js HTTP(s) Agent has infinite max open sockets by default. In some cases, you might want to limit that by using `ClickHouseClientConfigOptions.max_open_connections` setting.
632
+ - We have response (for example, select queries) compression enabled by default, but insert compression is disabled. When using large inserts, you might want to enable request compression as well. You can use `ClickHouseClientConfigOptions.compression.request` for that.
633
+
634
+ ## Contributing
635
+
636
+ Check out our [contributing guide](./CONTRIBUTING.md).
@@ -0,0 +1,17 @@
1
+ export declare type DataType = 'UInt8' | 'UInt16' | 'UInt32' | 'UInt64' | 'UInt128' | 'UInt256' | 'Int8' | 'Int16' | 'Int32' | 'Int64' | 'Int128' | 'Int256' | 'Float32' | 'Float64';
2
+ export interface ResponseJSON<T = unknown> {
3
+ data: Array<T>;
4
+ query_id?: string;
5
+ totals?: Record<string, number>;
6
+ extremes?: Record<string, any>;
7
+ meta?: Array<{
8
+ name: string;
9
+ type: DataType;
10
+ }>;
11
+ statistics?: {
12
+ elapsed: number;
13
+ rows_read: number;
14
+ bytes_read: number;
15
+ };
16
+ rows?: number;
17
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=clickhouse_types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clickhouse_types.js","sourceRoot":"","sources":["../src/clickhouse_types.ts"],"names":[],"mappings":""}