@quillsql/react 2.12.28 → 2.12.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/Chart.d.ts.map +1 -1
- package/dist/cjs/Chart.js +10 -8
- package/dist/cjs/ChartBuilder.d.ts +35 -1
- package/dist/cjs/ChartBuilder.d.ts.map +1 -1
- package/dist/cjs/ChartBuilder.js +38 -4
- package/dist/cjs/Context.d.ts +1 -19
- package/dist/cjs/Context.d.ts.map +1 -1
- package/dist/cjs/Context.js +32 -83
- package/dist/cjs/Dashboard.d.ts.map +1 -1
- package/dist/cjs/Dashboard.js +76 -49
- package/dist/cjs/ReportBuilder.d.ts +9 -0
- package/dist/cjs/ReportBuilder.d.ts.map +1 -1
- package/dist/cjs/ReportBuilder.js +330 -100
- package/dist/cjs/SQLEditor.d.ts.map +1 -1
- package/dist/cjs/SQLEditor.js +98 -29
- package/dist/cjs/Table.d.ts.map +1 -1
- package/dist/cjs/Table.js +8 -8
- package/dist/cjs/components/Chart/ChartTooltip.d.ts.map +1 -1
- package/dist/cjs/components/Dashboard/DataLoader.d.ts.map +1 -1
- package/dist/cjs/components/Dashboard/DataLoader.js +20 -16
- package/dist/cjs/hooks/useDashboard.d.ts +1 -1
- package/dist/cjs/hooks/useDashboard.d.ts.map +1 -1
- package/dist/cjs/hooks/useDashboard.js +18 -4
- package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
- package/dist/cjs/internals/ReportBuilder/PivotModal.js +56 -57
- package/dist/cjs/utils/columnProcessing.d.ts +1 -0
- package/dist/cjs/utils/columnProcessing.d.ts.map +1 -1
- package/dist/cjs/utils/columnProcessing.js +8 -1
- package/dist/cjs/utils/dashboard.js +1 -1
- package/dist/cjs/utils/dataFetcher.d.ts +1 -1
- package/dist/cjs/utils/dataFetcher.d.ts.map +1 -1
- package/dist/cjs/utils/dataFetcher.js +9 -4
- package/dist/cjs/utils/dates.d.ts +1 -0
- package/dist/cjs/utils/dates.d.ts.map +1 -1
- package/dist/cjs/utils/dates.js +12 -3
- package/dist/cjs/utils/monacoAutocomplete.d.ts +20 -0
- package/dist/cjs/utils/monacoAutocomplete.d.ts.map +1 -0
- package/dist/cjs/utils/monacoAutocomplete.js +145 -0
- package/dist/cjs/utils/pivotConstructor.d.ts.map +1 -1
- package/dist/cjs/utils/pivotConstructor.js +58 -5
- package/dist/cjs/utils/queryConstructor.d.ts +4 -2
- package/dist/cjs/utils/queryConstructor.d.ts.map +1 -1
- package/dist/cjs/utils/queryConstructor.js +118 -57
- package/dist/cjs/utils/queryConstructor.uspec.d.ts +2 -0
- package/dist/cjs/utils/queryConstructor.uspec.d.ts.map +1 -0
- package/dist/cjs/utils/queryConstructor.uspec.js +225 -0
- package/dist/cjs/utils/tableProcessing.d.ts +1 -0
- package/dist/cjs/utils/tableProcessing.d.ts.map +1 -1
- package/dist/cjs/utils/tableProcessing.js +42 -5
- package/dist/esm/Chart.d.ts.map +1 -1
- package/dist/esm/Chart.js +10 -8
- package/dist/esm/ChartBuilder.d.ts +35 -1
- package/dist/esm/ChartBuilder.d.ts.map +1 -1
- package/dist/esm/ChartBuilder.js +36 -3
- package/dist/esm/Context.d.ts +1 -19
- package/dist/esm/Context.d.ts.map +1 -1
- package/dist/esm/Context.js +32 -82
- package/dist/esm/Dashboard.d.ts.map +1 -1
- package/dist/esm/Dashboard.js +77 -50
- package/dist/esm/ReportBuilder.d.ts +9 -0
- package/dist/esm/ReportBuilder.d.ts.map +1 -1
- package/dist/esm/ReportBuilder.js +333 -103
- package/dist/esm/SQLEditor.d.ts.map +1 -1
- package/dist/esm/SQLEditor.js +99 -30
- package/dist/esm/Table.d.ts.map +1 -1
- package/dist/esm/Table.js +8 -8
- package/dist/esm/components/Chart/ChartTooltip.d.ts.map +1 -1
- package/dist/esm/components/Dashboard/DataLoader.d.ts.map +1 -1
- package/dist/esm/components/Dashboard/DataLoader.js +20 -16
- package/dist/esm/hooks/useDashboard.d.ts +1 -1
- package/dist/esm/hooks/useDashboard.d.ts.map +1 -1
- package/dist/esm/hooks/useDashboard.js +19 -5
- package/dist/esm/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
- package/dist/esm/internals/ReportBuilder/PivotModal.js +57 -58
- package/dist/esm/utils/columnProcessing.d.ts +1 -0
- package/dist/esm/utils/columnProcessing.d.ts.map +1 -1
- package/dist/esm/utils/columnProcessing.js +6 -0
- package/dist/esm/utils/dashboard.js +1 -1
- package/dist/esm/utils/dataFetcher.d.ts +1 -1
- package/dist/esm/utils/dataFetcher.d.ts.map +1 -1
- package/dist/esm/utils/dataFetcher.js +9 -4
- package/dist/esm/utils/dates.d.ts +1 -0
- package/dist/esm/utils/dates.d.ts.map +1 -1
- package/dist/esm/utils/dates.js +10 -2
- package/dist/esm/utils/monacoAutocomplete.d.ts +20 -0
- package/dist/esm/utils/monacoAutocomplete.d.ts.map +1 -0
- package/dist/esm/utils/monacoAutocomplete.js +140 -0
- package/dist/esm/utils/pivotConstructor.d.ts.map +1 -1
- package/dist/esm/utils/pivotConstructor.js +58 -5
- package/dist/esm/utils/queryConstructor.d.ts +4 -2
- package/dist/esm/utils/queryConstructor.d.ts.map +1 -1
- package/dist/esm/utils/queryConstructor.js +115 -56
- package/dist/esm/utils/queryConstructor.uspec.d.ts +2 -0
- package/dist/esm/utils/queryConstructor.uspec.d.ts.map +1 -0
- package/dist/esm/utils/queryConstructor.uspec.js +223 -0
- package/dist/esm/utils/tableProcessing.d.ts +1 -0
- package/dist/esm/utils/tableProcessing.d.ts.map +1 -1
- package/dist/esm/utils/tableProcessing.js +41 -5
- package/package.json +1 -1
- package/dist/cjs/internals/ReportBuilder/PivotModal.spec.d.ts +0 -2
- package/dist/cjs/internals/ReportBuilder/PivotModal.spec.d.ts.map +0 -1
- package/dist/cjs/internals/ReportBuilder/PivotModal.spec.js +0 -213
- package/dist/esm/internals/ReportBuilder/PivotModal.spec.d.ts +0 -2
- package/dist/esm/internals/ReportBuilder/PivotModal.spec.d.ts.map +0 -1
- package/dist/esm/internals/ReportBuilder/PivotModal.spec.js +0 -211
|
@@ -1,19 +1,69 @@
|
|
|
1
1
|
import { isValidPivot } from './pivotProcessing';
|
|
2
|
-
function
|
|
3
|
-
if (
|
|
2
|
+
function processSingleQuotes(value, databaseType) {
|
|
3
|
+
if (['postgresql', 'snowflake'].includes(databaseType.toLowerCase())) {
|
|
4
|
+
return value.replaceAll("'", "''");
|
|
5
|
+
}
|
|
6
|
+
return value.replaceAll("'", "\\'");
|
|
7
|
+
}
|
|
8
|
+
function processAggType(aggType, hasColumnField = false) {
|
|
9
|
+
if (aggType === 'count' && hasColumnField)
|
|
4
10
|
return 'SUM';
|
|
5
11
|
return aggType?.toLowerCase() === 'average' ? 'AVG' : aggType?.toLowerCase();
|
|
6
12
|
}
|
|
7
|
-
function
|
|
13
|
+
function replaceBigQuerySpecialCharacters(column) {
|
|
14
|
+
return column.replaceAll('/', 'quill_forward_slash');
|
|
15
|
+
}
|
|
16
|
+
export function processColumnReference(column, databaseType) {
|
|
17
|
+
if (['postgresql', 'snowflake'].includes(databaseType.toLowerCase())) {
|
|
18
|
+
const columnParts = column.split('.');
|
|
19
|
+
if (columnParts.length > 1) {
|
|
20
|
+
return `"${columnParts[0]}"."${columnParts[1]}"`;
|
|
21
|
+
}
|
|
22
|
+
return `"${column}"`;
|
|
23
|
+
}
|
|
24
|
+
const columnParts = column.split('.');
|
|
25
|
+
if (columnParts.length > 1) {
|
|
26
|
+
return `\`${columnParts[0]}\`.\`${columnParts[1]}\``;
|
|
27
|
+
}
|
|
28
|
+
return `\`${replaceBigQuerySpecialCharacters(column)}\``;
|
|
29
|
+
}
|
|
30
|
+
function processInterval(interval, rowField, databaseType) {
|
|
31
|
+
if (['postgresql', 'snowflake'].includes(databaseType.toLowerCase())) {
|
|
32
|
+
return `(${processColumnReference(rowField, databaseType)} + INTERVAL '${interval}')`;
|
|
33
|
+
}
|
|
34
|
+
return `TIMESTAMP_ADD(${processColumnReference(rowField, databaseType)}, INTERVAL ${interval} )`;
|
|
35
|
+
}
|
|
36
|
+
function processDateTrunc(dateBucket, rowField, databaseType, comparisonInterval) {
|
|
37
|
+
if (['postgresql', 'snowflake'].includes(databaseType.toLowerCase())) {
|
|
38
|
+
const date = comparisonInterval
|
|
39
|
+
? processInterval(comparisonInterval, rowField, databaseType)
|
|
40
|
+
: processColumnReference(rowField, databaseType);
|
|
41
|
+
return `date_trunc('${dateBucket}', ${date})`;
|
|
42
|
+
}
|
|
43
|
+
const date = comparisonInterval
|
|
44
|
+
? processInterval(comparisonInterval, rowField, databaseType)
|
|
45
|
+
: processColumnReference(rowField, databaseType);
|
|
46
|
+
return `TIMESTAMP_TRUNC(${date}, ${dateBucket})`;
|
|
47
|
+
}
|
|
48
|
+
function processValueField(aggType, databaseType, valueField) {
|
|
8
49
|
if (aggType === 'min' || aggType === 'max')
|
|
9
|
-
return
|
|
50
|
+
return `${processColumnReference(valueField, databaseType)} ELSE null`;
|
|
10
51
|
if (aggType === 'count')
|
|
11
52
|
return `1 ELSE 0`;
|
|
12
|
-
return valueField
|
|
53
|
+
return valueField
|
|
54
|
+
? `${processColumnReference(valueField, databaseType)} ELSE 0`
|
|
55
|
+
: `1 ELSE 0`;
|
|
56
|
+
}
|
|
57
|
+
export function generateCountQuery(fields, query, databaseType) {
|
|
58
|
+
const countQuery = fields.map((field) => {
|
|
59
|
+
return `SELECT '${field}' AS ${processColumnReference('field', databaseType)}, COUNT(DISTINCT ${processColumnReference(field, databaseType)}) AS ${processColumnReference('count', databaseType)} FROM querytable`;
|
|
60
|
+
});
|
|
61
|
+
return (`WITH querytable AS (${query.replace(';', '')}) ` +
|
|
62
|
+
countQuery.join(' UNION ALL '));
|
|
13
63
|
}
|
|
14
|
-
export function generateDistinctQuery(stringFields, query) {
|
|
64
|
+
export function generateDistinctQuery(stringFields, query, databaseType) {
|
|
15
65
|
const distinctQueries = stringFields.map((field) => {
|
|
16
|
-
return `SELECT '${field}' AS field, ARRAY_AGG(DISTINCT ${field}) AS string_values FROM querytable`;
|
|
66
|
+
return `SELECT '${field}' AS ${processColumnReference('field', databaseType)}, ARRAY_AGG(DISTINCT ${field}) AS ${processColumnReference('string_values', databaseType)} FROM querytable`;
|
|
17
67
|
});
|
|
18
68
|
const distinctQuery = distinctQueries.join(' UNION ALL ');
|
|
19
69
|
return `WITH querytable AS (${query.replace(';', '')}) ` + distinctQuery;
|
|
@@ -28,135 +78,144 @@ export function generateMinMaxRangeQueries(columnFields, query, databaseType) {
|
|
|
28
78
|
const distinctQuery = distinctQueries.join(' UNION ALL ');
|
|
29
79
|
return `WITH querytable AS (${query.replace(';', '')}) ` + distinctQuery;
|
|
30
80
|
}
|
|
31
|
-
export function generatePivotQuery(pivot, itemQueries,
|
|
81
|
+
export function generatePivotQuery(pivot, itemQueries, databaseType, comparisonInterval, distinctStrings, dateBucket) {
|
|
32
82
|
if (!isValidPivot(pivot)) {
|
|
33
83
|
return undefined;
|
|
34
84
|
}
|
|
35
85
|
if (pivot.columnField) {
|
|
36
|
-
return create2DPivotQuery(pivot, itemQueries,
|
|
86
|
+
return create2DPivotQuery(pivot, itemQueries, databaseType, dateBucket, comparisonInterval, distinctStrings);
|
|
37
87
|
}
|
|
38
88
|
if (pivot.rowField) {
|
|
39
|
-
return create1DPivotQuery(pivot, itemQueries, dateBucket, comparisonInterval);
|
|
89
|
+
return create1DPivotQuery(pivot, itemQueries, dateBucket, databaseType, comparisonInterval);
|
|
40
90
|
}
|
|
41
|
-
return createAggregationValuePivot(pivot, itemQueries);
|
|
91
|
+
return createAggregationValuePivot(pivot, itemQueries, databaseType);
|
|
42
92
|
}
|
|
43
|
-
function create2DPivotQuery(pivot, itemQueries,
|
|
93
|
+
function create2DPivotQuery(pivot, itemQueries, databaseType, dateBucket, comparisonInterval, columnFieldValues) {
|
|
44
94
|
if (!pivot || !pivot.columnField) {
|
|
45
95
|
return undefined;
|
|
46
96
|
}
|
|
47
|
-
|
|
48
|
-
const columnValues = rows.map((row) => row[pivot.columnField]);
|
|
49
|
-
const distinctColumnValues = distinctStrings
|
|
50
|
-
? distinctStrings
|
|
51
|
-
: Array.from(new Set(columnValues)).filter((value) => value !== undefined && value !== null);
|
|
52
|
-
if (distinctColumnValues.length === 0) {
|
|
97
|
+
if (!columnFieldValues) {
|
|
53
98
|
return undefined;
|
|
54
99
|
}
|
|
55
100
|
if (['string', 'varchar'].includes(pivot.rowFieldType) ||
|
|
56
101
|
!pivot.rowFieldType) {
|
|
57
|
-
return create2DStringPivotQuery(pivot, itemQueries,
|
|
102
|
+
return create2DStringPivotQuery(pivot, itemQueries, columnFieldValues, databaseType);
|
|
58
103
|
}
|
|
59
|
-
return create2DDatePivotQuery(pivot, itemQueries,
|
|
104
|
+
return create2DDatePivotQuery(pivot, itemQueries, columnFieldValues, databaseType, dateBucket, comparisonInterval);
|
|
60
105
|
}
|
|
61
|
-
function create2DStringPivotQuery(pivot, itemQueries,
|
|
62
|
-
|
|
63
|
-
return
|
|
106
|
+
function create2DStringPivotQuery(pivot, itemQueries, columnFieldValues, databaseType) {
|
|
107
|
+
if (!pivot.columnField || !pivot.rowField) {
|
|
108
|
+
return undefined;
|
|
109
|
+
}
|
|
110
|
+
const rowField = pivot.rowField;
|
|
111
|
+
const valueField = pivot.valueField;
|
|
112
|
+
const columnField = pivot.columnField;
|
|
113
|
+
const caseWhens = columnFieldValues.map((column) => {
|
|
114
|
+
return `${processAggType(pivot.aggregationType, true)}(CASE WHEN ${processColumnReference(columnField, databaseType)} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueField)} END) AS ${processColumnReference(column, databaseType)}`;
|
|
64
115
|
});
|
|
65
|
-
const caseWhensCompare =
|
|
66
|
-
return `${processAggType(pivot.aggregationType)}(CASE WHEN
|
|
116
|
+
const caseWhensCompare = columnFieldValues.map((column) => {
|
|
117
|
+
return `${processAggType(pivot.aggregationType, true)}(CASE WHEN ${processColumnReference(columnField, databaseType)} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueField)} END) AS ${processColumnReference(`comparison_${column}`, databaseType)}`;
|
|
67
118
|
});
|
|
68
119
|
const compareCTE = itemQueries[1]
|
|
69
120
|
? `, quill_ct as (${itemQueries[1]?.replaceAll(';', '')})`
|
|
70
121
|
: '';
|
|
71
122
|
const compareCaseWhenCTE = itemQueries[1]
|
|
72
|
-
? `, quill_ct_cw as (SELECT
|
|
123
|
+
? `, quill_ct_cw as (SELECT ${processColumnReference(rowField, databaseType)} as ${processColumnReference(`comparison_${rowField}`, databaseType)}, ${caseWhensCompare.join(', ')} FROM quill_ct GROUP BY ${processColumnReference(rowField, databaseType)})`
|
|
73
124
|
: '';
|
|
74
125
|
const joinQuery = itemQueries[1]
|
|
75
|
-
? `JOIN quill_ct_cw ct ON ct
|
|
126
|
+
? `JOIN quill_ct_cw ct ON ct.${processColumnReference(`comparison_${rowField}`, databaseType)} = qt.${processColumnReference(rowField, databaseType)}`
|
|
76
127
|
: '';
|
|
77
128
|
return `WITH quill_qt AS (${itemQueries[0]?.replaceAll(';', '')}),
|
|
78
|
-
quill_qt_cw AS (SELECT ${
|
|
129
|
+
quill_qt_cw AS (SELECT ${processColumnReference(rowField, databaseType)}, ${caseWhens.join(', ')} FROM quill_qt GROUP BY ${processColumnReference(rowField, databaseType)})
|
|
79
130
|
${compareCTE} ${compareCaseWhenCTE}
|
|
80
131
|
SELECT * FROM quill_qt_cw qt
|
|
81
132
|
${joinQuery}`;
|
|
82
133
|
}
|
|
83
|
-
function create2DDatePivotQuery(pivot, itemQueries,
|
|
84
|
-
|
|
85
|
-
return
|
|
134
|
+
function create2DDatePivotQuery(pivot, itemQueries, columnFieldValues, databaseType, dateBucket = 'month', comparisonInterval) {
|
|
135
|
+
if (!pivot.columnField || !pivot.rowField) {
|
|
136
|
+
return undefined;
|
|
137
|
+
}
|
|
138
|
+
const rowField = pivot.rowField;
|
|
139
|
+
const valueField = pivot.valueField;
|
|
140
|
+
const columnField = pivot.columnField;
|
|
141
|
+
const caseWhens = columnFieldValues.map((column) => {
|
|
142
|
+
return `${processAggType(pivot.aggregationType, true)}(CASE WHEN qt.${processColumnReference(columnField, databaseType)} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, pivot.valueField)} END) AS ${processColumnReference(column, databaseType)}`;
|
|
86
143
|
});
|
|
87
|
-
const caseWhensCompare =
|
|
88
|
-
return `${processAggType(pivot.aggregationType)}(CASE WHEN
|
|
144
|
+
const caseWhensCompare = columnFieldValues.map((column) => {
|
|
145
|
+
return `${processAggType(pivot.aggregationType, true)}(CASE WHEN ${processColumnReference(columnField, databaseType)} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, pivot.valueField)} END) AS ${processColumnReference(`comparison_${column}`, databaseType)}`;
|
|
89
146
|
});
|
|
90
147
|
const compareCTE = itemQueries[1] && comparisonInterval
|
|
91
148
|
? `, quill_ct as (${itemQueries[1]?.replaceAll(';', '')})`
|
|
92
149
|
: '';
|
|
93
150
|
const compareCaseWhenCTE = itemQueries[1] && comparisonInterval
|
|
94
|
-
? `, quill_ct_cw as (SELECT
|
|
151
|
+
? `, quill_ct_cw as (SELECT ${processDateTrunc(dateBucket, rowField, databaseType)} as ${processColumnReference(`comparison_${rowField}`, databaseType)}, ${caseWhensCompare.join(', ')} FROM quill_ct GROUP BY ${processDateTrunc(dateBucket, rowField, databaseType)})`
|
|
95
152
|
: '';
|
|
96
153
|
const joinQuery = itemQueries[1] && comparisonInterval
|
|
97
|
-
? `LEFT JOIN quill_ct_cw ct ON qt
|
|
154
|
+
? `LEFT JOIN quill_ct_cw ${processColumnReference(`ct`, databaseType)} ON qt.${processColumnReference(`${rowField}`, databaseType)} = ${processDateTrunc(dateBucket, `ct.comparison_${rowField}`, databaseType, comparisonInterval)}`
|
|
98
155
|
: '';
|
|
99
156
|
return `WITH quill_query_table AS (${itemQueries[0]?.replaceAll(';', '')}),
|
|
100
|
-
quill_qt_agg as (SELECT
|
|
157
|
+
quill_qt_agg as (SELECT ${processDateTrunc(dateBucket, rowField, databaseType)} as ${processColumnReference(rowField, databaseType)}, ${caseWhens.join(', ')} FROM quill_query_table qt GROUP BY ${processDateTrunc(dateBucket, rowField, databaseType)})
|
|
101
158
|
${compareCTE} ${compareCaseWhenCTE}
|
|
102
159
|
SELECT * FROM quill_qt_agg qt
|
|
103
|
-
${joinQuery} ORDER BY qt
|
|
160
|
+
${joinQuery} ORDER BY qt.${processColumnReference(`${rowField}`, databaseType)}`;
|
|
104
161
|
}
|
|
105
|
-
function create1DPivotQuery(pivot, itemQueries, dateBucket = 'month', comparisonInterval) {
|
|
162
|
+
function create1DPivotQuery(pivot, itemQueries, dateBucket = 'month', databaseType, comparisonInterval) {
|
|
106
163
|
if (['string', 'varchar'].includes(pivot.rowFieldType) ||
|
|
107
164
|
!pivot.rowFieldType) {
|
|
108
|
-
return create1DStringPivotQuery(pivot, itemQueries);
|
|
165
|
+
return create1DStringPivotQuery(pivot, itemQueries, databaseType);
|
|
109
166
|
}
|
|
110
|
-
return create1DDatePivotQuery(pivot, itemQueries, dateBucket, comparisonInterval);
|
|
167
|
+
return create1DDatePivotQuery(pivot, itemQueries, dateBucket, databaseType, comparisonInterval);
|
|
111
168
|
}
|
|
112
|
-
function create1DStringPivotQuery(pivot, itemQueries) {
|
|
169
|
+
function create1DStringPivotQuery(pivot, itemQueries, databaseType) {
|
|
170
|
+
const rowField = pivot.rowField;
|
|
171
|
+
const valueField = pivot.valueField;
|
|
113
172
|
const compareCTE = itemQueries[1]
|
|
114
173
|
? `, quill_ct as (${itemQueries[1]?.replaceAll(';', '')})`
|
|
115
174
|
: '';
|
|
116
175
|
const compareCaseWhenCTE = itemQueries[1]
|
|
117
|
-
? `, quill_ct_cw as (SELECT ${
|
|
176
|
+
? `, quill_ct_cw as (SELECT ${processColumnReference(`${rowField}`, databaseType)} as ${processColumnReference(`comparison_${rowField}`, databaseType)}, ${processAggType(pivot.aggregationType)}(${processColumnReference(`${valueField || rowField}`, databaseType)}) as ${processColumnReference(`comparison_${valueField || 'count'}`, databaseType)} FROM quill_ct GROUP BY ${processColumnReference(`${rowField}`, databaseType)})`
|
|
118
177
|
: '';
|
|
119
178
|
const joinQuery = itemQueries[1]
|
|
120
|
-
? `JOIN quill_ct_cw ct ON ct
|
|
179
|
+
? `JOIN quill_ct_cw ct ON ct.${processColumnReference(`comparison_${rowField}`, databaseType)} = qt.${processColumnReference(`${rowField}`, databaseType)}`
|
|
121
180
|
: '';
|
|
122
181
|
return `WITH quill_qt AS (${itemQueries[0]?.replaceAll(';', '')}),
|
|
123
|
-
quill_qt_cw AS (SELECT ${
|
|
182
|
+
quill_qt_cw AS (SELECT ${processColumnReference(`${rowField}`, databaseType)}, ${processAggType(pivot.aggregationType)}(${processColumnReference(`${valueField || rowField}`, databaseType)}) as ${processColumnReference(`${valueField}` || 'count', databaseType)} FROM quill_qt GROUP BY ${processColumnReference(`${rowField}`, databaseType)})
|
|
124
183
|
${compareCTE} ${compareCaseWhenCTE}
|
|
125
|
-
SELECT * FROM quill_qt_cw qt
|
|
184
|
+
SELECT * FROM quill_qt_cw qt
|
|
126
185
|
${joinQuery}`;
|
|
127
186
|
}
|
|
128
|
-
function create1DDatePivotQuery(pivot, itemQueries, dateBucket = 'month', comparisonInterval) {
|
|
187
|
+
function create1DDatePivotQuery(pivot, itemQueries, dateBucket = 'month', databaseType, comparisonInterval) {
|
|
188
|
+
const rowField = pivot.rowField;
|
|
189
|
+
const valueField = pivot.valueField;
|
|
129
190
|
const compareCTE = itemQueries[1] && comparisonInterval
|
|
130
191
|
? `, quill_ct as (${itemQueries[1]?.replaceAll(';', '')})`
|
|
131
192
|
: '';
|
|
132
193
|
const compareCaseWhenCTE = itemQueries[1] && comparisonInterval
|
|
133
|
-
? `, quill_ct_cw as (SELECT
|
|
194
|
+
? `, quill_ct_cw as (SELECT ${processDateTrunc(dateBucket, rowField, databaseType)} as ${processColumnReference(`comparison_${rowField}`, databaseType)}, ${processAggType(pivot.aggregationType)}(${processColumnReference(`${valueField || rowField}`, databaseType)}) as ${processColumnReference(`comparison_${valueField || 'count'}`, databaseType)} FROM quill_ct GROUP BY ${processDateTrunc(dateBucket, rowField, databaseType)})`
|
|
134
195
|
: '';
|
|
135
196
|
const joinQuery = itemQueries[1] && comparisonInterval
|
|
136
|
-
? `LEFT JOIN quill_ct_cw ct ON qt
|
|
197
|
+
? `LEFT JOIN quill_ct_cw ${processColumnReference(`ct`, databaseType)} ON qt.${processColumnReference(`${rowField}`, databaseType)} = ${processDateTrunc(dateBucket, `ct.comparison_${rowField}`, databaseType, comparisonInterval)}`
|
|
137
198
|
: '';
|
|
138
199
|
return `WITH quill_qt AS (${itemQueries[0]?.replaceAll(';', '')}),
|
|
139
|
-
quill_qt_agg AS (SELECT
|
|
200
|
+
quill_qt_agg AS (SELECT ${processDateTrunc(dateBucket, rowField, databaseType)} as ${processColumnReference(`${rowField}`, databaseType)}, ${processAggType(pivot.aggregationType)}(${processColumnReference(`${valueField || rowField}`, databaseType)}) as ${processColumnReference(`${valueField || 'count'}`, databaseType)} FROM quill_qt GROUP BY ${processDateTrunc(dateBucket, rowField, databaseType)})
|
|
140
201
|
${compareCTE} ${compareCaseWhenCTE}
|
|
141
202
|
SELECT * FROM quill_qt_agg qt
|
|
142
|
-
${joinQuery} ORDER BY qt
|
|
203
|
+
${joinQuery} ORDER BY qt.${processColumnReference(`${rowField}`, databaseType)}`;
|
|
143
204
|
}
|
|
144
|
-
function createAggregationValuePivot(pivot, itemQueries) {
|
|
205
|
+
function createAggregationValuePivot(pivot, itemQueries, databaseType) {
|
|
206
|
+
const valueField = pivot.valueField;
|
|
145
207
|
let aggregationType = processAggType(pivot.aggregationType);
|
|
146
|
-
if (pivot.aggregationType === 'count') {
|
|
147
|
-
aggregationType = 'COUNT';
|
|
148
|
-
}
|
|
149
208
|
if (!pivot.valueField)
|
|
150
209
|
return undefined;
|
|
151
210
|
const compareCTE = itemQueries[1]
|
|
152
211
|
? `, quill_ct as (${itemQueries[1]?.replaceAll(';', '')})`
|
|
153
212
|
: '';
|
|
154
213
|
const compareAggregation = itemQueries[1]
|
|
155
|
-
? `, quill_ct_cw as (SELECT ${aggregationType}(${
|
|
214
|
+
? `, quill_ct_cw as (SELECT ${aggregationType}(${processColumnReference(`${valueField}`, databaseType)}) as ${processColumnReference(`comparison_${valueField}`, databaseType)} FROM quill_ct)`
|
|
156
215
|
: '';
|
|
157
216
|
const joinQuery = itemQueries[1] ? `CROSS JOIN quill_ct_cw ct` : '';
|
|
158
217
|
return `WITH quill_qt AS (${itemQueries[0]?.replaceAll(';', '')}),
|
|
159
|
-
quill_qt_agg AS (SELECT ${aggregationType}(${
|
|
218
|
+
quill_qt_agg AS (SELECT ${aggregationType}(${processColumnReference(`${valueField}`, databaseType)}) as ${processColumnReference(`${valueField}`, databaseType)} FROM quill_qt)
|
|
160
219
|
${compareCTE} ${compareAggregation}
|
|
161
220
|
SELECT * FROM quill_qt_agg qt
|
|
162
221
|
${joinQuery}`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queryConstructor.uspec.d.ts","sourceRoot":"","sources":["../../../src/utils/queryConstructor.uspec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { generatePivotQuery } from './queryConstructor';
|
|
2
|
+
const removeExtraSpacesAndNewLines = (str) => {
|
|
3
|
+
return str.replace(/\s+/g, ' ').trim();
|
|
4
|
+
};
|
|
5
|
+
describe('queryConstructor', () => {
|
|
6
|
+
let default2DPivot = {
|
|
7
|
+
rowField: 'merchant',
|
|
8
|
+
rowFieldType: 'string',
|
|
9
|
+
columnField: 'user',
|
|
10
|
+
valueField: 'amount',
|
|
11
|
+
aggregationType: 'sum',
|
|
12
|
+
};
|
|
13
|
+
const nonComparisonQuery = ['select * from transactions'];
|
|
14
|
+
const comparisonQueries = [
|
|
15
|
+
`select * from transactions where created_at BETWEEN '2024-06-01' AND '2024-07-01'`,
|
|
16
|
+
`select * from transactions where created_at BETWEEN '2024-05-01' AND '2024-06-01'`,
|
|
17
|
+
];
|
|
18
|
+
describe('bigquery - generatePivotQuery', () => {
|
|
19
|
+
let databaseType = 'bigquery';
|
|
20
|
+
it('should return a 2d string pivot query', async () => {
|
|
21
|
+
const query = generatePivotQuery(default2DPivot, nonComparisonQuery, databaseType, undefined, ['value1', 'value2']);
|
|
22
|
+
const expected = `WITH quill_qt AS (select * from transactions),
|
|
23
|
+
quill_qt_cw AS (SELECT \`merchant\`,
|
|
24
|
+
sum(CASE WHEN \`user\` = 'value1' THEN \`amount\` ELSE 0 END) AS \`value1\`,
|
|
25
|
+
sum(CASE WHEN \`user\` = 'value2' THEN \`amount\` ELSE 0 END) AS \`value2\`
|
|
26
|
+
FROM quill_qt GROUP BY \`merchant\`)
|
|
27
|
+
SELECT * FROM quill_qt_cw qt`;
|
|
28
|
+
expect(removeExtraSpacesAndNewLines(query)).toEqual(removeExtraSpacesAndNewLines(expected));
|
|
29
|
+
});
|
|
30
|
+
it('should return a 2d date pivot query', async () => {
|
|
31
|
+
const query = generatePivotQuery({
|
|
32
|
+
...default2DPivot,
|
|
33
|
+
rowFieldType: 'MMM_DD_YYY',
|
|
34
|
+
rowField: 'created_at',
|
|
35
|
+
}, nonComparisonQuery, databaseType, undefined, ['value1', 'value2']);
|
|
36
|
+
const expected = `WITH quill_query_table AS (select * from transactions),
|
|
37
|
+
quill_qt_agg as (SELECT TIMESTAMP_TRUNC(\`created_at\`, month) as \`created_at\`,
|
|
38
|
+
sum(CASE WHEN qt.\`user\` = 'value1' THEN \`amount\` ELSE 0 END) AS \`value1\`,
|
|
39
|
+
sum(CASE WHEN qt.\`user\` = 'value2' THEN \`amount\` ELSE 0 END) AS \`value2\` FROM quill_query_table qt
|
|
40
|
+
GROUP BY TIMESTAMP_TRUNC(\`created_at\`, month))
|
|
41
|
+
SELECT * FROM quill_qt_agg qt ORDER BY qt.\`created_at\``;
|
|
42
|
+
expect(removeExtraSpacesAndNewLines(query)).toEqual(removeExtraSpacesAndNewLines(expected));
|
|
43
|
+
});
|
|
44
|
+
it('should return a 1d date pivot query', async () => {
|
|
45
|
+
const query = generatePivotQuery({
|
|
46
|
+
...default2DPivot,
|
|
47
|
+
rowFieldType: 'MMM_DD_YYY',
|
|
48
|
+
rowField: 'created_at',
|
|
49
|
+
columnField: undefined,
|
|
50
|
+
}, nonComparisonQuery, databaseType, undefined);
|
|
51
|
+
const expected = `WITH quill_qt AS (select * from transactions),
|
|
52
|
+
quill_qt_agg AS (SELECT TIMESTAMP_TRUNC(\`created_at\`, month) as \`created_at\`,
|
|
53
|
+
sum(\`amount\`) as \`amount\` FROM quill_qt GROUP BY TIMESTAMP_TRUNC(\`created_at\`, month))
|
|
54
|
+
SELECT * FROM quill_qt_agg qt ORDER BY qt.\`created_at\``;
|
|
55
|
+
expect(removeExtraSpacesAndNewLines(query)).toEqual(removeExtraSpacesAndNewLines(expected));
|
|
56
|
+
});
|
|
57
|
+
it('should return a 1d string pivot query', async () => {
|
|
58
|
+
const query = generatePivotQuery({ ...default2DPivot, columnField: undefined }, nonComparisonQuery, databaseType, undefined);
|
|
59
|
+
const expected = `WITH quill_qt AS (select * from transactions),
|
|
60
|
+
quill_qt_cw AS (SELECT \`merchant\`, sum(\`amount\`) as \`amount\`
|
|
61
|
+
FROM quill_qt GROUP BY \`merchant\`)
|
|
62
|
+
SELECT * FROM quill_qt_cw qt`;
|
|
63
|
+
expect(removeExtraSpacesAndNewLines(query)).toEqual(removeExtraSpacesAndNewLines(expected));
|
|
64
|
+
});
|
|
65
|
+
it('should return a value aggregation query', async () => {
|
|
66
|
+
const query = generatePivotQuery(
|
|
67
|
+
// @ts-ignore
|
|
68
|
+
{ ...default2DPivot, columnField: undefined, rowField: undefined }, nonComparisonQuery, databaseType, undefined);
|
|
69
|
+
const expected = `WITH quill_qt AS (select * from transactions),
|
|
70
|
+
quill_qt_agg AS (SELECT sum(\`amount\`) as \`amount\` FROM quill_qt) SELECT * FROM quill_qt_agg qt`;
|
|
71
|
+
expect(removeExtraSpacesAndNewLines(query)).toEqual(removeExtraSpacesAndNewLines(expected));
|
|
72
|
+
});
|
|
73
|
+
it('should return a 2d string pivot query with comparison', async () => {
|
|
74
|
+
const query = generatePivotQuery(default2DPivot, comparisonQueries, databaseType, undefined, ['value1', 'value2']);
|
|
75
|
+
const expected = `WITH quill_qt AS
|
|
76
|
+
(select * from transactions where created_at BETWEEN '2024-06-01' AND '2024-07-01'),
|
|
77
|
+
quill_qt_cw AS (SELECT \`merchant\`,
|
|
78
|
+
sum(CASE WHEN \`user\` = 'value1' THEN \`amount\` ELSE 0 END) AS \`value1\`,
|
|
79
|
+
sum(CASE WHEN \`user\` = 'value2' THEN \`amount\` ELSE 0 END) AS \`value2\` FROM quill_qt GROUP BY \`merchant\`) ,
|
|
80
|
+
quill_ct as (select * from transactions where created_at BETWEEN '2024-05-01' AND '2024-06-01') ,
|
|
81
|
+
quill_ct_cw as (SELECT \`merchant\` as \`comparison_merchant\`,
|
|
82
|
+
sum(CASE WHEN \`user\` = 'value1' THEN \`amount\` ELSE 0 END) AS \`comparison_value1\`,
|
|
83
|
+
sum(CASE WHEN \`user\` = 'value2' THEN \`amount\` ELSE 0 END) AS \`comparison_value2\` FROM quill_ct GROUP BY \`merchant\`)
|
|
84
|
+
SELECT * FROM quill_qt_cw qt JOIN quill_ct_cw ct ON ct.\`comparison_merchant\` = qt.\`merchant\``;
|
|
85
|
+
expect(removeExtraSpacesAndNewLines(query)).toEqual(removeExtraSpacesAndNewLines(expected));
|
|
86
|
+
});
|
|
87
|
+
it('should return a 2d date pivot query with comparison', async () => {
|
|
88
|
+
const query = generatePivotQuery({
|
|
89
|
+
...default2DPivot,
|
|
90
|
+
rowFieldType: 'MMM_DD_YYY',
|
|
91
|
+
rowField: 'created_at',
|
|
92
|
+
}, comparisonQueries, databaseType, '90', ['value1', 'value2']);
|
|
93
|
+
const expected = `WITH quill_query_table AS (select * from transactions where created_at BETWEEN '2024-06-01' AND '2024-07-01'),
|
|
94
|
+
quill_qt_agg as (SELECT TIMESTAMP_TRUNC(\`created_at\`, month) as \`created_at\`,
|
|
95
|
+
sum(CASE WHEN qt.\`user\` = 'value1' THEN \`amount\` ELSE 0 END) AS \`value1\`,
|
|
96
|
+
sum(CASE WHEN qt.\`user\` = 'value2' THEN \`amount\` ELSE 0 END) AS \`value2\`
|
|
97
|
+
FROM quill_query_table qt GROUP BY TIMESTAMP_TRUNC(\`created_at\`, month)) ,
|
|
98
|
+
quill_ct as (select * from transactions where created_at BETWEEN '2024-05-01' AND '2024-06-01') ,
|
|
99
|
+
quill_ct_cw as (SELECT TIMESTAMP_TRUNC(\`created_at\`, month) as \`comparison_created_at\`,
|
|
100
|
+
sum(CASE WHEN \`user\` = 'value1' THEN \`amount\` ELSE 0 END) AS \`comparison_value1\`,
|
|
101
|
+
sum(CASE WHEN \`user\` = 'value2' THEN \`amount\` ELSE 0 END) AS \`comparison_value2\`
|
|
102
|
+
FROM quill_ct GROUP BY TIMESTAMP_TRUNC(\`created_at\`, month))
|
|
103
|
+
SELECT * FROM quill_qt_agg qt
|
|
104
|
+
LEFT JOIN quill_ct_cw \`ct\` ON qt.\`created_at\` = TIMESTAMP_TRUNC(TIMESTAMP_ADD(\`ct\`.\`comparison_created_at\`, INTERVAL 90 ), month)
|
|
105
|
+
ORDER BY qt.\`created_at\``;
|
|
106
|
+
expect(removeExtraSpacesAndNewLines(query)).toEqual(removeExtraSpacesAndNewLines(expected));
|
|
107
|
+
});
|
|
108
|
+
it('should return a 1d date pivot query with comparison', async () => {
|
|
109
|
+
const query = generatePivotQuery({
|
|
110
|
+
...default2DPivot,
|
|
111
|
+
rowFieldType: 'MMM_DD_YYY',
|
|
112
|
+
rowField: 'created_at',
|
|
113
|
+
columnField: undefined,
|
|
114
|
+
}, comparisonQueries, databaseType, '3 month');
|
|
115
|
+
const expected = `WITH quill_qt AS (select * from transactions where created_at BETWEEN '2024-06-01' AND '2024-07-01'),
|
|
116
|
+
quill_qt_agg AS (SELECT TIMESTAMP_TRUNC(\`created_at\`, month) as \`created_at\`,
|
|
117
|
+
sum(\`amount\`) as \`amount\` FROM quill_qt GROUP BY TIMESTAMP_TRUNC(\`created_at\`, month)) ,
|
|
118
|
+
quill_ct as (select * from transactions where created_at BETWEEN '2024-05-01' AND '2024-06-01') ,
|
|
119
|
+
quill_ct_cw as (SELECT TIMESTAMP_TRUNC(\`created_at\`, month) as \`comparison_created_at\`,
|
|
120
|
+
sum(\`amount\`) as \`comparison_amount\` FROM quill_ct GROUP BY TIMESTAMP_TRUNC(\`created_at\`, month))
|
|
121
|
+
SELECT * FROM quill_qt_agg qt LEFT JOIN quill_ct_cw \`ct\` ON qt.\`created_at\` = TIMESTAMP_TRUNC(TIMESTAMP_ADD(\`ct\`.\`comparison_created_at\`, INTERVAL 3 month ), month)
|
|
122
|
+
ORDER BY qt.\`created_at\``;
|
|
123
|
+
expect(removeExtraSpacesAndNewLines(query)).toEqual(removeExtraSpacesAndNewLines(expected));
|
|
124
|
+
});
|
|
125
|
+
it('should return a 1d string pivot query with comparison', async () => {
|
|
126
|
+
const query = generatePivotQuery({ ...default2DPivot, columnField: undefined }, comparisonQueries, databaseType, undefined);
|
|
127
|
+
const expected = `WITH quill_qt AS (select * from transactions where created_at BETWEEN '2024-06-01' AND '2024-07-01'),
|
|
128
|
+
quill_qt_cw AS (SELECT \`merchant\`, sum(\`amount\`) as \`amount\` FROM quill_qt GROUP BY \`merchant\`) ,
|
|
129
|
+
quill_ct as (select * from transactions where created_at BETWEEN '2024-05-01' AND '2024-06-01') ,
|
|
130
|
+
quill_ct_cw as (SELECT \`merchant\` as \`comparison_merchant\`, sum(\`amount\`) as \`comparison_amount\` FROM quill_ct GROUP BY \`merchant\`)
|
|
131
|
+
SELECT * FROM quill_qt_cw qt JOIN quill_ct_cw ct ON ct.\`comparison_merchant\` = qt.\`merchant\``;
|
|
132
|
+
expect(removeExtraSpacesAndNewLines(query)).toEqual(removeExtraSpacesAndNewLines(expected));
|
|
133
|
+
});
|
|
134
|
+
it('should return a value aggregation query', async () => {
|
|
135
|
+
const query = generatePivotQuery(
|
|
136
|
+
// @ts-ignore
|
|
137
|
+
{ ...default2DPivot, columnField: undefined, rowField: undefined }, comparisonQueries, databaseType, undefined);
|
|
138
|
+
const expected = `WITH quill_qt AS (select * from transactions where created_at BETWEEN '2024-06-01' AND '2024-07-01'),
|
|
139
|
+
quill_qt_agg AS (SELECT sum(\`amount\`) as \`amount\` FROM quill_qt) ,
|
|
140
|
+
quill_ct as (select * from transactions where created_at BETWEEN '2024-05-01' AND '2024-06-01') ,
|
|
141
|
+
quill_ct_cw as (SELECT sum(\`amount\`) as \`comparison_amount\` FROM quill_ct)
|
|
142
|
+
SELECT * FROM quill_qt_agg qt CROSS JOIN quill_ct_cw ct`;
|
|
143
|
+
expect(removeExtraSpacesAndNewLines(query)).toEqual(removeExtraSpacesAndNewLines(expected));
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
describe('postgresql - generatePivotQuery', () => {
|
|
147
|
+
let databaseType = 'postgresql';
|
|
148
|
+
it('should return a 2d string pivot query', async () => {
|
|
149
|
+
const query = generatePivotQuery(default2DPivot, ['select * from transactions'], databaseType, undefined, ['value1', 'value2']);
|
|
150
|
+
const expected = `WITH quill_qt AS (select * from transactions),
|
|
151
|
+
quill_qt_cw AS
|
|
152
|
+
(SELECT \"merchant\", sum(CASE WHEN \"user\" = 'value1' THEN \"amount\" ELSE 0 END) AS \"value1\",
|
|
153
|
+
sum(CASE WHEN \"user\" = 'value2' THEN \"amount\" ELSE 0 END) AS \"value2\" FROM quill_qt GROUP BY \"merchant\")
|
|
154
|
+
SELECT * FROM quill_qt_cw qt`;
|
|
155
|
+
expect(removeExtraSpacesAndNewLines(query)).toEqual(removeExtraSpacesAndNewLines(expected));
|
|
156
|
+
});
|
|
157
|
+
it('should return a 2d date pivot query', async () => {
|
|
158
|
+
const query = generatePivotQuery({
|
|
159
|
+
...default2DPivot,
|
|
160
|
+
rowFieldType: 'MMM_DD_YYY',
|
|
161
|
+
rowField: 'created_at',
|
|
162
|
+
}, ['select * from transactions'], databaseType, undefined, ['value1', 'value2']);
|
|
163
|
+
const expected = `WITH quill_query_table AS (select * from transactions),
|
|
164
|
+
quill_qt_agg as (SELECT date_trunc('month', \"created_at\") as \"created_at\",
|
|
165
|
+
sum(CASE WHEN qt.\"user\" = 'value1' THEN \"amount\" ELSE 0 END) AS \"value1\",
|
|
166
|
+
sum(CASE WHEN qt.\"user\" = 'value2' THEN \"amount\" ELSE 0 END) AS \"value2\"
|
|
167
|
+
FROM quill_query_table qt
|
|
168
|
+
GROUP BY date_trunc('month', \"created_at\"))
|
|
169
|
+
SELECT * FROM quill_qt_agg qt ORDER BY qt.\"created_at\"`;
|
|
170
|
+
expect(removeExtraSpacesAndNewLines(query)).toEqual(removeExtraSpacesAndNewLines(expected));
|
|
171
|
+
});
|
|
172
|
+
it('should return a 1d date pivot query', async () => {
|
|
173
|
+
const query = generatePivotQuery({
|
|
174
|
+
...default2DPivot,
|
|
175
|
+
rowFieldType: 'MMM_DD_YYY',
|
|
176
|
+
rowField: 'created_at',
|
|
177
|
+
columnField: undefined,
|
|
178
|
+
}, ['select * from transactions'], databaseType, undefined);
|
|
179
|
+
const expected = `WITH quill_qt AS (select * from transactions),
|
|
180
|
+
quill_qt_agg AS (SELECT date_trunc('month', \"created_at\") as \"created_at\", sum(\"amount\") as \"amount\"
|
|
181
|
+
FROM quill_qt
|
|
182
|
+
GROUP BY date_trunc('month', \"created_at\"))
|
|
183
|
+
SELECT * FROM quill_qt_agg qt ORDER BY qt.\"created_at\"`;
|
|
184
|
+
expect(removeExtraSpacesAndNewLines(query)).toEqual(removeExtraSpacesAndNewLines(expected));
|
|
185
|
+
});
|
|
186
|
+
it('should return a 1d string pivot query', async () => {
|
|
187
|
+
const query = generatePivotQuery({ ...default2DPivot, columnField: undefined }, ['select * from transactions'], databaseType, undefined);
|
|
188
|
+
const expected = `WITH quill_qt AS (select * from transactions),
|
|
189
|
+
quill_qt_cw AS (SELECT "merchant", sum("amount") as "amount"
|
|
190
|
+
FROM quill_qt
|
|
191
|
+
GROUP BY "merchant")
|
|
192
|
+
SELECT * FROM quill_qt_cw qt`;
|
|
193
|
+
expect(removeExtraSpacesAndNewLines(query)).toEqual(removeExtraSpacesAndNewLines(expected));
|
|
194
|
+
});
|
|
195
|
+
it('should return a value aggregation query', async () => {
|
|
196
|
+
const query = generatePivotQuery(
|
|
197
|
+
// @ts-ignore
|
|
198
|
+
{ ...default2DPivot, columnField: undefined, rowField: undefined }, ['select * from transactions'], databaseType, undefined);
|
|
199
|
+
const expected = `WITH quill_qt AS (select * from transactions),
|
|
200
|
+
quill_qt_agg AS (SELECT sum("amount") as "amount" FROM quill_qt) SELECT * FROM quill_qt_agg qt`;
|
|
201
|
+
expect(removeExtraSpacesAndNewLines(query)).toEqual(removeExtraSpacesAndNewLines(expected));
|
|
202
|
+
});
|
|
203
|
+
it('should return a 2d date pivot query with comparison', async () => {
|
|
204
|
+
const query = generatePivotQuery({
|
|
205
|
+
...default2DPivot,
|
|
206
|
+
rowFieldType: 'MMM_DD_YYY',
|
|
207
|
+
rowField: 'created_at',
|
|
208
|
+
}, comparisonQueries, databaseType, '90 DAY', ['value1', 'value2']);
|
|
209
|
+
const expected = `WITH quill_query_table AS
|
|
210
|
+
(select * from transactions where created_at BETWEEN '2024-06-01' AND '2024-07-01'),
|
|
211
|
+
quill_qt_agg as (SELECT date_trunc('month', \"created_at\") as \"created_at\",
|
|
212
|
+
sum(CASE WHEN qt.\"user\" = 'value1' THEN \"amount\" ELSE 0 END) AS \"value1\",
|
|
213
|
+
sum(CASE WHEN qt.\"user\" = 'value2' THEN \"amount\" ELSE 0 END) AS \"value2\" FROM quill_query_table qt GROUP BY date_trunc('month', \"created_at\")) ,
|
|
214
|
+
quill_ct as (select * from transactions where created_at BETWEEN '2024-05-01' AND '2024-06-01') ,
|
|
215
|
+
quill_ct_cw as (SELECT date_trunc('month', \"created_at\") as \"comparison_created_at\",
|
|
216
|
+
sum(CASE WHEN \"user\" = 'value1' THEN \"amount\" ELSE 0 END) AS \"comparison_value1\",
|
|
217
|
+
sum(CASE WHEN \"user\" = 'value2' THEN \"amount\" ELSE 0 END) AS \"comparison_value2\" FROM quill_ct GROUP BY date_trunc('month', \"created_at\"))
|
|
218
|
+
SELECT * FROM quill_qt_agg qt LEFT JOIN quill_ct_cw \"ct\" ON qt.\"created_at\" = date_trunc('month', (\"ct\".\"comparison_created_at\" + INTERVAL '90 DAY'))
|
|
219
|
+
ORDER BY qt.\"created_at\"`;
|
|
220
|
+
expect(removeExtraSpacesAndNewLines(query)).toEqual(removeExtraSpacesAndNewLines(expected));
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
});
|
|
@@ -16,6 +16,7 @@ export declare const getUniqueValuesByColumns: (columns: Column[], query: string
|
|
|
16
16
|
[value: string]: boolean;
|
|
17
17
|
};
|
|
18
18
|
} | null>;
|
|
19
|
+
export declare const getCountsByColumns: (columns: Column[], query: string, client: any, customFields: any[]) => Promise<Column[]>;
|
|
19
20
|
export declare const getDateRangeByColumns: (columns: Column[], query: string, client: any, customFields: any[]) => Promise<{
|
|
20
21
|
[column: string]: {
|
|
21
22
|
dateRange: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tableProcessing.d.ts","sourceRoot":"","sources":["../../../src/utils/tableProcessing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"tableProcessing.d.ts","sourceRoot":"","sources":["../../../src/utils/tableProcessing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAW3C,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5C,IAAI,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;CACrD;AAED,eAAO,MAAM,cAAc,YAChB,MAAM,EAAE,qBACE,MAAM,EAAE,KAC1B,OAUF,CAAC;AAEF,eAAO,MAAM,wBAAwB,YAC1B,MAAM,EAAE,SACV,MAAM,QACP,GAAG,UACD,GAAG,gBACG,GAAG,EAAE;;;;SAiEpB,CAAC;AAEF,eAAO,MAAM,kBAAkB,YACpB,MAAM,EAAE,SACV,MAAM,UACL,GAAG,gBACG,GAAG,EAAE,KAClB,QAAQ,MAAM,EAAE,CA2ClB,CAAC;AAkDF,eAAO,MAAM,qBAAqB,YACvB,MAAM,EAAE,SACV,MAAM,UACL,GAAG,gBACG,GAAG,EAAE;;mBAEY;YAAE,KAAK,EAAE,IAAI,CAAC;YAAC,GAAG,EAAE,IAAI,CAAA;SAAE;;SAiB1D,CAAC;AA2DF,eAAO,MAAM,gBAAgB,WACnB,WAAW,UACX,GAAG,eACE,GAAG,YACN,GAAG,iBACE,GAAG;;EA4CnB,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { getData } from './dataFetcher';
|
|
2
|
+
import { parseDateByDatabaseType } from './dates';
|
|
2
3
|
import { processFilterErrorList } from './errorProcessing';
|
|
3
4
|
import { mergeComparisonRange } from './merge';
|
|
4
|
-
import { generateDistinctQuery, generateMinMaxRangeQueries, } from './queryConstructor';
|
|
5
|
+
import { generateCountQuery, generateDistinctQuery, generateMinMaxRangeQueries, } from './queryConstructor';
|
|
5
6
|
export const hasColumnAlias = (columns, referencedColumns) => {
|
|
6
7
|
if (!referencedColumns) {
|
|
7
8
|
return true;
|
|
@@ -48,7 +49,7 @@ export const getUniqueValuesByColumns = async (columns, query, rows, client, cus
|
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
else {
|
|
51
|
-
const distinctValueQuery = generateDistinctQuery(stringNames, query);
|
|
52
|
+
const distinctValueQuery = generateDistinctQuery(stringNames, query, client.databaseType);
|
|
52
53
|
const distinctStrings = await fetchDistinctStrings(distinctValueQuery, client, customFields);
|
|
53
54
|
if (!distinctStrings) {
|
|
54
55
|
return {};
|
|
@@ -59,6 +60,39 @@ export const getUniqueValuesByColumns = async (columns, query, rows, client, cus
|
|
|
59
60
|
}
|
|
60
61
|
return uniqueValues;
|
|
61
62
|
};
|
|
63
|
+
export const getCountsByColumns = async (columns, query, client, customFields) => {
|
|
64
|
+
const stringNames = columns.map((column) => column.field);
|
|
65
|
+
const countQuery = generateCountQuery(stringNames, query, client.databaseType);
|
|
66
|
+
try {
|
|
67
|
+
const hostedBody = {
|
|
68
|
+
metadata: {
|
|
69
|
+
query: countQuery,
|
|
70
|
+
task: 'query',
|
|
71
|
+
orgId: client.customerId || '*',
|
|
72
|
+
clientId: client.publicKey,
|
|
73
|
+
databaseType: client?.databaseType,
|
|
74
|
+
customFieldsByTable: customFields,
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
const cloudBody = { countQuery };
|
|
78
|
+
const data = await getData(client, 'dashquery', 'same-origin', hostedBody, cloudBody);
|
|
79
|
+
if (data.errorMessage) {
|
|
80
|
+
return columns;
|
|
81
|
+
}
|
|
82
|
+
const results = data.rows.map((columnInfo) => {
|
|
83
|
+
return { field: columnInfo.field, count: columnInfo.count };
|
|
84
|
+
});
|
|
85
|
+
const filteredColumns = columns.filter((column) => {
|
|
86
|
+
const columnInfo = results.find((result) => result.field === column.field);
|
|
87
|
+
return columnInfo.count <= 50;
|
|
88
|
+
});
|
|
89
|
+
return filteredColumns;
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
console.error(e);
|
|
93
|
+
return columns;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
62
96
|
const fetchDistinctStrings = async (query, client, customFields) => {
|
|
63
97
|
try {
|
|
64
98
|
const hostedBody = {
|
|
@@ -95,7 +129,9 @@ const fetchDistinctStrings = async (query, client, customFields) => {
|
|
|
95
129
|
}
|
|
96
130
|
};
|
|
97
131
|
export const getDateRangeByColumns = async (columns, query, client, customFields) => {
|
|
98
|
-
const columnNames = columns.map(
|
|
132
|
+
const columnNames = columns.map(
|
|
133
|
+
// @ts-ignore
|
|
134
|
+
(column) => column.field || column.name);
|
|
99
135
|
const distinctValueQuery = generateMinMaxRangeQueries(columnNames, query, client.databaseType);
|
|
100
136
|
const dateRanges = await fetchDateRanges(distinctValueQuery, client, customFields);
|
|
101
137
|
return dateRanges;
|
|
@@ -120,8 +156,8 @@ const fetchDateRanges = async (query, client, customFields) => {
|
|
|
120
156
|
const results = data.rows.reduce((acc, currentValue) => {
|
|
121
157
|
acc[currentValue.field] = {
|
|
122
158
|
dateRange: {
|
|
123
|
-
start:
|
|
124
|
-
end:
|
|
159
|
+
start: parseDateByDatabaseType(currentValue.min_range, client.databaseType),
|
|
160
|
+
end: parseDateByDatabaseType(currentValue.max_range, client.databaseType),
|
|
125
161
|
},
|
|
126
162
|
};
|
|
127
163
|
return acc;
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PivotModal.spec.d.ts","sourceRoot":"","sources":["../../../../src/internals/ReportBuilder/PivotModal.spec.ts"],"names":[],"mappings":""}
|