dsl-to-sql 1.0.0-fabric-1p-development.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. package/.turbo/turbo-build.log +9 -0
  2. package/.turbo/turbo-check-types.log +4 -0
  3. package/.turbo/turbo-lint.log +126 -0
  4. package/README.md +45 -0
  5. package/coverage/base.css +224 -0
  6. package/coverage/block-navigation.js +87 -0
  7. package/coverage/favicon.png +0 -0
  8. package/coverage/index.html +236 -0
  9. package/coverage/prettify.css +1 -0
  10. package/coverage/prettify.js +2 -0
  11. package/coverage/sort-arrow-sprite.png +0 -0
  12. package/coverage/sorter.js +210 -0
  13. package/coverage/src/constants.ts.html +826 -0
  14. package/coverage/src/database_types.ts.html +136 -0
  15. package/coverage/src/epm-query-builder/EpmQueryBuilder.ts.html +166 -0
  16. package/coverage/src/epm-query-builder/base/BaseAdvancedAggregations.ts.html +568 -0
  17. package/coverage/src/epm-query-builder/base/BaseAnalyticalFunctions.ts.html +694 -0
  18. package/coverage/src/epm-query-builder/base/BaseCTEGenerator.ts.html +1459 -0
  19. package/coverage/src/epm-query-builder/base/BaseCountQueryBuilder.ts.html +400 -0
  20. package/coverage/src/epm-query-builder/base/BaseMeasureBuilder.ts.html +295 -0
  21. package/coverage/src/epm-query-builder/base/BaseOrderBuilder.ts.html +670 -0
  22. package/coverage/src/epm-query-builder/base/BasePaginationBuilder.ts.html +364 -0
  23. package/coverage/src/epm-query-builder/base/BaseQueryBuilder.ts.html +238 -0
  24. package/coverage/src/epm-query-builder/base/BaseRollupBuilder.ts.html +532 -0
  25. package/coverage/src/epm-query-builder/base/BaseSqlBuilder.ts.html +601 -0
  26. package/coverage/src/epm-query-builder/base/BaseSuperFilterBuilder.ts.html +1966 -0
  27. package/coverage/src/epm-query-builder/base/BaseUtilities.ts.html +1798 -0
  28. package/coverage/src/epm-query-builder/base/ColumnRefUtils.ts.html +211 -0
  29. package/coverage/src/epm-query-builder/base/RelationshipResolver.ts.html +706 -0
  30. package/coverage/src/epm-query-builder/base/SharedFilterBuilder.ts.html +1717 -0
  31. package/coverage/src/epm-query-builder/base/index.html +326 -0
  32. package/coverage/src/epm-query-builder/constants/Aggregations.ts.html +133 -0
  33. package/coverage/src/epm-query-builder/constants/Database.ts.html +103 -0
  34. package/coverage/src/epm-query-builder/constants/Source.ts.html +106 -0
  35. package/coverage/src/epm-query-builder/constants/index.html +146 -0
  36. package/coverage/src/epm-query-builder/dialects/duckdb/DuckDbAdvancedAggregations.ts.html +286 -0
  37. package/coverage/src/epm-query-builder/dialects/duckdb/DuckDbJoinBuilder.ts.html +280 -0
  38. package/coverage/src/epm-query-builder/dialects/duckdb/DuckDbMeasureBuilder.ts.html +1924 -0
  39. package/coverage/src/epm-query-builder/dialects/duckdb/DuckDbOrderBuilder.ts.html +769 -0
  40. package/coverage/src/epm-query-builder/dialects/duckdb/DuckDbPaginationBuilder.ts.html +643 -0
  41. package/coverage/src/epm-query-builder/dialects/duckdb/DuckDbQueryBuilder.ts.html +2644 -0
  42. package/coverage/src/epm-query-builder/dialects/duckdb/DuckDbRollupBuilder.ts.html +478 -0
  43. package/coverage/src/epm-query-builder/dialects/duckdb/DuckDbSuperFilterBuilder.ts.html +1195 -0
  44. package/coverage/src/epm-query-builder/dialects/duckdb/index.html +221 -0
  45. package/coverage/src/epm-query-builder/errors/QueryBuilderErrors.ts.html +280 -0
  46. package/coverage/src/epm-query-builder/errors/index.html +116 -0
  47. package/coverage/src/epm-query-builder/index.html +116 -0
  48. package/coverage/src/epm-query-builder/interfaces/IDatabaseQueryBuilder.ts.html +100 -0
  49. package/coverage/src/epm-query-builder/interfaces/index.html +131 -0
  50. package/coverage/src/epm-query-builder/interfaces/index.ts.html +88 -0
  51. package/coverage/src/epm-query-builder/utils/format.ts.html +151 -0
  52. package/coverage/src/epm-query-builder/utils/index.html +146 -0
  53. package/coverage/src/epm-query-builder/utils/sql.ts.html +247 -0
  54. package/coverage/src/epm-query-builder/utils/validation.ts.html +124 -0
  55. package/coverage/src/epm-query-builder/validation/QueryOptionsValidator.ts.html +631 -0
  56. package/coverage/src/epm-query-builder/validation/SqlQueryValidator.ts.html +475 -0
  57. package/coverage/src/epm-query-builder/validation/index.html +131 -0
  58. package/coverage/src/filters/FilterConditionBuilder.ts.html +427 -0
  59. package/coverage/src/filters/filter-types.ts.html +484 -0
  60. package/coverage/src/filters/index.html +131 -0
  61. package/coverage/src/index.html +176 -0
  62. package/coverage/src/index.ts.html +103 -0
  63. package/coverage/src/js-lib/JsToSqlParser.ts.html +736 -0
  64. package/coverage/src/js-lib/ParseContext.ts.html +532 -0
  65. package/coverage/src/js-lib/db/azuresql/AzureSqlCallExpressionVisitor.ts.html +196 -0
  66. package/coverage/src/js-lib/db/azuresql/index.html +116 -0
  67. package/coverage/src/js-lib/db/base/ArrayExpressionVisitor.ts.html +133 -0
  68. package/coverage/src/js-lib/db/base/AssignmentExpressionVisitor.ts.html +187 -0
  69. package/coverage/src/js-lib/db/base/BinaryExpressionVisitor.ts.html +223 -0
  70. package/coverage/src/js-lib/db/base/CallExpressionVisitor.ts.html +5479 -0
  71. package/coverage/src/js-lib/db/base/IdentifierVisitor.ts.html +283 -0
  72. package/coverage/src/js-lib/db/base/LiteralVisitor.ts.html +199 -0
  73. package/coverage/src/js-lib/db/base/MemberExpressionVisitor.ts.html +193 -0
  74. package/coverage/src/js-lib/db/base/ProgramVisitor.ts.html +139 -0
  75. package/coverage/src/js-lib/db/base/UnaryExpressionVisitor.ts.html +181 -0
  76. package/coverage/src/js-lib/db/base/VisitorInterface.ts.html +103 -0
  77. package/coverage/src/js-lib/db/base/index.html +251 -0
  78. package/coverage/src/js-lib/db/bigquery/BigQueryCallExpressionVisitor.ts.html +1747 -0
  79. package/coverage/src/js-lib/db/bigquery/index.html +116 -0
  80. package/coverage/src/js-lib/db/commonTransforms.ts.html +2074 -0
  81. package/coverage/src/js-lib/db/databricks/DatabricksCallExpressionVisitor.ts.html +1303 -0
  82. package/coverage/src/js-lib/db/databricks/index.html +116 -0
  83. package/coverage/src/js-lib/db/fabricsql/FabricSqlCallExpressionVisitor.ts.html +196 -0
  84. package/coverage/src/js-lib/db/fabricsql/index.html +116 -0
  85. package/coverage/src/js-lib/db/fabricwarehouse/FabricWarehouseCallExpressionVisitor.ts.html +292 -0
  86. package/coverage/src/js-lib/db/fabricwarehouse/index.html +116 -0
  87. package/coverage/src/js-lib/db/index.html +116 -0
  88. package/coverage/src/js-lib/db/postgresql/PostgreSqlCallExpressionVisitor.ts.html +985 -0
  89. package/coverage/src/js-lib/db/postgresql/index.html +116 -0
  90. package/coverage/src/js-lib/db/redshift/RedshiftCallExpressionVisitor.ts.html +685 -0
  91. package/coverage/src/js-lib/db/redshift/index.html +116 -0
  92. package/coverage/src/js-lib/db/sample/SampleCallExpressionVisitor.ts.html +196 -0
  93. package/coverage/src/js-lib/db/sample/index.html +116 -0
  94. package/coverage/src/js-lib/db/snowflake/SnowflakeCallExpressionVisitor.ts.html +1447 -0
  95. package/coverage/src/js-lib/db/snowflake/index.html +116 -0
  96. package/coverage/src/js-lib/db/validator/FormulaValidator.ts.html +4162 -0
  97. package/coverage/src/js-lib/db/validator/index.html +116 -0
  98. package/coverage/src/js-lib/index.html +131 -0
  99. package/coverage/src/js-lib/objects/BaseObject.ts.html +169 -0
  100. package/coverage/src/js-lib/objects/DateObject.ts.html +169 -0
  101. package/coverage/src/js-lib/objects/PctObject.ts.html +178 -0
  102. package/coverage/src/js-lib/objects/index.html +146 -0
  103. package/coverage/src/query-builder/PaginationBuilder.ts.html +142 -0
  104. package/coverage/src/query-builder/QueryBuilder.ts.html +3118 -0
  105. package/coverage/src/query-builder/SuperFilterBuilder.ts.html +1969 -0
  106. package/coverage/src/query-builder/index.html +146 -0
  107. package/coverage/src/runtime_var.ts.html +109 -0
  108. package/coverage/src/sql-lib/binary_expr.ts.html +133 -0
  109. package/coverage/src/sql-lib/case.ts.html +133 -0
  110. package/coverage/src/sql-lib/column.ts.html +139 -0
  111. package/coverage/src/sql-lib/else.ts.html +124 -0
  112. package/coverage/src/sql-lib/function.ts.html +112 -0
  113. package/coverage/src/sql-lib/index.html +251 -0
  114. package/coverage/src/sql-lib/join.ts.html +127 -0
  115. package/coverage/src/sql-lib/literal.ts.html +130 -0
  116. package/coverage/src/sql-lib/select.ts.html +547 -0
  117. package/coverage/src/sql-lib/unary_expr.ts.html +112 -0
  118. package/coverage/src/sql-lib/when.ts.html +130 -0
  119. package/coverage/src/sql_query_gen.ts.html +535 -0
  120. package/coverage/src/superFilter/DateFilterFactory.ts.html +625 -0
  121. package/coverage/src/superFilter/dateFunction.ts.html +193 -0
  122. package/coverage/src/superFilter/index.html +131 -0
  123. package/coverage/src/utils.ts.html +571 -0
  124. package/dist/index.cjs +8440 -0
  125. package/dist/index.d.cts +927 -0
  126. package/dist/index.d.cts.map +1 -0
  127. package/dist/index.d.ts +927 -0
  128. package/dist/index.d.ts.map +1 -0
  129. package/dist/index.js +8387 -0
  130. package/dist/index.js.map +1 -0
  131. package/eslint.config.js +4 -0
  132. package/jest.config.ts +44 -0
  133. package/package.json +45 -0
  134. package/src/constants.ts +247 -0
  135. package/src/epm-query-builder/EpmQueryBuilder.ts +27 -0
  136. package/src/epm-query-builder/base/BaseAdvancedAggregations.ts +161 -0
  137. package/src/epm-query-builder/base/BaseAnalyticalFunctions.ts +203 -0
  138. package/src/epm-query-builder/base/BaseCTEGenerator.ts +458 -0
  139. package/src/epm-query-builder/base/BaseCountQueryBuilder.ts +105 -0
  140. package/src/epm-query-builder/base/BaseMeasureBuilder.ts +87 -0
  141. package/src/epm-query-builder/base/BaseOrderBuilder.ts +195 -0
  142. package/src/epm-query-builder/base/BasePaginationBuilder.ts +93 -0
  143. package/src/epm-query-builder/base/BaseQueryBuilder.ts +51 -0
  144. package/src/epm-query-builder/base/BaseRollupBuilder.ts +149 -0
  145. package/src/epm-query-builder/base/BaseSqlBuilder.ts +172 -0
  146. package/src/epm-query-builder/base/BaseSuperFilterBuilder.ts +627 -0
  147. package/src/epm-query-builder/base/BaseUtilities.ts +571 -0
  148. package/src/epm-query-builder/base/ColumnRefUtils.ts +42 -0
  149. package/src/epm-query-builder/base/RelationshipResolver.ts +207 -0
  150. package/src/epm-query-builder/base/SharedFilterBuilder.ts +544 -0
  151. package/src/epm-query-builder/constants/Aggregations.ts +16 -0
  152. package/src/epm-query-builder/constants/Database.ts +6 -0
  153. package/src/epm-query-builder/constants/Source.ts +7 -0
  154. package/src/epm-query-builder/dialects/duckdb/DuckDbAdvancedAggregations.ts +67 -0
  155. package/src/epm-query-builder/dialects/duckdb/DuckDbJoinBuilder.ts +65 -0
  156. package/src/epm-query-builder/dialects/duckdb/DuckDbMeasureBuilder.ts +626 -0
  157. package/src/epm-query-builder/dialects/duckdb/DuckDbOrderBuilder.ts +228 -0
  158. package/src/epm-query-builder/dialects/duckdb/DuckDbPaginationBuilder.ts +186 -0
  159. package/src/epm-query-builder/dialects/duckdb/DuckDbQueryBuilder.ts +853 -0
  160. package/src/epm-query-builder/dialects/duckdb/DuckDbRollupBuilder.ts +131 -0
  161. package/src/epm-query-builder/dialects/duckdb/DuckDbSuperFilterBuilder.ts +370 -0
  162. package/src/epm-query-builder/errors/QueryBuilderErrors.ts +65 -0
  163. package/src/epm-query-builder/interfaces/IDatabaseQueryBuilder.ts +5 -0
  164. package/src/epm-query-builder/interfaces/index.ts +1 -0
  165. package/src/epm-query-builder/types/query-builder-types.d.ts +289 -0
  166. package/src/epm-query-builder/utils/format.ts +22 -0
  167. package/src/epm-query-builder/utils/sql.ts +54 -0
  168. package/src/epm-query-builder/utils/validation.ts +13 -0
  169. package/src/epm-query-builder/validation/QueryOptionsValidator.ts +182 -0
  170. package/src/epm-query-builder/validation/SqlQueryValidator.ts +130 -0
  171. package/src/filters/FilterConditionBuilder.ts +114 -0
  172. package/src/filters/filter-types.ts +133 -0
  173. package/src/index.ts +10 -0
  174. package/src/js-lib/JsToSqlParser.ts +217 -0
  175. package/src/js-lib/ParseContext.ts +149 -0
  176. package/src/js-lib/db/base/ArrayExpressionVisitor.ts +16 -0
  177. package/src/js-lib/db/base/AssignmentExpressionVisitor.ts +34 -0
  178. package/src/js-lib/db/base/BinaryExpressionVisitor.ts +46 -0
  179. package/src/js-lib/db/base/CallExpressionVisitor.ts +1798 -0
  180. package/src/js-lib/db/base/IdentifierVisitor.ts +66 -0
  181. package/src/js-lib/db/base/LiteralVisitor.ts +38 -0
  182. package/src/js-lib/db/base/MemberExpressionVisitor.ts +36 -0
  183. package/src/js-lib/db/base/ProgramVisitor.ts +18 -0
  184. package/src/js-lib/db/base/UnaryExpressionVisitor.ts +32 -0
  185. package/src/js-lib/db/base/VisitorInterface.ts +6 -0
  186. package/src/js-lib/db/validator/FormulaValidator.ts +1235 -0
  187. package/src/js-lib/objects/BaseObject.ts +28 -0
  188. package/src/js-lib/objects/DateObject.ts +28 -0
  189. package/src/js-lib/objects/PctObject.ts +31 -0
  190. package/src/query-builder/PaginationBuilder.ts +19 -0
  191. package/src/query-builder/QueryBuilder.ts +1035 -0
  192. package/src/query-builder/SuperFilterBuilder.ts +628 -0
  193. package/src/runtime_var.ts +8 -0
  194. package/src/sql-lib/binary_expr.ts +16 -0
  195. package/src/sql-lib/case.ts +16 -0
  196. package/src/sql-lib/column.ts +18 -0
  197. package/src/sql-lib/else.ts +13 -0
  198. package/src/sql-lib/function.ts +9 -0
  199. package/src/sql-lib/join.ts +14 -0
  200. package/src/sql-lib/literal.ts +15 -0
  201. package/src/sql-lib/select.ts +154 -0
  202. package/src/sql-lib/unary_expr.ts +9 -0
  203. package/src/sql-lib/when.ts +15 -0
  204. package/src/sql-types.d.ts +565 -0
  205. package/src/sql_query_gen.ts +150 -0
  206. package/src/superFilter/DateFilterFactory.ts +180 -0
  207. package/src/superFilter/dateFunction.ts +36 -0
  208. package/src/utils.ts +354 -0
  209. package/test-output/report/junit.xml +329 -0
  210. package/tests/JsToSqlParser.test.ts +163 -0
  211. package/tests/QueryBuilder.test.ts +1320 -0
  212. package/tests/js-lib/CallExpressionVisitor.test.ts +820 -0
  213. package/tests/mocks/MockQueryResolver.ts +14 -0
  214. package/tests/sanity.test.ts +146 -0
  215. package/tests/sql-lib/binary_expr.test.ts +75 -0
  216. package/tests/sql-lib/case.test.ts +117 -0
  217. package/tests/sql-lib/column.test.ts +87 -0
  218. package/tests/sql-lib/else.test.ts +56 -0
  219. package/tests/sql-lib/function.test.ts +96 -0
  220. package/tests/sql-lib/literal.test.ts +75 -0
  221. package/tests/sql-lib/select.test.ts +245 -0
  222. package/tests/sql-lib/unary_expr.test.ts +32 -0
  223. package/tests/utils.test.ts +13 -0
  224. package/tsconfig.json +24 -0
  225. package/tsdown.config.ts +23 -0
@@ -0,0 +1,228 @@
1
+ import { BaseOrderBuilder } from '@epm-query-builder/base/BaseOrderBuilder';
2
+ import { OrderByConfig, RowColumnConfig } from '@epm-query-builder/types/query-builder-types';
3
+ import { BaseUtilities } from '@epm-query-builder/base/BaseUtilities';
4
+
5
+ export class DuckDbOrderBuilder extends BaseOrderBuilder {
6
+ buildOrderByClause(): string {
7
+ const orderByClauses = this.buildDuckDbOrderByClauses();
8
+
9
+ if (orderByClauses.length === 0) {
10
+ return '';
11
+ }
12
+
13
+ return `ORDER BY ${orderByClauses.join(', ')}`;
14
+ }
15
+
16
+ private buildDuckDbOrderByClauses(): string[] {
17
+ const clauses: string[] = [];
18
+
19
+ if (this.hasRollupOrdering()) {
20
+ clauses.push(...this.buildDuckDbRollupOrderClauses());
21
+ }
22
+
23
+ if (this.options.orderBy?.length) {
24
+ clauses.push(...this.buildDuckDbCustomOrderClauses());
25
+ } else {
26
+ clauses.push(...this.buildDuckDbDefaultOrderClauses());
27
+ }
28
+
29
+ return clauses;
30
+ }
31
+
32
+ private buildDuckDbCustomOrderClauses(): string[] {
33
+ if (!this.options.orderBy?.length) {
34
+ return [];
35
+ }
36
+
37
+ return this.options.orderBy.map((orderBy) => {
38
+ const column = this.resolveDuckDbOrderByColumn(orderBy);
39
+ const direction = this.mapSortDirection(orderBy.type);
40
+ const nullsHandling = this.buildDuckDbNullsHandling(direction);
41
+
42
+ const isMonth =
43
+ (orderBy.columnName || '').toLowerCase().includes('month') ||
44
+ (orderBy.id || '').toLowerCase().includes('month');
45
+ const isQuarter =
46
+ (orderBy.columnName || '').toLowerCase().includes('quarter') ||
47
+ (orderBy.id || '').toLowerCase().includes('quarter');
48
+
49
+ if (isMonth) {
50
+ const monthOrder = BaseUtilities.buildMonthOrderKey(column);
51
+ return `${monthOrder} ${direction}${nullsHandling}`;
52
+ }
53
+ if (isQuarter) {
54
+ const quarterOrder = BaseUtilities.buildQuarterOrderKey(column);
55
+ return `${quarterOrder} ${direction}${nullsHandling}`;
56
+ }
57
+
58
+ return `${column} ${direction}${nullsHandling}`;
59
+ });
60
+ }
61
+
62
+ private buildDuckDbDefaultOrderClauses(): string[] {
63
+ const clauses: string[] = [];
64
+
65
+ if (this.options.rows?.length) {
66
+ this.options.rows.forEach((row) => {
67
+ const useDot = BaseUtilities.shouldUseDotNotation(this.options);
68
+ const column = useDot
69
+ ? this.formatDuckDbOrderByColumn(row)
70
+ : `"${BaseUtilities.extractColumnIdFromHierarchy(row.id)}"`;
71
+ const nullsHandling = this.buildDuckDbNullsHandling('ASC');
72
+ const isMonth =
73
+ (row.columnName || '').toLowerCase().includes('month') ||
74
+ (row.label || '').toLowerCase().includes('month');
75
+ const isQuarter =
76
+ (row.columnName || '').toLowerCase().includes('quarter') ||
77
+ (row.label || '').toLowerCase().includes('quarter');
78
+ if (isMonth) {
79
+ const monthOrder = BaseUtilities.buildMonthOrderKey(column);
80
+ clauses.push(`${monthOrder} ASC${nullsHandling}`);
81
+ } else if (isQuarter) {
82
+ const quarterOrder = BaseUtilities.buildQuarterOrderKey(column);
83
+ clauses.push(`${quarterOrder} ASC${nullsHandling}`);
84
+ } else {
85
+ clauses.push(`${column} ASC${nullsHandling}`);
86
+ }
87
+ });
88
+ }
89
+
90
+ if (this.options.columns?.length) {
91
+ this.options.columns.forEach((col) => {
92
+ const useDot = BaseUtilities.shouldUseDotNotation(this.options);
93
+ const column = useDot
94
+ ? this.formatDuckDbOrderByColumn(col)
95
+ : `"${BaseUtilities.extractColumnIdFromHierarchy(col.id)}"`;
96
+ const nullsHandling = this.buildDuckDbNullsHandling('ASC');
97
+ const isMonth =
98
+ (col.columnName || '').toLowerCase().includes('month') ||
99
+ (col.label || '').toLowerCase().includes('month');
100
+ const isQuarter =
101
+ (col.columnName || '').toLowerCase().includes('quarter') ||
102
+ (col.label || '').toLowerCase().includes('quarter');
103
+ if (isMonth) {
104
+ const monthOrder = BaseUtilities.buildMonthOrderKey(column);
105
+ clauses.push(`${monthOrder} ASC${nullsHandling}`);
106
+ } else if (isQuarter) {
107
+ const quarterOrder = BaseUtilities.buildQuarterOrderKey(column);
108
+ clauses.push(`${quarterOrder} ASC${nullsHandling}`);
109
+ } else {
110
+ clauses.push(`${column} ASC${nullsHandling}`);
111
+ }
112
+ });
113
+ }
114
+
115
+ return clauses;
116
+ }
117
+
118
+ private buildDuckDbRollupOrderClauses(): string[] {
119
+ const clauses: string[] = [];
120
+
121
+ if (this.options.rows?.length && !this.options.skipRollup) {
122
+ clauses.push('"[IsRowGrandTotal]" DESC NULLS LAST');
123
+
124
+ const rowCount = this.options.rows.length;
125
+ for (let i = 1; i < rowCount; i++) {
126
+ clauses.push(`"[IsDM${i - 1}Total]" DESC NULLS LAST`);
127
+ }
128
+ }
129
+
130
+ if (this.options.columns?.length && !this.options.skipRollup) {
131
+ clauses.push('"[IsColumnGrandTotal]" DESC NULLS LAST');
132
+
133
+ const rowCount = this.options.rows?.length || 0;
134
+ const columnCount = this.options.columns.length;
135
+ for (let i = 1; i < columnCount; i++) {
136
+ clauses.push(`"[IsDM${rowCount + i - 1}Total]" DESC NULLS LAST`);
137
+ }
138
+ }
139
+
140
+ return clauses;
141
+ }
142
+
143
+ private getRollupColumnPosition(columnName: string): number {
144
+ let position = 1;
145
+
146
+ if (this.options.rows?.length) {
147
+ position += this.options.rows.length;
148
+ }
149
+
150
+ if (this.options.columns?.length) {
151
+ position += this.options.columns.length;
152
+ }
153
+
154
+ if (this.options.values?.length) {
155
+ position += this.options.values.length;
156
+ }
157
+
158
+ position += 1;
159
+
160
+ if (columnName.includes('IsRowGrandTotal')) {
161
+ return position + 2;
162
+ } else if (columnName.includes('IsColumnGrandTotal')) {
163
+ return position + 3;
164
+ } else {
165
+ return position + 4;
166
+ }
167
+ }
168
+
169
+ private resolveDuckDbOrderByColumn(orderBy: OrderByConfig): string {
170
+ if (orderBy.isColumnPresentInOutput) {
171
+ if (orderBy.aggregationType) {
172
+ return `"${orderBy.aggregationType}__${orderBy.tableName}[${orderBy.columnName}]"`;
173
+ }
174
+ return `"${orderBy.tableName}[${orderBy.columnName}]"`;
175
+ }
176
+
177
+ const config: RowColumnConfig = {
178
+ id: orderBy.id,
179
+ columnName: orderBy.columnName,
180
+ tableName: orderBy.tableName,
181
+ label: orderBy.id,
182
+ type: 'Column',
183
+ };
184
+ return BaseUtilities.formatColumnReferenceForDb(config, this.options);
185
+ }
186
+
187
+ private formatDuckDbOrderByColumn(config: RowColumnConfig): string {
188
+ if (config.orderByRef) {
189
+ return BaseUtilities.formatColumnReferenceForDb(config, this.options);
190
+ }
191
+
192
+ return BaseUtilities.formatColumnReferenceForDb(config, this.options);
193
+ }
194
+
195
+ private buildDuckDbNullsHandling(direction: 'ASC' | 'DESC'): string {
196
+ return direction === 'DESC' ? ' NULLS LAST' : ' NULLS FIRST';
197
+ }
198
+
199
+ private isDateHierarchyColumn(config: RowColumnConfig): boolean {
200
+ const dateColumns = ['Month', 'Quarter', 'Year'];
201
+ return dateColumns.some((dateCol) =>
202
+ config.columnName?.toLowerCase().includes(dateCol.toLowerCase()),
203
+ );
204
+ }
205
+
206
+ private getDuckDbDateColumnName(columnName: string): string {
207
+ const dateColumnMap: Record<string, string> = {
208
+ Month: 'MonthNo',
209
+ Quarter: 'QuarterNo',
210
+ Year: 'Year',
211
+ };
212
+
213
+ for (const [key, value] of Object.entries(dateColumnMap)) {
214
+ if (columnName.toLowerCase().includes(key.toLowerCase())) {
215
+ return value;
216
+ }
217
+ }
218
+
219
+ return columnName;
220
+ }
221
+
222
+ protected hasRollupOrdering(): boolean {
223
+ return (
224
+ BaseUtilities.shouldGenerateRollupForOptions(this.options) &&
225
+ BaseUtilities.hasMeasuresInOptions(this.options)
226
+ );
227
+ }
228
+ }
@@ -0,0 +1,186 @@
1
+ import { BasePaginationBuilder } from '@epm-query-builder/base/BasePaginationBuilder';
2
+ import { PaginationConfig } from '@epm-query-builder/types/query-builder-types';
3
+ import { PaginationError } from '@epm-query-builder/errors/QueryBuilderErrors';
4
+ import { BaseUtilities } from '@epm-query-builder/base/BaseUtilities';
5
+
6
+ export class DuckDbPaginationBuilder extends BasePaginationBuilder {
7
+ buildLimitClause(): string {
8
+ if (!this.options.pagination) {
9
+ return '';
10
+ }
11
+
12
+ const { skip = 0, limit } = this.options.pagination;
13
+
14
+ if (limit === undefined || limit <= 0) {
15
+ return '';
16
+ }
17
+
18
+ if (skip > 0) {
19
+ return `LIMIT ${limit} OFFSET ${skip}`;
20
+ }
21
+
22
+ return `LIMIT ${limit}`;
23
+ }
24
+
25
+ buildOffsetClause(): string {
26
+ if (!this.options.pagination?.skip) {
27
+ return '';
28
+ }
29
+
30
+ return `OFFSET ${this.options.pagination.skip}`;
31
+ }
32
+
33
+ buildAdditionalWhere(): string {
34
+ const reference = this.options.pagination?.reference;
35
+
36
+ if (!reference || !reference.command) return '';
37
+
38
+ switch (reference.command) {
39
+ case 'NEXT_HEIR':
40
+ return this.buildNextHeirWhere(reference);
41
+ case 'SIBLING':
42
+ return this.buildSiblingWhere(reference);
43
+ case 'CHILDREN':
44
+ return this.buildChildrenWhere(reference);
45
+ default:
46
+ return '';
47
+ }
48
+ }
49
+
50
+ private buildNextHeirWhere(reference: PaginationConfig['reference']): string {
51
+ if (!reference?.dimensions?.length || !reference.nextToken?.length) {
52
+ return '';
53
+ }
54
+
55
+ if (reference.dimensions.length !== reference.nextToken.length) {
56
+ throw new PaginationError(
57
+ 'NEXT_HEIR',
58
+ 'dimensions and nextToken arrays must have the same length',
59
+ );
60
+ }
61
+
62
+ const conditions = reference.dimensions
63
+ .map((dim, index) => {
64
+ const tokenValue = reference.nextToken?.[index];
65
+ if (!tokenValue) return null;
66
+
67
+ const operator = this.getHierarchicalOperator(index, reference.dimensions!.length);
68
+ return `${BaseUtilities.sanitizeIdentifierString(dim)} ${operator} '${tokenValue}'`;
69
+ })
70
+ .filter((condition): condition is string => Boolean(condition));
71
+
72
+ if (conditions.length === 0) {
73
+ throw new PaginationError(
74
+ 'NEXT_HEIR',
75
+ 'no valid conditions generated from dimensions and nextToken',
76
+ );
77
+ }
78
+
79
+ const hierarchicalCondition = this.buildHierarchicalCondition(conditions);
80
+ return hierarchicalCondition;
81
+ }
82
+
83
+ private buildSiblingWhere(reference: PaginationConfig['reference']): string {
84
+ if (!reference?.dimensions?.length || !reference.instances?.length) {
85
+ return '';
86
+ }
87
+
88
+ if (reference.dimensions.length === 0 || reference.instances.length === 0) {
89
+ throw new PaginationError('SIBLING', 'dimensions and instances cannot be empty');
90
+ }
91
+
92
+ const parentConditions: string[] = [];
93
+ const siblingConditions: string[] = [];
94
+
95
+ reference.dimensions.forEach((dim, index) => {
96
+ const instanceValue = reference.instances?.[index];
97
+ if (instanceValue && index < reference.dimensions!.length - 1) {
98
+ parentConditions.push(
99
+ `${BaseUtilities.sanitizeIdentifierString(dim)} = '${instanceValue}'`,
100
+ );
101
+ } else if (instanceValue && index === reference.dimensions!.length - 1) {
102
+ siblingConditions.push(
103
+ `${BaseUtilities.sanitizeIdentifierString(dim)} != '${instanceValue}'`,
104
+ );
105
+ }
106
+ });
107
+
108
+ const allConditions = [...parentConditions, ...siblingConditions];
109
+
110
+ if (allConditions.length === 0) {
111
+ throw new PaginationError('SIBLING', 'no valid conditions generated');
112
+ }
113
+
114
+ return BaseUtilities.combineConditions(allConditions, 'AND');
115
+ }
116
+
117
+ private buildChildrenWhere(reference: PaginationConfig['reference']): string {
118
+ if (!reference?.dimensions || !reference.instances) {
119
+ return '';
120
+ }
121
+
122
+ const parentConditions = reference.dimensions
123
+ .slice(0, -1)
124
+ .map((dim, index) => {
125
+ const instanceValue = reference.instances?.[index];
126
+ return instanceValue ? `${dim} = '${instanceValue}'` : null;
127
+ })
128
+ .filter(Boolean);
129
+
130
+ if (parentConditions.length === 0) {
131
+ return '';
132
+ }
133
+
134
+ return parentConditions.join(' AND ');
135
+ }
136
+
137
+ buildPaginationCTE(): string {
138
+ if (!this.options.pagination?.reference?.command) {
139
+ return '';
140
+ }
141
+
142
+ const { reference } = this.options.pagination;
143
+
144
+ if (!reference.dimensions) {
145
+ return '';
146
+ }
147
+
148
+ return `pagination_context AS (
149
+ SELECT ${reference.dimensions.join(', ')}
150
+ FROM (VALUES ${this.buildPaginationValues(reference)}) AS context(${reference.dimensions.join(', ')})
151
+ )`;
152
+ }
153
+
154
+ private buildPaginationValues(reference: { instances?: string[]; nextToken?: string[] }): string {
155
+ if (!reference.instances || !reference.nextToken) {
156
+ return "('')";
157
+ }
158
+
159
+ const instances = reference.instances.map((val: string) => `'${val}'`).join(', ');
160
+ const tokens = reference.nextToken.map((val: string) => `'${val}'`).join(', ');
161
+
162
+ return `(${instances}), (${tokens})`;
163
+ }
164
+
165
+ private getHierarchicalOperator(index: number, totalLevels: number): string {
166
+ if (index < totalLevels - 1) {
167
+ return '>=';
168
+ }
169
+ return '>';
170
+ }
171
+
172
+ private buildHierarchicalCondition(conditions: string[]): string {
173
+ if (conditions.length === 1) {
174
+ return conditions[0];
175
+ }
176
+
177
+ const primaryCondition = conditions[0];
178
+ const secondaryConditions = conditions.slice(1);
179
+
180
+ if (secondaryConditions.length === 0) {
181
+ return primaryCondition;
182
+ }
183
+
184
+ return `(${primaryCondition} OR (${secondaryConditions.join(' OR ')}))`;
185
+ }
186
+ }