@cleverbrush/knex-clickhouse 1.1.6 → 1.1.8
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/dist/index.d.ts +20 -2
- package/dist/index.js +67 -3
- package/package.json +3 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
import Knex from 'knex';
|
|
2
|
-
import ClickhouseDriver from '@clickhouse/client';
|
|
2
|
+
import ClickhouseDriver, { type ClickHouseSettings } from '@clickhouse/client';
|
|
3
|
+
import { retry } from '@cleverbrush/async';
|
|
4
|
+
type AdditionalClientOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* Options for retrying the query,
|
|
7
|
+
* by default it will retry 10 times with a delay factor of 2 and a minimum delay of
|
|
8
|
+
* 100ms and delay randomization of 10%.
|
|
9
|
+
* and will retry only if the error code is 'ECONNRESET',
|
|
10
|
+
* you can override this behavior by passing your own options.
|
|
11
|
+
* If this option is set to `null` then the query will not be retried.
|
|
12
|
+
*/
|
|
13
|
+
retry?: Parameters<typeof retry>[1];
|
|
14
|
+
};
|
|
3
15
|
export declare class ClickhouseKnexClient extends Knex.Client {
|
|
4
16
|
#private;
|
|
5
17
|
_driver(): typeof ClickhouseDriver;
|
|
6
|
-
constructor(config?:
|
|
18
|
+
constructor(config?: Knex.Knex.Config<any> & AdditionalClientOptions);
|
|
7
19
|
_escapeBinding(value: any): any;
|
|
8
20
|
/**
|
|
9
21
|
*
|
|
@@ -22,3 +34,9 @@ export declare class ClickhouseKnexClient extends Knex.Client {
|
|
|
22
34
|
acquireRawConnection(): Promise<any>;
|
|
23
35
|
destroyRawConnection(connection: any): Promise<void>;
|
|
24
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
*
|
|
39
|
+
* @returns {import('knex').Knex<any, unknown[]>}
|
|
40
|
+
*/
|
|
41
|
+
export declare const getClickhouseConnection: (config?: Knex.Knex.Config<any> & AdditionalClientOptions, clickHouseSettings?: ClickHouseSettings) => Knex.Knex<any, unknown[]>;
|
|
42
|
+
export {};
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import Knex from 'knex';
|
|
2
2
|
import ClickhouseDriver from '@clickhouse/client';
|
|
3
|
+
import { retry } from '@cleverbrush/async';
|
|
4
|
+
import { deepExtend } from '@cleverbrush/deep';
|
|
3
5
|
import { makeEscape } from './makeEscape.js';
|
|
4
6
|
const parseDate = (value) => new Date(Date.parse(value));
|
|
5
7
|
// this function is taken from knex npm package
|
|
@@ -28,8 +30,19 @@ export class ClickhouseKnexClient extends Knex.Client {
|
|
|
28
30
|
_driver() {
|
|
29
31
|
return ClickhouseDriver;
|
|
30
32
|
}
|
|
33
|
+
#retryOptions;
|
|
31
34
|
constructor(config = {}) {
|
|
35
|
+
const { retry: retryOptions } = config;
|
|
32
36
|
super(config);
|
|
37
|
+
this.#retryOptions = retryOptions
|
|
38
|
+
? deepExtend({
|
|
39
|
+
maxRetries: 10,
|
|
40
|
+
delayFactor: 2,
|
|
41
|
+
minDelay: 100,
|
|
42
|
+
delayRandomizationPercent: 0.1,
|
|
43
|
+
shouldRetry: (error) => error.code === 'ECONNRESET'
|
|
44
|
+
}, retryOptions)
|
|
45
|
+
: null;
|
|
33
46
|
}
|
|
34
47
|
#typeParsers = {
|
|
35
48
|
Date: parseDate,
|
|
@@ -125,14 +138,18 @@ export class ClickhouseKnexClient extends Knex.Client {
|
|
|
125
138
|
case 'first':
|
|
126
139
|
case 'pluck':
|
|
127
140
|
{
|
|
128
|
-
const p = await
|
|
141
|
+
const p = (await (this.#retryOptions
|
|
142
|
+
? retry(() => connection.query(queryParams), this.#retryOptions)
|
|
143
|
+
: connection.query(queryParams)));
|
|
129
144
|
response = await p.json();
|
|
130
145
|
const { data, meta, ...rest } = response;
|
|
131
146
|
obj.response = [data, meta, { ...rest }];
|
|
132
147
|
}
|
|
133
148
|
break;
|
|
134
149
|
default:
|
|
135
|
-
response = await
|
|
150
|
+
response = await (this.#retryOptions
|
|
151
|
+
? retry(() => connection.exec(queryParams), this.#retryOptions)
|
|
152
|
+
: connection.exec(queryParams));
|
|
136
153
|
}
|
|
137
154
|
return obj;
|
|
138
155
|
}
|
|
@@ -199,7 +216,9 @@ export class ClickhouseKnexClient extends Knex.Client {
|
|
|
199
216
|
password: this.config.connection.password,
|
|
200
217
|
// @ts-ignore
|
|
201
218
|
database: this.config.connection.database,
|
|
202
|
-
compression: { request: true, response: true }
|
|
219
|
+
compression: { request: true, response: true },
|
|
220
|
+
// @ts-ignore
|
|
221
|
+
clickhouse_settings: this.config.clickHouseSettings
|
|
203
222
|
});
|
|
204
223
|
// @ts-ignore
|
|
205
224
|
connection.connected = true;
|
|
@@ -216,3 +235,48 @@ Object.assign(ClickhouseKnexClient.prototype, {
|
|
|
216
235
|
driverName: 'clikhouse',
|
|
217
236
|
canCancelQuery: true
|
|
218
237
|
});
|
|
238
|
+
const registerKnexClickhouseExtensions = (knex) => {
|
|
239
|
+
Knex.QueryBuilder.extend('insertToClickhouse', function (rows) {
|
|
240
|
+
const getTuple = (r, p = ['(', ')']) => p[0] +
|
|
241
|
+
r
|
|
242
|
+
.map((c) => {
|
|
243
|
+
if (c === null) {
|
|
244
|
+
return 'NULL';
|
|
245
|
+
}
|
|
246
|
+
if (typeof c === 'string') {
|
|
247
|
+
return knex.raw('?', [c]).toQuery();
|
|
248
|
+
}
|
|
249
|
+
if (Array.isArray(c)) {
|
|
250
|
+
return getTuple(c, ['[', ']']);
|
|
251
|
+
}
|
|
252
|
+
if (typeof c === 'object') {
|
|
253
|
+
const keys = Object.keys(c);
|
|
254
|
+
return `[${keys
|
|
255
|
+
.map((k) => `(${knex.raw('?', [k]).toQuery()}, ${knex
|
|
256
|
+
.raw('?', [c[k]])
|
|
257
|
+
.toQuery()})`)
|
|
258
|
+
.join(', ')}]`;
|
|
259
|
+
}
|
|
260
|
+
return c;
|
|
261
|
+
})
|
|
262
|
+
.join(', ') +
|
|
263
|
+
p[1];
|
|
264
|
+
const values = rows.map((r) => getTuple(r));
|
|
265
|
+
// @ts-ignore
|
|
266
|
+
return knex.raw(`INSERT INTO ${this._single.table} VALUES ${values}`);
|
|
267
|
+
});
|
|
268
|
+
};
|
|
269
|
+
/**
|
|
270
|
+
*
|
|
271
|
+
* @returns {import('knex').Knex<any, unknown[]>}
|
|
272
|
+
*/
|
|
273
|
+
export const getClickhouseConnection = (config = {}, clickHouseSettings) => {
|
|
274
|
+
const connection = Knex({
|
|
275
|
+
...config,
|
|
276
|
+
client: ClickhouseKnexClient,
|
|
277
|
+
// @ts-ignore
|
|
278
|
+
clickHouseSettings
|
|
279
|
+
});
|
|
280
|
+
registerKnexClickhouseExtensions(connection);
|
|
281
|
+
return connection;
|
|
282
|
+
};
|
package/package.json
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
"email": "andrew_zol@cleverbrush.com"
|
|
6
6
|
},
|
|
7
7
|
"dependencies": {
|
|
8
|
+
"@cleverbrush/async": "^1.1.8",
|
|
9
|
+
"@cleverbrush/deep": "^1.1.8",
|
|
8
10
|
"@clickhouse/client": "^1.0.1"
|
|
9
11
|
},
|
|
10
12
|
"peerDependencies": {
|
|
@@ -35,5 +37,5 @@
|
|
|
35
37
|
},
|
|
36
38
|
"type": "module",
|
|
37
39
|
"types": "./dist/index.d.ts",
|
|
38
|
-
"version": "1.1.
|
|
40
|
+
"version": "1.1.8"
|
|
39
41
|
}
|