@hypequery/clickhouse 1.6.2 → 2.0.0

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.
Files changed (141) hide show
  1. package/README-CLI.md +43 -88
  2. package/README.md +84 -253
  3. package/dist/cli/bin.js +16 -8
  4. package/dist/core/adapters/clickhouse-adapter.d.ts.map +1 -1
  5. package/dist/core/adapters/clickhouse-adapter.js +3 -2
  6. package/dist/core/cache/cache-manager.d.ts.map +1 -1
  7. package/dist/core/cache/cache-manager.js +5 -3
  8. package/dist/core/connection.d.ts +6 -6
  9. package/dist/core/connection.js +9 -9
  10. package/dist/core/cross-filter.js +1 -1
  11. package/dist/core/dialects/clickhouse-dialect.d.ts +2 -2
  12. package/dist/core/dialects/clickhouse-dialect.d.ts.map +1 -1
  13. package/dist/core/dialects/clickhouse-dialect.js +39 -22
  14. package/dist/core/dialects/sql-dialect.d.ts +2 -2
  15. package/dist/core/dialects/sql-dialect.d.ts.map +1 -1
  16. package/dist/core/env/auto-client.d.ts.map +1 -1
  17. package/dist/core/env/auto-client.js +1 -1
  18. package/dist/core/features/aggregations.d.ts +7 -90
  19. package/dist/core/features/aggregations.d.ts.map +1 -1
  20. package/dist/core/features/aggregations.js +19 -7
  21. package/dist/core/features/analytics.d.ts +5 -870
  22. package/dist/core/features/analytics.d.ts.map +1 -1
  23. package/dist/core/features/analytics.js +15 -13
  24. package/dist/core/features/cross-filtering.d.ts +1 -1
  25. package/dist/core/features/cross-filtering.d.ts.map +1 -1
  26. package/dist/core/features/cross-filtering.js +28 -73
  27. package/dist/core/features/executor.d.ts +1 -1
  28. package/dist/core/features/executor.d.ts.map +1 -1
  29. package/dist/core/features/executor.js +9 -11
  30. package/dist/core/features/filtering.d.ts +5 -91
  31. package/dist/core/features/filtering.d.ts.map +1 -1
  32. package/dist/core/features/filtering.js +63 -77
  33. package/dist/core/features/joins.d.ts +2 -19
  34. package/dist/core/features/joins.d.ts.map +1 -1
  35. package/dist/core/features/joins.js +16 -5
  36. package/dist/core/features/query-modifiers.d.ts +10 -109
  37. package/dist/core/features/query-modifiers.d.ts.map +1 -1
  38. package/dist/core/features/query-modifiers.js +64 -18
  39. package/dist/core/formatters/sql-formatter.d.ts +16 -5
  40. package/dist/core/formatters/sql-formatter.d.ts.map +1 -1
  41. package/dist/core/formatters/sql-formatter.js +197 -93
  42. package/dist/core/join-relationships.d.ts +22 -5
  43. package/dist/core/join-relationships.d.ts.map +1 -1
  44. package/dist/core/join-relationships.js +1 -1
  45. package/dist/core/query-builder.d.ts +63 -12
  46. package/dist/core/query-builder.d.ts.map +1 -1
  47. package/dist/core/query-builder.js +210 -153
  48. package/dist/core/query-node.d.ts +7 -0
  49. package/dist/core/query-node.d.ts.map +1 -0
  50. package/dist/core/query-node.js +80 -0
  51. package/dist/core/tests/integration/setup.d.ts +1 -0
  52. package/dist/core/tests/integration/setup.d.ts.map +1 -1
  53. package/dist/core/tests/integration/setup.js +4 -2
  54. package/dist/core/types/select-types.d.ts +3 -0
  55. package/dist/core/types/select-types.d.ts.map +1 -1
  56. package/dist/core/utils/connection-endpoint.d.ts +3 -0
  57. package/dist/core/utils/connection-endpoint.d.ts.map +1 -0
  58. package/dist/core/utils/connection-endpoint.js +9 -0
  59. package/dist/core/utils/filter-application.d.ts +15 -0
  60. package/dist/core/utils/filter-application.d.ts.map +1 -0
  61. package/dist/core/utils/filter-application.js +32 -0
  62. package/dist/core/utils/query-config-compat.d.ts +48 -0
  63. package/dist/core/utils/query-config-compat.d.ts.map +1 -0
  64. package/dist/core/utils/query-config-compat.js +137 -0
  65. package/dist/core/utils/relation-application.d.ts +9 -0
  66. package/dist/core/utils/relation-application.d.ts.map +1 -0
  67. package/dist/core/utils/relation-application.js +19 -0
  68. package/dist/core/utils/relation-validation.d.ts +6 -0
  69. package/dist/core/utils/relation-validation.d.ts.map +1 -0
  70. package/dist/core/utils/relation-validation.js +29 -0
  71. package/dist/core/utils/sql-expressions.d.ts +14 -0
  72. package/dist/core/utils/sql-expressions.d.ts.map +1 -1
  73. package/dist/core/utils/sql-expressions.js +40 -0
  74. package/dist/core/utils/tuple-filter-validation.d.ts +3 -0
  75. package/dist/core/utils/tuple-filter-validation.d.ts.map +1 -0
  76. package/dist/core/utils/tuple-filter-validation.js +16 -0
  77. package/dist/index.d.ts +2 -13
  78. package/dist/index.d.ts.map +1 -1
  79. package/dist/index.js +3 -8
  80. package/dist/types/base.d.ts +88 -22
  81. package/dist/types/base.d.ts.map +1 -1
  82. package/dist/types/filters.d.ts +9 -5
  83. package/dist/types/filters.d.ts.map +1 -1
  84. package/package.json +5 -5
  85. package/dist/migrations/config/index.d.ts +0 -3
  86. package/dist/migrations/config/index.d.ts.map +0 -1
  87. package/dist/migrations/config/index.js +0 -1
  88. package/dist/migrations/config/types.d.ts +0 -45
  89. package/dist/migrations/config/types.d.ts.map +0 -1
  90. package/dist/migrations/config/types.js +0 -28
  91. package/dist/migrations/diff/diff.d.ts +0 -11
  92. package/dist/migrations/diff/diff.d.ts.map +0 -1
  93. package/dist/migrations/diff/diff.js +0 -240
  94. package/dist/migrations/diff/index.d.ts +0 -3
  95. package/dist/migrations/diff/index.d.ts.map +0 -1
  96. package/dist/migrations/diff/index.js +0 -1
  97. package/dist/migrations/diff/types.d.ts +0 -74
  98. package/dist/migrations/diff/types.d.ts.map +0 -1
  99. package/dist/migrations/diff/types.js +0 -1
  100. package/dist/migrations/plan/index.d.ts +0 -3
  101. package/dist/migrations/plan/index.d.ts.map +0 -1
  102. package/dist/migrations/plan/index.js +0 -1
  103. package/dist/migrations/plan/plan.d.ts +0 -12
  104. package/dist/migrations/plan/plan.d.ts.map +0 -1
  105. package/dist/migrations/plan/plan.js +0 -416
  106. package/dist/migrations/plan/types.d.ts +0 -93
  107. package/dist/migrations/plan/types.d.ts.map +0 -1
  108. package/dist/migrations/plan/types.js +0 -1
  109. package/dist/migrations/schema/column.d.ts +0 -71
  110. package/dist/migrations/schema/column.d.ts.map +0 -1
  111. package/dist/migrations/schema/column.js +0 -123
  112. package/dist/migrations/schema/define.d.ts +0 -24
  113. package/dist/migrations/schema/define.d.ts.map +0 -1
  114. package/dist/migrations/schema/define.js +0 -47
  115. package/dist/migrations/schema/index.d.ts +0 -4
  116. package/dist/migrations/schema/index.d.ts.map +0 -1
  117. package/dist/migrations/schema/index.js +0 -2
  118. package/dist/migrations/schema/types.d.ts +0 -74
  119. package/dist/migrations/schema/types.d.ts.map +0 -1
  120. package/dist/migrations/schema/types.js +0 -1
  121. package/dist/migrations/snapshot/index.d.ts +0 -3
  122. package/dist/migrations/snapshot/index.d.ts.map +0 -1
  123. package/dist/migrations/snapshot/index.js +0 -1
  124. package/dist/migrations/snapshot/serialize.d.ts +0 -21
  125. package/dist/migrations/snapshot/serialize.d.ts.map +0 -1
  126. package/dist/migrations/snapshot/serialize.js +0 -127
  127. package/dist/migrations/snapshot/types.d.ts +0 -47
  128. package/dist/migrations/snapshot/types.d.ts.map +0 -1
  129. package/dist/migrations/snapshot/types.js +0 -1
  130. package/dist/migrations/sql/index.d.ts +0 -4
  131. package/dist/migrations/sql/index.d.ts.map +0 -1
  132. package/dist/migrations/sql/index.js +0 -2
  133. package/dist/migrations/sql/render.d.ts +0 -10
  134. package/dist/migrations/sql/render.d.ts.map +0 -1
  135. package/dist/migrations/sql/render.js +0 -347
  136. package/dist/migrations/sql/types.d.ts +0 -53
  137. package/dist/migrations/sql/types.d.ts.map +0 -1
  138. package/dist/migrations/sql/types.js +0 -1
  139. package/dist/migrations/sql/write.d.ts +0 -10
  140. package/dist/migrations/sql/write.d.ts.map +0 -1
  141. package/dist/migrations/sql/write.js +0 -35
@@ -1 +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,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,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,EAC9J,OAAO,EAAE,UAAU;;;;;;;;;;;;;;;;;;IAarB,WAAW,CAAC,IAAI,EAAE,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAUrC"}
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,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEzE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,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,GAAG,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAStH,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,mBAAmB,GAAG,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IASnG,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,EAC9J,OAAO,EAAE,UAAU,GAClB,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAa3C,WAAW,CAAC,IAAI,EAAE,kBAAkB,GAAG,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAUhF"}
@@ -5,36 +5,38 @@ export class AnalyticsFeature {
5
5
  this.builder = builder;
6
6
  }
7
7
  addCTE(alias, subquery) {
8
- const config = this.builder.getConfig();
8
+ const query = this.builder.getQueryNode();
9
9
  const cte = typeof subquery === 'string' ? subquery : subquery.toSQL();
10
10
  return {
11
- ...config,
12
- ctes: [...(config.ctes || []), `${alias} AS (${cte})`]
11
+ ...query,
12
+ ctes: [...(query.ctes || []), { kind: 'cte', expression: `${alias} AS (${cte})` }]
13
13
  };
14
14
  }
15
15
  addScalar(alias, expression) {
16
- const config = this.builder.getConfig();
16
+ const query = this.builder.getQueryNode();
17
17
  const scalarExpression = substituteParameters(expression.sql, expression.parameters);
18
18
  return {
19
- ...config,
20
- ctes: [...(config.ctes || []), `${scalarExpression} AS ${alias}`]
19
+ ...query,
20
+ ctes: [...(query.ctes || []), { kind: 'cte', expression: `${scalarExpression} AS ${alias}` }]
21
21
  };
22
22
  }
23
23
  addTimeInterval(column, interval, method, dialect) {
24
- const config = this.builder.getConfig();
25
- const groupBy = config.groupBy || [];
26
- groupBy.push(dialect.formatTimeInterval(column, interval, method));
24
+ const query = this.builder.getQueryNode();
25
+ const groupBy = [
26
+ ...(query.groupBy || []),
27
+ { kind: 'group-by-item', expression: dialect.formatTimeInterval(column, interval, method) }
28
+ ];
27
29
  return {
28
- ...config,
30
+ ...query,
29
31
  groupBy
30
32
  };
31
33
  }
32
34
  addSettings(opts) {
33
- const config = this.builder.getConfig();
35
+ const query = this.builder.getQueryNode();
34
36
  return {
35
- ...config,
37
+ ...query,
36
38
  settings: {
37
- ...(config.settings || {}),
39
+ ...(query.settings || {}),
38
40
  ...opts,
39
41
  }
40
42
  };
@@ -4,7 +4,7 @@ import { CrossFilter } from '../cross-filter.js';
4
4
  export declare class CrossFilteringFeature<Schema extends SchemaDefinition<Schema>, State extends BuilderState<Schema, string, any, keyof Schema, Partial<Record<string, keyof Schema>>>> {
5
5
  private builder;
6
6
  constructor(builder: QueryBuilder<Schema, State>);
7
- applyCrossFilters(crossFilter: CrossFilter<Schema, Extract<keyof Schema, string>>): import("../../types/base.js").QueryConfig<State["output"], Schema>;
7
+ applyCrossFilters(crossFilter: CrossFilter<Schema, Extract<keyof Schema, string>>): QueryBuilder<Schema, State>;
8
8
  private applyAndConditions;
9
9
  private applyOrConditions;
10
10
  }
@@ -1 +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"}
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,EAAoB,MAAM,oBAAoB,CAAC;AAanE,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;IAYjF,OAAO,CAAC,kBAAkB;IAe1B,OAAO,CAAC,iBAAiB;CAsB1B"}
@@ -1,8 +1,5 @@
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;
1
+ function isFilterCondition(node) {
2
+ return 'column' in node;
6
3
  }
7
4
  export class CrossFilteringFeature {
8
5
  builder;
@@ -10,81 +7,39 @@ export class CrossFilteringFeature {
10
7
  this.builder = builder;
11
8
  }
12
9
  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
- });
10
+ const root = crossFilter.getConditions();
11
+ if (root.conditions.length === 0) {
12
+ return this.builder;
24
13
  }
25
- return this.builder.getConfig();
14
+ return root.operator === 'AND'
15
+ ? this.applyAndConditions(this.builder, root.conditions)
16
+ : this.builder.whereGroup(groupBuilder => this.applyOrConditions(groupBuilder, root.conditions));
26
17
  }
27
- applyAndConditions(conditions) {
28
- conditions.forEach(condition => {
18
+ applyAndConditions(builder, conditions) {
19
+ return conditions.reduce((currentBuilder, condition) => {
29
20
  if (isFilterCondition(condition)) {
30
- this.builder.where(condition.column, condition.operator, condition.value);
21
+ return currentBuilder.where(condition.column, condition.operator, condition.value);
31
22
  }
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
- });
23
+ return condition.operator === 'AND'
24
+ ? currentBuilder.whereGroup(groupBuilder => this.applyAndConditions(groupBuilder, condition.conditions))
25
+ : currentBuilder.whereGroup(groupBuilder => this.applyOrConditions(groupBuilder, condition.conditions));
26
+ }, builder);
47
27
  }
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];
28
+ applyOrConditions(builder, conditions) {
29
+ return conditions.reduce((currentBuilder, condition, index) => {
71
30
  if (isFilterCondition(condition)) {
72
- builder.orWhere(condition.column, condition.operator, condition.value);
31
+ return index === 0
32
+ ? currentBuilder.where(condition.column, condition.operator, condition.value)
33
+ : currentBuilder.orWhere(condition.column, condition.operator, condition.value);
73
34
  }
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
- }
35
+ if (condition.operator === 'AND') {
36
+ return index === 0
37
+ ? currentBuilder.whereGroup(groupBuilder => this.applyAndConditions(groupBuilder, condition.conditions))
38
+ : currentBuilder.orWhereGroup(groupBuilder => this.applyAndConditions(groupBuilder, condition.conditions));
87
39
  }
88
- }
40
+ return index === 0
41
+ ? currentBuilder.whereGroup(groupBuilder => this.applyOrConditions(groupBuilder, condition.conditions))
42
+ : currentBuilder.orWhereGroup(groupBuilder => this.applyOrConditions(groupBuilder, condition.conditions));
43
+ }, builder);
89
44
  }
90
45
  }
@@ -15,7 +15,7 @@ export declare class ExecutorFeature<Schema extends SchemaDefinition<Schema>, St
15
15
  toSQL(): string;
16
16
  execute(options?: ExecutorRunOptions): Promise<State['output'][]>;
17
17
  stream(): Promise<ReadableStream<State['output'][]>>;
18
- private toSQLWithoutParameters;
18
+ private compileQuery;
19
19
  }
20
20
  export {};
21
21
  //# sourceMappingURL=executor.d.ts.map
@@ -1 +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;AACnD,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;IAMT,OAAO,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;IAsDjE,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAgD1D,OAAO,CAAC,sBAAsB;CAM/B"}
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;AACnD,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;IAKrD,KAAK,IAAI,MAAM;IAMT,OAAO,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;IAsDjE,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IAgD1D,OAAO,CAAC,YAAY;CAMrB"}
@@ -6,10 +6,8 @@ export class ExecutorFeature {
6
6
  this.builder = builder;
7
7
  }
8
8
  toSQLWithParams() {
9
- const sql = this.toSQLWithoutParameters();
10
- const config = this.builder.getConfig();
11
- const parameters = config.parameters || [];
12
- return { sql, parameters };
9
+ const compiled = this.compileQuery();
10
+ return { sql: compiled.query, parameters: [...compiled.parameters] };
13
11
  }
14
12
  toSQL() {
15
13
  const { sql, parameters } = this.toSQLWithParams();
@@ -18,8 +16,8 @@ export class ExecutorFeature {
18
16
  }
19
17
  async execute(options) {
20
18
  const adapter = this.builder.getAdapter();
19
+ const queryNode = this.builder.toQueryNode();
21
20
  const { sql, parameters } = this.toSQLWithParams();
22
- const config = this.builder.getConfig();
23
21
  const renderSql = adapter.render ? adapter.render(sql, parameters) : substituteParameters(sql, parameters);
24
22
  const startTime = Date.now();
25
23
  logger.logQuery({
@@ -32,7 +30,7 @@ export class ExecutorFeature {
32
30
  });
33
31
  try {
34
32
  const rows = await adapter.query(sql, parameters, {
35
- clickhouseSettings: config.settings,
33
+ clickhouseSettings: queryNode.settings,
36
34
  queryId: options?.queryId,
37
35
  });
38
36
  const endTime = Date.now();
@@ -68,8 +66,8 @@ export class ExecutorFeature {
68
66
  }
69
67
  async stream() {
70
68
  const adapter = this.builder.getAdapter();
69
+ const queryNode = this.builder.toQueryNode();
71
70
  const { sql, parameters } = this.toSQLWithParams();
72
- const config = this.builder.getConfig();
73
71
  const renderSql = adapter.render ? adapter.render(sql, parameters) : substituteParameters(sql, parameters);
74
72
  const startTime = Date.now();
75
73
  logger.logQuery({
@@ -83,7 +81,7 @@ export class ExecutorFeature {
83
81
  throw new Error(`Streaming is not supported by adapter "${adapter.name}".`);
84
82
  }
85
83
  const webStream = await adapter.stream(sql, parameters, {
86
- clickhouseSettings: config.settings,
84
+ clickhouseSettings: queryNode.settings,
87
85
  });
88
86
  const endTime = Date.now();
89
87
  logger.logQuery({
@@ -110,9 +108,9 @@ export class ExecutorFeature {
110
108
  throw error;
111
109
  }
112
110
  }
113
- toSQLWithoutParameters() {
114
- const config = this.builder.getConfig();
115
- return this.builder.getDialect().compileQuery(config, {
111
+ compileQuery() {
112
+ const queryNode = this.builder.toQueryNode();
113
+ return this.builder.getDialect().compileQuery(queryNode, {
116
114
  tableName: this.builder.getTableName(),
117
115
  });
118
116
  }
@@ -1,99 +1,13 @@
1
1
  import type { BuilderState, SchemaDefinition } from '../types/builder-state.js';
2
2
  import { QueryBuilder } from '../query-builder.js';
3
- import { FilterOperator } from '../../types/index.js';
3
+ import { FilterOperator, type ExprNode, type SelectQueryNode } from '../../types/index.js';
4
4
  import { PredicateExpression } from '../utils/predicate-builder.js';
5
5
  export declare class FilteringFeature<Schema extends SchemaDefinition<Schema>, State extends BuilderState<Schema, string, any, keyof Schema, Partial<Record<string, keyof Schema>>>> {
6
6
  private builder;
7
7
  constructor(builder: QueryBuilder<Schema, State>);
8
- addCondition(conjunction: 'AND' | 'OR', column: string | string[], operator: FilterOperator, value: any): {
9
- where: import("../../types/base.js").WhereCondition[];
10
- parameters: any[];
11
- select?: (string | keyof State["output"])[] | undefined;
12
- groupBy?: string[];
13
- having?: string[];
14
- limit?: number;
15
- offset?: number;
16
- distinct?: boolean;
17
- orderBy?: {
18
- column: keyof State["output"] | import("../../types/schema.js").TableColumn<Schema>;
19
- direction: import("../../types/base.js").OrderDirection;
20
- }[] | undefined;
21
- joins?: import("../../types/base.js").JoinClause[];
22
- ctes?: string[];
23
- unionQueries?: string[];
24
- settings?: import("@clickhouse/client-common").ClickHouseSettings;
25
- };
26
- addExpressionCondition(conjunction: 'AND' | 'OR', expression: PredicateExpression): {
27
- where: import("../../types/base.js").WhereCondition[];
28
- parameters: any[];
29
- select?: (string | keyof State["output"])[] | undefined;
30
- groupBy?: string[];
31
- having?: string[];
32
- limit?: number;
33
- offset?: number;
34
- distinct?: boolean;
35
- orderBy?: {
36
- column: keyof State["output"] | import("../../types/schema.js").TableColumn<Schema>;
37
- direction: import("../../types/base.js").OrderDirection;
38
- }[] | undefined;
39
- joins?: import("../../types/base.js").JoinClause[];
40
- ctes?: string[];
41
- unionQueries?: string[];
42
- settings?: import("@clickhouse/client-common").ClickHouseSettings;
43
- };
44
- startWhereGroup(): {
45
- where: import("../../types/base.js").WhereCondition[];
46
- select?: (string | keyof State["output"])[] | undefined;
47
- groupBy?: string[];
48
- having?: string[];
49
- limit?: number;
50
- offset?: number;
51
- distinct?: boolean;
52
- orderBy?: {
53
- column: keyof State["output"] | import("../../types/schema.js").TableColumn<Schema>;
54
- direction: import("../../types/base.js").OrderDirection;
55
- }[] | undefined;
56
- joins?: import("../../types/base.js").JoinClause[];
57
- parameters?: any[];
58
- ctes?: string[];
59
- unionQueries?: string[];
60
- settings?: import("@clickhouse/client-common").ClickHouseSettings;
61
- };
62
- startOrWhereGroup(): {
63
- where: import("../../types/base.js").WhereCondition[];
64
- select?: (string | keyof State["output"])[] | undefined;
65
- groupBy?: string[];
66
- having?: string[];
67
- limit?: number;
68
- offset?: number;
69
- distinct?: boolean;
70
- orderBy?: {
71
- column: keyof State["output"] | import("../../types/schema.js").TableColumn<Schema>;
72
- direction: import("../../types/base.js").OrderDirection;
73
- }[] | undefined;
74
- joins?: import("../../types/base.js").JoinClause[];
75
- parameters?: any[];
76
- ctes?: string[];
77
- unionQueries?: string[];
78
- settings?: import("@clickhouse/client-common").ClickHouseSettings;
79
- };
80
- endWhereGroup(): {
81
- where: import("../../types/base.js").WhereCondition[];
82
- select?: (string | keyof State["output"])[] | undefined;
83
- groupBy?: string[];
84
- having?: string[];
85
- limit?: number;
86
- offset?: number;
87
- distinct?: boolean;
88
- orderBy?: {
89
- column: keyof State["output"] | import("../../types/schema.js").TableColumn<Schema>;
90
- direction: import("../../types/base.js").OrderDirection;
91
- }[] | undefined;
92
- joins?: import("../../types/base.js").JoinClause[];
93
- parameters?: any[];
94
- ctes?: string[];
95
- unionQueries?: string[];
96
- settings?: import("@clickhouse/client-common").ClickHouseSettings;
97
- };
8
+ private wrapValue;
9
+ addCondition(clause: 'where' | 'prewhere', conjunction: 'AND' | 'OR', column: string | string[], operator: FilterOperator, value: any): SelectQueryNode<State['output'], Schema>;
10
+ addExpressionCondition(clause: 'where' | 'prewhere', conjunction: 'AND' | 'OR', expression: PredicateExpression): SelectQueryNode<State['output'], Schema>;
11
+ addGroup(clause: 'where' | 'prewhere', conjunction: 'AND' | 'OR', expression: ExprNode | undefined): SelectQueryNode<State['output'], Schema>;
98
12
  }
99
13
  //# sourceMappingURL=filtering.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"filtering.d.ts","sourceRoot":"","sources":["../../../src/core/features/filtering.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAEpE,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,YAAY,CACV,WAAW,EAAE,KAAK,GAAG,IAAI,EACzB,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EACzB,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,GAAG;;;;;;;;;;;;;;;;;;IAwDZ,sBAAsB,CACpB,WAAW,EAAE,KAAK,GAAG,IAAI,EACzB,UAAU,EAAE,mBAAmB;;;;;;;;;;;;;;;;;;IAsBjC,eAAe;;;;;;;;;;;;;;;;;;IAkBf,iBAAiB;;;;;;;;;;;;;;;;;;IAkBjB,aAAa;;;;;;;;;;;;;;;;;;CAiBd"}
1
+ {"version":3,"file":"filtering.d.ts","sourceRoot":"","sources":["../../../src/core/features/filtering.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,KAAK,eAAe,EAAkB,MAAM,sBAAsB,CAAC;AAC3G,OAAO,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AA2BpE,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,OAAO,CAAC,SAAS;IAuBjB,YAAY,CACV,MAAM,EAAE,OAAO,GAAG,UAAU,EAC5B,WAAW,EAAE,KAAK,GAAG,IAAI,EACzB,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,EACzB,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,GAAG,GACT,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAyC3C,sBAAsB,CACpB,MAAM,EAAE,OAAO,GAAG,UAAU,EAC5B,WAAW,EAAE,KAAK,GAAG,IAAI,EACzB,UAAU,EAAE,mBAAmB,GAC9B,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAe3C,QAAQ,CACN,MAAM,EAAE,OAAO,GAAG,UAAU,EAC5B,WAAW,EAAE,KAAK,GAAG,IAAI,EACzB,UAAU,EAAE,QAAQ,GAAG,SAAS,GAC/B,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAgB5C"}
@@ -1,35 +1,58 @@
1
+ function appendExpression(existing, next, conjunction) {
2
+ if (!existing) {
3
+ return next;
4
+ }
5
+ if (existing.kind === 'sequence') {
6
+ return {
7
+ ...existing,
8
+ items: [...existing.items, { conjunction, expression: next }],
9
+ };
10
+ }
11
+ return {
12
+ kind: 'sequence',
13
+ items: [
14
+ { expression: existing },
15
+ { conjunction, expression: next },
16
+ ],
17
+ };
18
+ }
1
19
  export class FilteringFeature {
2
20
  builder;
3
21
  constructor(builder) {
4
22
  this.builder = builder;
5
23
  }
6
- addCondition(conjunction, column, operator, value) {
7
- const config = this.builder.getConfig();
8
- const where = config.where || [];
9
- const parameters = config.parameters || [];
24
+ wrapValue(operator, value) {
25
+ if (operator === 'inSubquery' || operator === 'globalInSubquery' || operator === 'inTable' || operator === 'globalInTable') {
26
+ return value;
27
+ }
28
+ if (operator === 'between') {
29
+ return [
30
+ { kind: 'value', value: value[0] },
31
+ { kind: 'value', value: value[1] },
32
+ ];
33
+ }
34
+ if (operator === 'inTuple' || operator === 'globalInTuple') {
35
+ return value.map((tuple) => tuple.map(tupleValue => ({ kind: 'value', value: tupleValue })));
36
+ }
37
+ if (operator === 'in' || operator === 'notIn' || operator === 'globalIn' || operator === 'globalNotIn') {
38
+ return value.map((item) => ({ kind: 'value', value: item }));
39
+ }
40
+ return { kind: 'value', value };
41
+ }
42
+ addCondition(clause, conjunction, column, operator, value) {
43
+ const query = this.builder.getQueryNode();
10
44
  const columnString = Array.isArray(column)
11
45
  ? `(${column.map(String).join(', ')})`
12
46
  : String(column);
13
- where.push({
14
- column: columnString,
15
- operator,
16
- value,
17
- conjunction,
18
- type: 'condition'
19
- });
20
47
  if (operator === 'in' || operator === 'notIn' || operator === 'globalIn' || operator === 'globalNotIn') {
21
48
  if (!Array.isArray(value)) {
22
49
  throw new Error(`Expected an array for ${operator} operator, but got ${typeof value}`);
23
50
  }
24
- parameters.push(...value);
25
51
  }
26
52
  else if (operator === 'inTuple' || operator === 'globalInTuple') {
27
53
  if (!Array.isArray(value)) {
28
54
  throw new Error(`Expected an array of tuples for ${operator} operator, but got ${typeof value}`);
29
55
  }
30
- value.forEach((tuple) => {
31
- parameters.push(...tuple);
32
- });
33
56
  }
34
57
  else if (operator === 'inSubquery' || operator === 'globalInSubquery') {
35
58
  if (typeof value !== 'string') {
@@ -41,78 +64,41 @@ export class FilteringFeature {
41
64
  throw new Error(`Expected a string (table name) for ${operator} operator, but got ${typeof value}`);
42
65
  }
43
66
  }
44
- else if (operator === 'between') {
45
- parameters.push(value[0], value[1]);
46
- }
47
- else {
48
- parameters.push(value);
49
- }
67
+ const nextExpr = {
68
+ kind: 'condition',
69
+ column: columnString,
70
+ operator,
71
+ value: this.wrapValue(operator, value),
72
+ };
50
73
  return {
51
- ...config,
52
- where,
53
- parameters
74
+ ...query,
75
+ [clause]: appendExpression(query[clause], nextExpr, conjunction)
54
76
  };
55
77
  }
56
- addExpressionCondition(conjunction, expression) {
57
- const config = this.builder.getConfig();
58
- const where = config.where || [];
59
- const parameters = config.parameters || [];
60
- where.push({
61
- type: 'expression',
78
+ addExpressionCondition(clause, conjunction, expression) {
79
+ const query = this.builder.getQueryNode();
80
+ const nextExpr = {
81
+ kind: 'raw',
62
82
  expression: expression.sql,
63
- parameters: expression.parameters,
64
- conjunction
65
- });
66
- parameters.push(...expression.parameters);
67
- return {
68
- ...config,
69
- where,
70
- parameters
83
+ parameters: expression.parameters.map(value => ({ kind: 'value', value })),
71
84
  };
72
- }
73
- startWhereGroup() {
74
- const config = this.builder.getConfig();
75
- const where = config.where || [];
76
- where.push({
77
- column: '',
78
- operator: 'eq',
79
- value: null,
80
- conjunction: 'AND',
81
- type: 'group-start'
82
- });
83
85
  return {
84
- ...config,
85
- where
86
+ ...query,
87
+ [clause]: appendExpression(query[clause], nextExpr, conjunction)
86
88
  };
87
89
  }
88
- startOrWhereGroup() {
89
- const config = this.builder.getConfig();
90
- const where = config.where || [];
91
- where.push({
92
- column: '',
93
- operator: 'eq',
94
- value: null,
95
- conjunction: 'OR',
96
- type: 'group-start'
97
- });
98
- return {
99
- ...config,
100
- where
90
+ addGroup(clause, conjunction, expression) {
91
+ const query = this.builder.getQueryNode();
92
+ if (!expression) {
93
+ return query;
94
+ }
95
+ const grouped = {
96
+ kind: 'group',
97
+ expression,
101
98
  };
102
- }
103
- endWhereGroup() {
104
- const config = this.builder.getConfig();
105
- const where = config.where || [];
106
- where.push({
107
- column: '',
108
- operator: 'eq',
109
- value: null,
110
- conjunction: 'AND',
111
- type: 'group-end'
112
- });
113
99
  return {
114
- ...config,
115
- where
100
+ ...query,
101
+ [clause]: appendExpression(query[clause], grouped, conjunction)
116
102
  };
117
103
  }
118
104
  }
@@ -1,26 +1,9 @@
1
1
  import type { BuilderState, SchemaDefinition } from '../types/builder-state.js';
2
2
  import { QueryBuilder } from '../query-builder.js';
3
- import { JoinType } from '../../types/index.js';
3
+ import { JoinType, type SelectQueryNode } from '../../types/index.js';
4
4
  export declare class JoinFeature<Schema extends SchemaDefinition<Schema>, State extends BuilderState<Schema, string, any, keyof Schema, Partial<Record<string, keyof Schema>>>> {
5
5
  private builder;
6
6
  constructor(builder: QueryBuilder<Schema, State>);
7
- addJoin<TableName extends keyof Schema>(type: JoinType, table: TableName, leftColumn: string, rightColumn: `${TableName & string}.${keyof Schema[TableName] & string}`, alias?: string): {
8
- joins: import("../../types/base.js").JoinClause[];
9
- select?: (string | keyof State["output"])[] | undefined;
10
- where?: import("../../types/base.js").WhereCondition[];
11
- groupBy?: string[];
12
- having?: string[];
13
- limit?: number;
14
- offset?: number;
15
- distinct?: boolean;
16
- orderBy?: {
17
- column: keyof State["output"] | import("../../types/schema.js").TableColumn<Schema>;
18
- direction: import("../../types/base.js").OrderDirection;
19
- }[] | undefined;
20
- parameters?: any[];
21
- ctes?: string[];
22
- unionQueries?: string[];
23
- settings?: import("@clickhouse/client-common").ClickHouseSettings;
24
- };
7
+ addJoin<TableName extends keyof Schema>(type: JoinType, table: TableName, leftColumn: string, rightColumn: `${TableName & string}.${keyof Schema[TableName] & string}`, alias?: string, leftSource?: string): SelectQueryNode<State['output'], Schema>;
25
8
  }
26
9
  //# sourceMappingURL=joins.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"joins.d.ts","sourceRoot":"","sources":["../../../src/core/features/joins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,qBAAa,WAAW,CACtB,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,SAAS,SAAS,MAAM,MAAM,EACpC,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,GAAG,SAAS,GAAG,MAAM,IAAI,MAAM,MAAM,CAAC,SAAS,CAAC,GAAG,MAAM,EAAE,EACxE,KAAK,CAAC,EAAE,MAAM;;;;;;;;;;;;;;;;;;CAYjB"}
1
+ {"version":3,"file":"joins.d.ts","sourceRoot":"","sources":["../../../src/core/features/joins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEtE,qBAAa,WAAW,CACtB,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,SAAS,SAAS,MAAM,MAAM,EACpC,IAAI,EAAE,QAAQ,EACd,KAAK,EAAE,SAAS,EAChB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,GAAG,SAAS,GAAG,MAAM,IAAI,MAAM,MAAM,CAAC,SAAS,CAAC,GAAG,MAAM,EAAE,EACxE,KAAK,CAAC,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,GAClB,eAAe,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAsB5C"}
@@ -3,13 +3,24 @@ export class JoinFeature {
3
3
  constructor(builder) {
4
4
  this.builder = builder;
5
5
  }
6
- addJoin(type, table, leftColumn, rightColumn, alias) {
7
- const config = this.builder.getConfig();
6
+ addJoin(type, table, leftColumn, rightColumn, alias, leftSource) {
7
+ const query = this.builder.getQueryNode();
8
+ const renderedRightColumn = alias
9
+ ? rightColumn.replace(`${String(table)}.`, `${alias}.`)
10
+ : rightColumn;
8
11
  const newConfig = {
9
- ...config,
12
+ ...query,
10
13
  joins: [
11
- ...(config.joins || []),
12
- { type, table: String(table), leftColumn: String(leftColumn), rightColumn, alias }
14
+ ...(query.joins || []),
15
+ {
16
+ kind: 'join',
17
+ type,
18
+ table: String(table),
19
+ leftColumn: String(leftColumn),
20
+ leftSource,
21
+ rightColumn: renderedRightColumn,
22
+ alias,
23
+ }
13
24
  ]
14
25
  };
15
26
  return newConfig;