@hypequery/clickhouse 0.0.0-canary-20260306132943
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 +201 -0
- package/README-CLI.md +123 -0
- package/README.md +316 -0
- package/dist/cli/bin.js +285 -0
- package/dist/cli/generate-types.d.ts +5 -0
- package/dist/cli/generate-types.js +218 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +2 -0
- package/dist/core/cache/cache-manager.d.ts +4 -0
- package/dist/core/cache/cache-manager.d.ts.map +1 -0
- package/dist/core/cache/cache-manager.js +176 -0
- package/dist/core/cache/controller.d.ts +15 -0
- package/dist/core/cache/controller.d.ts.map +1 -0
- package/dist/core/cache/controller.js +58 -0
- package/dist/core/cache/key.d.ts +11 -0
- package/dist/core/cache/key.d.ts.map +1 -0
- package/dist/core/cache/key.js +26 -0
- package/dist/core/cache/providers/memory-lru.d.ts +31 -0
- package/dist/core/cache/providers/memory-lru.d.ts.map +1 -0
- package/dist/core/cache/providers/memory-lru.js +156 -0
- package/dist/core/cache/providers/noop.d.ts +7 -0
- package/dist/core/cache/providers/noop.d.ts.map +1 -0
- package/dist/core/cache/providers/noop.js +11 -0
- package/dist/core/cache/runtime-context.d.ts +30 -0
- package/dist/core/cache/runtime-context.d.ts.map +1 -0
- package/dist/core/cache/runtime-context.js +58 -0
- package/dist/core/cache/serialization.d.ts +6 -0
- package/dist/core/cache/serialization.d.ts.map +1 -0
- package/dist/core/cache/serialization.js +166 -0
- package/dist/core/cache/types.d.ts +52 -0
- package/dist/core/cache/types.d.ts.map +1 -0
- package/dist/core/cache/types.js +1 -0
- package/dist/core/cache/utils.d.ts +9 -0
- package/dist/core/cache/utils.d.ts.map +1 -0
- package/dist/core/cache/utils.js +30 -0
- package/dist/core/connection.d.ts +112 -0
- package/dist/core/connection.d.ts.map +1 -0
- package/dist/core/connection.js +150 -0
- package/dist/core/cross-filter.d.ts +73 -0
- package/dist/core/cross-filter.d.ts.map +1 -0
- package/dist/core/cross-filter.js +142 -0
- package/dist/core/env/auto-client.browser.d.ts +3 -0
- package/dist/core/env/auto-client.browser.d.ts.map +1 -0
- package/dist/core/env/auto-client.browser.js +3 -0
- package/dist/core/env/auto-client.d.ts +9 -0
- package/dist/core/env/auto-client.d.ts.map +1 -0
- package/dist/core/env/auto-client.js +21 -0
- package/dist/core/features/aggregations.d.ts +98 -0
- package/dist/core/features/aggregations.d.ts.map +1 -0
- package/dist/core/features/aggregations.js +36 -0
- package/dist/core/features/analytics.d.ts +81 -0
- package/dist/core/features/analytics.d.ts.map +1 -0
- package/dist/core/features/analytics.js +45 -0
- package/dist/core/features/cross-filtering.d.ts +11 -0
- package/dist/core/features/cross-filtering.d.ts.map +1 -0
- package/dist/core/features/cross-filtering.js +90 -0
- package/dist/core/features/executor.d.ts +21 -0
- package/dist/core/features/executor.d.ts.map +1 -0
- package/dist/core/features/executor.js +146 -0
- package/dist/core/features/filtering.d.ts +99 -0
- package/dist/core/features/filtering.d.ts.map +1 -0
- package/dist/core/features/filtering.js +118 -0
- package/dist/core/features/joins.d.ts +26 -0
- package/dist/core/features/joins.d.ts.map +1 -0
- package/dist/core/features/joins.js +17 -0
- package/dist/core/features/query-modifiers.d.ts +116 -0
- package/dist/core/features/query-modifiers.d.ts.map +1 -0
- package/dist/core/features/query-modifiers.js +51 -0
- package/dist/core/formatters/sql-formatter.d.ts +9 -0
- package/dist/core/formatters/sql-formatter.d.ts.map +1 -0
- package/dist/core/formatters/sql-formatter.js +131 -0
- package/dist/core/join-relationships.d.ts +51 -0
- package/dist/core/join-relationships.d.ts.map +1 -0
- package/dist/core/join-relationships.js +54 -0
- package/dist/core/query-builder.d.ts +236 -0
- package/dist/core/query-builder.d.ts.map +1 -0
- package/dist/core/query-builder.js +495 -0
- package/dist/core/tests/index.d.ts +2 -0
- package/dist/core/tests/index.d.ts.map +1 -0
- package/dist/core/tests/index.js +1 -0
- package/dist/core/tests/integration/setup.d.ts +48 -0
- package/dist/core/tests/integration/setup.d.ts.map +1 -0
- package/dist/core/tests/integration/setup.js +349 -0
- package/dist/core/tests/integration/test-config.d.ts +15 -0
- package/dist/core/tests/integration/test-config.d.ts.map +1 -0
- package/dist/core/tests/integration/test-config.js +14 -0
- package/dist/core/tests/integration/test-data.json +190 -0
- package/dist/core/tests/test-utils.d.ts +44 -0
- package/dist/core/tests/test-utils.d.ts.map +1 -0
- package/dist/core/tests/test-utils.js +65 -0
- package/dist/core/types/builder-state.d.ts +27 -0
- package/dist/core/types/builder-state.d.ts.map +1 -0
- package/dist/core/types/builder-state.js +1 -0
- package/dist/core/types/select-types.d.ts +33 -0
- package/dist/core/types/select-types.d.ts.map +1 -0
- package/dist/core/types/select-types.js +1 -0
- package/dist/core/types/type-helpers.d.ts +5 -0
- package/dist/core/types/type-helpers.d.ts.map +1 -0
- package/dist/core/types/type-helpers.js +1 -0
- package/dist/core/utils/logger.d.ts +43 -0
- package/dist/core/utils/logger.d.ts.map +1 -0
- package/dist/core/utils/logger.js +104 -0
- package/dist/core/utils/predicate-builder.d.ts +33 -0
- package/dist/core/utils/predicate-builder.d.ts.map +1 -0
- package/dist/core/utils/predicate-builder.js +95 -0
- package/dist/core/utils/sql-expressions.d.ts +77 -0
- package/dist/core/utils/sql-expressions.d.ts.map +1 -0
- package/dist/core/utils/sql-expressions.js +54 -0
- package/dist/core/utils/streaming-helpers.d.ts +2 -0
- package/dist/core/utils/streaming-helpers.d.ts.map +1 -0
- package/dist/core/utils/streaming-helpers.js +137 -0
- package/dist/core/utils.d.ts +3 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/core/utils.js +29 -0
- package/dist/core/validators/filter-validator.d.ts +9 -0
- package/dist/core/validators/filter-validator.d.ts.map +1 -0
- package/dist/core/validators/filter-validator.js +19 -0
- package/dist/core/validators/value-validator.d.ts +7 -0
- package/dist/core/validators/value-validator.d.ts.map +1 -0
- package/dist/core/validators/value-validator.js +47 -0
- package/dist/formatters/index.d.ts +2 -0
- package/dist/formatters/index.d.ts.map +1 -0
- package/dist/formatters/index.js +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/types/base.d.ts +50 -0
- package/dist/types/base.d.ts.map +1 -0
- package/dist/types/base.js +1 -0
- package/dist/types/clickhouse-types.d.ts +17 -0
- package/dist/types/clickhouse-types.d.ts.map +1 -0
- package/dist/types/clickhouse-types.js +1 -0
- package/dist/types/filters.d.ts +53 -0
- package/dist/types/filters.d.ts.map +1 -0
- package/dist/types/filters.js +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/schema.d.ts +19 -0
- package/dist/types/schema.d.ts.map +1 -0
- package/dist/types/schema.js +1 -0
- package/package.json +90 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { FilterValidator } from './validators/filter-validator.js';
|
|
2
|
+
/**
|
|
3
|
+
* A type-safe filter builder supporting both simple conditions and complex nested groups.
|
|
4
|
+
* @template Schema - The full database schema type
|
|
5
|
+
* @template TableName - The specific table being filtered
|
|
6
|
+
*/
|
|
7
|
+
export class CrossFilter {
|
|
8
|
+
// Root group holding filter conditions or nested groups, defaulting to an implicit AND.
|
|
9
|
+
rootGroup;
|
|
10
|
+
schema;
|
|
11
|
+
targetTable;
|
|
12
|
+
constructor(schema, tableName) {
|
|
13
|
+
this.schema = schema;
|
|
14
|
+
this.targetTable = tableName;
|
|
15
|
+
this.rootGroup = { operator: 'AND', conditions: [] };
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Adds a single filter condition to the root group with an implicit AND conjunction.
|
|
19
|
+
* Performs type-safe validation if a schema is provided.
|
|
20
|
+
*/
|
|
21
|
+
add(condition) {
|
|
22
|
+
if (this.schema) {
|
|
23
|
+
const columnType = this.getColumnType(String(condition.column));
|
|
24
|
+
this.validateValueType(columnType, condition.value, String(condition.column), condition.operator);
|
|
25
|
+
}
|
|
26
|
+
// Convert Date objects to ISO strings for ClickHouse
|
|
27
|
+
let value = condition.value;
|
|
28
|
+
if (Array.isArray(value)) {
|
|
29
|
+
value = value.map(v => v instanceof Date ? v.toISOString() : v);
|
|
30
|
+
}
|
|
31
|
+
else if (value instanceof Date) {
|
|
32
|
+
value = value.toISOString();
|
|
33
|
+
}
|
|
34
|
+
this.rootGroup.conditions.push({
|
|
35
|
+
...condition,
|
|
36
|
+
value
|
|
37
|
+
});
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Adds multiple filter conditions to the root group.
|
|
42
|
+
*/
|
|
43
|
+
addMultiple(conditions) {
|
|
44
|
+
if (this.schema) {
|
|
45
|
+
this.validateGroup(conditions);
|
|
46
|
+
}
|
|
47
|
+
this.rootGroup.conditions.push(...conditions);
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Adds a nested group of filter conditions to the root group using the specified logical operator.
|
|
52
|
+
* @param groupConditions - Array of filter conditions or nested groups to be grouped together.
|
|
53
|
+
* @param operator - Logical operator ('AND' or 'OR') to combine the conditions in the group.
|
|
54
|
+
*/
|
|
55
|
+
addGroup(groupConditions, operator) {
|
|
56
|
+
if (this.schema) {
|
|
57
|
+
this.validateGroup(groupConditions);
|
|
58
|
+
}
|
|
59
|
+
const group = {
|
|
60
|
+
operator,
|
|
61
|
+
conditions: groupConditions
|
|
62
|
+
};
|
|
63
|
+
this.rootGroup.conditions.push(group);
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Returns the current filter tree representing all conditions and groups.
|
|
68
|
+
*/
|
|
69
|
+
getConditions() {
|
|
70
|
+
return this.rootGroup;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Looks up a column's type from the schema.
|
|
74
|
+
* Defaults to 'String' if no schema is provided.
|
|
75
|
+
* @param column - The column name as a string.
|
|
76
|
+
*/
|
|
77
|
+
getColumnType(column) {
|
|
78
|
+
if (!this.schema) {
|
|
79
|
+
return 'String';
|
|
80
|
+
}
|
|
81
|
+
const tables = this.targetTable ? [this.targetTable] : Object.keys(this.schema);
|
|
82
|
+
for (const table of tables) {
|
|
83
|
+
const tableSchema = this.schema[table];
|
|
84
|
+
if (column in tableSchema) {
|
|
85
|
+
const columnKey = column;
|
|
86
|
+
return tableSchema[columnKey];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
throw new Error(`Column '${column}' not found in schema`);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Validates the value of a filter condition against its expected column type.
|
|
93
|
+
*/
|
|
94
|
+
validateValueType(columnType, value, columnName, operator) {
|
|
95
|
+
FilterValidator.validateFilterCondition({ column: columnName, operator, value }, columnType, { allowNull: true } // CrossFilter allows null values
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Recursively validates an array of filter conditions and nested groups.
|
|
100
|
+
*/
|
|
101
|
+
validateGroup(conditions) {
|
|
102
|
+
for (const condition of conditions) {
|
|
103
|
+
if (this.isGroup(condition)) {
|
|
104
|
+
// Recursively validate nested groups
|
|
105
|
+
this.validateGroup(condition.conditions);
|
|
106
|
+
}
|
|
107
|
+
else {
|
|
108
|
+
const columnType = this.getColumnType(String(condition.column));
|
|
109
|
+
this.validateValueType(columnType, condition.value, String(condition.column), condition.operator);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Type guard to check if an item is a FilterGroup.
|
|
115
|
+
*/
|
|
116
|
+
isGroup(item) {
|
|
117
|
+
return typeof item.conditions !== 'undefined';
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Creates a filter for top N records by a value column
|
|
121
|
+
* @param valueColumn - The column to filter and order by
|
|
122
|
+
* @param n - Number of records to return
|
|
123
|
+
* @param orderBy - Sort direction, defaults to 'desc'
|
|
124
|
+
*/
|
|
125
|
+
topN(valueColumn, n, orderBy = 'desc') {
|
|
126
|
+
this.add({
|
|
127
|
+
column: valueColumn,
|
|
128
|
+
operator: 'gt',
|
|
129
|
+
value: 0
|
|
130
|
+
});
|
|
131
|
+
// Store limit and order information in the root group's metadata
|
|
132
|
+
this.rootGroup = {
|
|
133
|
+
...this.rootGroup,
|
|
134
|
+
limit: n,
|
|
135
|
+
orderBy: {
|
|
136
|
+
column: valueColumn,
|
|
137
|
+
direction: orderBy.toUpperCase()
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
return this;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auto-client.browser.d.ts","sourceRoot":"","sources":["../../../src/core/env/auto-client.browser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,wBAAgB,mBAAmB,IAAI,gBAAgB,CAEtD"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ClickHouseSettings } from '@clickhouse/client-common';
|
|
2
|
+
type NodeClientModule = typeof import('@clickhouse/client');
|
|
3
|
+
export interface AutoClientModule {
|
|
4
|
+
createClient: NodeClientModule['createClient'];
|
|
5
|
+
ClickHouseSettings?: ClickHouseSettings;
|
|
6
|
+
}
|
|
7
|
+
export declare function getAutoClientModule(): AutoClientModule;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=auto-client.d.ts.map
|
|
@@ -0,0 +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;AAID,wBAAgB,mBAAmB,IAAI,gBAAgB,CAqBtD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
let cachedModule;
|
|
3
|
+
export function getAutoClientModule() {
|
|
4
|
+
if (!cachedModule) {
|
|
5
|
+
try {
|
|
6
|
+
const nodeRequire = createRequire(`${process.cwd()}/noop.js`);
|
|
7
|
+
const clientModule = nodeRequire('@clickhouse/client');
|
|
8
|
+
const settings = clientModule.ClickHouseSettings;
|
|
9
|
+
cachedModule = {
|
|
10
|
+
createClient: clientModule.createClient,
|
|
11
|
+
ClickHouseSettings: settings ?? {}
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
throw new Error('@clickhouse/client is required for Node.js environments.\n\n' +
|
|
16
|
+
'Install with: npm install @clickhouse/client\n\n' +
|
|
17
|
+
'Alternatively, you can provide a client instance directly in the config.client option.', { cause: error instanceof Error ? error : undefined });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return cachedModule;
|
|
21
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import type { BuilderState, SchemaDefinition } from '../types/builder-state.js';
|
|
2
|
+
import { QueryBuilder } from '../query-builder.js';
|
|
3
|
+
export declare class AggregationFeature<Schema extends SchemaDefinition<Schema>, State extends BuilderState<Schema, string, any, keyof Schema, Partial<Record<string, keyof Schema>>>> {
|
|
4
|
+
private builder;
|
|
5
|
+
constructor(builder: QueryBuilder<Schema, State>);
|
|
6
|
+
private createAggregation;
|
|
7
|
+
sum(column: string, alias: string): {
|
|
8
|
+
select: string[];
|
|
9
|
+
where?: import("../../types/base.js").WhereCondition[];
|
|
10
|
+
groupBy?: string[];
|
|
11
|
+
having?: string[];
|
|
12
|
+
limit?: number;
|
|
13
|
+
offset?: number;
|
|
14
|
+
distinct?: boolean;
|
|
15
|
+
orderBy?: {
|
|
16
|
+
column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
|
|
17
|
+
direction: import("../../index.js").OrderDirection;
|
|
18
|
+
}[] | undefined;
|
|
19
|
+
joins?: import("../../types/base.js").JoinClause[];
|
|
20
|
+
parameters?: any[];
|
|
21
|
+
ctes?: string[];
|
|
22
|
+
unionQueries?: string[];
|
|
23
|
+
settings?: string;
|
|
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?: string;
|
|
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?: string;
|
|
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?: string;
|
|
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[];
|
|
94
|
+
unionQueries?: string[];
|
|
95
|
+
settings?: string;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=aggregations.d.ts.map
|
|
@@ -0,0 +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;AAEnD,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;IAExF,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC;IAExD,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;;;;;;;;;;;;;;;;;;CAGlC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export class AggregationFeature {
|
|
2
|
+
builder;
|
|
3
|
+
constructor(builder) {
|
|
4
|
+
this.builder = builder;
|
|
5
|
+
}
|
|
6
|
+
createAggregation(column, fn, alias) {
|
|
7
|
+
const aggregationSQL = `${fn}(${column}) AS ${alias}`;
|
|
8
|
+
const config = this.builder.getConfig();
|
|
9
|
+
if (config.select) {
|
|
10
|
+
return {
|
|
11
|
+
...config,
|
|
12
|
+
select: [...(config.select || []).map(String), aggregationSQL],
|
|
13
|
+
groupBy: (config.select || []).map(String).filter(col => !col.includes(' AS '))
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
...config,
|
|
18
|
+
select: [aggregationSQL]
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
sum(column, alias) {
|
|
22
|
+
return this.createAggregation(column, 'SUM', alias);
|
|
23
|
+
}
|
|
24
|
+
count(column, alias) {
|
|
25
|
+
return this.createAggregation(column, 'COUNT', alias);
|
|
26
|
+
}
|
|
27
|
+
avg(column, alias) {
|
|
28
|
+
return this.createAggregation(column, 'AVG', alias);
|
|
29
|
+
}
|
|
30
|
+
min(column, alias) {
|
|
31
|
+
return this.createAggregation(column, 'MIN', alias);
|
|
32
|
+
}
|
|
33
|
+
max(column, alias) {
|
|
34
|
+
return this.createAggregation(column, 'MAX', alias);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { ClickHouseSettings } from '@clickhouse/client-common';
|
|
2
|
+
import type { AnyBuilderState, BuilderState, SchemaDefinition } from '../types/builder-state.js';
|
|
3
|
+
import { QueryBuilder } from '../query-builder.js';
|
|
4
|
+
import type { PredicateExpression } from '../utils/predicate-builder.js';
|
|
5
|
+
export declare class AnalyticsFeature<Schema extends SchemaDefinition<Schema>, State extends BuilderState<Schema, string, any, keyof Schema, Partial<Record<string, keyof Schema>>>> {
|
|
6
|
+
private builder;
|
|
7
|
+
constructor(builder: QueryBuilder<Schema, State>);
|
|
8
|
+
addCTE(alias: string, subquery: QueryBuilder<any, AnyBuilderState> | string): {
|
|
9
|
+
ctes: string[];
|
|
10
|
+
select?: (string | keyof State["output"])[] | undefined;
|
|
11
|
+
where?: import("../../types/base.js").WhereCondition[];
|
|
12
|
+
groupBy?: string[];
|
|
13
|
+
having?: string[];
|
|
14
|
+
limit?: number;
|
|
15
|
+
offset?: number;
|
|
16
|
+
distinct?: boolean;
|
|
17
|
+
orderBy?: {
|
|
18
|
+
column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
|
|
19
|
+
direction: import("../../index.js").OrderDirection;
|
|
20
|
+
}[] | undefined;
|
|
21
|
+
joins?: import("../../types/base.js").JoinClause[];
|
|
22
|
+
parameters?: any[];
|
|
23
|
+
unionQueries?: string[];
|
|
24
|
+
settings?: string;
|
|
25
|
+
};
|
|
26
|
+
addScalar(alias: string, expression: PredicateExpression): {
|
|
27
|
+
ctes: string[];
|
|
28
|
+
select?: (string | keyof State["output"])[] | undefined;
|
|
29
|
+
where?: import("../../types/base.js").WhereCondition[];
|
|
30
|
+
groupBy?: string[];
|
|
31
|
+
having?: string[];
|
|
32
|
+
limit?: number;
|
|
33
|
+
offset?: number;
|
|
34
|
+
distinct?: boolean;
|
|
35
|
+
orderBy?: {
|
|
36
|
+
column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
|
|
37
|
+
direction: import("../../index.js").OrderDirection;
|
|
38
|
+
}[] | undefined;
|
|
39
|
+
joins?: import("../../types/base.js").JoinClause[];
|
|
40
|
+
parameters?: any[];
|
|
41
|
+
unionQueries?: string[];
|
|
42
|
+
settings?: string;
|
|
43
|
+
};
|
|
44
|
+
addTimeInterval(column: string, interval: string, method: 'toStartOfInterval' | 'toStartOfMinute' | 'toStartOfHour' | 'toStartOfDay' | 'toStartOfWeek' | 'toStartOfMonth' | 'toStartOfQuarter' | 'toStartOfYear'): {
|
|
45
|
+
groupBy: string[];
|
|
46
|
+
select?: (string | keyof State["output"])[] | undefined;
|
|
47
|
+
where?: import("../../types/base.js").WhereCondition[];
|
|
48
|
+
having?: string[];
|
|
49
|
+
limit?: number;
|
|
50
|
+
offset?: number;
|
|
51
|
+
distinct?: boolean;
|
|
52
|
+
orderBy?: {
|
|
53
|
+
column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
|
|
54
|
+
direction: import("../../index.js").OrderDirection;
|
|
55
|
+
}[] | undefined;
|
|
56
|
+
joins?: import("../../types/base.js").JoinClause[];
|
|
57
|
+
parameters?: any[];
|
|
58
|
+
ctes?: string[];
|
|
59
|
+
unionQueries?: string[];
|
|
60
|
+
settings?: string;
|
|
61
|
+
};
|
|
62
|
+
addSettings(opts: ClickHouseSettings): {
|
|
63
|
+
settings: string;
|
|
64
|
+
select?: (string | keyof State["output"])[] | undefined;
|
|
65
|
+
where?: import("../../types/base.js").WhereCondition[];
|
|
66
|
+
groupBy?: string[];
|
|
67
|
+
having?: string[];
|
|
68
|
+
limit?: number;
|
|
69
|
+
offset?: number;
|
|
70
|
+
distinct?: boolean;
|
|
71
|
+
orderBy?: {
|
|
72
|
+
column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
|
|
73
|
+
direction: import("../../index.js").OrderDirection;
|
|
74
|
+
}[] | undefined;
|
|
75
|
+
joins?: import("../../types/base.js").JoinClause[];
|
|
76
|
+
parameters?: any[];
|
|
77
|
+
ctes?: string[];
|
|
78
|
+
unionQueries?: string[];
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=analytics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../../src/core/features/analytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AACjG,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAGzE,qBAAa,gBAAgB,CAC3B,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;IAExF,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC;IAExD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,CAAC,GAAG,EAAE,eAAe,CAAC,GAAG,MAAM;;;;;;;;;;;;;;;;;;IAS3E,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,mBAAmB;;;;;;;;;;;;;;;;;;IASxD,eAAe,CACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,mBAAmB,GAAG,iBAAiB,GAAG,eAAe,GAAG,cAAc,GAAG,eAAe,GAAG,gBAAgB,GAAG,kBAAkB,GAAG,eAAe;;;;;;;;;;;;;;;;;;IAiBhK,WAAW,CAAC,IAAI,EAAE,kBAAkB;;;;;;;;;;;;;;;;;;CAQrC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { substituteParameters } from '../utils.js';
|
|
2
|
+
export class AnalyticsFeature {
|
|
3
|
+
builder;
|
|
4
|
+
constructor(builder) {
|
|
5
|
+
this.builder = builder;
|
|
6
|
+
}
|
|
7
|
+
addCTE(alias, subquery) {
|
|
8
|
+
const config = this.builder.getConfig();
|
|
9
|
+
const cte = typeof subquery === 'string' ? subquery : subquery.toSQL();
|
|
10
|
+
return {
|
|
11
|
+
...config,
|
|
12
|
+
ctes: [...(config.ctes || []), `${alias} AS (${cte})`]
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
addScalar(alias, expression) {
|
|
16
|
+
const config = this.builder.getConfig();
|
|
17
|
+
const scalarExpression = substituteParameters(expression.sql, expression.parameters);
|
|
18
|
+
return {
|
|
19
|
+
...config,
|
|
20
|
+
ctes: [...(config.ctes || []), `${scalarExpression} AS ${alias}`]
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
addTimeInterval(column, interval, method) {
|
|
24
|
+
const config = this.builder.getConfig();
|
|
25
|
+
const groupBy = config.groupBy || [];
|
|
26
|
+
if (method === 'toStartOfInterval') {
|
|
27
|
+
groupBy.push(`${method}(${column}, INTERVAL ${interval})`);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
groupBy.push(`${method}(${column})`);
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
...config,
|
|
34
|
+
groupBy
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
addSettings(opts) {
|
|
38
|
+
const config = this.builder.getConfig();
|
|
39
|
+
const settingsFragments = Object.entries(opts).map(([key, value]) => `${key}=${value}`);
|
|
40
|
+
return {
|
|
41
|
+
...config,
|
|
42
|
+
settings: settingsFragments.join(', ')
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { BuilderState, SchemaDefinition } from '../types/builder-state.js';
|
|
2
|
+
import { QueryBuilder } from '../query-builder.js';
|
|
3
|
+
import { CrossFilter } from '../cross-filter.js';
|
|
4
|
+
export declare class CrossFilteringFeature<Schema extends SchemaDefinition<Schema>, State extends BuilderState<Schema, string, any, keyof Schema, Partial<Record<string, keyof Schema>>>> {
|
|
5
|
+
private builder;
|
|
6
|
+
constructor(builder: QueryBuilder<Schema, State>);
|
|
7
|
+
applyCrossFilters(crossFilter: CrossFilter<Schema, Extract<keyof Schema, string>>): import("../../types/base.js").QueryConfig<State["output"], Schema>;
|
|
8
|
+
private applyAndConditions;
|
|
9
|
+
private applyOrConditions;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=cross-filtering.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cross-filtering.d.ts","sourceRoot":"","sources":["../../../src/core/features/cross-filtering.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAe,MAAM,oBAAoB,CAAC;AAW9D,qBAAa,qBAAqB,CAChC,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;IAExF,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC;IAExD,iBAAiB,CAAC,WAAW,EAAE,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,MAAM,EAAE,MAAM,CAAC,CAAC;IAkBjF,OAAO,CAAC,kBAAkB;IAwB1B,OAAO,CAAC,iBAAiB;CAkD1B"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
function isFilterCondition(obj) {
|
|
2
|
+
return obj && 'column' in obj && 'operator' in obj && 'value' in obj;
|
|
3
|
+
}
|
|
4
|
+
function isFilterGroup(obj) {
|
|
5
|
+
return obj && 'conditions' in obj && 'operator' in obj;
|
|
6
|
+
}
|
|
7
|
+
export class CrossFilteringFeature {
|
|
8
|
+
builder;
|
|
9
|
+
constructor(builder) {
|
|
10
|
+
this.builder = builder;
|
|
11
|
+
}
|
|
12
|
+
applyCrossFilters(crossFilter) {
|
|
13
|
+
const filterGroup = crossFilter.getConditions();
|
|
14
|
+
if (filterGroup.conditions.length === 0) {
|
|
15
|
+
return this.builder.getConfig();
|
|
16
|
+
}
|
|
17
|
+
if (filterGroup.operator === 'AND') {
|
|
18
|
+
this.applyAndConditions(filterGroup.conditions);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
this.builder.whereGroup(builder => {
|
|
22
|
+
this.applyOrConditions(filterGroup.conditions, builder);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
return this.builder.getConfig();
|
|
26
|
+
}
|
|
27
|
+
applyAndConditions(conditions) {
|
|
28
|
+
conditions.forEach(condition => {
|
|
29
|
+
if (isFilterCondition(condition)) {
|
|
30
|
+
this.builder.where(condition.column, condition.operator, condition.value);
|
|
31
|
+
}
|
|
32
|
+
else if (isFilterGroup(condition)) {
|
|
33
|
+
if (condition.operator === 'AND') {
|
|
34
|
+
this.builder.whereGroup(builder => {
|
|
35
|
+
const feature = new CrossFilteringFeature(builder);
|
|
36
|
+
feature.applyAndConditions(condition.conditions);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
this.builder.whereGroup(builder => {
|
|
41
|
+
const feature = new CrossFilteringFeature(builder);
|
|
42
|
+
feature.applyOrConditions(condition.conditions, builder);
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
applyOrConditions(conditions, builder = this.builder) {
|
|
49
|
+
if (conditions.length === 0)
|
|
50
|
+
return;
|
|
51
|
+
const firstCondition = conditions[0];
|
|
52
|
+
if (isFilterCondition(firstCondition)) {
|
|
53
|
+
builder.where(firstCondition.column, firstCondition.operator, firstCondition.value);
|
|
54
|
+
}
|
|
55
|
+
else if (isFilterGroup(firstCondition)) {
|
|
56
|
+
if (firstCondition.operator === 'AND') {
|
|
57
|
+
builder.whereGroup(innerBuilder => {
|
|
58
|
+
const feature = new CrossFilteringFeature(innerBuilder);
|
|
59
|
+
feature.applyAndConditions(firstCondition.conditions);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
builder.whereGroup(innerBuilder => {
|
|
64
|
+
const feature = new CrossFilteringFeature(innerBuilder);
|
|
65
|
+
feature.applyOrConditions(firstCondition.conditions, innerBuilder);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
for (let i = 1; i < conditions.length; i++) {
|
|
70
|
+
const condition = conditions[i];
|
|
71
|
+
if (isFilterCondition(condition)) {
|
|
72
|
+
builder.orWhere(condition.column, condition.operator, condition.value);
|
|
73
|
+
}
|
|
74
|
+
else if (isFilterGroup(condition)) {
|
|
75
|
+
if (condition.operator === 'AND') {
|
|
76
|
+
builder.orWhereGroup(innerBuilder => {
|
|
77
|
+
const feature = new CrossFilteringFeature(innerBuilder);
|
|
78
|
+
feature.applyAndConditions(condition.conditions);
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
builder.orWhereGroup(innerBuilder => {
|
|
83
|
+
const feature = new CrossFilteringFeature(innerBuilder);
|
|
84
|
+
feature.applyOrConditions(condition.conditions, innerBuilder);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { BuilderState, SchemaDefinition } from '../types/builder-state.js';
|
|
2
|
+
import { QueryBuilder } from '../query-builder.js';
|
|
3
|
+
import { type QueryLog } from '../utils/logger.js';
|
|
4
|
+
interface ExecutorRunOptions {
|
|
5
|
+
queryId?: string;
|
|
6
|
+
logContext?: Partial<QueryLog>;
|
|
7
|
+
}
|
|
8
|
+
export declare class ExecutorFeature<Schema extends SchemaDefinition<Schema>, State extends BuilderState<Schema, string, any, keyof Schema, Partial<Record<string, keyof Schema>>>> {
|
|
9
|
+
private builder;
|
|
10
|
+
constructor(builder: QueryBuilder<Schema, State>);
|
|
11
|
+
toSQLWithParams(): {
|
|
12
|
+
sql: string;
|
|
13
|
+
parameters: any[];
|
|
14
|
+
};
|
|
15
|
+
toSQL(): string;
|
|
16
|
+
execute(options?: ExecutorRunOptions): Promise<State['output'][]>;
|
|
17
|
+
stream(): Promise<ReadableStream<State['output'][]>>;
|
|
18
|
+
private toSQLWithoutParameters;
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"executor.d.ts","sourceRoot":"","sources":["../../../src/core/features/executor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,EAAU,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAG3D,UAAU,kBAAkB;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;CAChC;AAED,qBAAa,eAAe,CAC1B,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;IAExF,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC;IAExD,eAAe,IAAI;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,GAAG,EAAE,CAAA;KAAE;IAOrD,KAAK,IAAI,MAAM;IAKT,OAAO,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;IAuDjE,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAgD1D,OAAO,CAAC,sBAAsB;CA0C/B"}
|