@quillsql/react 2.13.35 → 2.13.37
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 +0 -1
- package/dist/cjs/Chart.d.ts.map +1 -1
- package/dist/cjs/Chart.js +17 -14
- package/dist/cjs/ChartBuilder.d.ts +1 -0
- package/dist/cjs/ChartBuilder.d.ts.map +1 -1
- package/dist/cjs/ChartBuilder.js +178 -96
- package/dist/cjs/Context.d.ts.map +1 -1
- package/dist/cjs/Context.js +6 -8
- package/dist/cjs/Dashboard.d.ts +2 -1
- package/dist/cjs/Dashboard.d.ts.map +1 -1
- package/dist/cjs/Dashboard.js +18 -8
- package/dist/cjs/ReportBuilder.d.ts +2 -0
- package/dist/cjs/ReportBuilder.d.ts.map +1 -1
- package/dist/cjs/ReportBuilder.js +398 -271
- package/dist/cjs/SQLEditor.d.ts.map +1 -1
- package/dist/cjs/SQLEditor.js +33 -11
- package/dist/cjs/Table.d.ts.map +1 -1
- package/dist/cjs/Table.js +17 -1
- package/dist/cjs/components/Chart/InternalChart.d.ts +0 -1
- package/dist/cjs/components/Chart/InternalChart.d.ts.map +1 -1
- package/dist/cjs/components/Chart/InternalChart.js +6 -7
- package/dist/cjs/components/Dashboard/DataLoader.d.ts.map +1 -1
- package/dist/cjs/components/Dashboard/DataLoader.js +75 -30
- package/dist/cjs/components/Dashboard/MetricComponent.d.ts +1 -1
- package/dist/cjs/components/Dashboard/MetricComponent.d.ts.map +1 -1
- package/dist/cjs/components/Dashboard/MetricComponent.js +98 -106
- package/dist/cjs/components/QuillMultiSelectSectionList.d.ts.map +1 -1
- package/dist/cjs/components/QuillMultiSelectSectionList.js +21 -16
- package/dist/cjs/components/QuillMultiSelectWithCombo.js +18 -8
- package/dist/cjs/components/QuillSelectWithCombo.js +17 -7
- package/dist/cjs/components/ReportBuilder/AddLimitPopover.d.ts +1 -1
- package/dist/cjs/components/ReportBuilder/AddLimitPopover.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/AddLimitPopover.js +2 -2
- package/dist/cjs/components/ReportBuilder/AddSortPopover.d.ts +16 -4
- package/dist/cjs/components/ReportBuilder/AddSortPopover.d.ts.map +1 -1
- package/dist/cjs/components/ReportBuilder/AddSortPopover.js +9 -18
- package/dist/cjs/components/UiComponents.d.ts +2 -1
- package/dist/cjs/components/UiComponents.d.ts.map +1 -1
- package/dist/cjs/components/UiComponents.js +44 -28
- package/dist/cjs/hooks/useAskQuill.d.ts.map +1 -1
- package/dist/cjs/hooks/useAskQuill.js +28 -4
- package/dist/cjs/hooks/useQuill.d.ts.map +1 -1
- package/dist/cjs/hooks/useQuill.js +9 -1
- package/dist/cjs/hooks/useVirtualTables.d.ts.map +1 -1
- package/dist/cjs/hooks/useVirtualTables.js +11 -35
- package/dist/cjs/internals/ReportBuilder/PivotForm.d.ts.map +1 -1
- package/dist/cjs/internals/ReportBuilder/PivotForm.js +14 -2
- package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts +12 -11
- package/dist/cjs/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
- package/dist/cjs/internals/ReportBuilder/PivotModal.js +63 -18
- package/dist/cjs/models/Client.d.ts +4 -5
- package/dist/cjs/models/Client.d.ts.map +1 -1
- package/dist/cjs/models/Pivot.d.ts +10 -0
- package/dist/cjs/models/Pivot.d.ts.map +1 -1
- package/dist/cjs/models/Report.d.ts +13 -1
- package/dist/cjs/models/Report.d.ts.map +1 -1
- package/dist/cjs/utils/astFilterProcessing.d.ts +1 -1
- package/dist/cjs/utils/astFilterProcessing.d.ts.map +1 -1
- package/dist/cjs/utils/astFilterProcessing.js +799 -64
- package/dist/cjs/utils/astProcessing.d.ts +4 -1
- package/dist/cjs/utils/astProcessing.d.ts.map +1 -1
- package/dist/cjs/utils/astProcessing.js +2 -2
- package/dist/cjs/utils/client.d.ts.map +1 -1
- package/dist/cjs/utils/client.js +6 -3
- 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 +1 -0
- package/dist/cjs/utils/dashboard.d.ts +2 -1
- package/dist/cjs/utils/dashboard.d.ts.map +1 -1
- package/dist/cjs/utils/dashboard.js +38 -10
- package/dist/cjs/utils/filterProcessing.d.ts +1 -1
- package/dist/cjs/utils/filterProcessing.d.ts.map +1 -1
- package/dist/cjs/utils/merge.d.ts +16 -0
- package/dist/cjs/utils/merge.d.ts.map +1 -1
- package/dist/cjs/utils/merge.js +210 -0
- package/dist/cjs/utils/paginationProcessing.d.ts +1 -1
- package/dist/cjs/utils/paginationProcessing.d.ts.map +1 -1
- package/dist/cjs/utils/paginationProcessing.js +3 -2
- package/dist/cjs/utils/pivotConstructor.d.ts +19 -9
- package/dist/cjs/utils/pivotConstructor.d.ts.map +1 -1
- package/dist/cjs/utils/pivotConstructor.js +90 -34
- package/dist/cjs/utils/queryConstructor.d.ts +8 -1
- package/dist/cjs/utils/queryConstructor.d.ts.map +1 -1
- package/dist/cjs/utils/queryConstructor.js +276 -310
- package/dist/cjs/utils/report.d.ts +25 -12
- package/dist/cjs/utils/report.d.ts.map +1 -1
- package/dist/cjs/utils/report.js +13 -7
- package/dist/cjs/utils/schema.d.ts +1 -1
- package/dist/cjs/utils/schema.d.ts.map +1 -1
- package/dist/cjs/utils/schema.js +3 -32
- package/dist/cjs/utils/tableProcessing.d.ts +43 -13
- package/dist/cjs/utils/tableProcessing.d.ts.map +1 -1
- package/dist/cjs/utils/tableProcessing.js +140 -75
- package/dist/cjs/utils/textProcessing.d.ts.map +1 -1
- package/dist/cjs/utils/textProcessing.js +10 -1
- package/dist/cjs/utils/valueFormatter.d.ts +2 -1
- package/dist/cjs/utils/valueFormatter.d.ts.map +1 -1
- package/dist/cjs/utils/valueFormatter.js +18 -14
- package/dist/esm/Chart.d.ts +0 -1
- package/dist/esm/Chart.d.ts.map +1 -1
- package/dist/esm/Chart.js +0 -6
- package/dist/esm/ChartBuilder.d.ts +1 -0
- package/dist/esm/ChartBuilder.d.ts.map +1 -1
- package/dist/esm/ChartBuilder.js +179 -97
- package/dist/esm/Context.d.ts.map +1 -1
- package/dist/esm/Context.js +7 -9
- package/dist/esm/Dashboard.d.ts +2 -1
- package/dist/esm/Dashboard.d.ts.map +1 -1
- package/dist/esm/Dashboard.js +1 -1
- package/dist/esm/ReportBuilder.d.ts +2 -0
- package/dist/esm/ReportBuilder.d.ts.map +1 -1
- package/dist/esm/ReportBuilder.js +399 -272
- package/dist/esm/SQLEditor.d.ts.map +1 -1
- package/dist/esm/SQLEditor.js +33 -11
- package/dist/esm/Table.d.ts.map +1 -1
- package/dist/esm/Table.js +17 -1
- package/dist/esm/components/Chart/InternalChart.d.ts +0 -1
- package/dist/esm/components/Chart/InternalChart.d.ts.map +1 -1
- package/dist/esm/components/Chart/InternalChart.js +6 -6
- package/dist/esm/components/Dashboard/DataLoader.d.ts.map +1 -1
- package/dist/esm/components/Dashboard/DataLoader.js +75 -30
- package/dist/esm/components/Dashboard/MetricComponent.d.ts +1 -1
- package/dist/esm/components/Dashboard/MetricComponent.d.ts.map +1 -1
- package/dist/esm/components/Dashboard/MetricComponent.js +98 -106
- package/dist/esm/components/QuillMultiSelectSectionList.d.ts.map +1 -1
- package/dist/esm/components/QuillMultiSelectSectionList.js +5 -12
- package/dist/esm/components/QuillMultiSelectWithCombo.js +1 -1
- package/dist/esm/components/ReportBuilder/AddLimitPopover.d.ts +1 -1
- package/dist/esm/components/ReportBuilder/AddLimitPopover.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/AddLimitPopover.js +2 -2
- package/dist/esm/components/ReportBuilder/AddSortPopover.d.ts +16 -4
- package/dist/esm/components/ReportBuilder/AddSortPopover.d.ts.map +1 -1
- package/dist/esm/components/ReportBuilder/AddSortPopover.js +9 -18
- package/dist/esm/components/UiComponents.d.ts +2 -1
- package/dist/esm/components/UiComponents.d.ts.map +1 -1
- package/dist/esm/components/UiComponents.js +27 -21
- package/dist/esm/hooks/useAskQuill.d.ts.map +1 -1
- package/dist/esm/hooks/useAskQuill.js +28 -4
- package/dist/esm/hooks/useQuill.d.ts.map +1 -1
- package/dist/esm/hooks/useQuill.js +10 -2
- package/dist/esm/hooks/useVirtualTables.d.ts.map +1 -1
- package/dist/esm/hooks/useVirtualTables.js +12 -36
- package/dist/esm/internals/ReportBuilder/PivotForm.d.ts.map +1 -1
- package/dist/esm/internals/ReportBuilder/PivotForm.js +14 -2
- package/dist/esm/internals/ReportBuilder/PivotModal.d.ts +12 -11
- package/dist/esm/internals/ReportBuilder/PivotModal.d.ts.map +1 -1
- package/dist/esm/internals/ReportBuilder/PivotModal.js +63 -18
- package/dist/esm/models/Client.d.ts +4 -5
- package/dist/esm/models/Client.d.ts.map +1 -1
- package/dist/esm/models/Pivot.d.ts +10 -0
- package/dist/esm/models/Pivot.d.ts.map +1 -1
- package/dist/esm/models/Report.d.ts +13 -1
- package/dist/esm/models/Report.d.ts.map +1 -1
- package/dist/esm/utils/astFilterProcessing.d.ts +1 -1
- package/dist/esm/utils/astFilterProcessing.d.ts.map +1 -1
- package/dist/esm/utils/astFilterProcessing.js +799 -64
- package/dist/esm/utils/astProcessing.d.ts +4 -1
- package/dist/esm/utils/astProcessing.d.ts.map +1 -1
- package/dist/esm/utils/astProcessing.js +2 -2
- package/dist/esm/utils/client.d.ts.map +1 -1
- package/dist/esm/utils/client.js +6 -3
- 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 +1 -1
- package/dist/esm/utils/dashboard.d.ts +2 -1
- package/dist/esm/utils/dashboard.d.ts.map +1 -1
- package/dist/esm/utils/dashboard.js +39 -11
- package/dist/esm/utils/filterProcessing.d.ts +1 -1
- package/dist/esm/utils/filterProcessing.d.ts.map +1 -1
- package/dist/esm/utils/merge.d.ts +16 -0
- package/dist/esm/utils/merge.d.ts.map +1 -1
- package/dist/esm/utils/merge.js +207 -0
- package/dist/esm/utils/paginationProcessing.d.ts +1 -1
- package/dist/esm/utils/paginationProcessing.d.ts.map +1 -1
- package/dist/esm/utils/paginationProcessing.js +3 -2
- package/dist/esm/utils/pivotConstructor.d.ts +19 -9
- package/dist/esm/utils/pivotConstructor.d.ts.map +1 -1
- package/dist/esm/utils/pivotConstructor.js +91 -35
- package/dist/esm/utils/queryConstructor.d.ts +8 -1
- package/dist/esm/utils/queryConstructor.d.ts.map +1 -1
- package/dist/esm/utils/queryConstructor.js +274 -314
- package/dist/esm/utils/report.d.ts +25 -12
- package/dist/esm/utils/report.d.ts.map +1 -1
- package/dist/esm/utils/report.js +13 -7
- package/dist/esm/utils/schema.d.ts +1 -1
- package/dist/esm/utils/schema.d.ts.map +1 -1
- package/dist/esm/utils/schema.js +1 -30
- package/dist/esm/utils/tableProcessing.d.ts +43 -13
- package/dist/esm/utils/tableProcessing.d.ts.map +1 -1
- package/dist/esm/utils/tableProcessing.js +140 -75
- package/dist/esm/utils/textProcessing.d.ts.map +1 -1
- package/dist/esm/utils/textProcessing.js +10 -1
- package/dist/esm/utils/valueFormatter.d.ts +2 -1
- package/dist/esm/utils/valueFormatter.d.ts.map +1 -1
- package/dist/esm/utils/valueFormatter.js +18 -14
- package/package.json +1 -1
|
@@ -2,13 +2,13 @@ import { isStringType } from './columnProcessing';
|
|
|
2
2
|
import { MAX_PIVOT_UNIQUE_VALUES } from './constants';
|
|
3
3
|
import { isValidPivot } from './pivotProcessing';
|
|
4
4
|
import { matchCasing } from './textProcessing';
|
|
5
|
-
function processSingleQuotes(value, databaseType) {
|
|
5
|
+
export function processSingleQuotes(value, databaseType) {
|
|
6
6
|
if (['postgresql', 'snowflake', 'clickhouse'].includes(databaseType.toLowerCase())) {
|
|
7
7
|
return value.replaceAll("'", "''");
|
|
8
8
|
}
|
|
9
9
|
return value.replaceAll("'", "\\'");
|
|
10
10
|
}
|
|
11
|
-
function processAggType(aggType, hasColumnField = false) {
|
|
11
|
+
export function processAggType(aggType, hasColumnField = false) {
|
|
12
12
|
if (aggType === 'count' && hasColumnField)
|
|
13
13
|
return 'SUM';
|
|
14
14
|
return aggType?.toLowerCase() === 'average' ? 'AVG' : aggType?.toLowerCase();
|
|
@@ -84,6 +84,23 @@ isPivotColumnFieldAlias, isPivotValueFieldAlias) {
|
|
|
84
84
|
}
|
|
85
85
|
return `\`${replaceBigQuerySpecialCharacters(column.replaceAll('`', ''))}\``;
|
|
86
86
|
}
|
|
87
|
+
case 'mssql': {
|
|
88
|
+
if (column === '') {
|
|
89
|
+
return fallbackOnNull ? `[${fallbackOnNull}]` : `[_]`;
|
|
90
|
+
}
|
|
91
|
+
if (isPivotColumnFieldAlias) {
|
|
92
|
+
return `[${column.replaceAll(']', '').replaceAll('[', '')}]`;
|
|
93
|
+
}
|
|
94
|
+
const columnParts = column.split('.');
|
|
95
|
+
if (columnParts.length > 1) {
|
|
96
|
+
return (`[` +
|
|
97
|
+
columnParts
|
|
98
|
+
.map((part) => part.replaceAll(']', '').replaceAll('[', ''))
|
|
99
|
+
.join('].[`') +
|
|
100
|
+
`]`);
|
|
101
|
+
}
|
|
102
|
+
return `[${column.replaceAll(']', '').replaceAll('[', '')}]`;
|
|
103
|
+
}
|
|
87
104
|
default:
|
|
88
105
|
return column;
|
|
89
106
|
}
|
|
@@ -100,31 +117,37 @@ function processInterval(interval, rowField, databaseType) {
|
|
|
100
117
|
}
|
|
101
118
|
return `TIMESTAMP_ADD(${processColumnReference(rowField, databaseType)}, INTERVAL ${interval} )`;
|
|
102
119
|
}
|
|
103
|
-
function processDateTrunc(dateBucket, rowField, databaseType, comparisonInterval) {
|
|
120
|
+
export function processDateTrunc(dateBucket, rowField, databaseType, comparisonInterval) {
|
|
121
|
+
const dateField = comparisonInterval
|
|
122
|
+
? processInterval(comparisonInterval, rowField, databaseType)
|
|
123
|
+
: processColumnReference(rowField, databaseType);
|
|
104
124
|
if (['postgresql', 'snowflake'].includes(databaseType.toLowerCase())) {
|
|
105
|
-
const dateField = comparisonInterval
|
|
106
|
-
? processInterval(comparisonInterval, rowField, databaseType)
|
|
107
|
-
: processColumnReference(rowField, databaseType);
|
|
108
125
|
return `date_trunc('${dateBucket}', ${dateField})`;
|
|
109
126
|
}
|
|
110
127
|
if (['clickhouse'].includes(databaseType.toLowerCase())) {
|
|
111
|
-
const dateField = comparisonInterval
|
|
112
|
-
? processInterval(comparisonInterval, rowField, databaseType)
|
|
113
|
-
: processColumnReference(rowField, databaseType);
|
|
114
128
|
return `dateTrunc('${dateBucket}', ${dateField})`;
|
|
115
129
|
}
|
|
116
130
|
if (['mysql'].includes(databaseType.toLowerCase())) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
131
|
+
switch (dateBucket.toLowerCase()) {
|
|
132
|
+
case 'year':
|
|
133
|
+
return `DATE_FORMAT(${dateField}, '%Y-01-01 00:00:00')`;
|
|
134
|
+
case 'month':
|
|
135
|
+
return `DATE_FORMAT(${dateField}, '%Y-%m-01 00:00:00')`;
|
|
136
|
+
case 'week':
|
|
137
|
+
return `DATE_FORMAT(${dateField}, '%Y-%U-1 00:00:00')`;
|
|
138
|
+
case 'day':
|
|
139
|
+
default:
|
|
140
|
+
return `DATE(${dateField})`;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (['mssql'].includes(databaseType.toLowerCase())) {
|
|
144
|
+
// note DATETRUNC is for mssql >= 2022
|
|
145
|
+
return `DATETRUNC(${dateBucket}, ${dateField})`;
|
|
146
|
+
// return `FORMAT(${dateField}, '${mssqlDateBucketFormat(dateBucket)}')`;
|
|
121
147
|
}
|
|
122
|
-
const dateField = comparisonInterval
|
|
123
|
-
? processInterval(comparisonInterval, rowField, databaseType)
|
|
124
|
-
: processColumnReference(rowField, databaseType);
|
|
125
148
|
return `TIMESTAMP_TRUNC(${dateField}, ${dateBucket})`;
|
|
126
149
|
}
|
|
127
|
-
function processValueField(aggType, databaseType, valueField) {
|
|
150
|
+
export function processValueField(aggType, databaseType, valueField) {
|
|
128
151
|
if (aggType === 'min' ||
|
|
129
152
|
aggType === 'max' ||
|
|
130
153
|
aggType?.toLowerCase() === 'average')
|
|
@@ -164,6 +187,8 @@ export function generateDistinctQuery(stringFields, query, databaseType) {
|
|
|
164
187
|
return generateDistinctQueryPostgres(stringFields, query);
|
|
165
188
|
case 'snowflake':
|
|
166
189
|
return generateDistinctQuerySnowflake(stringFields, query);
|
|
190
|
+
case 'mssql':
|
|
191
|
+
return generateDistinctQueryMSSQL(stringFields, query);
|
|
167
192
|
default:
|
|
168
193
|
return generateDistinctQueryDefault(stringFields, query, databaseType);
|
|
169
194
|
}
|
|
@@ -199,44 +224,73 @@ function generateDistinctQuerySnowflake(stringFields, query) {
|
|
|
199
224
|
const distinctQuery = distinctQueries.join(' UNION ALL ');
|
|
200
225
|
return `WITH querytable AS (${query.replace(';', '')}) ` + distinctQuery;
|
|
201
226
|
}
|
|
227
|
+
// Not the ideal way to do things, but node-sql-parser doesn't support
|
|
228
|
+
// DISTINCT or JSON PATH for transactsql at the moment
|
|
229
|
+
// Note, this does not return an array like the other functions, so we need to keep that in mind
|
|
230
|
+
// for mssql distinct values when we attempt to parse them
|
|
231
|
+
function generateDistinctQueryMSSQL(stringFields, query) {
|
|
232
|
+
const escapeFieldName = (field) => field.replace(/'/g, "''");
|
|
233
|
+
const distinctQueries = stringFields.map((field) => {
|
|
234
|
+
return `
|
|
235
|
+
SELECT
|
|
236
|
+
'${escapeFieldName(field)}' AS field,
|
|
237
|
+
STRING_AGG(${field}, ',') AS string_values
|
|
238
|
+
FROM (
|
|
239
|
+
SELECT ${field}
|
|
240
|
+
FROM querytable
|
|
241
|
+
WHERE ${field} IS NOT NULL
|
|
242
|
+
GROUP BY ${field}
|
|
243
|
+
) AS grouped
|
|
244
|
+
`
|
|
245
|
+
.replace(/\s+/g, ' ')
|
|
246
|
+
.trim();
|
|
247
|
+
});
|
|
248
|
+
const distinctQuery = distinctQueries.join(' UNION ALL ');
|
|
249
|
+
return `
|
|
250
|
+
WITH querytable AS (
|
|
251
|
+
${query.replace(';', '')}
|
|
252
|
+
)
|
|
253
|
+
${distinctQuery}`
|
|
254
|
+
.replace(/\s+/g, ' ')
|
|
255
|
+
.trim();
|
|
256
|
+
}
|
|
202
257
|
export function generateMinMaxDateRangeQueries(columnFields, query, databaseType) {
|
|
203
258
|
const max = 'MAX';
|
|
204
259
|
const min = 'MIN';
|
|
260
|
+
const cast = databaseType.toLowerCase() === 'snowflake' ? '::TIMESTAMP_TZ' : '';
|
|
205
261
|
const distinctQueries = columnFields.map((field) => {
|
|
206
262
|
const wrappedField = ['postgresql', 'clickhouse'].includes(databaseType.toLowerCase())
|
|
207
263
|
? `"${field}"`
|
|
208
264
|
: field;
|
|
209
|
-
return `SELECT '${field}' AS field, ${min}(${wrappedField}) AS min_range, ${max}(${wrappedField}) AS max_range FROM querytable`;
|
|
265
|
+
return `SELECT '${field}' AS field, ${min}(${wrappedField})${cast} AS min_range, ${max}(${wrappedField})${cast} AS max_range FROM querytable`;
|
|
210
266
|
});
|
|
211
267
|
const distinctQuery = distinctQueries.join(' UNION ALL ');
|
|
212
268
|
return `WITH querytable AS (${query.replace(';', '')}) ` + distinctQuery;
|
|
213
269
|
}
|
|
214
|
-
export function generatePivotQuery(pivot,
|
|
270
|
+
export function generatePivotQuery(pivot, itemQuery, databaseType, distinctStrings, dateBucket) {
|
|
215
271
|
if (!isValidPivot(pivot).valid) {
|
|
216
272
|
return undefined;
|
|
217
273
|
}
|
|
218
|
-
if (pivot.columnField) {
|
|
219
|
-
return create2DPivotQuery(pivot,
|
|
274
|
+
if (pivot.columnField && distinctStrings && distinctStrings.length > 0) {
|
|
275
|
+
return create2DPivotQuery(pivot, itemQuery, databaseType, distinctStrings, dateBucket);
|
|
220
276
|
}
|
|
221
277
|
if (pivot.rowField) {
|
|
222
|
-
return create1DPivotQuery(pivot,
|
|
278
|
+
return create1DPivotQuery(pivot, itemQuery, dateBucket, databaseType);
|
|
223
279
|
}
|
|
224
|
-
return createAggregationValuePivot(pivot,
|
|
280
|
+
return createAggregationValuePivot(pivot, itemQuery, databaseType);
|
|
225
281
|
}
|
|
226
|
-
function create2DPivotQuery(pivot,
|
|
282
|
+
function create2DPivotQuery(pivot, itemQuery, databaseType, columnFieldValues, dateBucket) {
|
|
227
283
|
if (!pivot || !pivot.columnField) {
|
|
228
284
|
return undefined;
|
|
229
285
|
}
|
|
230
|
-
if (!columnFieldValues) {
|
|
231
|
-
return undefined;
|
|
232
|
-
}
|
|
233
286
|
if (isStringType(pivot.rowFieldType || '') || !pivot.rowFieldType) {
|
|
234
|
-
return create2DStringPivotQuery(pivot,
|
|
287
|
+
return create2DStringPivotQuery(pivot, itemQuery, columnFieldValues, databaseType);
|
|
235
288
|
}
|
|
236
|
-
return create2DDatePivotQuery(pivot,
|
|
289
|
+
return create2DDatePivotQuery(pivot, itemQuery, columnFieldValues, databaseType, dateBucket);
|
|
237
290
|
}
|
|
238
|
-
function create2DStringPivotQuery(pivot,
|
|
239
|
-
|
|
291
|
+
function create2DStringPivotQuery(pivot, itemQuery, columnFieldValues, databaseType) {
|
|
292
|
+
const isValidBaseQuery = itemQuery.match(/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/);
|
|
293
|
+
if (!isValidBaseQuery || !pivot.columnField || !pivot.rowField) {
|
|
240
294
|
return undefined;
|
|
241
295
|
}
|
|
242
296
|
const rowField = pivot.rowField;
|
|
@@ -245,97 +299,44 @@ function create2DStringPivotQuery(pivot, itemQueries, columnFieldValues, databas
|
|
|
245
299
|
const rowFieldAlias = processColumnReference(rowField, databaseType, undefined, false, true);
|
|
246
300
|
const valueFieldAlias = processColumnReference(valueField ?? rowField, databaseType, undefined, false, true);
|
|
247
301
|
const columnFieldAlias = processColumnReference(columnField, databaseType, undefined, false, true);
|
|
248
|
-
const max = 'GREATEST';
|
|
249
302
|
const valueAliasSubstring = valueField
|
|
250
303
|
? `${processColumnReference(valueField, databaseType, undefined, true)} AS ${valueFieldAlias},`
|
|
251
304
|
: '';
|
|
305
|
+
let value2AliasSubstring = '';
|
|
306
|
+
let caseWhens = columnFieldValues.map((column) => {
|
|
307
|
+
return `${processAggType(pivot.aggregationType, true)}(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueFieldAlias)} END) AS ${processColumnReference(column, databaseType, '_', true)}`;
|
|
308
|
+
});
|
|
252
309
|
if (pivot.aggregationType === 'percentage' && pivot.valueField2) {
|
|
253
310
|
const valueField2Alias = processColumnReference(pivot.valueField2, databaseType, undefined, false, true);
|
|
254
|
-
const value2AliasSubstring = `${processColumnReference(pivot.valueField2, databaseType, undefined, true)} AS ${valueField2Alias},`;
|
|
255
311
|
if (pivot.valueField === pivot.valueField2) {
|
|
256
|
-
|
|
257
|
-
return `sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueFieldAlias)} END) /
|
|
312
|
+
caseWhens = columnFieldValues.map((column) => {
|
|
313
|
+
return `sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueFieldAlias)} END) / GREATEST(sum(${processColumnReference(pivot.valueField2, databaseType)}), 1) AS ${processColumnReference(column, databaseType, '_', true)}`;
|
|
258
314
|
});
|
|
259
|
-
|
|
260
|
-
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
value2AliasSubstring = `${processColumnReference(pivot.valueField2, databaseType, undefined, true)} AS ${valueField2Alias},`;
|
|
318
|
+
caseWhens = columnFieldValues.map((column) => {
|
|
319
|
+
return `sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueFieldAlias)} END) / GREATEST(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueField2Alias)} END), 1) AS ${processColumnReference(column, databaseType, '_', true)}`;
|
|
261
320
|
});
|
|
262
|
-
const compareCTE = itemQueries[1]
|
|
263
|
-
? `, quill_ct as (${itemQueries[1]?.replaceAll(';', '')})`
|
|
264
|
-
: '';
|
|
265
|
-
const aliasCTE = itemQueries[1]
|
|
266
|
-
? `, quill_c_alias as (SELECT ${processColumnReference(rowField, databaseType, undefined, true)} AS ${rowFieldAlias}, ${valueAliasSubstring}
|
|
267
|
-
${processColumnReference(columnField, databaseType, undefined, true)} AS ${columnFieldAlias} FROM quill_ct)`
|
|
268
|
-
: '';
|
|
269
|
-
const compareCaseWhenCTE = itemQueries[1]
|
|
270
|
-
? `, quill_ct_cw as (SELECT ${rowFieldAlias} as ${processColumnReference(`comparison_${rowFieldAlias}`, databaseType)}${caseWhensCompare.length > 0 ? `, ${caseWhensCompare.join(', ')}` : ''} FROM quill_c_alias GROUP BY ${rowFieldAlias})`
|
|
271
|
-
: '';
|
|
272
|
-
const joinQuery = itemQueries[1]
|
|
273
|
-
? `JOIN quill_ct_cw ct ON ct.${processColumnReference(`comparison_${rowFieldAlias}`, databaseType)} = qt.${rowFieldAlias}`
|
|
274
|
-
: '';
|
|
275
|
-
return `WITH quill_qt AS (${itemQueries[0]?.replaceAll(';', '')}),
|
|
276
|
-
quill_alias AS (SELECT ${processColumnReference(rowField, databaseType, undefined, true)} AS ${rowFieldAlias}, ${valueAliasSubstring}
|
|
277
|
-
${processColumnReference(columnField, databaseType, undefined, true)} AS ${columnFieldAlias} FROM quill_qt),
|
|
278
|
-
quill_qt_cw AS (SELECT ${rowFieldAlias}${caseWhens.length > 0 ? `, ${caseWhens.join(', ')}` : ''} FROM quill_alias GROUP BY ${rowFieldAlias})
|
|
279
|
-
${compareCTE} ${aliasCTE} ${compareCaseWhenCTE}
|
|
280
|
-
SELECT * FROM quill_qt_cw qt
|
|
281
|
-
${joinQuery}${rowLimit ? ` LIMIT ${rowLimit}` : ''}`;
|
|
282
321
|
}
|
|
283
|
-
const caseWhens = columnFieldValues.map((column) => {
|
|
284
|
-
return `sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueFieldAlias)} END) / ${max}(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueField2Alias)} END), 1) AS ${processColumnReference(column, databaseType, '_', true)}`;
|
|
285
|
-
});
|
|
286
|
-
const caseWhensCompare = columnFieldValues.map((column) => {
|
|
287
|
-
return `sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueFieldAlias)} END) / ${max}(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueField2Alias)} END), 1) AS ${processColumnReference(`comparison_${column}`, databaseType, '_', true)}`;
|
|
288
|
-
});
|
|
289
|
-
const compareCTE = itemQueries[1]
|
|
290
|
-
? `, quill_ct as (${itemQueries[1]?.replaceAll(';', '')})`
|
|
291
|
-
: '';
|
|
292
|
-
const aliasCTE = itemQueries[1]
|
|
293
|
-
? `, quill_c_alias as (SELECT ${processColumnReference(rowField, databaseType, undefined, true)} AS ${rowFieldAlias}, ${valueAliasSubstring} ${value2AliasSubstring}
|
|
294
|
-
${processColumnReference(columnField, databaseType, undefined, true)} AS ${columnFieldAlias} FROM quill_ct)`
|
|
295
|
-
: '';
|
|
296
|
-
const compareCaseWhenCTE = itemQueries[1]
|
|
297
|
-
? `, quill_ct_cw as (SELECT ${rowFieldAlias} as ${processColumnReference(`comparison_${rowFieldAlias}`, databaseType)}${caseWhensCompare.length > 0 ? `, ${caseWhensCompare.join(', ')}` : ''} FROM quill_c_alias GROUP BY ${rowFieldAlias})`
|
|
298
|
-
: '';
|
|
299
|
-
const joinQuery = itemQueries[1]
|
|
300
|
-
? `JOIN quill_ct_cw ct ON ct.${processColumnReference(`comparison_${rowFieldAlias}`, databaseType)} = qt.${rowFieldAlias}`
|
|
301
|
-
: '';
|
|
302
|
-
return `WITH quill_qt AS (${itemQueries[0]?.replaceAll(';', '')}),
|
|
303
|
-
quill_alias AS (SELECT ${processColumnReference(rowField, databaseType, undefined, true)} AS ${rowFieldAlias}, ${valueAliasSubstring} ${value2AliasSubstring}
|
|
304
|
-
${processColumnReference(columnField, databaseType, undefined, true)} AS ${columnFieldAlias} FROM quill_qt),
|
|
305
|
-
quill_qt_cw AS (SELECT ${rowFieldAlias}${caseWhens.length > 0 ? `, ${caseWhens.join(', ')}` : ''} FROM quill_alias GROUP BY ${rowFieldAlias})
|
|
306
|
-
${compareCTE} ${aliasCTE} ${compareCaseWhenCTE}
|
|
307
|
-
SELECT * FROM quill_qt_cw qt
|
|
308
|
-
${joinQuery}${rowLimit ? ` LIMIT ${rowLimit}` : ''}`;
|
|
309
322
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
})
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
const compareCaseWhenCTE = itemQueries[1]
|
|
324
|
-
? `, quill_ct_cw as (SELECT ${rowFieldAlias} as ${processColumnReference(`comparison_${rowFieldAlias}`, databaseType)}${caseWhensCompare.length > 0 ? `, ${caseWhensCompare.join(', ')}` : ''} FROM quill_c_alias GROUP BY ${rowFieldAlias})`
|
|
325
|
-
: '';
|
|
326
|
-
const joinQuery = itemQueries[1]
|
|
327
|
-
? `JOIN quill_ct_cw ct ON ct.${processColumnReference(`comparison_${rowFieldAlias}`, databaseType)} = qt.${rowFieldAlias}`
|
|
328
|
-
: '';
|
|
329
|
-
return `WITH quill_qt AS (${itemQueries[0]?.replaceAll(';', '')}),
|
|
330
|
-
quill_alias AS (SELECT ${processColumnReference(rowField, databaseType, undefined, true)} AS ${rowFieldAlias}, ${valueAliasSubstring}
|
|
331
|
-
${processColumnReference(columnField, databaseType, undefined, true)} AS ${columnFieldAlias} FROM quill_qt),
|
|
332
|
-
quill_qt_cw AS (SELECT ${rowFieldAlias}${caseWhens.length > 0 ? `, ${caseWhens.join(', ')}` : ''} FROM quill_alias GROUP BY ${rowFieldAlias})
|
|
333
|
-
${compareCTE} ${aliasCTE} ${compareCaseWhenCTE}
|
|
334
|
-
SELECT * FROM quill_qt_cw qt
|
|
335
|
-
${joinQuery}${rowLimit ? ` LIMIT ${rowLimit}` : ''}`;
|
|
323
|
+
// pivot sort matters in the base query when there is a rowLimit. In mssql, an orderby must be accompanied by a limit in a subquery and not allowed in a cte
|
|
324
|
+
const sortQuery = `${pivot.sort && pivot.sortField && pivot.rowLimit ? ` ORDER BY ${processColumnReference(pivot.sortField, databaseType)} ${pivot.sortDirection || ''} ` : ''}`;
|
|
325
|
+
const pivotQuery = `
|
|
326
|
+
,quill_alias AS (SELECT ${processColumnReference(rowField, databaseType, undefined, true)} AS ${rowFieldAlias}, ${valueAliasSubstring} ${value2AliasSubstring}
|
|
327
|
+
${processColumnReference(columnField, databaseType, undefined, true)} AS ${columnFieldAlias} FROM quill_base_table),
|
|
328
|
+
quill_qt_cw AS (SELECT ${rowFieldAlias}${caseWhens.length > 0 ? `, ${caseWhens.join(', ')}` : ''} FROM quill_alias GROUP BY ${rowFieldAlias}),
|
|
329
|
+
quill_base_pivot AS (SELECT ${pivot.rowLimit && databaseType.toLowerCase() === 'mssql' ? `TOP ${pivot.rowLimit}` : ''} * FROM quill_qt_cw qt
|
|
330
|
+
${sortQuery}${pivot.rowLimit && databaseType.toLowerCase() !== 'mssql' ? ` LIMIT ${pivot.rowLimit}` : ''})
|
|
331
|
+
SELECT * FROM quill_base_pivot
|
|
332
|
+
`
|
|
333
|
+
.replace(/\s+/g, ' ')
|
|
334
|
+
.trim();
|
|
335
|
+
return itemQuery.replace(/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/, pivotQuery);
|
|
336
336
|
}
|
|
337
|
-
function create2DDatePivotQuery(pivot,
|
|
338
|
-
|
|
337
|
+
function create2DDatePivotQuery(pivot, itemQuery, columnFieldValues, databaseType, dateBucket = 'month') {
|
|
338
|
+
const isValidBaseQuery = itemQuery.match(/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/);
|
|
339
|
+
if (!isValidBaseQuery || !pivot.columnField || !pivot.rowField) {
|
|
339
340
|
return undefined;
|
|
340
341
|
}
|
|
341
342
|
const rowField = pivot.rowField;
|
|
@@ -346,246 +347,205 @@ function create2DDatePivotQuery(pivot, itemQueries, columnFieldValues, databaseT
|
|
|
346
347
|
const valueAliasSubstring = pivot.valueField
|
|
347
348
|
? `${processColumnReference(pivot.valueField, databaseType, undefined, true)} AS ${valueFieldAlias},`
|
|
348
349
|
: '';
|
|
349
|
-
|
|
350
|
+
let value2AliasSubstring = '';
|
|
351
|
+
let caseWhens = columnFieldValues.map((column) => {
|
|
352
|
+
return `${processAggType(pivot.aggregationType, true)}(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueFieldAlias)} END) AS ${processColumnReference(column, databaseType, '_', true)}`;
|
|
353
|
+
});
|
|
350
354
|
if (pivot.aggregationType === 'percentage' && pivot.valueField2) {
|
|
351
355
|
const valueField2Alias = processColumnReference(pivot.valueField2, databaseType, undefined, false, true);
|
|
352
|
-
const value2AliasSubstring = `${processColumnReference(pivot.valueField2, databaseType, undefined, true)} AS ${valueField2Alias},`;
|
|
353
356
|
// edge case. if the user picks amount and amount, we assume they want a pie chart like breakdown of amount. so the summation of valueField2 has to be moved outside of the case when
|
|
354
357
|
if (pivot.valueField === pivot.valueField2) {
|
|
355
|
-
|
|
356
|
-
return `sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueFieldAlias)} END) /
|
|
358
|
+
caseWhens = columnFieldValues.map((column) => {
|
|
359
|
+
return `sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueFieldAlias)} END) / GREATEST(sum(${processColumnReference(valueField2Alias, databaseType)}), 1) AS ${processColumnReference(column, databaseType, '_', true)}`;
|
|
357
360
|
});
|
|
358
|
-
|
|
359
|
-
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
value2AliasSubstring = `${processColumnReference(pivot.valueField2, databaseType, undefined, true)} AS ${valueField2Alias},`;
|
|
364
|
+
caseWhens = columnFieldValues.map((column) => {
|
|
365
|
+
return `sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueFieldAlias)} END) / GREATEST(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueField2Alias)} END), 1) AS ${processColumnReference(column, databaseType, '_', true)}`;
|
|
360
366
|
});
|
|
361
|
-
const compareCTE = itemQueries[1] && comparisonInterval
|
|
362
|
-
? `, quill_ct as (${itemQueries[1]?.replaceAll(';', '')})`
|
|
363
|
-
: '';
|
|
364
|
-
const aliasCTE = itemQueries[1] && comparisonInterval
|
|
365
|
-
? `, quill_c_alias as (SELECT ${processColumnReference(rowField, databaseType, undefined, true)} AS ${rowFieldAlias}, ${valueAliasSubstring}
|
|
366
|
-
${processColumnReference(columnField, databaseType, undefined, true)} AS ${columnFieldAlias} FROM quill_ct)`
|
|
367
|
-
: '';
|
|
368
|
-
const compareCaseWhenCTE = itemQueries[1] && comparisonInterval
|
|
369
|
-
? `, quill_ct_cw as (SELECT ${processDateTrunc(dateBucket, rowField, databaseType)} as ${processColumnReference(`comparison_${rowFieldAlias}`, databaseType)}${caseWhensCompare.length > 0 ? `, ${caseWhensCompare.join(', ')}` : ''} FROM quill_c_alias GROUP BY ${databaseType.toLowerCase() === 'clickhouse' ? processColumnReference(`${rowField}`, databaseType) : processDateTrunc(dateBucket, rowFieldAlias, databaseType)})`
|
|
370
|
-
: '';
|
|
371
|
-
const joinQuery = itemQueries[1] && comparisonInterval
|
|
372
|
-
? `LEFT JOIN quill_ct_cw ${processColumnReference(`ct`, databaseType)} ON qt.${rowFieldAlias} = ${processDateTrunc(dateBucket, `ct.comparison_${rowFieldAlias}`, databaseType, comparisonInterval)}`
|
|
373
|
-
: '';
|
|
374
|
-
return `WITH quill_query_table AS (${itemQueries[0]?.replaceAll(';', '')}),
|
|
375
|
-
quill_alias AS (SELECT ${processColumnReference(`${rowField}`, databaseType, undefined, true)} AS ${rowFieldAlias}, ${valueAliasSubstring}
|
|
376
|
-
${processColumnReference(columnField, databaseType, undefined, true, true)} AS ${columnFieldAlias} FROM quill_query_table),
|
|
377
|
-
quill_qt_agg as (SELECT ${processDateTrunc(dateBucket, rowFieldAlias, databaseType)} as ${rowFieldAlias}${caseWhens.length > 0 ? `, ${caseWhens.join(', ')}` : ''} FROM quill_alias GROUP BY ${databaseType.toLowerCase() === 'clickhouse' ? processColumnReference(`${rowField}`, databaseType) : processDateTrunc(dateBucket, rowFieldAlias, databaseType)})
|
|
378
|
-
${compareCTE} ${aliasCTE} ${compareCaseWhenCTE}
|
|
379
|
-
SELECT * FROM quill_qt_agg qt
|
|
380
|
-
${joinQuery} ORDER BY qt.${rowFieldAlias}${rowLimit ? ` LIMIT ${rowLimit}` : ''}`;
|
|
381
367
|
}
|
|
382
|
-
const caseWhens = columnFieldValues.map((column) => {
|
|
383
|
-
return `sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueFieldAlias)} END) / ${max}(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueField2Alias)} END), 1) AS ${processColumnReference(column, databaseType, '_', true)}`;
|
|
384
|
-
});
|
|
385
|
-
const caseWhensCompare = columnFieldValues.map((column) => {
|
|
386
|
-
return `sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueFieldAlias)} END) / ${max}(sum(CASE WHEN ${columnFieldAlias} = '${processSingleQuotes(column, databaseType)}' THEN ${processValueField(pivot.aggregationType, databaseType, valueField2Alias)} END), 1) AS ${processColumnReference(`comparison_${column}`, databaseType, '_', true)}`;
|
|
387
|
-
});
|
|
388
|
-
const compareCTE = itemQueries[1] && comparisonInterval
|
|
389
|
-
? `, quill_ct as (${itemQueries[1]?.replaceAll(';', '')})`
|
|
390
|
-
: '';
|
|
391
|
-
const aliasCTE = itemQueries[1] && comparisonInterval
|
|
392
|
-
? `, quill_c_alias as (SELECT ${processColumnReference(rowField, databaseType, undefined, true)} AS ${rowFieldAlias}, ${valueAliasSubstring} ${value2AliasSubstring}
|
|
393
|
-
${processColumnReference(columnField, databaseType, undefined, true)} AS ${columnFieldAlias} FROM quill_ct)`
|
|
394
|
-
: '';
|
|
395
|
-
const compareCaseWhenCTE = itemQueries[1] && comparisonInterval
|
|
396
|
-
? `, quill_ct_cw as (SELECT ${processDateTrunc(dateBucket, rowField, databaseType)} as ${processColumnReference(`comparison_${rowFieldAlias}`, databaseType)}${caseWhensCompare.length > 0 ? `, ${caseWhensCompare.join(', ')}` : ''} FROM quill_c_alias GROUP BY ${databaseType.toLowerCase() === 'clickhouse' ? processColumnReference(`${rowField}`, databaseType) : processDateTrunc(dateBucket, rowFieldAlias, databaseType)})`
|
|
397
|
-
: '';
|
|
398
|
-
const joinQuery = itemQueries[1] && comparisonInterval
|
|
399
|
-
? `LEFT JOIN quill_ct_cw ${processColumnReference(`ct`, databaseType)} ON qt.${rowFieldAlias} = ${processDateTrunc(dateBucket, `ct.comparison_${rowFieldAlias}`, databaseType, comparisonInterval)}`
|
|
400
|
-
: '';
|
|
401
|
-
return `WITH quill_query_table AS (${itemQueries[0]?.replaceAll(';', '')}),
|
|
402
|
-
quill_alias AS (SELECT ${processColumnReference(`${rowField}`, databaseType, undefined, true)} AS ${rowFieldAlias}, ${valueAliasSubstring} ${value2AliasSubstring}
|
|
403
|
-
${processColumnReference(columnField, databaseType, undefined, true, true)} AS ${columnFieldAlias} FROM quill_query_table),
|
|
404
|
-
quill_qt_agg as (SELECT ${processDateTrunc(dateBucket, rowFieldAlias, databaseType)} as ${rowFieldAlias}${caseWhens.length > 0 ? `, ${caseWhens.join(', ')}` : ''} FROM quill_alias GROUP BY ${databaseType.toLowerCase() === 'clickhouse' ? processColumnReference(`${rowField}`, databaseType) : processDateTrunc(dateBucket, rowFieldAlias, databaseType)})
|
|
405
|
-
${compareCTE} ${aliasCTE} ${compareCaseWhenCTE}
|
|
406
|
-
SELECT * FROM quill_qt_agg qt
|
|
407
|
-
${joinQuery} ORDER BY qt.${rowFieldAlias}${rowLimit ? ` LIMIT ${rowLimit}` : ''}`;
|
|
408
368
|
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
})
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
const compareCaseWhenCTE = itemQueries[1] && comparisonInterval
|
|
423
|
-
? `, quill_ct_cw as (SELECT ${processDateTrunc(dateBucket, rowField, databaseType)} as ${processColumnReference(`comparison_${rowFieldAlias}`, databaseType)}${caseWhensCompare.length > 0 ? `, ${caseWhensCompare.join(', ')}` : ''} FROM quill_c_alias GROUP BY ${databaseType.toLowerCase() === 'clickhouse' ? processColumnReference(`${rowField}`, databaseType) : processDateTrunc(dateBucket, rowFieldAlias, databaseType)})`
|
|
424
|
-
: '';
|
|
425
|
-
const joinQuery = itemQueries[1] && comparisonInterval
|
|
426
|
-
? `LEFT JOIN quill_ct_cw ${processColumnReference(`ct`, databaseType)} ON qt.${rowFieldAlias} = ${processDateTrunc(dateBucket, `ct.comparison_${rowFieldAlias}`, databaseType, comparisonInterval)}`
|
|
427
|
-
: '';
|
|
428
|
-
return `WITH quill_query_table AS (${itemQueries[0]?.replaceAll(';', '')}),
|
|
429
|
-
quill_alias AS (SELECT ${processColumnReference(`${rowField}`, databaseType, undefined, true)} AS ${rowFieldAlias}, ${valueAliasSubstring}
|
|
430
|
-
${processColumnReference(columnField, databaseType, undefined, true, true)} AS ${columnFieldAlias} FROM quill_query_table),
|
|
431
|
-
quill_qt_agg as (SELECT ${processDateTrunc(dateBucket, rowFieldAlias, databaseType)} as ${rowFieldAlias}${caseWhens.length > 0 ? `, ${caseWhens.join(', ')}` : ''} FROM quill_alias GROUP BY ${databaseType.toLowerCase() === 'clickhouse' ? processColumnReference(`${rowField}`, databaseType) : processDateTrunc(dateBucket, rowFieldAlias, databaseType)})
|
|
432
|
-
${compareCTE} ${aliasCTE} ${compareCaseWhenCTE}
|
|
433
|
-
SELECT * FROM quill_qt_agg qt
|
|
434
|
-
${joinQuery} ORDER BY qt.${rowFieldAlias}${rowLimit ? ` LIMIT ${rowLimit}` : ''}`;
|
|
369
|
+
// pivot sort matters in the base query when there is a rowLimit. In mssql, an orderby must be accompanied by a limit in a subquery and not allowed in a cte
|
|
370
|
+
const sortQuery = `${pivot.sort && pivot.sortField && pivot.rowLimit ? ` ORDER BY ${processColumnReference(pivot.sortField, databaseType)} ${pivot.sortDirection || ''} ` : ''}`;
|
|
371
|
+
const pivotQuery = `
|
|
372
|
+
, quill_alias AS (SELECT ${processColumnReference(`${rowField}`, databaseType, undefined, true)} AS ${rowFieldAlias}, ${valueAliasSubstring} ${value2AliasSubstring}
|
|
373
|
+
${processColumnReference(columnField, databaseType, undefined, true, true)} AS ${columnFieldAlias} FROM quill_base_table),
|
|
374
|
+
quill_qt_agg AS (SELECT ${processDateTrunc(dateBucket, rowFieldAlias, databaseType)} as ${rowFieldAlias}${caseWhens.length > 0 ? `, ${caseWhens.join(', ')}` : ''} FROM quill_alias GROUP BY ${databaseType.toLowerCase() === 'clickhouse' ? processColumnReference(`${rowField}`, databaseType) : processDateTrunc(dateBucket, rowFieldAlias, databaseType)}),
|
|
375
|
+
quill_base_pivot AS (SELECT ${pivot.rowLimit && databaseType.toLowerCase() === 'mssql' ? `TOP ${pivot.rowLimit}` : ''} * FROM quill_qt_agg qt
|
|
376
|
+
${sortQuery}${pivot.rowLimit && databaseType.toLowerCase() !== 'mssql' ? ` LIMIT ${pivot.rowLimit}` : ''})
|
|
377
|
+
SELECT * FROM quill_base_pivot
|
|
378
|
+
`
|
|
379
|
+
.replace(/\s+/g, ' ')
|
|
380
|
+
.trim();
|
|
381
|
+
return itemQuery.replace(/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/, pivotQuery);
|
|
435
382
|
}
|
|
436
|
-
function create1DPivotQuery(pivot,
|
|
383
|
+
function create1DPivotQuery(pivot, itemQuery, dateBucket = 'month', databaseType) {
|
|
437
384
|
if (isStringType(pivot.rowFieldType || '') || !pivot.rowFieldType) {
|
|
438
|
-
return create1DStringPivotQuery(pivot,
|
|
385
|
+
return create1DStringPivotQuery(pivot, itemQuery, databaseType);
|
|
439
386
|
}
|
|
440
|
-
return create1DDatePivotQuery(pivot,
|
|
387
|
+
return create1DDatePivotQuery(pivot, itemQuery, dateBucket, databaseType);
|
|
441
388
|
}
|
|
442
|
-
|
|
389
|
+
// we have an item query that is guaranteed to end in SELECT * FROM [quill_base_table]
|
|
390
|
+
// also, stop fetching the comparison rows in the same query, since we're no longer wrapping everything in
|
|
391
|
+
// their own with statements and withs with the same name will conflict
|
|
392
|
+
function create1DStringPivotQuery(pivot, itemQuery, databaseType) {
|
|
393
|
+
const isValidBaseQuery = itemQuery.match(/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/);
|
|
394
|
+
if (!isValidBaseQuery) {
|
|
395
|
+
return undefined;
|
|
396
|
+
}
|
|
443
397
|
const rowField = pivot.rowField;
|
|
444
398
|
const valueField = pivot.valueField;
|
|
445
399
|
const rowAlias = processColumnReference(rowField, databaseType, undefined, false, true);
|
|
446
400
|
const valueAlias = processColumnReference(valueField ?? rowField, databaseType, undefined, false, true);
|
|
447
401
|
const countAlias = processColumnReference('count', databaseType);
|
|
448
|
-
const max = 'GREATEST';
|
|
449
402
|
const valueAliasSubstring = valueField
|
|
450
403
|
? `, ${processColumnReference(`${valueField}`, databaseType, undefined, true)} AS ${valueAlias}`
|
|
451
404
|
: ``;
|
|
405
|
+
let value2AliasSubstring = '';
|
|
406
|
+
let quillSelectSubstring = `${rowAlias}, ${processAggType(pivot.aggregationType)}(${valueField ? valueAlias : '*'}) as ${valueField ? valueAlias : countAlias}`;
|
|
452
407
|
if (pivot.aggregationType === 'percentage' && pivot.valueField2) {
|
|
453
408
|
const value2Alias = processColumnReference(pivot.valueField2, databaseType, undefined, false, true);
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
? `, quill_c_alias as (SELECT ${processColumnReference(rowField, databaseType, undefined, true)} AS ${rowAlias}${valueAliasSubstring}${value2AliasSubstring} FROM quill_ct)`
|
|
462
|
-
: '';
|
|
463
|
-
const compareCaseWhenCTE = itemQueries[1]
|
|
464
|
-
? `, quill_ct_cw as (SELECT ${rowAlias} as ${processColumnReference(`comparison_${rowAlias}`, databaseType)}, ${processAggType(pivot.aggregationType)}(${valueField ? valueAlias : '*'}) as ${processColumnReference(`comparison_${valueField ? valueAlias : countAlias}`, databaseType)} FROM quill_c_alias GROUP BY ${rowAlias})`
|
|
465
|
-
: '';
|
|
466
|
-
const joinQuery = itemQueries[1]
|
|
467
|
-
? `JOIN quill_ct_cw ct ON ct.${processColumnReference(`comparison_${rowField}`, databaseType)} = qt.${processColumnReference(`${rowField}`, databaseType)}`
|
|
468
|
-
: '';
|
|
469
|
-
return `WITH quill_qt AS (${itemQueries[0]?.replaceAll(';', '')}),
|
|
470
|
-
quill_alias AS (SELECT ${processColumnReference(`${rowField}`, databaseType, undefined, true)} AS ${rowAlias}${valueAliasSubstring}${value2AliasSubstring} FROM quill_qt),
|
|
471
|
-
quill_qt_cw AS (SELECT ${rowAlias}, sum(${valueAlias}) / ${max}(sum(${value2Alias}), 1) as ${processColumnReference(`${valueField ?? ''}_${matchCasing('percentage', valueField)}`, databaseType, undefined, false, true)} FROM quill_alias GROUP BY ${rowAlias})
|
|
472
|
-
${compareCTE} ${aliasCTE} ${compareCaseWhenCTE}
|
|
473
|
-
SELECT * FROM quill_qt_cw qt
|
|
474
|
-
${joinQuery}${rowLimit ? ` LIMIT ${rowLimit}` : ''}`;
|
|
409
|
+
if (pivot.valueField !== pivot.valueField2) {
|
|
410
|
+
value2AliasSubstring =
|
|
411
|
+
valueField && valueField !== pivot.valueField2
|
|
412
|
+
? `, ${processColumnReference(`${pivot.valueField2}`, databaseType, undefined, true)} AS ${value2Alias}`
|
|
413
|
+
: '';
|
|
414
|
+
}
|
|
415
|
+
quillSelectSubstring = `${rowAlias}, sum(${valueAlias}) / GREATEST(sum(${value2Alias}), 1) as ${processColumnReference(`${valueField ?? ''}_${matchCasing('percentage', valueField)}`, databaseType, undefined, false, true)}`;
|
|
475
416
|
}
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
: '';
|
|
488
|
-
return `WITH quill_qt AS (${itemQueries[0]?.replaceAll(';', '')}),
|
|
489
|
-
quill_alias AS (SELECT ${processColumnReference(`${rowField}`, databaseType, undefined, true)} AS ${rowAlias}${valueAliasSubstring} FROM quill_qt),
|
|
490
|
-
quill_qt_cw AS (SELECT ${rowAlias}, ${processAggType(pivot.aggregationType)}(${valueField ? valueAlias : '*'}) as ${valueField ? valueAlias : countAlias} FROM quill_alias GROUP BY ${rowAlias})
|
|
491
|
-
${compareCTE} ${aliasCTE} ${compareCaseWhenCTE}
|
|
492
|
-
SELECT * FROM quill_qt_cw qt
|
|
493
|
-
${joinQuery}${rowLimit ? ` LIMIT ${rowLimit}` : ''}`;
|
|
417
|
+
// pivot sort matters in the base query when there is a rowLimit. In mssql, an orderby must be accompanied by a limit in a subquery and not allowed in a cte
|
|
418
|
+
const sortQuery = `${pivot.sort && pivot.sortField && pivot.rowLimit ? ` ORDER BY ${processColumnReference(pivot.sortField, databaseType)} ${pivot.sortDirection || ''} ` : ''}`;
|
|
419
|
+
const pivotQuery = `, quill_alias AS (SELECT ${processColumnReference(`${rowField}`, databaseType, undefined, true)} AS ${rowAlias}${valueAliasSubstring}${value2AliasSubstring} FROM quill_base_table),
|
|
420
|
+
quill_qt_cw AS (SELECT ${quillSelectSubstring} FROM quill_alias GROUP BY ${rowAlias}),
|
|
421
|
+
quill_base_pivot AS (SELECT ${pivot.rowLimit && databaseType.toLowerCase() === 'mssql' ? `TOP ${pivot.rowLimit}` : ''} * FROM quill_qt_cw qt
|
|
422
|
+
${sortQuery}${pivot.rowLimit && databaseType.toLowerCase() !== 'mssql' ? ` LIMIT ${pivot.rowLimit}` : ''})
|
|
423
|
+
SELECT * FROM quill_base_pivot
|
|
424
|
+
`
|
|
425
|
+
.replace(/\s+/g, ' ')
|
|
426
|
+
.trim();
|
|
427
|
+
return itemQuery.replace(/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/, pivotQuery);
|
|
494
428
|
}
|
|
495
|
-
function create1DDatePivotQuery(pivot,
|
|
429
|
+
function create1DDatePivotQuery(pivot, itemQuery, dateBucket = 'month', databaseType) {
|
|
430
|
+
const isValidBaseQuery = itemQuery.match(/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/);
|
|
431
|
+
if (!isValidBaseQuery) {
|
|
432
|
+
return undefined;
|
|
433
|
+
}
|
|
496
434
|
const rowField = pivot.rowField || '';
|
|
497
435
|
const valueField = pivot.valueField;
|
|
498
436
|
const rowFieldAlias = processColumnReference(rowField, databaseType, undefined);
|
|
499
437
|
const valueFieldAlias = processColumnReference(valueField ?? rowField, databaseType, undefined, false, true);
|
|
500
|
-
const
|
|
501
|
-
const
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
438
|
+
const comparisonValueFieldAlias = processColumnReference(valueField ?? rowField, databaseType, undefined, false, true);
|
|
439
|
+
const countAlias = processColumnReference(`count`, databaseType);
|
|
440
|
+
const valueAliasSubstring = valueField ? `, ${valueFieldAlias}` : ``;
|
|
441
|
+
let value2AliasSubstring = '';
|
|
442
|
+
let quillAggSubstring = `
|
|
443
|
+
${processDateTrunc(dateBucket, rowFieldAlias, databaseType)} as ${processColumnReference(`${rowField}`, databaseType)}
|
|
444
|
+
, ${processAggType(pivot.aggregationType)}(${valueField ? valueFieldAlias : rowFieldAlias}) as ${valueField ? comparisonValueFieldAlias : countAlias}
|
|
445
|
+
`;
|
|
505
446
|
// this "and" is for typescript. in reality, pivot.valueField2 must exist if pivot.aggregationType === 'percentage'
|
|
506
447
|
if (pivot.aggregationType === 'percentage' && pivot.valueField2) {
|
|
507
448
|
const valueField2Alias = processColumnReference(pivot.valueField2, databaseType, undefined, false, true);
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
const aliasCTE = itemQueries[1] && comparisonInterval
|
|
515
|
-
? `, quill_c_alias as (SELECT ${processColumnReference(rowField, databaseType, undefined, true)} AS ${rowFieldAlias}${valueAliasSubstring}${value2AliasSubstring} FROM quill_ct)`
|
|
516
|
-
: '';
|
|
517
|
-
const compareCaseWhenCTE = itemQueries[1] && comparisonInterval
|
|
518
|
-
? `, quill_ct_cw as (SELECT ${processDateTrunc(dateBucket, rowFieldAlias, databaseType)} as ${processColumnReference(`comparison_${rowFieldAlias}`, databaseType)},
|
|
519
|
-
sum(${processColumnReference(`${valueFieldAlias}`, databaseType, undefined, true)}) / ${max}(sum(${processColumnReference(`${valueField2Alias}`, databaseType, undefined, true)}), 1) as ${processColumnReference(`comparison_${valueField ? valueFieldAlias : 'count'}_${matchCasing('percentage', valueField)}`, databaseType, undefined, false, true)} FROM quill_c_alias GROUP BY ${processDateTrunc(dateBucket, rowFieldAlias, databaseType)})`
|
|
520
|
-
: '';
|
|
521
|
-
const joinQuery = itemQueries[1] && comparisonInterval
|
|
522
|
-
? `LEFT JOIN quill_ct_cw ${processColumnReference(`ct`, databaseType)} ON qt.${processColumnReference(rowField, databaseType)} = ${processDateTrunc(dateBucket, `ct.comparison_${rowField}`, databaseType, comparisonInterval)}`
|
|
523
|
-
: '';
|
|
524
|
-
return `WITH quill_qt AS (${itemQueries[0]?.replaceAll(';', '')}),
|
|
525
|
-
quill_alias AS (SELECT ${processColumnReference(`${rowField}`, databaseType, undefined, true)} AS ${rowFieldAlias}${valueAliasSubstring}${value2AliasSubstring} FROM quill_qt),
|
|
526
|
-
quill_qt_agg AS (SELECT ${processDateTrunc(dateBucket, rowFieldAlias, databaseType)} as ${processColumnReference(`${rowField}`, databaseType)}, sum(${valueFieldAlias}) / ${max}(sum(${valueField2Alias}), 1) as ${processColumnReference(`${valueField ?? ''}_${matchCasing('percentage', valueField)}`, databaseType, undefined, false, true)} FROM quill_alias GROUP BY ${databaseType.toLowerCase() === 'clickhouse' ? processColumnReference(`${rowField}`, databaseType) : processDateTrunc(dateBucket, rowFieldAlias, databaseType)})
|
|
527
|
-
${compareCTE} ${aliasCTE} ${compareCaseWhenCTE}
|
|
528
|
-
SELECT * FROM quill_qt_agg qt
|
|
529
|
-
${joinQuery} ORDER BY qt.${processColumnReference(`${rowField}`, databaseType)}${rowLimit ? ` LIMIT ${rowLimit}` : ''}`;
|
|
449
|
+
value2AliasSubstring =
|
|
450
|
+
valueField !== pivot.valueField2 ? `, ${valueField2Alias}` : '';
|
|
451
|
+
quillAggSubstring = `
|
|
452
|
+
${processDateTrunc(dateBucket, rowFieldAlias, databaseType)} as ${processColumnReference(rowField, databaseType)}
|
|
453
|
+
, sum(${valueFieldAlias}) / GREATEST(sum(${valueField2Alias}), 1) as ${processColumnReference(`${valueField ?? ''}_${matchCasing('percentage', valueField)}`, databaseType, undefined, false, true)}
|
|
454
|
+
`;
|
|
530
455
|
}
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
return
|
|
545
|
-
quill_alias AS (SELECT ${processColumnReference(`${rowField}`, databaseType, undefined, true)} AS ${rowFieldAlias}${valueAliasSubstring} FROM quill_qt),
|
|
546
|
-
quill_qt_agg AS (SELECT ${processDateTrunc(dateBucket, rowFieldAlias, databaseType)} as ${processColumnReference(`${rowField}`, databaseType)}, ${processAggType(pivot.aggregationType)}(${valueField ? valueFieldAlias : rowFieldAlias}) as ${valueField ? valueFieldAlias : countAlias} FROM quill_alias GROUP BY ${databaseType.toLowerCase() === 'clickhouse' ? processColumnReference(`${rowField}`, databaseType) : processDateTrunc(dateBucket, rowFieldAlias, databaseType)})
|
|
547
|
-
${compareCTE} ${aliasCTE} ${compareCaseWhenCTE}
|
|
548
|
-
SELECT * FROM quill_qt_agg qt
|
|
549
|
-
${joinQuery} ORDER BY qt.${processColumnReference(`${rowField}`, databaseType)}${rowLimit ? ` LIMIT ${rowLimit}` : ''}`;
|
|
456
|
+
// pivot sort matters in the base query when there is a rowLimit. In mssql, an orderby must be accompanied by a limit in a subquery and not allowed in a cte
|
|
457
|
+
const sortQuery = `${pivot.sort && pivot.sortField && pivot.rowLimit ? ` ORDER BY ${processColumnReference(pivot.sortField, databaseType)} ${pivot.sortDirection || ''} ` : ''}`;
|
|
458
|
+
const pivotQuery = `, quill_alias AS (SELECT ${processColumnReference(`${rowField}`, databaseType, undefined, true)} AS ${rowFieldAlias}${valueAliasSubstring}
|
|
459
|
+
${value2AliasSubstring}
|
|
460
|
+
FROM quill_base_table),
|
|
461
|
+
quill_qt_agg AS (SELECT ${quillAggSubstring}
|
|
462
|
+
FROM quill_alias GROUP BY ${databaseType.toLowerCase() === 'clickhouse' ? processColumnReference(`${rowField}`, databaseType) : processDateTrunc(dateBucket, rowFieldAlias, databaseType)}),
|
|
463
|
+
quill_base_pivot AS (SELECT ${pivot.rowLimit && databaseType.toLowerCase() === 'mssql' ? `TOP ${pivot.rowLimit}` : ''} * FROM quill_qt_agg qt
|
|
464
|
+
${sortQuery}${pivot.rowLimit && databaseType.toLowerCase() !== 'mssql' ? ` LIMIT ${pivot.rowLimit}` : ''})
|
|
465
|
+
SELECT * FROM quill_base_pivot
|
|
466
|
+
`
|
|
467
|
+
.replace(/\s+/g, ' ')
|
|
468
|
+
.trim();
|
|
469
|
+
return itemQuery.replace(/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/, pivotQuery);
|
|
550
470
|
}
|
|
551
|
-
function createAggregationValuePivot(pivot,
|
|
471
|
+
function createAggregationValuePivot(pivot, itemQuery, databaseType) {
|
|
472
|
+
const isValidBaseQuery = itemQuery.match(/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/);
|
|
473
|
+
if (!isValidBaseQuery || !pivot.valueField) {
|
|
474
|
+
return undefined;
|
|
475
|
+
}
|
|
552
476
|
const valueField = pivot.valueField;
|
|
553
477
|
const aggregationType = processAggType(pivot.aggregationType);
|
|
554
|
-
if (!pivot.valueField)
|
|
555
|
-
return undefined;
|
|
556
478
|
const valueAlias = processColumnReference(valueField, databaseType, undefined, false, true);
|
|
479
|
+
let value2AliasSubstring = '';
|
|
480
|
+
let quillAggSubstring = `SELECT ${aggregationType}(${valueAlias}) as ${processColumnReference(valueField, databaseType)}`;
|
|
557
481
|
if (aggregationType === 'percentage' && pivot.valueField2) {
|
|
558
482
|
const value2Alias = processColumnReference(pivot.valueField2, databaseType, undefined, false, true);
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
? `, quill_ct as (${itemQueries[1]?.replaceAll(';', '')})`
|
|
562
|
-
: '';
|
|
563
|
-
const aliasCTE = itemQueries[1]
|
|
564
|
-
? `, quill_c_alias as (SELECT ${processColumnReference(valueField, databaseType, undefined, true)} AS ${valueAlias}, ${processColumnReference(pivot.valueField2, databaseType, undefined, true)} AS ${value2Alias} FROM quill_ct)`
|
|
565
|
-
: '';
|
|
566
|
-
const compareAggregation = itemQueries[1]
|
|
567
|
-
? `, quill_ct_cw as (SELECT sum(${processColumnReference(`${valueField}`, databaseType)}) / ${max}(sum(${processColumnReference(`${pivot.valueField2}`, databaseType)}), 1) as ${processColumnReference(`comparison_${valueField}_${matchCasing('percentage', valueField)}`, databaseType, undefined, false, true)} FROM quill_c_alias)`
|
|
568
|
-
: '';
|
|
569
|
-
const joinQuery = itemQueries[1] ? `CROSS JOIN quill_ct_cw ct` : '';
|
|
570
|
-
return `WITH quill_qt AS (${itemQueries[0]?.replaceAll(';', '')}), quill_alias AS (SELECT ${processColumnReference(`${valueField}`, databaseType, undefined, true)} AS ${valueAlias}, ${processColumnReference(`${pivot.valueField2}`, databaseType, undefined, true)} AS ${value2Alias} FROM quill_qt),
|
|
571
|
-
quill_qt_agg AS (SELECT sum(${valueAlias}) / ${max}(sum(${value2Alias}), 1) as ${processColumnReference(`${valueField}_${matchCasing('percentage', valueField)}`, databaseType)} FROM quill_alias)
|
|
572
|
-
${compareCTE} ${aliasCTE} ${compareAggregation}
|
|
573
|
-
SELECT * FROM quill_qt_agg qt
|
|
574
|
-
${joinQuery}${rowLimit ? ` LIMIT ${rowLimit}` : ''}`;
|
|
483
|
+
value2AliasSubstring = `, ${value2Alias}`;
|
|
484
|
+
quillAggSubstring = `SELECT sum(${valueAlias}) / GREATEST(sum(${value2Alias}), 1) as ${processColumnReference(`${valueField}_${matchCasing('percentage', valueField)}`, databaseType, undefined, false, true)}`;
|
|
575
485
|
}
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
: ''
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
return
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
486
|
+
// pivot sort matters in the base query when there is a rowLimit. In mssql, an orderby must be accompanied by a limit in a subquery and not allowed in a cte
|
|
487
|
+
const sortQuery = `${pivot.sort && pivot.sortField && pivot.rowLimit ? ` ORDER BY ${processColumnReference(pivot.sortField, databaseType)} ${pivot.sortDirection || ''} ` : ''}`;
|
|
488
|
+
const pivotQuery = `, quill_alias AS (SELECT ${valueAlias}${value2AliasSubstring} FROM quill_base_table),
|
|
489
|
+
quill_qt_agg AS (${quillAggSubstring} FROM quill_alias),
|
|
490
|
+
quill_base_pivot AS (SELECT ${pivot.rowLimit && databaseType.toLowerCase() === 'mssql' ? `TOP ${pivot.rowLimit}` : ''} * FROM quill_qt_agg qt
|
|
491
|
+
${sortQuery}${pivot.rowLimit && databaseType.toLowerCase() !== 'mssql' ? ` LIMIT ${pivot.rowLimit}` : ''})
|
|
492
|
+
SELECT * FROM quill_base_pivot
|
|
493
|
+
`
|
|
494
|
+
.replace(/\s+/g, ' ')
|
|
495
|
+
.trim();
|
|
496
|
+
return itemQuery.replace(/SELECT \* FROM\s+["'[`]?quill_base_table["'\]`]?\s*$/, pivotQuery);
|
|
497
|
+
}
|
|
498
|
+
export function additionalProcessingOnPivotQuery(pivot, query, additionalProcessing, databaseType = 'postgresql') {
|
|
499
|
+
if (!additionalProcessing || !query)
|
|
500
|
+
return query;
|
|
501
|
+
const isValidBaseQuery = query.match(/SELECT \* FROM\s+["'[`]?quill_base_pivot["'\]`]?\s*$/);
|
|
502
|
+
if (!isValidBaseQuery) {
|
|
503
|
+
return undefined;
|
|
504
|
+
}
|
|
505
|
+
let rowsPerPage = 0;
|
|
506
|
+
let currentInterval = 0;
|
|
507
|
+
let offset = 0;
|
|
508
|
+
let limit = 1000;
|
|
509
|
+
let sortQuery = `${pivot.sort && pivot.sortField
|
|
510
|
+
? ` ORDER BY ${processColumnReference(pivot.sortField, databaseType, undefined, true)} ${pivot.sortDirection || ''}`
|
|
511
|
+
: pivot.rowField
|
|
512
|
+
? `ORDER BY ${processColumnReference(`${pivot.rowField}`, databaseType)}`
|
|
513
|
+
: pivot.valueField
|
|
514
|
+
? pivot.aggregationType === 'percentage'
|
|
515
|
+
? `ORDER BY ${processColumnReference(`${pivot.valueField}_${matchCasing('percentage', pivot.valueField)}`, databaseType, undefined, false, true)}`
|
|
516
|
+
: `ORDER BY ${processColumnReference(pivot.valueField, databaseType, undefined, false, true)}`
|
|
517
|
+
: ''}`;
|
|
518
|
+
if (additionalProcessing.page) {
|
|
519
|
+
const page = additionalProcessing.page.page || 0;
|
|
520
|
+
if (additionalProcessing.page.rowsPerRequest) {
|
|
521
|
+
limit = additionalProcessing.page.rowsPerRequest;
|
|
522
|
+
}
|
|
523
|
+
rowsPerPage = additionalProcessing.page.rowsPerPage || 0;
|
|
524
|
+
currentInterval = page ? Math.floor(page / (limit / rowsPerPage)) : 0;
|
|
525
|
+
offset = currentInterval * limit;
|
|
526
|
+
}
|
|
527
|
+
if (additionalProcessing.sort) {
|
|
528
|
+
sortQuery = `ORDER BY ${processColumnReference(additionalProcessing.sort.field, databaseType)} ${additionalProcessing.sort.direction || ''}`;
|
|
529
|
+
}
|
|
530
|
+
const additionalProcessingQuery = `
|
|
531
|
+
SELECT *
|
|
532
|
+
FROM quill_base_pivot ${sortQuery}${databaseType === 'mssql' ? ` OFFSET ${offset} ROWS FETCH NEXT ${limit} ROWS ONLY` : ` LIMIT ${limit} OFFSET ${offset}`}
|
|
533
|
+
`
|
|
534
|
+
.replace(/\s+/g, ' ')
|
|
535
|
+
.trim();
|
|
536
|
+
return query.replace(/SELECT \* FROM\s+["'[`]?quill_base_pivot["'\]`]?\s*$/, additionalProcessingQuery);
|
|
537
|
+
}
|
|
538
|
+
export function generateRowCountQuery(query, databaseType) {
|
|
539
|
+
if (!query)
|
|
540
|
+
return query;
|
|
541
|
+
const isValidBaseQuery = query.match(/SELECT \* FROM\s+["'[`]?quill_base_pivot["'\]`]?\s*$/);
|
|
542
|
+
if (!isValidBaseQuery) {
|
|
543
|
+
return undefined;
|
|
544
|
+
}
|
|
545
|
+
const rowCountQuery = `, subview_row_count_cte AS (SELECT * FROM quill_base_pivot)
|
|
546
|
+
SELECT count(*) as ${processColumnReference('row_count', databaseType || 'postgresql', undefined, true)} FROM subview_row_count_cte
|
|
547
|
+
`
|
|
548
|
+
.replace(/\s+/g, ' ')
|
|
549
|
+
.trim();
|
|
550
|
+
return query.replace(/SELECT \* FROM\s+["'[`]?quill_base_pivot["'\]`]?\s*$/, rowCountQuery);
|
|
591
551
|
}
|