@hypequery/clickhouse 1.3.1-beta.0 → 1.3.2
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.md +18 -1
- package/dist/cli/generate-types.js +41 -3
- package/dist/core/connection.d.ts.map +1 -1
- package/dist/core/connection.js +4 -3
- package/dist/core/cross-filter.d.ts +3 -7
- package/dist/core/cross-filter.d.ts.map +1 -1
- package/dist/core/cross-filter.js +3 -2
- 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 +18 -22
- package/dist/core/features/aggregations.d.ts.map +1 -1
- package/dist/core/features/aggregations.js +6 -6
- package/dist/core/features/analytics.d.ts +15 -19
- package/dist/core/features/analytics.d.ts.map +1 -1
- package/dist/core/features/analytics.js +2 -2
- package/dist/core/features/cross-filtering.d.ts +5 -24
- package/dist/core/features/cross-filtering.d.ts.map +1 -1
- package/dist/core/features/cross-filtering.js +0 -33
- package/dist/core/features/executor.d.ts +5 -9
- package/dist/core/features/executor.d.ts.map +1 -1
- package/dist/core/features/filtering.d.ts +32 -28
- package/dist/core/features/filtering.d.ts.map +1 -1
- package/dist/core/features/filtering.js +27 -26
- package/dist/core/features/joins.d.ts +7 -10
- package/dist/core/features/joins.d.ts.map +1 -1
- package/dist/core/features/pagination.d.ts +8 -10
- package/dist/core/features/pagination.d.ts.map +1 -1
- package/dist/core/features/pagination.js +13 -41
- package/dist/core/features/query-modifiers.d.ts +18 -21
- package/dist/core/features/query-modifiers.d.ts.map +1 -1
- package/dist/core/formatters/sql-formatter.d.ts.map +1 -1
- package/dist/core/formatters/sql-formatter.js +6 -0
- package/dist/core/join-relationships.d.ts +2 -1
- package/dist/core/join-relationships.d.ts.map +1 -1
- package/dist/core/query-builder.d.ts +50 -73
- package/dist/core/query-builder.d.ts.map +1 -1
- package/dist/core/query-builder.js +113 -92
- package/dist/core/tests/integration/setup.d.ts +1 -1
- package/dist/core/tests/test-utils.d.ts +4 -3
- package/dist/core/tests/test-utils.d.ts.map +1 -1
- package/dist/core/tests/test-utils.js +18 -8
- package/dist/core/types/builder-state.d.ts +25 -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 +25 -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/predicate-builder.d.ts +29 -0
- package/dist/core/utils/predicate-builder.d.ts.map +1 -0
- package/dist/core/utils/predicate-builder.js +92 -0
- package/dist/core/utils/sql-expressions.d.ts +11 -10
- package/dist/core/utils/sql-expressions.d.ts.map +1 -1
- package/dist/core/utils/sql-expressions.js +4 -2
- package/dist/core/validators/filter-validator.d.ts +2 -1
- package/dist/core/validators/filter-validator.d.ts.map +1 -1
- package/dist/core/validators/value-validator.d.ts +2 -1
- package/dist/core/validators/value-validator.d.ts.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/types/base.d.ts +10 -15
- package/dist/types/base.d.ts.map +1 -1
- package/dist/types/clickhouse-types.d.ts +2 -2
- package/dist/types/clickhouse-types.d.ts.map +1 -1
- package/dist/types/filters.d.ts +1 -1
- package/dist/types/filters.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -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 +7 -3
- package/dist/core/tests/integration/test-initializer.d.ts +0 -7
- package/dist/core/tests/integration/test-initializer.d.ts.map +0 -1
- package/dist/core/tests/integration/test-initializer.js +0 -32
package/README.md
CHANGED
|
@@ -184,8 +184,25 @@ const tripsWithDrivers = await db.table('trips')
|
|
|
184
184
|
.join('drivers', 'trips.driver_id', 'drivers.id')
|
|
185
185
|
.execute();
|
|
186
186
|
|
|
187
|
+
// After joining, TypeScript understands the expanded scope
|
|
188
|
+
const tripsWithUsers = await db.table('trips')
|
|
189
|
+
.innerJoin('users', 'trips.user_id', 'users.id')
|
|
190
|
+
.select(['users.email', 'trips.trip_id'])
|
|
191
|
+
.where('users.email', 'like', '%@example.com')
|
|
192
|
+
.execute();
|
|
193
|
+
|
|
194
|
+
// Keep literal column inference with selectConst and reuse joined columns in ORDER BY / HAVING
|
|
195
|
+
const sortedTrips = await db.table('trips')
|
|
196
|
+
.innerJoin('users', 'trips.user_id', 'users.id')
|
|
197
|
+
.selectConst('users.email', 'trips.trip_id')
|
|
198
|
+
.groupBy(['users.email', 'trips.trip_id'])
|
|
199
|
+
.having('COUNT(*) > 1')
|
|
200
|
+
.orderBy('users.email', 'DESC')
|
|
201
|
+
.execute();
|
|
202
|
+
|
|
187
203
|
```
|
|
188
204
|
|
|
205
|
+
`selectConst()` preserves literal column names (including aliases like `users.email`), which means TypeScript keeps those identifiers available for downstream `orderBy`, `groupBy`, and `having` calls.
|
|
189
206
|
|
|
190
207
|
**Benefits:**
|
|
191
208
|
- ✅ Works in all environments (Node.js, browser, bundlers)
|
|
@@ -250,4 +267,4 @@ This project is licensed under the Apache-2.0 License - see the [LICENSE](LICENS
|
|
|
250
267
|
|
|
251
268
|
<div align="center">
|
|
252
269
|
<sub>Built with ❤️ by the hypequery team</sub>
|
|
253
|
-
</div>
|
|
270
|
+
</div>
|
|
@@ -35,6 +35,40 @@ const clickhouseToTsType = (type) => {
|
|
|
35
35
|
return `${clickhouseToTsType(innerType)} | null`;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
// Handle Map types
|
|
39
|
+
if (type.startsWith('Map(')) {
|
|
40
|
+
// Extract key and value types from Map(KeyType, ValueType)
|
|
41
|
+
const mapContent = type.slice(4, -1); // Remove 'Map(' and ')'
|
|
42
|
+
const commaIndex = mapContent.lastIndexOf(',');
|
|
43
|
+
if (commaIndex !== -1) {
|
|
44
|
+
const keyType = mapContent.substring(0, commaIndex).trim();
|
|
45
|
+
const valueType = mapContent.substring(commaIndex + 1).trim();
|
|
46
|
+
|
|
47
|
+
// Handle different key types
|
|
48
|
+
let keyTsType = 'string';
|
|
49
|
+
if (keyType === 'LowCardinality(String)') {
|
|
50
|
+
keyTsType = 'string';
|
|
51
|
+
} else if (keyType.includes('Int') || keyType.includes('UInt')) {
|
|
52
|
+
keyTsType = 'number';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Handle different value types
|
|
56
|
+
let valueTsType = 'unknown';
|
|
57
|
+
if (valueType.startsWith('Array(')) {
|
|
58
|
+
const innerType = valueType.slice(6, -1);
|
|
59
|
+
valueTsType = `Array<${clickhouseToTsType(innerType)}>`;
|
|
60
|
+
} else if (valueType.startsWith('Nullable(')) {
|
|
61
|
+
const innerType = valueType.slice(9, -1);
|
|
62
|
+
valueTsType = `${clickhouseToTsType(innerType)} | null`;
|
|
63
|
+
} else {
|
|
64
|
+
valueTsType = clickhouseToTsType(valueType);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return `Record<${keyTsType}, ${valueTsType}>`;
|
|
68
|
+
}
|
|
69
|
+
return 'Record<string, unknown>';
|
|
70
|
+
}
|
|
71
|
+
|
|
38
72
|
switch (type.toLowerCase()) {
|
|
39
73
|
case 'string':
|
|
40
74
|
case 'fixedstring':
|
|
@@ -43,12 +77,16 @@ const clickhouseToTsType = (type) => {
|
|
|
43
77
|
case 'int16':
|
|
44
78
|
case 'int32':
|
|
45
79
|
case 'uint8':
|
|
80
|
+
case 'int64':
|
|
46
81
|
case 'uint16':
|
|
47
82
|
case 'uint32':
|
|
48
|
-
return 'number';
|
|
49
|
-
case 'int64':
|
|
50
83
|
case 'uint64':
|
|
51
|
-
return '
|
|
84
|
+
return 'number';
|
|
85
|
+
case 'uint128':
|
|
86
|
+
case 'uint256':
|
|
87
|
+
case 'int128':
|
|
88
|
+
case 'int256':
|
|
89
|
+
return 'string';
|
|
52
90
|
case 'float32':
|
|
53
91
|
case 'float64':
|
|
54
92
|
case 'decimal':
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/core/connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,IAAI,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACnF,OAAO,KAAK,EAAE,gBAAgB,IAAI,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/core/connection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,IAAI,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AACnF,OAAO,KAAK,EAAE,gBAAgB,IAAI,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAM3D,KAAK,gBAAgB,GAAG,oBAAoB,GAAG,mBAAmB,CAAC;AAsCnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAiC;IACxD,OAAO,CAAC,MAAM,CAAC,YAAY,CAAuC;IAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,oBAAoB;IAaxE;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,SAAS,IAAI,gBAAgB;IAOpC;;;;;OAKG;IACH,MAAM,CAAC,qBAAqB,IAAI,kBAAkB;CAGnD"}
|
package/dist/core/connection.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createClient as createNodeClient } from '@clickhouse/client';
|
|
2
1
|
import { isClientConfig } from './query-builder.js';
|
|
2
|
+
import { getAutoClientModule } from './env/auto-client.js';
|
|
3
3
|
// Function to synchronously get the appropriate client
|
|
4
4
|
function getClickHouseClientSync() {
|
|
5
5
|
const isDev = process.env.NODE_ENV === 'development';
|
|
@@ -9,9 +9,10 @@ function getClickHouseClientSync() {
|
|
|
9
9
|
if (isDev) {
|
|
10
10
|
console.log('hypequery: Using @clickhouse/client for Node.js environment');
|
|
11
11
|
}
|
|
12
|
+
const clientModule = getAutoClientModule();
|
|
12
13
|
return {
|
|
13
|
-
createClient:
|
|
14
|
-
ClickHouseSettings: {}
|
|
14
|
+
createClient: clientModule.createClient,
|
|
15
|
+
ClickHouseSettings: clientModule.ClickHouseSettings || {}
|
|
15
16
|
};
|
|
16
17
|
}
|
|
17
18
|
// For browser environments, require() doesn't work, so we can't auto-detect
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FilterConditionInput, FilterOperator, OperatorValueMap } from '../types/index.js';
|
|
2
|
-
import type {
|
|
3
|
-
export interface FilterGroup<Schema extends
|
|
2
|
+
import type { AnySchema, InferColumnType } from '../types/schema.js';
|
|
3
|
+
export interface FilterGroup<Schema extends AnySchema = AnySchema, OriginalT extends Record<string, any> = Record<string, any>> {
|
|
4
4
|
operator: 'AND' | 'OR';
|
|
5
5
|
conditions: Array<FilterConditionInput<any, Schema, OriginalT> | FilterGroup<Schema, OriginalT>>;
|
|
6
6
|
limit?: number;
|
|
@@ -14,11 +14,7 @@ export interface FilterGroup<Schema extends Record<string, Record<string, any>>
|
|
|
14
14
|
* @template Schema - The full database schema type
|
|
15
15
|
* @template TableName - The specific table being filtered
|
|
16
16
|
*/
|
|
17
|
-
export declare class CrossFilter<Schema extends {
|
|
18
|
-
[tableName: string]: {
|
|
19
|
-
[columnName: string]: ColumnType;
|
|
20
|
-
};
|
|
21
|
-
} = any, TableName extends keyof Schema = Extract<keyof Schema, string>> {
|
|
17
|
+
export declare class CrossFilter<Schema extends AnySchema = AnySchema, TableName extends keyof Schema & string = Extract<keyof Schema, string>> {
|
|
22
18
|
private schema?;
|
|
23
19
|
private rootGroup;
|
|
24
20
|
constructor(schema?: Schema | undefined);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cross-filter.d.ts","sourceRoot":"","sources":["../../src/core/cross-filter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"cross-filter.d.ts","sourceRoot":"","sources":["../../src/core/cross-filter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC3F,OAAO,KAAK,EAAE,SAAS,EAAc,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAGjF,MAAM,WAAW,WAAW,CAC1B,MAAM,SAAS,SAAS,GAAG,SAAS,EACpC,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAE3D,QAAQ,EAAE,KAAK,GAAG,IAAI,CAAC;IACvB,UAAU,EAAE,KAAK,CACf,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAC9E,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE;QACR,MAAM,EAAE,MAAM,SAAS,CAAC;QACxB,SAAS,EAAE,KAAK,GAAG,MAAM,CAAC;KAC3B,CAAC;CACH;AAED;;;;GAIG;AACH,qBAAa,WAAW,CACtB,MAAM,SAAS,SAAS,GAAG,SAAS,EACpC,SAAS,SAAS,MAAM,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,MAAM,EAAE,MAAM,CAAC;IAM3D,OAAO,CAAC,MAAM,CAAC;IAH3B,OAAO,CAAC,SAAS,CAAyC;gBAGtC,MAAM,CAAC,EAAE,MAAM,YAAA;IAInC;;;OAGG;IACH,GAAG,CACD,UAAU,SAAS,OAAO,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,EAC3D,EAAE,SAAS,cAAc,EAEzB,SAAS,EAAE,oBAAoB,CAC7B,gBAAgB,CAAC,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EACpE,MAAM,EACN,MAAM,CAAC,SAAS,CAAC,CAClB,GACA,IAAI;IA0BP;;OAEG;IACH,WAAW,CACT,UAAU,EAAE,KAAK,CAAC,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,GACtE,IAAI;IAQP;;;;OAIG;IACH,QAAQ,CACN,eAAe,EAAE,KAAK,CACpB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAC9F,EACD,QAAQ,EAAE,KAAK,GAAG,IAAI,GACrB,IAAI;IAYP;;OAEG;IACH,aAAa,IAAI,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;IAIvD;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAcrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAazB;;OAEG;IACH,OAAO,CAAC,aAAa;IAqBrB;;OAEG;IACH,OAAO,CAAC,OAAO;IAMf;;;;;OAKG;IACH,IAAI,CAAC,CAAC,SAAS,MAAM,MAAM,CAAC,SAAS,CAAC,EACpC,WAAW,EAAE,CAAC,EACd,CAAC,EAAE,MAAM,EACT,OAAO,GAAE,MAAM,GAAG,KAAc,GAC/B,IAAI;CAmBR"}
|
|
@@ -77,10 +77,11 @@ export class CrossFilter {
|
|
|
77
77
|
if (!this.schema) {
|
|
78
78
|
return 'String';
|
|
79
79
|
}
|
|
80
|
-
for (const table
|
|
80
|
+
for (const table of Object.keys(this.schema)) {
|
|
81
81
|
const tableSchema = this.schema[table];
|
|
82
82
|
if (column in tableSchema) {
|
|
83
|
-
|
|
83
|
+
const columnKey = column;
|
|
84
|
+
return tableSchema[columnKey];
|
|
84
85
|
}
|
|
85
86
|
}
|
|
86
87
|
throw new Error(`Column '${column}' not found in schema`);
|
|
@@ -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
|
+
}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
+
import type { BuilderState, SchemaDefinition } from '../types/builder-state.js';
|
|
1
2
|
import { QueryBuilder } from '../query-builder.js';
|
|
2
|
-
|
|
3
|
-
export declare class AggregationFeature<Schema extends {
|
|
4
|
-
[tableName: string]: {
|
|
5
|
-
[columnName: string]: ColumnType;
|
|
6
|
-
};
|
|
7
|
-
}, T, HasSelect extends boolean = false, Aggregations = {}, OriginalT = T> {
|
|
3
|
+
export declare class AggregationFeature<Schema extends SchemaDefinition<Schema>, State extends BuilderState<Schema, string, any, keyof Schema, Partial<Record<string, keyof Schema>>>> {
|
|
8
4
|
private builder;
|
|
9
|
-
constructor(builder: QueryBuilder<Schema,
|
|
5
|
+
constructor(builder: QueryBuilder<Schema, State>);
|
|
10
6
|
private createAggregation;
|
|
11
|
-
sum
|
|
7
|
+
sum(column: string, alias: string): {
|
|
12
8
|
select: string[];
|
|
13
9
|
where?: import("../../types/base.js").WhereCondition[];
|
|
14
10
|
groupBy?: string[];
|
|
@@ -17,8 +13,8 @@ export declare class AggregationFeature<Schema extends {
|
|
|
17
13
|
offset?: number;
|
|
18
14
|
distinct?: boolean;
|
|
19
15
|
orderBy?: {
|
|
20
|
-
column: keyof
|
|
21
|
-
direction: import("../../
|
|
16
|
+
column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
|
|
17
|
+
direction: import("../../index.js").OrderDirection;
|
|
22
18
|
}[] | undefined;
|
|
23
19
|
joins?: import("../../types/base.js").JoinClause[];
|
|
24
20
|
parameters?: any[];
|
|
@@ -26,7 +22,7 @@ export declare class AggregationFeature<Schema extends {
|
|
|
26
22
|
unionQueries?: string[];
|
|
27
23
|
settings?: string;
|
|
28
24
|
};
|
|
29
|
-
count
|
|
25
|
+
count(column: string, alias: string): {
|
|
30
26
|
select: string[];
|
|
31
27
|
where?: import("../../types/base.js").WhereCondition[];
|
|
32
28
|
groupBy?: string[];
|
|
@@ -35,8 +31,8 @@ export declare class AggregationFeature<Schema extends {
|
|
|
35
31
|
offset?: number;
|
|
36
32
|
distinct?: boolean;
|
|
37
33
|
orderBy?: {
|
|
38
|
-
column: keyof
|
|
39
|
-
direction: import("../../
|
|
34
|
+
column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
|
|
35
|
+
direction: import("../../index.js").OrderDirection;
|
|
40
36
|
}[] | undefined;
|
|
41
37
|
joins?: import("../../types/base.js").JoinClause[];
|
|
42
38
|
parameters?: any[];
|
|
@@ -44,7 +40,7 @@ export declare class AggregationFeature<Schema extends {
|
|
|
44
40
|
unionQueries?: string[];
|
|
45
41
|
settings?: string;
|
|
46
42
|
};
|
|
47
|
-
avg
|
|
43
|
+
avg(column: string, alias: string): {
|
|
48
44
|
select: string[];
|
|
49
45
|
where?: import("../../types/base.js").WhereCondition[];
|
|
50
46
|
groupBy?: string[];
|
|
@@ -53,8 +49,8 @@ export declare class AggregationFeature<Schema extends {
|
|
|
53
49
|
offset?: number;
|
|
54
50
|
distinct?: boolean;
|
|
55
51
|
orderBy?: {
|
|
56
|
-
column: keyof
|
|
57
|
-
direction: import("../../
|
|
52
|
+
column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
|
|
53
|
+
direction: import("../../index.js").OrderDirection;
|
|
58
54
|
}[] | undefined;
|
|
59
55
|
joins?: import("../../types/base.js").JoinClause[];
|
|
60
56
|
parameters?: any[];
|
|
@@ -62,7 +58,7 @@ export declare class AggregationFeature<Schema extends {
|
|
|
62
58
|
unionQueries?: string[];
|
|
63
59
|
settings?: string;
|
|
64
60
|
};
|
|
65
|
-
min
|
|
61
|
+
min(column: string, alias: string): {
|
|
66
62
|
select: string[];
|
|
67
63
|
where?: import("../../types/base.js").WhereCondition[];
|
|
68
64
|
groupBy?: string[];
|
|
@@ -71,8 +67,8 @@ export declare class AggregationFeature<Schema extends {
|
|
|
71
67
|
offset?: number;
|
|
72
68
|
distinct?: boolean;
|
|
73
69
|
orderBy?: {
|
|
74
|
-
column: keyof
|
|
75
|
-
direction: import("../../
|
|
70
|
+
column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
|
|
71
|
+
direction: import("../../index.js").OrderDirection;
|
|
76
72
|
}[] | undefined;
|
|
77
73
|
joins?: import("../../types/base.js").JoinClause[];
|
|
78
74
|
parameters?: any[];
|
|
@@ -80,7 +76,7 @@ export declare class AggregationFeature<Schema extends {
|
|
|
80
76
|
unionQueries?: string[];
|
|
81
77
|
settings?: string;
|
|
82
78
|
};
|
|
83
|
-
max
|
|
79
|
+
max(column: string, alias: string): {
|
|
84
80
|
select: string[];
|
|
85
81
|
where?: import("../../types/base.js").WhereCondition[];
|
|
86
82
|
groupBy?: string[];
|
|
@@ -89,8 +85,8 @@ export declare class AggregationFeature<Schema extends {
|
|
|
89
85
|
offset?: number;
|
|
90
86
|
distinct?: boolean;
|
|
91
87
|
orderBy?: {
|
|
92
|
-
column: keyof
|
|
93
|
-
direction: import("../../
|
|
88
|
+
column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
|
|
89
|
+
direction: import("../../index.js").OrderDirection;
|
|
94
90
|
}[] | undefined;
|
|
95
91
|
joins?: import("../../types/base.js").JoinClause[];
|
|
96
92
|
parameters?: any[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aggregations.d.ts","sourceRoot":"","sources":["../../../src/core/features/aggregations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,
|
|
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"}
|
|
@@ -4,7 +4,7 @@ export class AggregationFeature {
|
|
|
4
4
|
this.builder = builder;
|
|
5
5
|
}
|
|
6
6
|
createAggregation(column, fn, alias) {
|
|
7
|
-
const aggregationSQL = `${fn}(${
|
|
7
|
+
const aggregationSQL = `${fn}(${column}) AS ${alias}`;
|
|
8
8
|
const config = this.builder.getConfig();
|
|
9
9
|
if (config.select) {
|
|
10
10
|
return {
|
|
@@ -19,18 +19,18 @@ export class AggregationFeature {
|
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
21
|
sum(column, alias) {
|
|
22
|
-
return this.createAggregation(column, 'SUM', alias
|
|
22
|
+
return this.createAggregation(column, 'SUM', alias);
|
|
23
23
|
}
|
|
24
24
|
count(column, alias) {
|
|
25
|
-
return this.createAggregation(column, 'COUNT', alias
|
|
25
|
+
return this.createAggregation(column, 'COUNT', alias);
|
|
26
26
|
}
|
|
27
27
|
avg(column, alias) {
|
|
28
|
-
return this.createAggregation(column, 'AVG', alias
|
|
28
|
+
return this.createAggregation(column, 'AVG', alias);
|
|
29
29
|
}
|
|
30
30
|
min(column, alias) {
|
|
31
|
-
return this.createAggregation(column, 'MIN', alias
|
|
31
|
+
return this.createAggregation(column, 'MIN', alias);
|
|
32
32
|
}
|
|
33
33
|
max(column, alias) {
|
|
34
|
-
return this.createAggregation(column, 'MAX', alias
|
|
34
|
+
return this.createAggregation(column, 'MAX', alias);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -1,16 +1,12 @@
|
|
|
1
|
-
import { QueryBuilder } from '../query-builder.js';
|
|
2
|
-
import { ColumnType, TableColumn } from '../../types/index.js';
|
|
3
1
|
import { ClickHouseSettings } from '@clickhouse/client-common';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
};
|
|
8
|
-
}, T, HasSelect extends boolean = false, Aggregations = {}, OriginalT = T> {
|
|
2
|
+
import type { AnyBuilderState, BuilderState, SchemaDefinition } from '../types/builder-state.js';
|
|
3
|
+
import { QueryBuilder } from '../query-builder.js';
|
|
4
|
+
export declare class AnalyticsFeature<Schema extends SchemaDefinition<Schema>, State extends BuilderState<Schema, string, any, keyof Schema, Partial<Record<string, keyof Schema>>>> {
|
|
9
5
|
private builder;
|
|
10
|
-
constructor(builder: QueryBuilder<Schema,
|
|
11
|
-
addCTE(alias: string, subquery: QueryBuilder<any,
|
|
6
|
+
constructor(builder: QueryBuilder<Schema, State>);
|
|
7
|
+
addCTE(alias: string, subquery: QueryBuilder<any, AnyBuilderState> | string): {
|
|
12
8
|
ctes: string[];
|
|
13
|
-
select?: (string | keyof
|
|
9
|
+
select?: (string | keyof State["output"])[] | undefined;
|
|
14
10
|
where?: import("../../types/base.js").WhereCondition[];
|
|
15
11
|
groupBy?: string[];
|
|
16
12
|
having?: string[];
|
|
@@ -18,25 +14,25 @@ export declare class AnalyticsFeature<Schema extends {
|
|
|
18
14
|
offset?: number;
|
|
19
15
|
distinct?: boolean;
|
|
20
16
|
orderBy?: {
|
|
21
|
-
column: keyof
|
|
22
|
-
direction: import("../../
|
|
17
|
+
column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
|
|
18
|
+
direction: import("../../index.js").OrderDirection;
|
|
23
19
|
}[] | undefined;
|
|
24
20
|
joins?: import("../../types/base.js").JoinClause[];
|
|
25
21
|
parameters?: any[];
|
|
26
22
|
unionQueries?: string[];
|
|
27
23
|
settings?: string;
|
|
28
24
|
};
|
|
29
|
-
addTimeInterval(column:
|
|
25
|
+
addTimeInterval(column: string, interval: string, method: 'toStartOfInterval' | 'toStartOfMinute' | 'toStartOfHour' | 'toStartOfDay' | 'toStartOfWeek' | 'toStartOfMonth' | 'toStartOfQuarter' | 'toStartOfYear'): {
|
|
30
26
|
groupBy: string[];
|
|
31
|
-
select?: (string | keyof
|
|
27
|
+
select?: (string | keyof State["output"])[] | undefined;
|
|
32
28
|
where?: import("../../types/base.js").WhereCondition[];
|
|
33
29
|
having?: string[];
|
|
34
30
|
limit?: number;
|
|
35
31
|
offset?: number;
|
|
36
32
|
distinct?: boolean;
|
|
37
33
|
orderBy?: {
|
|
38
|
-
column: keyof
|
|
39
|
-
direction: import("../../
|
|
34
|
+
column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
|
|
35
|
+
direction: import("../../index.js").OrderDirection;
|
|
40
36
|
}[] | undefined;
|
|
41
37
|
joins?: import("../../types/base.js").JoinClause[];
|
|
42
38
|
parameters?: any[];
|
|
@@ -46,7 +42,7 @@ export declare class AnalyticsFeature<Schema extends {
|
|
|
46
42
|
};
|
|
47
43
|
addSettings(opts: ClickHouseSettings): {
|
|
48
44
|
settings: string;
|
|
49
|
-
select?: (string | keyof
|
|
45
|
+
select?: (string | keyof State["output"])[] | undefined;
|
|
50
46
|
where?: import("../../types/base.js").WhereCondition[];
|
|
51
47
|
groupBy?: string[];
|
|
52
48
|
having?: string[];
|
|
@@ -54,8 +50,8 @@ export declare class AnalyticsFeature<Schema extends {
|
|
|
54
50
|
offset?: number;
|
|
55
51
|
distinct?: boolean;
|
|
56
52
|
orderBy?: {
|
|
57
|
-
column: keyof
|
|
58
|
-
direction: import("../../
|
|
53
|
+
column: keyof State["output"] | import("../../index.js").TableColumn<Schema>;
|
|
54
|
+
direction: import("../../index.js").OrderDirection;
|
|
59
55
|
}[] | undefined;
|
|
60
56
|
joins?: import("../../types/base.js").JoinClause[];
|
|
61
57
|
parameters?: any[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"analytics.d.ts","sourceRoot":"","sources":["../../../src/core/features/analytics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
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;AAEnD,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,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"}
|
|
@@ -15,10 +15,10 @@ export class AnalyticsFeature {
|
|
|
15
15
|
const config = this.builder.getConfig();
|
|
16
16
|
const groupBy = config.groupBy || [];
|
|
17
17
|
if (method === 'toStartOfInterval') {
|
|
18
|
-
groupBy.push(`${method}(${
|
|
18
|
+
groupBy.push(`${method}(${column}, INTERVAL ${interval})`);
|
|
19
19
|
}
|
|
20
20
|
else {
|
|
21
|
-
groupBy.push(`${method}(${
|
|
21
|
+
groupBy.push(`${method}(${column})`);
|
|
22
22
|
}
|
|
23
23
|
return {
|
|
24
24
|
...config,
|
|
@@ -1,31 +1,12 @@
|
|
|
1
|
+
import type { BuilderState } from '../types/builder-state.js';
|
|
1
2
|
import { QueryBuilder } from '../query-builder.js';
|
|
2
3
|
import { CrossFilter } from '../cross-filter.js';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
* Feature for handling cross-filter operations on queries
|
|
6
|
-
*/
|
|
7
|
-
export declare class CrossFilteringFeature<Schema extends {
|
|
8
|
-
[tableName: string]: {
|
|
9
|
-
[columnName: string]: ColumnType;
|
|
10
|
-
};
|
|
11
|
-
}, T, HasSelect extends boolean = false, Aggregations = {}, OriginalT = T> {
|
|
4
|
+
import { AnySchema } from '../../types/schema.js';
|
|
5
|
+
export declare class CrossFilteringFeature<Schema extends AnySchema, State extends BuilderState<Schema, string, any, keyof Schema, Partial<Record<string, keyof Schema>>>> {
|
|
12
6
|
private builder;
|
|
13
|
-
constructor(builder: QueryBuilder<Schema,
|
|
14
|
-
|
|
15
|
-
* Applies a set of cross filters to the query
|
|
16
|
-
* @param crossFilter - An instance of CrossFilter containing shared filter conditions
|
|
17
|
-
* @returns Updated query config
|
|
18
|
-
*/
|
|
19
|
-
applyCrossFilters(crossFilter: CrossFilter<Schema, keyof Schema>): import("../../types/base.js").QueryConfig<T, Schema>;
|
|
20
|
-
/**
|
|
21
|
-
* Apply AND conditions - each condition is applied with WHERE
|
|
22
|
-
*/
|
|
7
|
+
constructor(builder: QueryBuilder<Schema, State>);
|
|
8
|
+
applyCrossFilters(crossFilter: CrossFilter<Schema, Extract<keyof Schema, string>>): import("../../types/base.js").QueryConfig<State["output"], Schema>;
|
|
23
9
|
private applyAndConditions;
|
|
24
|
-
/**
|
|
25
|
-
* Apply direct OR conditions without adding extra conjunctions
|
|
26
|
-
* @param conditions The conditions to apply
|
|
27
|
-
* @param builder The builder to apply conditions to, defaults to this.builder
|
|
28
|
-
*/
|
|
29
10
|
private applyOrConditions;
|
|
30
11
|
}
|
|
31
12
|
//# sourceMappingURL=cross-filtering.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cross-filtering.d.ts","sourceRoot":"","sources":["../../../src/core/features/cross-filtering.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAe,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"cross-filtering.d.ts","sourceRoot":"","sources":["../../../src/core/features/cross-filtering.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,WAAW,EAAe,MAAM,oBAAoB,CAAC;AAE9D,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAUlD,qBAAa,qBAAqB,CAChC,MAAM,SAAS,SAAS,EACxB,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"}
|
|
@@ -1,68 +1,43 @@
|
|
|
1
1
|
//@ts-
|
|
2
|
-
/**
|
|
3
|
-
* Type guard to check if an object is a FilterConditionInput
|
|
4
|
-
*/
|
|
5
2
|
function isFilterCondition(obj) {
|
|
6
3
|
return obj && 'column' in obj && 'operator' in obj && 'value' in obj;
|
|
7
4
|
}
|
|
8
|
-
/**
|
|
9
|
-
* Type guard to check if an object is a FilterGroup
|
|
10
|
-
*/
|
|
11
5
|
function isFilterGroup(obj) {
|
|
12
6
|
return obj && 'conditions' in obj && 'operator' in obj;
|
|
13
7
|
}
|
|
14
|
-
/**
|
|
15
|
-
* Feature for handling cross-filter operations on queries
|
|
16
|
-
*/
|
|
17
8
|
export class CrossFilteringFeature {
|
|
18
9
|
builder;
|
|
19
10
|
constructor(builder) {
|
|
20
11
|
this.builder = builder;
|
|
21
12
|
}
|
|
22
|
-
/**
|
|
23
|
-
* Applies a set of cross filters to the query
|
|
24
|
-
* @param crossFilter - An instance of CrossFilter containing shared filter conditions
|
|
25
|
-
* @returns Updated query config
|
|
26
|
-
*/
|
|
27
13
|
applyCrossFilters(crossFilter) {
|
|
28
14
|
const filterGroup = crossFilter.getConditions();
|
|
29
15
|
if (filterGroup.conditions.length === 0) {
|
|
30
16
|
return this.builder.getConfig();
|
|
31
17
|
}
|
|
32
|
-
// Apply conditions based on filter group operator
|
|
33
18
|
if (filterGroup.operator === 'AND') {
|
|
34
|
-
// For AND groups, apply each condition directly
|
|
35
19
|
this.applyAndConditions(filterGroup.conditions);
|
|
36
20
|
}
|
|
37
21
|
else {
|
|
38
|
-
// For OR groups, special handling to ensure proper parentheses
|
|
39
|
-
// We use whereGroup instead of orWhereGroup here since this is a top-level group
|
|
40
22
|
this.builder.whereGroup(builder => {
|
|
41
23
|
this.applyOrConditions(filterGroup.conditions, builder);
|
|
42
24
|
});
|
|
43
25
|
}
|
|
44
26
|
return this.builder.getConfig();
|
|
45
27
|
}
|
|
46
|
-
/**
|
|
47
|
-
* Apply AND conditions - each condition is applied with WHERE
|
|
48
|
-
*/
|
|
49
28
|
applyAndConditions(conditions) {
|
|
50
29
|
conditions.forEach(condition => {
|
|
51
30
|
if (isFilterCondition(condition)) {
|
|
52
|
-
// Simple condition - apply with WHERE
|
|
53
31
|
this.builder.where(condition.column, condition.operator, condition.value);
|
|
54
32
|
}
|
|
55
33
|
else if (isFilterGroup(condition)) {
|
|
56
|
-
// Nested group
|
|
57
34
|
if (condition.operator === 'AND') {
|
|
58
|
-
// AND subgroup - apply all conditions
|
|
59
35
|
this.builder.whereGroup(builder => {
|
|
60
36
|
const feature = new CrossFilteringFeature(builder);
|
|
61
37
|
feature.applyAndConditions(condition.conditions);
|
|
62
38
|
});
|
|
63
39
|
}
|
|
64
40
|
else {
|
|
65
|
-
// OR subgroup within AND - needs special parentheses handling
|
|
66
41
|
this.builder.whereGroup(builder => {
|
|
67
42
|
const feature = new CrossFilteringFeature(builder);
|
|
68
43
|
feature.applyOrConditions(condition.conditions, builder);
|
|
@@ -71,21 +46,14 @@ export class CrossFilteringFeature {
|
|
|
71
46
|
}
|
|
72
47
|
});
|
|
73
48
|
}
|
|
74
|
-
/**
|
|
75
|
-
* Apply direct OR conditions without adding extra conjunctions
|
|
76
|
-
* @param conditions The conditions to apply
|
|
77
|
-
* @param builder The builder to apply conditions to, defaults to this.builder
|
|
78
|
-
*/
|
|
79
49
|
applyOrConditions(conditions, builder = this.builder) {
|
|
80
50
|
if (conditions.length === 0)
|
|
81
51
|
return;
|
|
82
|
-
// Handle first condition
|
|
83
52
|
const firstCondition = conditions[0];
|
|
84
53
|
if (isFilterCondition(firstCondition)) {
|
|
85
54
|
builder.where(firstCondition.column, firstCondition.operator, firstCondition.value);
|
|
86
55
|
}
|
|
87
56
|
else if (isFilterGroup(firstCondition)) {
|
|
88
|
-
// Handle nested group
|
|
89
57
|
if (firstCondition.operator === 'AND') {
|
|
90
58
|
builder.whereGroup(innerBuilder => {
|
|
91
59
|
const feature = new CrossFilteringFeature(innerBuilder);
|
|
@@ -99,7 +67,6 @@ export class CrossFilteringFeature {
|
|
|
99
67
|
});
|
|
100
68
|
}
|
|
101
69
|
}
|
|
102
|
-
// Handle remaining conditions
|
|
103
70
|
for (let i = 1; i < conditions.length; i++) {
|
|
104
71
|
const condition = conditions[i];
|
|
105
72
|
if (isFilterCondition(condition)) {
|