@hypequery/clickhouse 1.6.2 → 2.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/README-CLI.md +43 -88
- package/README.md +84 -253
- package/dist/cli/bin.js +16 -8
- package/dist/core/adapters/clickhouse-adapter.d.ts.map +1 -1
- package/dist/core/adapters/clickhouse-adapter.js +3 -2
- package/dist/core/cache/cache-manager.d.ts.map +1 -1
- package/dist/core/cache/cache-manager.js +5 -3
- package/dist/core/connection.d.ts +6 -6
- package/dist/core/connection.js +9 -9
- package/dist/core/cross-filter.js +1 -1
- package/dist/core/dialects/clickhouse-dialect.d.ts +2 -2
- package/dist/core/dialects/clickhouse-dialect.d.ts.map +1 -1
- package/dist/core/dialects/clickhouse-dialect.js +39 -22
- package/dist/core/dialects/sql-dialect.d.ts +2 -2
- package/dist/core/dialects/sql-dialect.d.ts.map +1 -1
- package/dist/core/env/auto-client.d.ts.map +1 -1
- package/dist/core/env/auto-client.js +1 -1
- package/dist/core/features/aggregations.d.ts +27 -84
- package/dist/core/features/aggregations.d.ts.map +1 -1
- package/dist/core/features/aggregations.js +59 -7
- package/dist/core/features/analytics.d.ts +5 -870
- package/dist/core/features/analytics.d.ts.map +1 -1
- package/dist/core/features/analytics.js +15 -13
- package/dist/core/features/cross-filtering.d.ts +1 -1
- package/dist/core/features/cross-filtering.d.ts.map +1 -1
- package/dist/core/features/cross-filtering.js +28 -73
- package/dist/core/features/executor.d.ts +1 -1
- package/dist/core/features/executor.d.ts.map +1 -1
- package/dist/core/features/executor.js +9 -11
- package/dist/core/features/filtering.d.ts +5 -91
- package/dist/core/features/filtering.d.ts.map +1 -1
- package/dist/core/features/filtering.js +63 -77
- package/dist/core/features/joins.d.ts +2 -19
- package/dist/core/features/joins.d.ts.map +1 -1
- package/dist/core/features/joins.js +16 -5
- package/dist/core/features/query-modifiers.d.ts +10 -109
- package/dist/core/features/query-modifiers.d.ts.map +1 -1
- package/dist/core/features/query-modifiers.js +64 -18
- package/dist/core/formatters/sql-formatter.d.ts +16 -5
- package/dist/core/formatters/sql-formatter.d.ts.map +1 -1
- package/dist/core/formatters/sql-formatter.js +197 -93
- package/dist/core/join-relationships.d.ts +22 -5
- package/dist/core/join-relationships.d.ts.map +1 -1
- package/dist/core/join-relationships.js +1 -1
- package/dist/core/query-builder.d.ts +64 -12
- package/dist/core/query-builder.d.ts.map +1 -1
- package/dist/core/query-builder.js +213 -153
- package/dist/core/query-node.d.ts +7 -0
- package/dist/core/query-node.d.ts.map +1 -0
- package/dist/core/query-node.js +80 -0
- package/dist/core/tests/integration/setup.d.ts +3 -10
- package/dist/core/tests/integration/setup.d.ts.map +1 -1
- package/dist/core/tests/integration/setup.js +30 -249
- package/dist/core/types/select-types.d.ts +3 -0
- package/dist/core/types/select-types.d.ts.map +1 -1
- package/dist/core/utils/connection-endpoint.d.ts +3 -0
- package/dist/core/utils/connection-endpoint.d.ts.map +1 -0
- package/dist/core/utils/connection-endpoint.js +9 -0
- package/dist/core/utils/filter-application.d.ts +15 -0
- package/dist/core/utils/filter-application.d.ts.map +1 -0
- package/dist/core/utils/filter-application.js +32 -0
- package/dist/core/utils/query-config-compat.d.ts +48 -0
- package/dist/core/utils/query-config-compat.d.ts.map +1 -0
- package/dist/core/utils/query-config-compat.js +137 -0
- package/dist/core/utils/relation-application.d.ts +9 -0
- package/dist/core/utils/relation-application.d.ts.map +1 -0
- package/dist/core/utils/relation-application.js +19 -0
- package/dist/core/utils/relation-validation.d.ts +6 -0
- package/dist/core/utils/relation-validation.d.ts.map +1 -0
- package/dist/core/utils/relation-validation.js +29 -0
- package/dist/core/utils/sql-expressions.d.ts +14 -0
- package/dist/core/utils/sql-expressions.d.ts.map +1 -1
- package/dist/core/utils/sql-expressions.js +40 -0
- package/dist/core/utils/tuple-filter-validation.d.ts +3 -0
- package/dist/core/utils/tuple-filter-validation.d.ts.map +1 -0
- package/dist/core/utils/tuple-filter-validation.js +16 -0
- package/dist/index.d.ts +2 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -8
- package/dist/types/base.d.ts +89 -22
- package/dist/types/base.d.ts.map +1 -1
- package/dist/types/filters.d.ts +9 -5
- package/dist/types/filters.d.ts.map +1 -1
- package/package.json +5 -5
- package/dist/core/tests/integration/test-data.json +0 -190
- package/dist/migrations/config/index.d.ts +0 -3
- package/dist/migrations/config/index.d.ts.map +0 -1
- package/dist/migrations/config/index.js +0 -1
- package/dist/migrations/config/types.d.ts +0 -45
- package/dist/migrations/config/types.d.ts.map +0 -1
- package/dist/migrations/config/types.js +0 -28
- package/dist/migrations/diff/diff.d.ts +0 -11
- package/dist/migrations/diff/diff.d.ts.map +0 -1
- package/dist/migrations/diff/diff.js +0 -240
- package/dist/migrations/diff/index.d.ts +0 -3
- package/dist/migrations/diff/index.d.ts.map +0 -1
- package/dist/migrations/diff/index.js +0 -1
- package/dist/migrations/diff/types.d.ts +0 -74
- package/dist/migrations/diff/types.d.ts.map +0 -1
- package/dist/migrations/diff/types.js +0 -1
- package/dist/migrations/plan/index.d.ts +0 -3
- package/dist/migrations/plan/index.d.ts.map +0 -1
- package/dist/migrations/plan/index.js +0 -1
- package/dist/migrations/plan/plan.d.ts +0 -12
- package/dist/migrations/plan/plan.d.ts.map +0 -1
- package/dist/migrations/plan/plan.js +0 -416
- package/dist/migrations/plan/types.d.ts +0 -93
- package/dist/migrations/plan/types.d.ts.map +0 -1
- package/dist/migrations/plan/types.js +0 -1
- package/dist/migrations/schema/column.d.ts +0 -71
- package/dist/migrations/schema/column.d.ts.map +0 -1
- package/dist/migrations/schema/column.js +0 -123
- package/dist/migrations/schema/define.d.ts +0 -24
- package/dist/migrations/schema/define.d.ts.map +0 -1
- package/dist/migrations/schema/define.js +0 -47
- package/dist/migrations/schema/index.d.ts +0 -4
- package/dist/migrations/schema/index.d.ts.map +0 -1
- package/dist/migrations/schema/index.js +0 -2
- package/dist/migrations/schema/types.d.ts +0 -74
- package/dist/migrations/schema/types.d.ts.map +0 -1
- package/dist/migrations/schema/types.js +0 -1
- package/dist/migrations/snapshot/index.d.ts +0 -3
- package/dist/migrations/snapshot/index.d.ts.map +0 -1
- package/dist/migrations/snapshot/index.js +0 -1
- package/dist/migrations/snapshot/serialize.d.ts +0 -21
- package/dist/migrations/snapshot/serialize.d.ts.map +0 -1
- package/dist/migrations/snapshot/serialize.js +0 -127
- package/dist/migrations/snapshot/types.d.ts +0 -47
- package/dist/migrations/snapshot/types.d.ts.map +0 -1
- package/dist/migrations/snapshot/types.js +0 -1
- package/dist/migrations/sql/index.d.ts +0 -4
- package/dist/migrations/sql/index.d.ts.map +0 -1
- package/dist/migrations/sql/index.js +0 -2
- package/dist/migrations/sql/render.d.ts +0 -10
- package/dist/migrations/sql/render.d.ts.map +0 -1
- package/dist/migrations/sql/render.js +0 -347
- package/dist/migrations/sql/types.d.ts +0 -53
- package/dist/migrations/sql/types.d.ts.map +0 -1
- package/dist/migrations/sql/types.js +0 -1
- package/dist/migrations/sql/write.d.ts +0 -10
- package/dist/migrations/sql/write.d.ts.map +0 -1
- package/dist/migrations/sql/write.js +0 -35
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cache-manager.d.ts","sourceRoot":"","sources":["../../../src/core/cache/cache-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"cache-manager.d.ts","sourceRoot":"","sources":["../../../src/core/cache/cache-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AA6DnF,wBAAsB,gBAAgB,CACpC,MAAM,SAAS,gBAAgB,CAAC,MAAM,CAAC,EACvC,KAAK,SAAS,eAAe,EAE7B,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,EACpC,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CA6J5B"}
|
|
@@ -8,9 +8,10 @@ function isCacheable(options) {
|
|
|
8
8
|
return ttl > 0 || stale > 0;
|
|
9
9
|
}
|
|
10
10
|
function deriveTags(builder) {
|
|
11
|
+
const queryNode = builder.toQueryNode();
|
|
11
12
|
const tags = new Set();
|
|
12
|
-
tags.add(builder.getTableName());
|
|
13
|
-
const joins =
|
|
13
|
+
tags.add(queryNode.from?.kind === 'table' ? queryNode.from.name : builder.getTableName());
|
|
14
|
+
const joins = queryNode.joins || [];
|
|
14
15
|
joins.forEach(join => tags.add(join.table));
|
|
15
16
|
return Array.from(tags);
|
|
16
17
|
}
|
|
@@ -49,11 +50,12 @@ export async function executeWithCache(builder, options) {
|
|
|
49
50
|
const renderSql = adapter.render ? adapter.render(sql, parameters) : substituteParameters(sql, parameters);
|
|
50
51
|
const tableName = builder.getTableName();
|
|
51
52
|
const namespace = mergedOptions.namespace || runtime.namespace;
|
|
53
|
+
const queryNode = builder.toQueryNode();
|
|
52
54
|
const key = mergedOptions.key || computeCacheKey({
|
|
53
55
|
namespace,
|
|
54
56
|
sql,
|
|
55
57
|
parameters,
|
|
56
|
-
settings:
|
|
58
|
+
settings: queryNode.settings,
|
|
57
59
|
version: runtime.versionTag,
|
|
58
60
|
tableName
|
|
59
61
|
});
|
|
@@ -17,20 +17,20 @@ type ClickHouseClient = NodeClickHouseClient | WebClickHouseClient;
|
|
|
17
17
|
* // Method 1: Manual injection (required for browser environments)
|
|
18
18
|
* import { createClient } from '@clickhouse/client-web';
|
|
19
19
|
* const client = createClient({
|
|
20
|
-
*
|
|
20
|
+
* url: 'http://localhost:8123',
|
|
21
21
|
* username: 'default',
|
|
22
22
|
* password: 'password'
|
|
23
23
|
* });
|
|
24
24
|
*
|
|
25
25
|
* ClickHouseConnection.initialize({
|
|
26
|
-
*
|
|
26
|
+
* url: 'http://localhost:8123',
|
|
27
27
|
* database: 'my_database',
|
|
28
28
|
* client // Explicitly provide the client
|
|
29
29
|
* });
|
|
30
30
|
*
|
|
31
31
|
* // Method 2: Auto-detection (Node.js environments only)
|
|
32
32
|
* ClickHouseConnection.initialize({
|
|
33
|
-
*
|
|
33
|
+
* url: 'http://localhost:8123',
|
|
34
34
|
* username: 'default',
|
|
35
35
|
* password: 'password',
|
|
36
36
|
* database: 'my_database'
|
|
@@ -71,12 +71,12 @@ export declare class ClickHouseConnection {
|
|
|
71
71
|
* ```typescript
|
|
72
72
|
* // Manual injection (required for browser environments)
|
|
73
73
|
* import { createClient } from '@clickhouse/client-web';
|
|
74
|
-
* const client = createClient({
|
|
75
|
-
* ClickHouseConnection.initialize({
|
|
74
|
+
* const client = createClient({ url: 'http://localhost:8123' });
|
|
75
|
+
* ClickHouseConnection.initialize({ url: 'http://localhost:8123', client });
|
|
76
76
|
*
|
|
77
77
|
* // Auto-detection (Node.js environments only)
|
|
78
78
|
* ClickHouseConnection.initialize({
|
|
79
|
-
*
|
|
79
|
+
* url: 'http://localhost:8123',
|
|
80
80
|
* username: 'default',
|
|
81
81
|
* password: 'password',
|
|
82
82
|
* database: 'my_database'
|
package/dist/core/connection.js
CHANGED
|
@@ -21,8 +21,8 @@ function getClickHouseClientSync() {
|
|
|
21
21
|
'Please use manual injection by providing a client instance:\n\n' +
|
|
22
22
|
'```typescript\n' +
|
|
23
23
|
'import { createClient } from \'@clickhouse/client-web\';\n' +
|
|
24
|
-
'const client = createClient({
|
|
25
|
-
'ClickHouseConnection.initialize({
|
|
24
|
+
'const client = createClient({ url: \'http://localhost:8123\' });\n' +
|
|
25
|
+
'ClickHouseConnection.initialize({ url: \'http://localhost:8123\', client });\n' +
|
|
26
26
|
'```\n\n' +
|
|
27
27
|
'This is required because browser environments cannot use require() to load modules.');
|
|
28
28
|
}
|
|
@@ -40,20 +40,20 @@ function getClickHouseClientSync() {
|
|
|
40
40
|
* // Method 1: Manual injection (required for browser environments)
|
|
41
41
|
* import { createClient } from '@clickhouse/client-web';
|
|
42
42
|
* const client = createClient({
|
|
43
|
-
*
|
|
43
|
+
* url: 'http://localhost:8123',
|
|
44
44
|
* username: 'default',
|
|
45
45
|
* password: 'password'
|
|
46
46
|
* });
|
|
47
47
|
*
|
|
48
48
|
* ClickHouseConnection.initialize({
|
|
49
|
-
*
|
|
49
|
+
* url: 'http://localhost:8123',
|
|
50
50
|
* database: 'my_database',
|
|
51
51
|
* client // Explicitly provide the client
|
|
52
52
|
* });
|
|
53
53
|
*
|
|
54
54
|
* // Method 2: Auto-detection (Node.js environments only)
|
|
55
55
|
* ClickHouseConnection.initialize({
|
|
56
|
-
*
|
|
56
|
+
* url: 'http://localhost:8123',
|
|
57
57
|
* username: 'default',
|
|
58
58
|
* password: 'password',
|
|
59
59
|
* database: 'my_database'
|
|
@@ -94,12 +94,12 @@ export class ClickHouseConnection {
|
|
|
94
94
|
* ```typescript
|
|
95
95
|
* // Manual injection (required for browser environments)
|
|
96
96
|
* import { createClient } from '@clickhouse/client-web';
|
|
97
|
-
* const client = createClient({
|
|
98
|
-
* ClickHouseConnection.initialize({
|
|
97
|
+
* const client = createClient({ url: 'http://localhost:8123' });
|
|
98
|
+
* ClickHouseConnection.initialize({ url: 'http://localhost:8123', client });
|
|
99
99
|
*
|
|
100
100
|
* // Auto-detection (Node.js environments only)
|
|
101
101
|
* ClickHouseConnection.initialize({
|
|
102
|
-
*
|
|
102
|
+
* url: 'http://localhost:8123',
|
|
103
103
|
* username: 'default',
|
|
104
104
|
* password: 'password',
|
|
105
105
|
* database: 'my_database'
|
|
@@ -112,7 +112,7 @@ export class ClickHouseConnection {
|
|
|
112
112
|
this.instance = config.client;
|
|
113
113
|
return ClickHouseConnection;
|
|
114
114
|
}
|
|
115
|
-
// Otherwise, auto-detect the client
|
|
115
|
+
// Otherwise, auto-detect the client using the provided ClickHouse connection config.
|
|
116
116
|
this.clientModule = getClickHouseClientSync();
|
|
117
117
|
this.instance = this.clientModule.createClient(config);
|
|
118
118
|
return ClickHouseConnection;
|
|
@@ -114,7 +114,7 @@ export class CrossFilter {
|
|
|
114
114
|
* Type guard to check if an item is a FilterGroup.
|
|
115
115
|
*/
|
|
116
116
|
isGroup(item) {
|
|
117
|
-
return
|
|
117
|
+
return 'conditions' in item;
|
|
118
118
|
}
|
|
119
119
|
/**
|
|
120
120
|
* Creates a filter for top N records by a value column
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CompiledQuery, SelectQueryNode } from '../../types/index.js';
|
|
2
2
|
import type { CompileQueryContext, SqlDialect } from './sql-dialect.js';
|
|
3
3
|
export declare class ClickHouseDialect implements SqlDialect {
|
|
4
4
|
readonly name = "clickhouse";
|
|
5
5
|
private formatter;
|
|
6
|
-
compileQuery(
|
|
6
|
+
compileQuery(query: SelectQueryNode<any, any>, context: CompileQueryContext): CompiledQuery;
|
|
7
7
|
formatTimeInterval(column: string, interval: string, method: string): string;
|
|
8
8
|
formatSettings(settings: Record<string, unknown>): string;
|
|
9
9
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clickhouse-dialect.d.ts","sourceRoot":"","sources":["../../../src/core/dialects/clickhouse-dialect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"clickhouse-dialect.d.ts","sourceRoot":"","sources":["../../../src/core/dialects/clickhouse-dialect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAExE,qBAAa,iBAAkB,YAAW,UAAU;IAClD,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,OAAO,CAAC,SAAS,CAAsB;IAEvC,YAAY,CAAC,KAAK,EAAE,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,mBAAmB,GAAG,aAAa;IA6D3F,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM;IAQ5E,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM;CAK1D"}
|
|
@@ -2,36 +2,53 @@ import { SQLFormatter } from '../formatters/sql-formatter.js';
|
|
|
2
2
|
export class ClickHouseDialect {
|
|
3
3
|
name = 'clickhouse';
|
|
4
4
|
formatter = new SQLFormatter();
|
|
5
|
-
compileQuery(
|
|
5
|
+
compileQuery(query, context) {
|
|
6
6
|
const parts = [];
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const parameters = [];
|
|
8
|
+
if (query.ctes?.length) {
|
|
9
|
+
parts.push(`WITH ${this.formatter.formatCtes(query)}`);
|
|
9
10
|
}
|
|
10
|
-
parts.push(`SELECT ${this.formatter.formatSelect(
|
|
11
|
-
parts.push(`FROM ${context.tableName}`);
|
|
12
|
-
if (
|
|
13
|
-
parts.push(this.formatter.
|
|
11
|
+
parts.push(`SELECT ${this.formatter.formatSelect(query)}`);
|
|
12
|
+
parts.push(`FROM ${this.formatter.formatFrom(query.from ?? { kind: 'table', name: context.tableName })}`);
|
|
13
|
+
if (query.arrayJoins?.length) {
|
|
14
|
+
parts.push(this.formatter.formatArrayJoins(query));
|
|
14
15
|
}
|
|
15
|
-
if (
|
|
16
|
-
parts.push(
|
|
16
|
+
if (query.joins?.length) {
|
|
17
|
+
parts.push(this.formatter.formatJoins(query));
|
|
17
18
|
}
|
|
18
|
-
if (
|
|
19
|
-
|
|
19
|
+
if (query.prewhere) {
|
|
20
|
+
const compiled = this.formatter.compileExpr(query.prewhere);
|
|
21
|
+
parts.push(`PREWHERE ${compiled.query}`);
|
|
22
|
+
parameters.push(...compiled.parameters);
|
|
20
23
|
}
|
|
21
|
-
if (
|
|
22
|
-
|
|
24
|
+
if (query.where) {
|
|
25
|
+
const compiled = this.formatter.compileExpr(query.where);
|
|
26
|
+
parts.push(`WHERE ${compiled.query}`);
|
|
27
|
+
parameters.push(...compiled.parameters);
|
|
23
28
|
}
|
|
24
|
-
if (
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
.join(', ');
|
|
28
|
-
parts.push(`ORDER BY ${orderBy}`);
|
|
29
|
+
if (query.groupBy?.length) {
|
|
30
|
+
const groupByClause = `GROUP BY ${this.formatter.formatGroupBy(query)}`;
|
|
31
|
+
parts.push(query.withTotals ? `${groupByClause} WITH TOTALS` : groupByClause);
|
|
29
32
|
}
|
|
30
|
-
if (
|
|
31
|
-
const
|
|
32
|
-
parts.push(`
|
|
33
|
+
if (query.having?.length) {
|
|
34
|
+
const compiled = this.formatter.compileHaving(query);
|
|
35
|
+
parts.push(`HAVING ${compiled.query}`);
|
|
36
|
+
parameters.push(...compiled.parameters);
|
|
33
37
|
}
|
|
34
|
-
|
|
38
|
+
if (query.orderBy?.length) {
|
|
39
|
+
parts.push(`ORDER BY ${this.formatter.formatOrderBy(query)}`);
|
|
40
|
+
}
|
|
41
|
+
if (query.limitBy) {
|
|
42
|
+
parts.push(`LIMIT ${this.formatter.formatLimitBy(query)}`);
|
|
43
|
+
}
|
|
44
|
+
if (query.limit) {
|
|
45
|
+
const offsetClause = query.offset ? `OFFSET ${query.offset}` : '';
|
|
46
|
+
parts.push(`LIMIT ${query.limit} ${offsetClause}`);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
query: parts.join(' ').trim(),
|
|
50
|
+
parameters,
|
|
51
|
+
};
|
|
35
52
|
}
|
|
36
53
|
formatTimeInterval(column, interval, method) {
|
|
37
54
|
if (method === 'toStartOfInterval') {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CompiledQuery, SelectQueryNode } from '../../types/index.js';
|
|
2
2
|
export interface CompileQueryContext {
|
|
3
3
|
tableName: string;
|
|
4
4
|
}
|
|
5
5
|
export interface SqlDialect {
|
|
6
6
|
readonly name: string;
|
|
7
|
-
compileQuery(
|
|
7
|
+
compileQuery(query: SelectQueryNode<any, any>, context: CompileQueryContext): CompiledQuery;
|
|
8
8
|
formatTimeInterval(column: string, interval: string, method: string): string;
|
|
9
9
|
formatSettings(settings: Record<string, unknown>): string;
|
|
10
10
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql-dialect.d.ts","sourceRoot":"","sources":["../../../src/core/dialects/sql-dialect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"sql-dialect.d.ts","sourceRoot":"","sources":["../../../src/core/dialects/sql-dialect.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE3E,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,KAAK,EAAE,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,mBAAmB,GAAG,aAAa,CAAC;IAC5F,kBAAkB,CAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,GACb,MAAM,CAAC;IACV,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC;CAC3D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auto-client.d.ts","sourceRoot":"","sources":["../../../src/core/env/auto-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,KAAK,gBAAgB,GAAG,cAAc,oBAAoB,CAAC,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC;
|
|
1
|
+
{"version":3,"file":"auto-client.d.ts","sourceRoot":"","sources":["../../../src/core/env/auto-client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,KAAK,gBAAgB,GAAG,cAAc,oBAAoB,CAAC,CAAC;AAE5D,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,gBAAgB,CAAC,cAAc,CAAC,CAAC;IAC/C,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC;AAKD,wBAAgB,mBAAmB,IAAI,gBAAgB,CAoBtD"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { createRequire } from 'module';
|
|
2
2
|
let cachedModule;
|
|
3
|
+
const nodeRequire = createRequire(import.meta.url);
|
|
3
4
|
export function getAutoClientModule() {
|
|
4
5
|
if (!cachedModule) {
|
|
5
6
|
try {
|
|
6
|
-
const nodeRequire = createRequire(`${process.cwd()}/noop.js`);
|
|
7
7
|
const clientModule = nodeRequire('@clickhouse/client');
|
|
8
8
|
const settings = clientModule.ClickHouseSettings;
|
|
9
9
|
cachedModule = {
|
|
@@ -1,96 +1,39 @@
|
|
|
1
1
|
import type { BuilderState, SchemaDefinition } from '../types/builder-state.js';
|
|
2
2
|
import { QueryBuilder } from '../query-builder.js';
|
|
3
|
+
import type { SelectQueryNode, SelectionNode } from '../../types/index.js';
|
|
3
4
|
export declare class AggregationFeature<Schema extends SchemaDefinition<Schema>, State extends BuilderState<Schema, string, any, keyof Schema, Partial<Record<string, keyof Schema>>>> {
|
|
4
5
|
private builder;
|
|
6
|
+
private static readonly TRAILING_ALIAS_PATTERN;
|
|
7
|
+
private static readonly LEADING_AGGREGATE_CALL_PATTERN;
|
|
5
8
|
constructor(builder: QueryBuilder<Schema, State>);
|
|
9
|
+
private stripTrailingAlias;
|
|
10
|
+
private isAggregateSelection;
|
|
11
|
+
private createAggregateSelection;
|
|
12
|
+
private shouldInferGroupByFromSelection;
|
|
13
|
+
private inferGroupBySelections;
|
|
6
14
|
private createAggregation;
|
|
7
|
-
sum(column: string, alias: string):
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
15
|
+
sum(column: string, alias: string): SelectQueryNode<State["output"], Schema>;
|
|
16
|
+
count(column: string, alias: string): SelectQueryNode<State["output"], Schema>;
|
|
17
|
+
avg(column: string, alias: string): SelectQueryNode<State["output"], Schema>;
|
|
18
|
+
min(column: string, alias: string): SelectQueryNode<State["output"], Schema>;
|
|
19
|
+
max(column: string, alias: string): SelectQueryNode<State["output"], Schema>;
|
|
20
|
+
countDistinct(column: string, alias: string): {
|
|
21
|
+
select: SelectionNode[];
|
|
22
|
+
kind: "select-query";
|
|
23
|
+
from?: import("../../types/base.js").SourceNode;
|
|
24
|
+
arrayJoins?: import("../../types/base.js").ArrayJoinNode[];
|
|
25
|
+
prewhere?: import("../../types/base.js").ExprNode;
|
|
26
|
+
where?: import("../../types/base.js").ExprNode;
|
|
27
|
+
groupBy?: import("../../types/base.js").GroupByItemNode[];
|
|
28
|
+
withTotals?: boolean;
|
|
29
|
+
having?: import("../../types/base.js").HavingNode[];
|
|
30
|
+
limitBy?: import("../../types/base.js").LimitByNode;
|
|
12
31
|
limit?: number;
|
|
13
32
|
offset?: number;
|
|
14
33
|
distinct?: boolean;
|
|
15
|
-
orderBy?:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}[] | undefined;
|
|
19
|
-
joins?: import("../../types/base.js").JoinClause[];
|
|
20
|
-
parameters?: any[];
|
|
21
|
-
ctes?: string[];
|
|
22
|
-
unionQueries?: string[];
|
|
23
|
-
settings?: import("@clickhouse/client-common").ClickHouseSettings;
|
|
24
|
-
};
|
|
25
|
-
count(column: string, alias: string): {
|
|
26
|
-
select: string[];
|
|
27
|
-
where?: import("../../types/base.js").WhereCondition[];
|
|
28
|
-
groupBy?: string[];
|
|
29
|
-
having?: string[];
|
|
30
|
-
limit?: number;
|
|
31
|
-
offset?: number;
|
|
32
|
-
distinct?: boolean;
|
|
33
|
-
orderBy?: {
|
|
34
|
-
column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
|
|
35
|
-
direction: import("../../index.js").OrderDirection;
|
|
36
|
-
}[] | undefined;
|
|
37
|
-
joins?: import("../../types/base.js").JoinClause[];
|
|
38
|
-
parameters?: any[];
|
|
39
|
-
ctes?: string[];
|
|
40
|
-
unionQueries?: string[];
|
|
41
|
-
settings?: import("@clickhouse/client-common").ClickHouseSettings;
|
|
42
|
-
};
|
|
43
|
-
avg(column: string, alias: string): {
|
|
44
|
-
select: string[];
|
|
45
|
-
where?: import("../../types/base.js").WhereCondition[];
|
|
46
|
-
groupBy?: string[];
|
|
47
|
-
having?: string[];
|
|
48
|
-
limit?: number;
|
|
49
|
-
offset?: number;
|
|
50
|
-
distinct?: boolean;
|
|
51
|
-
orderBy?: {
|
|
52
|
-
column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
|
|
53
|
-
direction: import("../../index.js").OrderDirection;
|
|
54
|
-
}[] | undefined;
|
|
55
|
-
joins?: import("../../types/base.js").JoinClause[];
|
|
56
|
-
parameters?: any[];
|
|
57
|
-
ctes?: string[];
|
|
58
|
-
unionQueries?: string[];
|
|
59
|
-
settings?: import("@clickhouse/client-common").ClickHouseSettings;
|
|
60
|
-
};
|
|
61
|
-
min(column: string, alias: string): {
|
|
62
|
-
select: string[];
|
|
63
|
-
where?: import("../../types/base.js").WhereCondition[];
|
|
64
|
-
groupBy?: string[];
|
|
65
|
-
having?: string[];
|
|
66
|
-
limit?: number;
|
|
67
|
-
offset?: number;
|
|
68
|
-
distinct?: boolean;
|
|
69
|
-
orderBy?: {
|
|
70
|
-
column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
|
|
71
|
-
direction: import("../../index.js").OrderDirection;
|
|
72
|
-
}[] | undefined;
|
|
73
|
-
joins?: import("../../types/base.js").JoinClause[];
|
|
74
|
-
parameters?: any[];
|
|
75
|
-
ctes?: string[];
|
|
76
|
-
unionQueries?: string[];
|
|
77
|
-
settings?: import("@clickhouse/client-common").ClickHouseSettings;
|
|
78
|
-
};
|
|
79
|
-
max(column: string, alias: string): {
|
|
80
|
-
select: string[];
|
|
81
|
-
where?: import("../../types/base.js").WhereCondition[];
|
|
82
|
-
groupBy?: string[];
|
|
83
|
-
having?: string[];
|
|
84
|
-
limit?: number;
|
|
85
|
-
offset?: number;
|
|
86
|
-
distinct?: boolean;
|
|
87
|
-
orderBy?: {
|
|
88
|
-
column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
|
|
89
|
-
direction: import("../../index.js").OrderDirection;
|
|
90
|
-
}[] | undefined;
|
|
91
|
-
joins?: import("../../types/base.js").JoinClause[];
|
|
92
|
-
parameters?: any[];
|
|
93
|
-
ctes?: string[];
|
|
34
|
+
orderBy?: import("../../types/base.js").OrderByItemNode[];
|
|
35
|
+
joins?: import("../../types/base.js").JoinNode[];
|
|
36
|
+
ctes?: import("../../types/base.js").CteNode[];
|
|
94
37
|
unionQueries?: string[];
|
|
95
38
|
settings?: import("@clickhouse/client-common").ClickHouseSettings;
|
|
96
39
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aggregations.d.ts","sourceRoot":"","sources":["../../../src/core/features/aggregations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"aggregations.d.ts","sourceRoot":"","sources":["../../../src/core/features/aggregations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE3E,qBAAa,kBAAkB,CAC7B,MAAM,SAAS,gBAAgB,CAAC,MAAM,CAAC,EACvC,KAAK,SAAS,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,MAAM,CAAC,CAAC,CAAC;IAKxF,OAAO,CAAC,OAAO;IAH3B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAsC;IACpF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,8BAA8B,CAAoC;gBAEtE,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC;IAExD,OAAO,CAAC,kBAAkB;IAI1B,OAAO,CAAC,oBAAoB;IAK5B,OAAO,CAAC,wBAAwB;IAQhC,OAAO,CAAC,+BAA+B;IAYvC,OAAO,CAAC,sBAAsB;IAa9B,OAAO,CAAC,iBAAiB;IAsBzB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAIjC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAInC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAIjC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAIjC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAIjC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;CAiB5C"}
|
|
@@ -1,21 +1,58 @@
|
|
|
1
1
|
export class AggregationFeature {
|
|
2
2
|
builder;
|
|
3
|
+
static TRAILING_ALIAS_PATTERN = /\s+AS\s+[A-Za-z_][A-Za-z0-9_]*$/i;
|
|
4
|
+
static LEADING_AGGREGATE_CALL_PATTERN = /^(COUNT|SUM|AVG|MIN|MAX)\s*\(/i;
|
|
3
5
|
constructor(builder) {
|
|
4
6
|
this.builder = builder;
|
|
5
7
|
}
|
|
8
|
+
stripTrailingAlias(selection) {
|
|
9
|
+
return selection.replace(AggregationFeature.TRAILING_ALIAS_PATTERN, '').trim();
|
|
10
|
+
}
|
|
11
|
+
isAggregateSelection(selection) {
|
|
12
|
+
const expressionWithoutAlias = this.stripTrailingAlias(selection);
|
|
13
|
+
return AggregationFeature.LEADING_AGGREGATE_CALL_PATTERN.test(expressionWithoutAlias);
|
|
14
|
+
}
|
|
15
|
+
createAggregateSelection(selection) {
|
|
16
|
+
return {
|
|
17
|
+
kind: 'selection',
|
|
18
|
+
selection,
|
|
19
|
+
isAggregate: true,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
shouldInferGroupByFromSelection(item) {
|
|
23
|
+
if (item.selection === '*') {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
if (item.isAggregate === true) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
return !this.isAggregateSelection(item.selection);
|
|
30
|
+
}
|
|
31
|
+
inferGroupBySelections(select) {
|
|
32
|
+
return select
|
|
33
|
+
.filter(item => this.shouldInferGroupByFromSelection(item))
|
|
34
|
+
.map(item => item.selection)
|
|
35
|
+
.map(selection => {
|
|
36
|
+
const aliasMatch = selection.match(/\s+AS\s+([A-Za-z_][A-Za-z0-9_]*)$/i);
|
|
37
|
+
return {
|
|
38
|
+
kind: 'group-by-item',
|
|
39
|
+
expression: aliasMatch ? aliasMatch[1] : selection,
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
}
|
|
6
43
|
createAggregation(column, fn, alias) {
|
|
7
44
|
const aggregationSQL = `${fn}(${column}) AS ${alias}`;
|
|
8
|
-
const
|
|
9
|
-
if (
|
|
45
|
+
const query = this.builder.getQueryNode();
|
|
46
|
+
if (query.select) {
|
|
10
47
|
return {
|
|
11
|
-
...
|
|
12
|
-
select: [...
|
|
13
|
-
groupBy:
|
|
48
|
+
...query,
|
|
49
|
+
select: [...query.select, this.createAggregateSelection(aggregationSQL)],
|
|
50
|
+
groupBy: query.groupBy || this.inferGroupBySelections(query.select)
|
|
14
51
|
};
|
|
15
52
|
}
|
|
16
53
|
return {
|
|
17
|
-
...
|
|
18
|
-
select: [aggregationSQL]
|
|
54
|
+
...query,
|
|
55
|
+
select: [this.createAggregateSelection(aggregationSQL)]
|
|
19
56
|
};
|
|
20
57
|
}
|
|
21
58
|
sum(column, alias) {
|
|
@@ -33,4 +70,19 @@ export class AggregationFeature {
|
|
|
33
70
|
max(column, alias) {
|
|
34
71
|
return this.createAggregation(column, 'MAX', alias);
|
|
35
72
|
}
|
|
73
|
+
countDistinct(column, alias) {
|
|
74
|
+
const aggregationSQL = `COUNT(DISTINCT ${column}) AS ${alias}`;
|
|
75
|
+
const query = this.builder.getQueryNode();
|
|
76
|
+
if (query.select) {
|
|
77
|
+
return {
|
|
78
|
+
...query,
|
|
79
|
+
select: [...query.select, this.createAggregateSelection(aggregationSQL)],
|
|
80
|
+
groupBy: query.groupBy || this.inferGroupBySelections(query.select),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
...query,
|
|
85
|
+
select: [this.createAggregateSelection(aggregationSQL)],
|
|
86
|
+
};
|
|
87
|
+
}
|
|
36
88
|
}
|