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,14 @@
1
+ import { QueryResolver, FilterResolverParams } from '../../src';
2
+ import { buildFilterCondition } from '../../src/filters/FilterConditionBuilder';
3
+
4
+ export class MockQueryResolver implements QueryResolver {
5
+ private tableName: string;
6
+
7
+ constructor(tableName: string) {
8
+ this.tableName = tableName;
9
+ }
10
+
11
+ filterResolver(params: FilterResolverParams): string {
12
+ return buildFilterCondition(this.tableName, params.filterConfig);
13
+ }
14
+ }
@@ -0,0 +1,146 @@
1
+ import { createJsToSqlParser } from '../src/js-lib/JsToSqlParser';
2
+ import { MDM_COLUMN_TYPE, ParseContext } from '../src/js-lib/ParseContext';
3
+
4
+ describe('sanity', () => {
5
+ test('should create sql query from formula for project status tracking', () => {
6
+ const formula = `IF(
7
+ AND(DueDate < TODAY(), Status != "Completed"), "Overdue",
8
+ IF(AND(StartDate <= TODAY(), DueDate >= TODAY(), Status != "Completed"), "In Progress",
9
+ IF(Status == "Completed", "Completed", "Not Started")))`;
10
+ const expectedSql = `CASE WHEN [DueDate] < CURRENT_DATE AND [Status] != 'Completed' THEN 'Overdue' WHEN [StartDate] <= CURRENT_DATE AND [DueDate] >= CURRENT_DATE AND [Status] != 'Completed' THEN 'In Progress' WHEN [Status] = 'Completed' THEN 'Completed' ELSE 'Not Started' END`;
11
+ const columnConfigMap = {
12
+ DueDate: {
13
+ columnName: 'DueDate',
14
+ columnType: MDM_COLUMN_TYPE.DATE,
15
+ columnMeta: { tableName: 'Project' },
16
+ },
17
+ Status: {
18
+ columnName: 'Status',
19
+ columnType: MDM_COLUMN_TYPE.TEXT,
20
+ columnMeta: { tableName: 'Project' },
21
+ },
22
+ StartDate: {
23
+ columnName: 'StartDate',
24
+ columnType: MDM_COLUMN_TYPE.DATE,
25
+ columnMeta: { tableName: 'Project' },
26
+ },
27
+ };
28
+ const context = new ParseContext({
29
+ columnConfigMap,
30
+ currentColumnId: 'ProjectStatus',
31
+ primaryKeyColumns: ['PK'],
32
+ tableName: 'Project',
33
+ });
34
+ const parser = createJsToSqlParser(context);
35
+ const ast = parser.parse(formula);
36
+ const resultSql = parser.toSql(ast);
37
+ expect(resultSql).toEqual(expectedSql);
38
+ });
39
+
40
+ test('should create sql query from formula for ROI', () => {
41
+ const formula = `IF(Revenue - Cost > 0, (Revenue - Cost) / Cost * 100, 0)`;
42
+ const expectedSql = `CASE WHEN (COALESCE([Revenue], 0) - COALESCE([Cost], 0)) > 0 THEN (COALESCE((CAST(COALESCE((COALESCE([Revenue], 0) - COALESCE([Cost], 0)), 0) AS FLOAT) / COALESCE([Cost], 0)), 0) * COALESCE(100, 0)) ELSE 0 END`;
43
+ const columnConfigMap = {
44
+ Revenue: {
45
+ columnName: 'Revenue',
46
+ columnType: MDM_COLUMN_TYPE.NUMBER,
47
+ columnMeta: { tableName: 'Investment' },
48
+ },
49
+ Cost: {
50
+ columnName: 'Cost',
51
+ columnType: MDM_COLUMN_TYPE.NUMBER,
52
+ columnMeta: { tableName: 'Investment' },
53
+ },
54
+ };
55
+ const context = new ParseContext({
56
+ columnConfigMap,
57
+ currentColumnId: 'ROI',
58
+ primaryKeyColumns: ['PK'],
59
+ tableName: 'Investment',
60
+ });
61
+ const parser = createJsToSqlParser(context);
62
+ const ast = parser.parse(formula);
63
+ const resultSql = parser.toSql(ast);
64
+ expect(resultSql).toEqual(expectedSql);
65
+ });
66
+
67
+ test('should create sql query from formula for priority sorting', () => {
68
+ const formula = `(IF(Deadline_Category == "Critical", 100, IF(Deadline_Category == "High", 70, IF(Deadline_Category == "Medium", 40, 10)))) +
69
+ (IF(Client_Tier == "Enterprise", 50, IF(Client_Tier == "Mid-Market", 30, 10))) +
70
+ (IF(Revenue_Impact > 100000, 50, IF(Revenue_Impact > 50000, 30, 10)))`;
71
+ const expectedSql = `(COALESCE((COALESCE(CASE WHEN [Deadline_Category] = 'Critical' THEN 100 WHEN [Deadline_Category] = 'High' THEN 70 WHEN [Deadline_Category] = 'Medium' THEN 40 ELSE 10 END, 0) + COALESCE(CASE WHEN [Client_Tier] = 'Enterprise' THEN 50 WHEN [Client_Tier] = 'Mid-Market' THEN 30 ELSE 10 END, 0)), 0) + COALESCE(CASE WHEN [Revenue_Impact] > 100000 THEN 50 WHEN [Revenue_Impact] > 50000 THEN 30 ELSE 10 END, 0))`;
72
+ const columnConfigMap = {
73
+ Revenue: {
74
+ columnName: 'Revenue',
75
+ columnType: MDM_COLUMN_TYPE.NUMBER,
76
+ columnMeta: { tableName: 'Revenue' },
77
+ },
78
+ Cost: {
79
+ columnName: 'Cost',
80
+ columnType: MDM_COLUMN_TYPE.NUMBER,
81
+ columnMeta: { tableName: 'Revenue' },
82
+ },
83
+ Deadline_Category: {
84
+ columnName: 'Deadline_Category',
85
+ columnType: MDM_COLUMN_TYPE.TEXT,
86
+ columnMeta: { tableName: 'Revenue' },
87
+ },
88
+ Client_Tier: {
89
+ columnName: 'Client_Tier',
90
+ columnType: MDM_COLUMN_TYPE.TEXT,
91
+ columnMeta: { tableName: 'Revenue' },
92
+ },
93
+ Revenue_Impact: {
94
+ columnName: 'Revenue_Impact',
95
+ columnType: MDM_COLUMN_TYPE.NUMBER,
96
+ columnMeta: { tableName: 'Revenue' },
97
+ },
98
+ };
99
+ const context = new ParseContext({
100
+ columnConfigMap,
101
+ currentColumnId: 'Priority',
102
+ primaryKeyColumns: ['PK'],
103
+ tableName: 'Revenue',
104
+ });
105
+ const parser = createJsToSqlParser(context);
106
+ const ast = parser.parse(formula);
107
+ const resultSql = parser.toSql(ast);
108
+ expect(resultSql).toEqual(expectedSql);
109
+ });
110
+
111
+ test('should create sql query from formula for date intelligence', () => {
112
+ const formula = `
113
+ DATEDIFF(TODAY(), Follow_Up_Date, 'days') +
114
+ IF(Interaction_Count < 3, 10, 0) +
115
+ IF(Lead_Source == "Referral", -5, 0)
116
+ `;
117
+ const expectedSql = `(COALESCE((COALESCE(DATEDIFF(DAY, CURRENT_DATE, [Follow_Up_Date]), 0) + COALESCE(CASE WHEN [Interaction_Count] < 3 THEN 10 ELSE 0 END, 0)), 0) + COALESCE(CASE WHEN [Lead_Source] = 'Referral' THEN -5 ELSE 0 END, 0))`;
118
+ const columnConfigMap = {
119
+ Follow_Up_Date: {
120
+ columnName: 'Follow_Up_Date',
121
+ columnType: MDM_COLUMN_TYPE.DATE,
122
+ columnMeta: { tableName: 'Project' },
123
+ },
124
+ Interaction_Count: {
125
+ columnName: 'Interaction_Count',
126
+ columnType: MDM_COLUMN_TYPE.NUMBER,
127
+ columnMeta: { tableName: 'Project' },
128
+ },
129
+ Lead_Source: {
130
+ columnName: 'Lead_Source',
131
+ columnType: MDM_COLUMN_TYPE.TEXT,
132
+ columnMeta: { tableName: 'Project' },
133
+ },
134
+ };
135
+ const context = new ParseContext({
136
+ columnConfigMap,
137
+ currentColumnId: 'DateIntelligence',
138
+ primaryKeyColumns: ['PK'],
139
+ tableName: 'Project',
140
+ });
141
+ const parser = createJsToSqlParser(context);
142
+ const ast = parser.parse(formula);
143
+ const resultSql = parser.toSql(ast);
144
+ expect(resultSql).toEqual(expectedSql);
145
+ });
146
+ });
@@ -0,0 +1,75 @@
1
+ import { toBinaryExpression } from '../../src/sql-lib/binary_expr';
2
+ import { toValue, DataType } from '../../src/sql-lib/literal';
3
+ import { toColumnRef } from '../../src/sql-lib/column';
4
+
5
+ describe('toBinaryExpression', () => {
6
+ test('should create a binary expression with two literals', () => {
7
+ const left = toValue(DataType.NUMBER, 10);
8
+ const right = toValue(DataType.NUMBER, 20);
9
+ const result = toBinaryExpression('+', left, right);
10
+
11
+ expect(result).toEqual({
12
+ type: 'binary_expr',
13
+ operator: '+',
14
+ left: { type: 'number', value: 10 },
15
+ right: { type: 'number', value: 20 },
16
+ parentheses: false,
17
+ });
18
+ });
19
+
20
+ test('should create a binary expression with column references', () => {
21
+ const left = toColumnRef('column1', 'table1');
22
+ const right = toColumnRef('column2', 'table1');
23
+ const result = toBinaryExpression('=', left, right);
24
+
25
+ expect(result).toEqual({
26
+ type: 'binary_expr',
27
+ operator: '=',
28
+ left: { type: 'column_ref', table: 'table1', column: 'column1', collate: undefined },
29
+ right: { type: 'column_ref', table: 'table1', column: 'column2', collate: undefined },
30
+ parentheses: false,
31
+ });
32
+ });
33
+
34
+ test('should create a binary expression with parentheses', () => {
35
+ const left = toValue(DataType.NUMBER, 5);
36
+ const right = toValue(DataType.NUMBER, 10);
37
+ const result = toBinaryExpression('*', left, right, true);
38
+
39
+ expect(result).toEqual({
40
+ type: 'binary_expr',
41
+ operator: '*',
42
+ left: { type: 'number', value: 5 },
43
+ right: { type: 'number', value: 10 },
44
+ parentheses: true,
45
+ });
46
+ });
47
+
48
+ test('should create a binary expression with mixed operand types', () => {
49
+ const left = toColumnRef('price');
50
+ const right = toValue(DataType.NUMBER, 100);
51
+ const result = toBinaryExpression('>', left, right);
52
+
53
+ expect(result).toEqual({
54
+ type: 'binary_expr',
55
+ operator: '>',
56
+ left: { type: 'column_ref', table: null, column: 'price', collate: undefined },
57
+ right: { type: 'number', value: 100 },
58
+ parentheses: false,
59
+ });
60
+ });
61
+
62
+ test('should create a binary expression with string literals', () => {
63
+ const left = toValue(DataType.STRING, 'hello');
64
+ const right = toValue(DataType.STRING, 'world');
65
+ const result = toBinaryExpression('||', left, right);
66
+
67
+ expect(result).toEqual({
68
+ type: 'binary_expr',
69
+ operator: '||',
70
+ left: { type: 'string', value: 'hello' },
71
+ right: { type: 'string', value: 'world' },
72
+ parentheses: false,
73
+ });
74
+ });
75
+ });
@@ -0,0 +1,117 @@
1
+ import { toCase } from '../../src/sql-lib/case';
2
+ import { toWhen } from '../../src/sql-lib/when';
3
+ import { toElse } from '../../src/sql-lib/else';
4
+ import { toBinaryExpression } from '../../src/sql-lib/binary_expr';
5
+ import { toValue, DataType } from '../../src/sql-lib/literal';
6
+ import { toColumnRef } from '../../src/sql-lib/column';
7
+
8
+ describe('toCase', () => {
9
+ test('should create a CASE expression with single WHEN-THEN-ELSE', () => {
10
+ const condition = toBinaryExpression('>', toColumnRef('amount'), toValue(DataType.NUMBER, 100));
11
+ const whenResult = toValue(DataType.STRING, 'High');
12
+ const elseResult = toValue(DataType.STRING, 'Low');
13
+
14
+ const whenClause = toWhen(condition, whenResult);
15
+ const elseClause = toElse(elseResult);
16
+
17
+ const result = toCase({
18
+ whenList: [whenClause],
19
+ elseResult: elseClause,
20
+ });
21
+
22
+ expect(result).toEqual({
23
+ type: 'case',
24
+ expr: null,
25
+ args: [
26
+ {
27
+ type: 'when',
28
+ cond: {
29
+ type: 'binary_expr',
30
+ operator: '>',
31
+ left: {
32
+ type: 'column_ref',
33
+ table: null,
34
+ column: 'amount',
35
+ collate: undefined,
36
+ },
37
+ right: { type: 'number', value: 100 },
38
+ parentheses: false,
39
+ },
40
+ result: { type: 'string', value: 'High' },
41
+ },
42
+ {
43
+ type: 'else',
44
+ result: { type: 'string', value: 'Low' },
45
+ },
46
+ ],
47
+ });
48
+ });
49
+
50
+ test('should create a CASE expression with multiple WHEN-THEN clauses', () => {
51
+ const condition1 = toBinaryExpression(
52
+ '>',
53
+ toColumnRef('amount'),
54
+ toValue(DataType.NUMBER, 1000),
55
+ );
56
+ const condition2 = toBinaryExpression(
57
+ '>',
58
+ toColumnRef('amount'),
59
+ toValue(DataType.NUMBER, 500),
60
+ );
61
+ const whenResult1 = toValue(DataType.STRING, 'Very High');
62
+ const whenResult2 = toValue(DataType.STRING, 'High');
63
+ const elseResult = toValue(DataType.STRING, 'Normal');
64
+
65
+ const whenClause1 = toWhen(condition1, whenResult1);
66
+ const whenClause2 = toWhen(condition2, whenResult2);
67
+ const elseClause = toElse(elseResult);
68
+
69
+ const result = toCase({
70
+ whenList: [whenClause1, whenClause2],
71
+ elseResult: elseClause,
72
+ });
73
+
74
+ expect(result).toEqual({
75
+ type: 'case',
76
+ expr: null,
77
+ args: [
78
+ {
79
+ type: 'when',
80
+ cond: {
81
+ type: 'binary_expr',
82
+ operator: '>',
83
+ left: {
84
+ type: 'column_ref',
85
+ table: null,
86
+ column: 'amount',
87
+ collate: undefined,
88
+ },
89
+ right: { type: 'number', value: 1000 },
90
+ parentheses: false,
91
+ },
92
+ result: { type: 'string', value: 'Very High' },
93
+ },
94
+ {
95
+ type: 'when',
96
+ cond: {
97
+ type: 'binary_expr',
98
+ operator: '>',
99
+ left: {
100
+ type: 'column_ref',
101
+ table: null,
102
+ column: 'amount',
103
+ collate: undefined,
104
+ },
105
+ right: { type: 'number', value: 500 },
106
+ parentheses: false,
107
+ },
108
+ result: { type: 'string', value: 'High' },
109
+ },
110
+ {
111
+ type: 'else',
112
+ result: { type: 'string', value: 'Normal' },
113
+ },
114
+ ],
115
+ });
116
+ });
117
+ });
@@ -0,0 +1,87 @@
1
+ import { toColumnRef, toColumn } from '../../src/sql-lib/column';
2
+ import { toValue, DataType } from '../../src/sql-lib/literal';
3
+ import { Binary } from '../../src/sql-types';
4
+
5
+ describe('toColumnRef', () => {
6
+ test('should create a column reference without table name', () => {
7
+ const result = toColumnRef('amount');
8
+
9
+ expect(result).toEqual({
10
+ type: 'column_ref',
11
+ table: null,
12
+ column: 'amount',
13
+ collate: undefined,
14
+ });
15
+ });
16
+
17
+ test('should create a column reference with table name', () => {
18
+ const result = toColumnRef('amount', 'invoices');
19
+
20
+ expect(result).toEqual({
21
+ type: 'column_ref',
22
+ table: 'invoices',
23
+ column: 'amount',
24
+ collate: undefined,
25
+ });
26
+ });
27
+ });
28
+
29
+ describe('toColumn', () => {
30
+ test('should create a column without alias', () => {
31
+ const expr = toValue(DataType.NUMBER, 100);
32
+ const result = toColumn(expr);
33
+
34
+ expect(result).toEqual({
35
+ type: 'column',
36
+ expr: { type: 'number', value: 100 },
37
+ as: null,
38
+ });
39
+ });
40
+
41
+ test('should create a column with alias', () => {
42
+ const expr = toColumnRef('amount', 'invoices');
43
+ const result = toColumn(expr, 'invoice_amount');
44
+
45
+ expect(result).toEqual({
46
+ type: 'column',
47
+ expr: {
48
+ type: 'column_ref',
49
+ table: 'invoices',
50
+ column: 'amount',
51
+ collate: undefined,
52
+ },
53
+ as: 'invoice_amount',
54
+ });
55
+ });
56
+
57
+ test('should create a column from a complex expression', () => {
58
+ const columnRef = toColumnRef('price');
59
+ const numValue = toValue(DataType.NUMBER, 1.1);
60
+ const expr: Binary = {
61
+ type: 'binary_expr',
62
+ operator: '*',
63
+ left: columnRef,
64
+ right: numValue,
65
+ parentheses: false,
66
+ };
67
+
68
+ const result = toColumn(expr, 'price_with_tax');
69
+
70
+ expect(result).toEqual({
71
+ type: 'column',
72
+ expr: {
73
+ type: 'binary_expr',
74
+ operator: '*',
75
+ left: {
76
+ type: 'column_ref',
77
+ table: null,
78
+ column: 'price',
79
+ collate: undefined,
80
+ },
81
+ right: { type: 'number', value: 1.1 },
82
+ parentheses: false,
83
+ },
84
+ as: 'price_with_tax',
85
+ });
86
+ });
87
+ });
@@ -0,0 +1,56 @@
1
+ import { toElse } from '../../src/sql-lib/else';
2
+ import { toValue, DataType } from '../../src/sql-lib/literal';
3
+ import { toColumnRef } from '../../src/sql-lib/column';
4
+
5
+ describe('toElse', () => {
6
+ test('should create an ELSE clause with a string literal', () => {
7
+ const result = toElse(toValue(DataType.STRING, 'Default'));
8
+
9
+ expect(result).toEqual({
10
+ type: 'else',
11
+ result: { type: 'string', value: 'Default' },
12
+ });
13
+ });
14
+
15
+ test('should create an ELSE clause with a number literal', () => {
16
+ const result = toElse(toValue(DataType.NUMBER, 0));
17
+
18
+ expect(result).toEqual({
19
+ type: 'else',
20
+ result: { type: 'number', value: 0 },
21
+ });
22
+ });
23
+
24
+ test('should create an ELSE clause with a column reference', () => {
25
+ const columnRef = toColumnRef('default_value', 'settings');
26
+ const result = toElse(columnRef);
27
+
28
+ expect(result).toEqual({
29
+ type: 'else',
30
+ result: {
31
+ type: 'column_ref',
32
+ table: 'settings',
33
+ column: 'default_value',
34
+ collate: undefined,
35
+ },
36
+ });
37
+ });
38
+
39
+ test('should create an ELSE clause with a boolean literal', () => {
40
+ const result = toElse(toValue(DataType.BOOLEAN, false));
41
+
42
+ expect(result).toEqual({
43
+ type: 'else',
44
+ result: { type: 'boolean', value: false },
45
+ });
46
+ });
47
+
48
+ test('should create an ELSE clause with a NULL literal', () => {
49
+ const result = toElse(toValue(DataType.NULL, null));
50
+
51
+ expect(result).toEqual({
52
+ type: 'else',
53
+ result: { type: 'null', value: null },
54
+ });
55
+ });
56
+ });
@@ -0,0 +1,96 @@
1
+ import { toFunction } from '../../src/sql-lib/function';
2
+ import { toValue, DataType } from '../../src/sql-lib/literal';
3
+ import { toColumnRef } from '../../src/sql-lib/column';
4
+ import { ValueExpr } from 'node-sql-parser';
5
+
6
+ describe('toFunction', () => {
7
+ test('should create a function with no arguments', () => {
8
+ const name = toValue(DataType.STRING, 'NOW');
9
+ const result = toFunction(name as ValueExpr<string>, []);
10
+
11
+ expect(result).toEqual({
12
+ type: 'function',
13
+ name: { name: [{ type: 'string', value: 'NOW' }] },
14
+ args: { type: 'expr_list', value: [] },
15
+ });
16
+ });
17
+
18
+ test('should create a function with a single argument', () => {
19
+ const name = toValue(DataType.STRING, 'ABS');
20
+ const arg = toValue(DataType.NUMBER, -10);
21
+ const result = toFunction(name as ValueExpr<string>, [arg]);
22
+
23
+ expect(result).toEqual({
24
+ type: 'function',
25
+ name: { name: [{ type: 'string', value: 'ABS' }] },
26
+ args: { type: 'expr_list', value: [{ type: 'number', value: -10 }] },
27
+ });
28
+ });
29
+
30
+ test('should create a function with multiple arguments', () => {
31
+ const name = toValue(DataType.STRING, 'CONCAT');
32
+ const arg1 = toValue(DataType.STRING, 'Hello');
33
+ const arg2 = toValue(DataType.STRING, 'World');
34
+ const result = toFunction(name as ValueExpr<string>, [arg1, arg2]);
35
+
36
+ expect(result).toEqual({
37
+ type: 'function',
38
+ name: { name: [{ type: 'string', value: 'CONCAT' }] },
39
+ args: {
40
+ type: 'expr_list',
41
+ value: [
42
+ { type: 'string', value: 'Hello' },
43
+ { type: 'string', value: 'World' },
44
+ ],
45
+ },
46
+ });
47
+ });
48
+
49
+ test('should create a function with column reference arguments', () => {
50
+ const name = toValue(DataType.STRING, 'SUM');
51
+ const arg = toColumnRef('amount', 'invoices');
52
+ const result = toFunction(name as ValueExpr<string>, [arg]);
53
+
54
+ expect(result).toEqual({
55
+ type: 'function',
56
+ name: { name: [{ type: 'string', value: 'SUM' }] },
57
+ args: {
58
+ type: 'expr_list',
59
+ value: [
60
+ {
61
+ type: 'column_ref',
62
+ table: 'invoices',
63
+ column: 'amount',
64
+ collate: undefined,
65
+ },
66
+ ],
67
+ },
68
+ });
69
+ });
70
+
71
+ test('should create a function with mixed argument types', () => {
72
+ const name = toValue(DataType.STRING, 'DATEADD');
73
+ const arg1 = toValue(DataType.STRING, 'day');
74
+ const arg2 = toValue(DataType.NUMBER, 7);
75
+ const arg3 = toColumnRef('date_column');
76
+ const result = toFunction(name as ValueExpr<string>, [arg1, arg2, arg3]);
77
+
78
+ expect(result).toEqual({
79
+ type: 'function',
80
+ name: { name: [{ type: 'string', value: 'DATEADD' }] },
81
+ args: {
82
+ type: 'expr_list',
83
+ value: [
84
+ { type: 'string', value: 'day' },
85
+ { type: 'number', value: 7 },
86
+ {
87
+ type: 'column_ref',
88
+ table: null,
89
+ column: 'date_column',
90
+ collate: undefined,
91
+ },
92
+ ],
93
+ },
94
+ });
95
+ });
96
+ });
@@ -0,0 +1,75 @@
1
+ import { toValue, DataType } from '../../src/sql-lib/literal';
2
+
3
+ describe('toValue', () => {
4
+ test('should create a number literal', () => {
5
+ const result = toValue(DataType.NUMBER, 42);
6
+
7
+ expect(result).toEqual({
8
+ type: 'number',
9
+ value: 42,
10
+ });
11
+ });
12
+
13
+ test('should create a string literal', () => {
14
+ const result = toValue(DataType.STRING, 'hello');
15
+
16
+ expect(result).toEqual({
17
+ type: 'string',
18
+ value: 'hello',
19
+ });
20
+ });
21
+
22
+ test('should create a boolean literal - true', () => {
23
+ const result = toValue(DataType.BOOLEAN, true);
24
+
25
+ expect(result).toEqual({
26
+ type: 'boolean',
27
+ value: true,
28
+ });
29
+ });
30
+
31
+ test('should create a boolean literal - false', () => {
32
+ const result = toValue(DataType.BOOLEAN, false);
33
+
34
+ expect(result).toEqual({
35
+ type: 'boolean',
36
+ value: false,
37
+ });
38
+ });
39
+
40
+ test('should create a null literal', () => {
41
+ const result = toValue(DataType.NULL, null);
42
+
43
+ expect(result).toEqual({
44
+ type: 'null',
45
+ value: null,
46
+ });
47
+ });
48
+
49
+ test('should handle decimal numbers', () => {
50
+ const result = toValue(DataType.NUMBER, 3.14159);
51
+
52
+ expect(result).toEqual({
53
+ type: 'number',
54
+ value: 3.14159,
55
+ });
56
+ });
57
+
58
+ test('should handle negative numbers', () => {
59
+ const result = toValue(DataType.NUMBER, -100);
60
+
61
+ expect(result).toEqual({
62
+ type: 'number',
63
+ value: -100,
64
+ });
65
+ });
66
+
67
+ test('should handle empty strings', () => {
68
+ const result = toValue(DataType.STRING, '');
69
+
70
+ expect(result).toEqual({
71
+ type: 'string',
72
+ value: '',
73
+ });
74
+ });
75
+ });