@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.
- package/LICENSE +203 -0
- package/README.md +636 -0
- package/dist/clickhouse_types.d.ts +17 -0
- package/dist/clickhouse_types.js +3 -0
- package/dist/clickhouse_types.js.map +1 -0
- package/dist/client.d.ts +56 -0
- package/dist/client.js +180 -0
- package/dist/client.js.map +1 -0
- package/dist/connection/adapter/base_http_adapter.d.ts +33 -0
- package/dist/connection/adapter/base_http_adapter.js +257 -0
- package/dist/connection/adapter/base_http_adapter.js.map +1 -0
- package/dist/connection/adapter/http_adapter.d.ts +10 -0
- package/dist/connection/adapter/http_adapter.js +27 -0
- package/dist/connection/adapter/http_adapter.js.map +1 -0
- package/dist/connection/adapter/http_search_params.d.ts +9 -0
- package/dist/connection/adapter/http_search_params.js +36 -0
- package/dist/connection/adapter/http_search_params.js.map +1 -0
- package/dist/connection/adapter/https_adapter.d.ts +10 -0
- package/dist/connection/adapter/https_adapter.js +27 -0
- package/dist/connection/adapter/https_adapter.js.map +1 -0
- package/dist/connection/adapter/index.d.ts +2 -0
- package/dist/connection/adapter/index.js +8 -0
- package/dist/connection/adapter/index.js.map +1 -0
- package/dist/connection/adapter/transform_url.d.ts +5 -0
- package/dist/connection/adapter/transform_url.js +15 -0
- package/dist/connection/adapter/transform_url.js.map +1 -0
- package/dist/connection/connection.d.ts +34 -0
- package/dist/connection/connection.js +17 -0
- package/dist/connection/connection.js.map +1 -0
- package/dist/connection/index.d.ts +1 -0
- package/dist/connection/index.js +18 -0
- package/dist/connection/index.js.map +1 -0
- package/dist/data_formatter/format_query_params.d.ts +1 -0
- package/dist/data_formatter/format_query_params.js +61 -0
- package/dist/data_formatter/format_query_params.js.map +1 -0
- package/dist/data_formatter/format_query_settings.d.ts +2 -0
- package/dist/data_formatter/format_query_settings.js +21 -0
- package/dist/data_formatter/format_query_settings.js.map +1 -0
- package/dist/data_formatter/formatter.d.ts +23 -0
- package/dist/data_formatter/formatter.js +81 -0
- package/dist/data_formatter/formatter.js.map +1 -0
- package/dist/data_formatter/index.d.ts +3 -0
- package/dist/data_formatter/index.js +23 -0
- package/dist/data_formatter/index.js.map +1 -0
- package/dist/error/index.d.ts +1 -0
- package/dist/error/index.js +18 -0
- package/dist/error/index.js.map +1 -0
- package/dist/error/parse_error.d.ts +12 -0
- package/dist/error/parse_error.js +39 -0
- package/dist/error/parse_error.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +8 -0
- package/dist/logger.js +35 -0
- package/dist/logger.js.map +1 -0
- package/dist/rows.d.ts +50 -0
- package/dist/rows.js +114 -0
- package/dist/rows.js.map +1 -0
- package/dist/schema/common.d.ts +8 -0
- package/dist/schema/common.js +3 -0
- package/dist/schema/common.js.map +1 -0
- package/dist/schema/compact.d.ts +3 -0
- package/dist/schema/compact.js +24 -0
- package/dist/schema/compact.js.map +1 -0
- package/dist/schema/engines.d.ts +40 -0
- package/dist/schema/engines.js +61 -0
- package/dist/schema/engines.js.map +1 -0
- package/dist/schema/index.d.ts +7 -0
- package/dist/schema/index.js +24 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/query_formatter.d.ts +9 -0
- package/dist/schema/query_formatter.js +48 -0
- package/dist/schema/query_formatter.js.map +1 -0
- package/dist/schema/result.d.ts +13 -0
- package/dist/schema/result.js +3 -0
- package/dist/schema/result.js.map +1 -0
- package/dist/schema/schema.d.ts +6 -0
- package/dist/schema/schema.js +20 -0
- package/dist/schema/schema.js.map +1 -0
- package/dist/schema/stream.d.ts +11 -0
- package/dist/schema/stream.js +25 -0
- package/dist/schema/stream.js.map +1 -0
- package/dist/schema/table.d.ts +44 -0
- package/dist/schema/table.js +70 -0
- package/dist/schema/table.js.map +1 -0
- package/dist/schema/types.d.ts +201 -0
- package/dist/schema/types.js +268 -0
- package/dist/schema/types.js.map +1 -0
- package/dist/schema/where.d.ts +8 -0
- package/dist/schema/where.js +43 -0
- package/dist/schema/where.js.map +1 -0
- package/dist/settings.d.ts +1453 -0
- package/dist/settings.js +28 -0
- package/dist/settings.js.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +19 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/stream.d.ts +5 -0
- package/dist/utils/stream.js +32 -0
- package/dist/utils/stream.js.map +1 -0
- package/dist/utils/string.d.ts +1 -0
- package/dist/utils/string.js +9 -0
- package/dist/utils/string.js.map +1 -0
- 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 @@
|
|
|
1
|
+
{"version":3,"file":"clickhouse_types.js","sourceRoot":"","sources":["../src/clickhouse_types.ts"],"names":[],"mappings":""}
|