diff --git a/.github/workflows/drivers-tests.yml b/.github/workflows/drivers-tests.yml index a98caa579832..61ed522855f3 100644 --- a/.github/workflows/drivers-tests.yml +++ b/.github/workflows/drivers-tests.yml @@ -268,4 +268,4 @@ jobs: run: | cd ./packages/cubejs-testing-drivers export DEBUG=testcontainers - yarn ${{ matrix.database }}-full \ No newline at end of file + yarn ${{ matrix.database }}-full diff --git a/packages/cubejs-api-gateway/src/gateway.ts b/packages/cubejs-api-gateway/src/gateway.ts index 393cf5dd5aed..d8cfdd43ae86 100644 --- a/packages/cubejs-api-gateway/src/gateway.ts +++ b/packages/cubejs-api-gateway/src/gateway.ts @@ -1274,12 +1274,20 @@ class ApiGateway { const obj = JSON.parse(memberExpression); const args = obj.cube_params; args.push(`return \`${obj.expr}\``); + + const groupingSet = obj.grouping_set ? { + groupType: obj.grouping_set.group_type, + id: obj.grouping_set.id, + subId: obj.grouping_set.sub_id ? obj.grouping_set.sub_id : undefined + } : undefined; + return { cubeName: obj.cube_name, name: obj.alias, expressionName: obj.alias, expression: Function.constructor.apply(null, args), definition: memberExpression, + groupingSet, }; } else { return memberExpression; diff --git a/packages/cubejs-api-gateway/src/query.js b/packages/cubejs-api-gateway/src/query.js index 8348cb405db6..e6a3908b4d66 100644 --- a/packages/cubejs-api-gateway/src/query.js +++ b/packages/cubejs-api-gateway/src/query.js @@ -47,6 +47,11 @@ const memberExpression = Joi.object().keys({ name: Joi.string().required(), expressionName: Joi.string(), definition: Joi.string(), + groupingSet: Joi.object().keys({ + groupType: Joi.valid('Rollup', 'Cube').required(), + id: Joi.number().required(), + subId: Joi.number() + }) }); const operators = [ diff --git a/packages/cubejs-api-gateway/src/types/query.ts b/packages/cubejs-api-gateway/src/types/query.ts index e1083e827088..8456ecad1277 100644 --- a/packages/cubejs-api-gateway/src/types/query.ts +++ b/packages/cubejs-api-gateway/src/types/query.ts @@ -39,12 +39,19 @@ type LogicalOrFilter = { or: (QueryFilter | LogicalAndFilter)[] }; +type GroupingSet = { + groupType: string, + id: number, + subId?: null | number +}; + type MemberExpression = { expression: Function; cubeName: string; name: string; expressionName: string; definition: string; + groupingSet?: GroupingSet }; /** diff --git a/packages/cubejs-backend-native/Cargo.lock b/packages/cubejs-backend-native/Cargo.lock index c6d26f6dbf2e..1ff36bee3a73 100644 --- a/packages/cubejs-backend-native/Cargo.lock +++ b/packages/cubejs-backend-native/Cargo.lock @@ -635,7 +635,7 @@ dependencies = [ [[package]] name = "cube-ext" version = "1.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=554dac236d586bda9e39ea9a82f4411787f51032#554dac236d586bda9e39ea9a82f4411787f51032" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=38c8946ecb2fff7948b57e2f7151655d041a5b39#38c8946ecb2fff7948b57e2f7151655d041a5b39" dependencies = [ "arrow", "chrono", @@ -743,7 +743,7 @@ dependencies = [ [[package]] name = "datafusion" version = "7.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=554dac236d586bda9e39ea9a82f4411787f51032#554dac236d586bda9e39ea9a82f4411787f51032" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=38c8946ecb2fff7948b57e2f7151655d041a5b39#38c8946ecb2fff7948b57e2f7151655d041a5b39" dependencies = [ "ahash 0.7.7", "arrow", @@ -776,7 +776,7 @@ dependencies = [ [[package]] name = "datafusion-common" version = "7.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=554dac236d586bda9e39ea9a82f4411787f51032#554dac236d586bda9e39ea9a82f4411787f51032" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=38c8946ecb2fff7948b57e2f7151655d041a5b39#38c8946ecb2fff7948b57e2f7151655d041a5b39" dependencies = [ "arrow", "ordered-float 2.10.1", @@ -787,7 +787,7 @@ dependencies = [ [[package]] name = "datafusion-data-access" version = "1.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=554dac236d586bda9e39ea9a82f4411787f51032#554dac236d586bda9e39ea9a82f4411787f51032" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=38c8946ecb2fff7948b57e2f7151655d041a5b39#38c8946ecb2fff7948b57e2f7151655d041a5b39" dependencies = [ "async-trait", "chrono", @@ -800,7 +800,7 @@ dependencies = [ [[package]] name = "datafusion-expr" version = "7.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=554dac236d586bda9e39ea9a82f4411787f51032#554dac236d586bda9e39ea9a82f4411787f51032" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=38c8946ecb2fff7948b57e2f7151655d041a5b39#38c8946ecb2fff7948b57e2f7151655d041a5b39" dependencies = [ "ahash 0.7.7", "arrow", @@ -811,7 +811,7 @@ dependencies = [ [[package]] name = "datafusion-physical-expr" version = "7.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=554dac236d586bda9e39ea9a82f4411787f51032#554dac236d586bda9e39ea9a82f4411787f51032" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=38c8946ecb2fff7948b57e2f7151655d041a5b39#38c8946ecb2fff7948b57e2f7151655d041a5b39" dependencies = [ "ahash 0.7.7", "arrow", diff --git a/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js b/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js index 41a694239a09..08fa518c1fb6 100644 --- a/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js +++ b/packages/cubejs-schema-compiler/src/adapter/BaseQuery.js @@ -1899,7 +1899,11 @@ export class BaseQuery { return ''; } const dimensionColumns = this.dimensionColumns(); - return dimensionColumns.length ? ` GROUP BY ${dimensionColumns.map((c, i) => `${i + 1}`).join(', ')}` : ''; + if (!dimensionColumns.length) { + return ''; + } + const dimensionNames = dimensionColumns.map((c, i) => `${i + 1}`); + return this.rollupGroupByClause(dimensionNames); } getFieldIndex(id) { @@ -1993,6 +1997,53 @@ export class BaseQuery { return this.limitOffsetClause(limit, offset); } + /** + * @protected + * @param {Array} dimensionNames + * @returns {string} + */ + rollupGroupByClause(dimensionNames) { + if (this.ungrouped) { + return ''; + } + const dimensionColumns = this.dimensionColumns(); + if (!dimensionColumns.length) { + return ''; + } + + const groupingSets = R.flatten(this.dimensionsForSelect().map(d => d.dimension).filter(d => !!d)).map(d => d.groupingSet); + + let result = ' GROUP BY '; + + dimensionColumns.forEach((c, i) => { + const groupingSet = groupingSets[i]; + const comma = i > 0 ? ', ' : ''; + const prevId = i > 0 ? (groupingSets[i - 1] || { id: null }).id : null; + const currId = (groupingSet || { id: null }).id; + + if (prevId !== null && currId !== prevId) { + result += ')'; + } + + if ((prevId === null || currId !== prevId) && groupingSet != null) { + if (groupingSet.groupType === 'Rollup') { + result += `${comma}ROLLUP(`; + } else if (groupingSet.groupType === 'Cube') { + result += `${comma}CUBE(`; + } + } else { + result += `${comma}`; + } + + result += dimensionNames[i]; + }); + if (groupingSets[groupingSets.length - 1] != null) { + result += ')'; + } + + return result; + } + /** * @protected * @param limit @@ -2937,10 +2988,11 @@ export class BaseQuery { '{{ from | indent(2, true) }}\n' + ') AS {{ from_alias }}{% endif %}' + '{% if filter %}\nWHERE {{ filter }}{% endif %}' + - '{% if group_by %}\nGROUP BY {{ group_by | map(attribute=\'index\') | join(\', \') }}{% endif %}' + + '{% if group_by %}\nGROUP BY {{ group_by }}{% endif %}' + '{% if order_by %}\nORDER BY {{ order_by | map(attribute=\'expr\') | join(\', \') }}{% endif %}' + '{% if limit %}\nLIMIT {{ limit }}{% endif %}' + '{% if offset %}\nOFFSET {{ offset }}{% endif %}', + group_by_exprs: '{{ group_by | map(attribute=\'index\') | join(\', \') }}', }, expressions: { column_aliased: '{{expr}} {{quoted_alias}}', @@ -2954,6 +3006,8 @@ export class BaseQuery { in_list: '{{ expr }} {% if negated %}NOT {% endif %}IN ({{ in_exprs_concat }})', subquery: '({{ expr }})', in_subquery: '{{ expr }} {% if negated %}NOT {% endif %}IN {{ subquery_expr }}', + rollup: 'ROLLUP({{ exprs_concat }})', + cube: 'CUBE({{ exprs_concat }})', negative: '-({{ expr }})', not: 'NOT ({{ expr }})', true: 'TRUE', diff --git a/packages/cubejs-schema-compiler/src/adapter/PrestodbQuery.ts b/packages/cubejs-schema-compiler/src/adapter/PrestodbQuery.ts index 72f8ce45527c..926c510b7870 100644 --- a/packages/cubejs-schema-compiler/src/adapter/PrestodbQuery.ts +++ b/packages/cubejs-schema-compiler/src/adapter/PrestodbQuery.ts @@ -114,7 +114,7 @@ export class PrestodbQuery extends BaseQuery { templates.functions.DATEPART = 'DATE_PART({{ args_concat }})'; templates.statements.select = 'SELECT {{ select_concat | map(attribute=\'aliased\') | join(\', \') }} \n' + 'FROM (\n {{ from }}\n) AS {{ from_alias }} \n' + - '{% if group_by %} GROUP BY {{ group_by | map(attribute=\'index\') | join(\', \') }}{% endif %}' + + '{% if group_by %} GROUP BY {{ group_by }}{% endif %}' + '{% if order_by %} ORDER BY {{ order_by | map(attribute=\'expr\') | join(\', \') }}{% endif %}' + '{% if offset %}\nOFFSET {{ offset }}{% endif %}' + '{% if limit %}\nLIMIT {{ limit }}{% endif %}'; diff --git a/packages/cubejs-testing-drivers/fixtures/athena.json b/packages/cubejs-testing-drivers/fixtures/athena.json index e8a54a2bb179..5a9916f227d7 100644 --- a/packages/cubejs-testing-drivers/fixtures/athena.json +++ b/packages/cubejs-testing-drivers/fixtures/athena.json @@ -143,8 +143,15 @@ "querying BigECommerce: null sum", "querying BigECommerce: null boolean", "--------------------", + "week granularity is not supported for intervals", "--------------------", - "querying BigECommerce: rolling window by 2 week" + "querying BigECommerce: rolling window by 2 week", + + "SKIPPED SQL API (Need work)", + "---------------------------------------", + "SQL API: Simple Rollup", + "SQL API: Complex Rollup", + "SQL API: Nested Rollup" ] } diff --git a/packages/cubejs-testing-drivers/fixtures/bigquery.json b/packages/cubejs-testing-drivers/fixtures/bigquery.json index 97add1420953..5e2eae6efaaf 100644 --- a/packages/cubejs-testing-drivers/fixtures/bigquery.json +++ b/packages/cubejs-testing-drivers/fixtures/bigquery.json @@ -165,6 +165,7 @@ "SKIPPED SQL API (Need work)", "---------------------------------------", - "SQL API: reuse params" + "SQL API: reuse params", + "SQL API: Complex Rollup" ] } diff --git a/packages/cubejs-testing-drivers/fixtures/databricks-jdbc.json b/packages/cubejs-testing-drivers/fixtures/databricks-jdbc.json index 9909c4f37357..2bab8d802d8f 100644 --- a/packages/cubejs-testing-drivers/fixtures/databricks-jdbc.json +++ b/packages/cubejs-testing-drivers/fixtures/databricks-jdbc.json @@ -156,6 +156,10 @@ "querying Products: dimensions -- doesn't work wo ordering", "querying ECommerce: total quantity, avg discount, total sales, total profit by product + order + total -- rounding in athena", "querying ECommerce: total sales, total profit by month + order (date) + total -- doesn't work with the BigQuery", - "querying ECommerce: total quantity, avg discount, total sales, total profit by product + order + total -- noisy test" + "querying ECommerce: total quantity, avg discount, total sales, total profit by product + order + total -- noisy test", + + "SKIPPED SQL API (Need work)", + "---------------------------------------", + "SQL API: Nested Rollup" ] -} \ No newline at end of file +} diff --git a/packages/cubejs-testing-drivers/fixtures/mssql.json b/packages/cubejs-testing-drivers/fixtures/mssql.json index ba38902b2897..cba343b7b858 100644 --- a/packages/cubejs-testing-drivers/fixtures/mssql.json +++ b/packages/cubejs-testing-drivers/fixtures/mssql.json @@ -138,6 +138,9 @@ "SQL API: reuse params", "SQL API: post-aggregate percentage of total", "SQL API: powerbi min max ungrouped flag", - "SQL API: powerbi min max push down" + "SQL API: powerbi min max push down", + "SQL API: Simple Rollup", + "SQL API: Complex Rollup", + "SQL API: Nested Rollup" ] } diff --git a/packages/cubejs-testing-drivers/fixtures/mysql.json b/packages/cubejs-testing-drivers/fixtures/mysql.json index fa53937e11b7..40b5cdfdd9a8 100644 --- a/packages/cubejs-testing-drivers/fixtures/mysql.json +++ b/packages/cubejs-testing-drivers/fixtures/mysql.json @@ -130,6 +130,9 @@ "SKIPPED SQL API (Need work)", "---------------------------------------", - "SQL API: reuse params" + "SQL API: reuse params", + "SQL API: Simple Rollup", + "SQL API: Complex Rollup", + "SQL API: Nested Rollup" ] } diff --git a/packages/cubejs-testing-drivers/src/tests/testQueries.ts b/packages/cubejs-testing-drivers/src/tests/testQueries.ts index dd7bb0fd9f4b..d4e02f108d4a 100644 --- a/packages/cubejs-testing-drivers/src/tests/testQueries.ts +++ b/packages/cubejs-testing-drivers/src/tests/testQueries.ts @@ -1628,5 +1628,54 @@ from `); expect(res.rows).toMatchSnapshot('reuse_params'); }); + + executePg('SQL API: Simple Rollup', async () => { + const connection = await createPostgresClient(); + const res = await connection.query(` + select + rowId, orderId, orderDate, sum(count) + from + "ECommerce" as "ECommerce" + group by + ROLLUP(1, 2, 3) + order by 1, 2, 3 + + `); + expect(res.rows).toMatchSnapshot('simple_rollup'); + }); + + executePg('SQL API: Complex Rollup', async () => { + const connection = await createPostgresClient(); + const res = await connection.query(` + select + rowId, orderId, orderDate, city, sum(count) + from + "ECommerce" as "ECommerce" + group by + ROLLUP(1, 2), 3, ROLLUP(4) + order by 1, 2, 3, 4 + + `); + expect(res.rows).toMatchSnapshot('complex_rollup'); + }); + executePg('SQL API: Nested Rollup', async () => { + const connection = await createPostgresClient(); + const res = await connection.query(` + select rowId, orderId, orderDate, sum(cnt) + from ( + select + rowId, orderId, orderDate, sum(count) as cnt + from + "ECommerce" as "ECommerce" + group by 1, 2, 3 + + ) a + group by + ROLLUP(1, 2, 3) + order by 1, 2, 3 + + `); + expect(res.rows).toMatchSnapshot('nested_rollup'); + }); }); } diff --git a/packages/cubejs-testing-drivers/test/__snapshots__/postgres-full.test.ts.snap b/packages/cubejs-testing-drivers/test/__snapshots__/postgres-full.test.ts.snap index 435ad3e01571..ffb9ea707b4e 100644 --- a/packages/cubejs-testing-drivers/test/__snapshots__/postgres-full.test.ts.snap +++ b/packages/cubejs-testing-drivers/test/__snapshots__/postgres-full.test.ts.snap @@ -1,5 +1,3408 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Queries with the @cubejs-backend/postgres-driver SQL API: Complex Rollup: complex_rollup 1`] = ` +Array [ + Object { + "SUM(ECommerce.count)": "1", + "city": "Detroit", + "orderDate": 2020-01-23T00:00:00.000Z, + "orderId": "CA-2017-145142", + "rowId": 523, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-01-23T00:00:00.000Z, + "orderId": "CA-2017-145142", + "rowId": 523, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Detroit", + "orderDate": 2020-01-23T00:00:00.000Z, + "orderId": null, + "rowId": 523, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-01-23T00:00:00.000Z, + "orderId": null, + "rowId": 523, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Lorain", + "orderDate": 2020-01-01T00:00:00.000Z, + "orderId": "CA-2017-107503", + "rowId": 849, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-01-01T00:00:00.000Z, + "orderId": "CA-2017-107503", + "rowId": 849, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Lorain", + "orderDate": 2020-01-01T00:00:00.000Z, + "orderId": null, + "rowId": 849, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-01-01T00:00:00.000Z, + "orderId": null, + "rowId": 849, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Olympia", + "orderDate": 2020-06-17T00:00:00.000Z, + "orderId": "CA-2017-118437", + "rowId": 1013, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-17T00:00:00.000Z, + "orderId": "CA-2017-118437", + "rowId": 1013, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Olympia", + "orderDate": 2020-06-17T00:00:00.000Z, + "orderId": null, + "rowId": 1013, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-17T00:00:00.000Z, + "orderId": null, + "rowId": 1013, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Vancouver", + "orderDate": 2020-10-30T00:00:00.000Z, + "orderId": "CA-2017-139661", + "rowId": 1494, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-10-30T00:00:00.000Z, + "orderId": "CA-2017-139661", + "rowId": 1494, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Vancouver", + "orderDate": 2020-10-30T00:00:00.000Z, + "orderId": null, + "rowId": 1494, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-10-30T00:00:00.000Z, + "orderId": null, + "rowId": 1494, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-06-25T00:00:00.000Z, + "orderId": "CA-2017-133648", + "rowId": 1995, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-25T00:00:00.000Z, + "orderId": "CA-2017-133648", + "rowId": 1995, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-06-25T00:00:00.000Z, + "orderId": null, + "rowId": 1995, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-25T00:00:00.000Z, + "orderId": null, + "rowId": 1995, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-09-23T00:00:00.000Z, + "orderId": "CA-2017-138422", + "rowId": 2329, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-09-23T00:00:00.000Z, + "orderId": "CA-2017-138422", + "rowId": 2329, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-09-23T00:00:00.000Z, + "orderId": null, + "rowId": 2329, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-09-23T00:00:00.000Z, + "orderId": null, + "rowId": 2329, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "New York City", + "orderDate": 2020-03-17T00:00:00.000Z, + "orderId": "CA-2017-140949", + "rowId": 2455, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-03-17T00:00:00.000Z, + "orderId": "CA-2017-140949", + "rowId": 2455, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "New York City", + "orderDate": 2020-03-17T00:00:00.000Z, + "orderId": null, + "rowId": 2455, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-03-17T00:00:00.000Z, + "orderId": null, + "rowId": 2455, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-05-13T00:00:00.000Z, + "orderId": "CA-2017-149048", + "rowId": 2595, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-05-13T00:00:00.000Z, + "orderId": "CA-2017-149048", + "rowId": 2595, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-05-13T00:00:00.000Z, + "orderId": null, + "rowId": 2595, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-05-13T00:00:00.000Z, + "orderId": null, + "rowId": 2595, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Provo", + "orderDate": 2020-09-17T00:00:00.000Z, + "orderId": "CA-2017-112515", + "rowId": 2655, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-09-17T00:00:00.000Z, + "orderId": "CA-2017-112515", + "rowId": 2655, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Provo", + "orderDate": 2020-09-17T00:00:00.000Z, + "orderId": null, + "rowId": 2655, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-09-17T00:00:00.000Z, + "orderId": null, + "rowId": 2655, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-11-28T00:00:00.000Z, + "orderId": "CA-2017-123372", + "rowId": 2661, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-28T00:00:00.000Z, + "orderId": "CA-2017-123372", + "rowId": 2661, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-11-28T00:00:00.000Z, + "orderId": null, + "rowId": 2661, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-28T00:00:00.000Z, + "orderId": null, + "rowId": 2661, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Glendale", + "orderDate": 2020-11-12T00:00:00.000Z, + "orderId": "CA-2017-134915", + "rowId": 2952, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-12T00:00:00.000Z, + "orderId": "CA-2017-134915", + "rowId": 2952, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Glendale", + "orderDate": 2020-11-12T00:00:00.000Z, + "orderId": null, + "rowId": 2952, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-12T00:00:00.000Z, + "orderId": null, + "rowId": 2952, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "San Francisco", + "orderDate": 2020-10-19T00:00:00.000Z, + "orderId": "CA-2017-131492", + "rowId": 3059, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-10-19T00:00:00.000Z, + "orderId": "CA-2017-131492", + "rowId": 3059, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "San Francisco", + "orderDate": 2020-10-19T00:00:00.000Z, + "orderId": null, + "rowId": 3059, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-10-19T00:00:00.000Z, + "orderId": null, + "rowId": 3059, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "San Francisco", + "orderDate": 2020-10-19T00:00:00.000Z, + "orderId": "CA-2017-131492", + "rowId": 3060, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-10-19T00:00:00.000Z, + "orderId": "CA-2017-131492", + "rowId": 3060, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "San Francisco", + "orderDate": 2020-10-19T00:00:00.000Z, + "orderId": null, + "rowId": 3060, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-10-19T00:00:00.000Z, + "orderId": null, + "rowId": 3060, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Louisville", + "orderDate": 2020-05-27T00:00:00.000Z, + "orderId": "US-2017-132297", + "rowId": 3083, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-05-27T00:00:00.000Z, + "orderId": "US-2017-132297", + "rowId": 3083, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Louisville", + "orderDate": 2020-05-27T00:00:00.000Z, + "orderId": null, + "rowId": 3083, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-05-27T00:00:00.000Z, + "orderId": null, + "rowId": 3083, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Auburn", + "orderDate": 2020-06-11T00:00:00.000Z, + "orderId": "CA-2017-102554", + "rowId": 3448, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-11T00:00:00.000Z, + "orderId": "CA-2017-102554", + "rowId": 3448, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Auburn", + "orderDate": 2020-06-11T00:00:00.000Z, + "orderId": null, + "rowId": 3448, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-11T00:00:00.000Z, + "orderId": null, + "rowId": 3448, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Omaha", + "orderDate": 2020-05-29T00:00:00.000Z, + "orderId": "CA-2017-144568", + "rowId": 3717, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-05-29T00:00:00.000Z, + "orderId": "CA-2017-144568", + "rowId": 3717, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Omaha", + "orderDate": 2020-05-29T00:00:00.000Z, + "orderId": null, + "rowId": 3717, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-05-29T00:00:00.000Z, + "orderId": null, + "rowId": 3717, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Bakersfield", + "orderDate": 2020-09-02T00:00:00.000Z, + "orderId": "CA-2017-123001", + "rowId": 3934, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-09-02T00:00:00.000Z, + "orderId": "CA-2017-123001", + "rowId": 3934, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Bakersfield", + "orderDate": 2020-09-02T00:00:00.000Z, + "orderId": null, + "rowId": 3934, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-09-02T00:00:00.000Z, + "orderId": null, + "rowId": 3934, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Philadelphia", + "orderDate": 2020-11-21T00:00:00.000Z, + "orderId": "CA-2017-100811", + "rowId": 4012, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-21T00:00:00.000Z, + "orderId": "CA-2017-100811", + "rowId": 4012, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Philadelphia", + "orderDate": 2020-11-21T00:00:00.000Z, + "orderId": null, + "rowId": 4012, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-21T00:00:00.000Z, + "orderId": null, + "rowId": 4012, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Lafayette", + "orderDate": 2020-12-24T00:00:00.000Z, + "orderId": "CA-2017-124296", + "rowId": 4031, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-24T00:00:00.000Z, + "orderId": "CA-2017-124296", + "rowId": 4031, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Lafayette", + "orderDate": 2020-12-24T00:00:00.000Z, + "orderId": null, + "rowId": 4031, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-24T00:00:00.000Z, + "orderId": null, + "rowId": 4031, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "New York City", + "orderDate": 2020-05-14T00:00:00.000Z, + "orderId": "CA-2017-115546", + "rowId": 4161, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-05-14T00:00:00.000Z, + "orderId": "CA-2017-115546", + "rowId": 4161, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "New York City", + "orderDate": 2020-05-14T00:00:00.000Z, + "orderId": null, + "rowId": 4161, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-05-14T00:00:00.000Z, + "orderId": null, + "rowId": 4161, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-11-11T00:00:00.000Z, + "orderId": "CA-2017-120327", + "rowId": 4227, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-11T00:00:00.000Z, + "orderId": "CA-2017-120327", + "rowId": 4227, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-11-11T00:00:00.000Z, + "orderId": null, + "rowId": 4227, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-11T00:00:00.000Z, + "orderId": null, + "rowId": 4227, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-11-02T00:00:00.000Z, + "orderId": "CA-2017-143567", + "rowId": 4882, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-02T00:00:00.000Z, + "orderId": "CA-2017-143567", + "rowId": 4882, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-11-02T00:00:00.000Z, + "orderId": null, + "rowId": 4882, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-02T00:00:00.000Z, + "orderId": null, + "rowId": 4882, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Detroit", + "orderDate": 2020-09-01T00:00:00.000Z, + "orderId": "CA-2017-145653", + "rowId": 5220, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-09-01T00:00:00.000Z, + "orderId": "CA-2017-145653", + "rowId": 5220, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Detroit", + "orderDate": 2020-09-01T00:00:00.000Z, + "orderId": null, + "rowId": 5220, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-09-01T00:00:00.000Z, + "orderId": null, + "rowId": 5220, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-12-14T00:00:00.000Z, + "orderId": "CA-2017-147333", + "rowId": 5277, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-14T00:00:00.000Z, + "orderId": "CA-2017-147333", + "rowId": 5277, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-12-14T00:00:00.000Z, + "orderId": null, + "rowId": 5277, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-14T00:00:00.000Z, + "orderId": null, + "rowId": 5277, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Los Angeles", + "orderDate": 2020-06-03T00:00:00.000Z, + "orderId": "CA-2017-145772", + "rowId": 6125, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-03T00:00:00.000Z, + "orderId": "CA-2017-145772", + "rowId": 6125, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Los Angeles", + "orderDate": 2020-06-03T00:00:00.000Z, + "orderId": null, + "rowId": 6125, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-03T00:00:00.000Z, + "orderId": null, + "rowId": 6125, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Marion", + "orderDate": 2020-12-01T00:00:00.000Z, + "orderId": "CA-2017-145660", + "rowId": 6205, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-01T00:00:00.000Z, + "orderId": "CA-2017-145660", + "rowId": 6205, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Marion", + "orderDate": 2020-12-01T00:00:00.000Z, + "orderId": null, + "rowId": 6205, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-01T00:00:00.000Z, + "orderId": null, + "rowId": 6205, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Oakland", + "orderDate": 2020-12-02T00:00:00.000Z, + "orderId": "CA-2017-102379", + "rowId": 6272, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-02T00:00:00.000Z, + "orderId": "CA-2017-102379", + "rowId": 6272, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Oakland", + "orderDate": 2020-12-02T00:00:00.000Z, + "orderId": null, + "rowId": 6272, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-02T00:00:00.000Z, + "orderId": null, + "rowId": 6272, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Baltimore", + "orderDate": 2020-05-14T00:00:00.000Z, + "orderId": "US-2017-133361", + "rowId": 6459, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-05-14T00:00:00.000Z, + "orderId": "US-2017-133361", + "rowId": 6459, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Baltimore", + "orderDate": 2020-05-14T00:00:00.000Z, + "orderId": null, + "rowId": 6459, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-05-14T00:00:00.000Z, + "orderId": null, + "rowId": 6459, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Arlington", + "orderDate": 2020-09-08T00:00:00.000Z, + "orderId": "US-2017-124779", + "rowId": 6651, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-09-08T00:00:00.000Z, + "orderId": "US-2017-124779", + "rowId": 6651, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Arlington", + "orderDate": 2020-09-08T00:00:00.000Z, + "orderId": null, + "rowId": 6651, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-09-08T00:00:00.000Z, + "orderId": null, + "rowId": 6651, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Houston", + "orderDate": 2020-03-26T00:00:00.000Z, + "orderId": "US-2017-141677", + "rowId": 7174, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-03-26T00:00:00.000Z, + "orderId": "US-2017-141677", + "rowId": 7174, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Houston", + "orderDate": 2020-03-26T00:00:00.000Z, + "orderId": null, + "rowId": 7174, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-03-26T00:00:00.000Z, + "orderId": null, + "rowId": 7174, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-12-04T00:00:00.000Z, + "orderId": "CA-2017-109183", + "rowId": 7293, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-04T00:00:00.000Z, + "orderId": "CA-2017-109183", + "rowId": 7293, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-12-04T00:00:00.000Z, + "orderId": null, + "rowId": 7293, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-04T00:00:00.000Z, + "orderId": null, + "rowId": 7293, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "New York City", + "orderDate": 2020-06-10T00:00:00.000Z, + "orderId": "CA-2017-112172", + "rowId": 7310, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-10T00:00:00.000Z, + "orderId": "CA-2017-112172", + "rowId": 7310, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "New York City", + "orderDate": 2020-06-10T00:00:00.000Z, + "orderId": null, + "rowId": 7310, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-10T00:00:00.000Z, + "orderId": null, + "rowId": 7310, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Philadelphia", + "orderDate": 2020-04-10T00:00:00.000Z, + "orderId": "CA-2017-135069", + "rowId": 7425, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-04-10T00:00:00.000Z, + "orderId": "CA-2017-135069", + "rowId": 7425, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Philadelphia", + "orderDate": 2020-04-10T00:00:00.000Z, + "orderId": null, + "rowId": 7425, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-04-10T00:00:00.000Z, + "orderId": null, + "rowId": 7425, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-12-14T00:00:00.000Z, + "orderId": "CA-2017-151799", + "rowId": 7698, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-14T00:00:00.000Z, + "orderId": "CA-2017-151799", + "rowId": 7698, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-12-14T00:00:00.000Z, + "orderId": null, + "rowId": 7698, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-14T00:00:00.000Z, + "orderId": null, + "rowId": 7698, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Lakewood", + "orderDate": 2020-10-12T00:00:00.000Z, + "orderId": "CA-2017-150091", + "rowId": 8425, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-10-12T00:00:00.000Z, + "orderId": "CA-2017-150091", + "rowId": 8425, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Lakewood", + "orderDate": 2020-10-12T00:00:00.000Z, + "orderId": null, + "rowId": 8425, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-10-12T00:00:00.000Z, + "orderId": null, + "rowId": 8425, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Dallas", + "orderDate": 2020-11-06T00:00:00.000Z, + "orderId": "US-2017-119319", + "rowId": 8621, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-06T00:00:00.000Z, + "orderId": "US-2017-119319", + "rowId": 8621, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Dallas", + "orderDate": 2020-11-06T00:00:00.000Z, + "orderId": null, + "rowId": 8621, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-06T00:00:00.000Z, + "orderId": null, + "rowId": 8621, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Decatur", + "orderDate": 2020-02-16T00:00:00.000Z, + "orderId": "CA-2017-163265", + "rowId": 8673, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-02-16T00:00:00.000Z, + "orderId": "CA-2017-163265", + "rowId": 8673, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Decatur", + "orderDate": 2020-02-16T00:00:00.000Z, + "orderId": null, + "rowId": 8673, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-02-16T00:00:00.000Z, + "orderId": null, + "rowId": 8673, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-06-15T00:00:00.000Z, + "orderId": "CA-2017-119284", + "rowId": 8697, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-15T00:00:00.000Z, + "orderId": "CA-2017-119284", + "rowId": 8697, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-06-15T00:00:00.000Z, + "orderId": null, + "rowId": 8697, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-15T00:00:00.000Z, + "orderId": null, + "rowId": 8697, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Morristown", + "orderDate": 2020-09-17T00:00:00.000Z, + "orderId": "CA-2017-126928", + "rowId": 8878, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-09-17T00:00:00.000Z, + "orderId": "CA-2017-126928", + "rowId": 8878, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Morristown", + "orderDate": 2020-09-17T00:00:00.000Z, + "orderId": null, + "rowId": 8878, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-09-17T00:00:00.000Z, + "orderId": null, + "rowId": 8878, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-12-25T00:00:00.000Z, + "orderId": "CA-2017-105620", + "rowId": 8958, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-25T00:00:00.000Z, + "orderId": "CA-2017-105620", + "rowId": 8958, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-12-25T00:00:00.000Z, + "orderId": null, + "rowId": 8958, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-25T00:00:00.000Z, + "orderId": null, + "rowId": 8958, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "New York City", + "orderDate": 2020-11-05T00:00:00.000Z, + "orderId": "CA-2017-102925", + "rowId": 9473, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-05T00:00:00.000Z, + "orderId": "CA-2017-102925", + "rowId": 9473, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "New York City", + "orderDate": 2020-11-05T00:00:00.000Z, + "orderId": null, + "rowId": 9473, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-05T00:00:00.000Z, + "orderId": null, + "rowId": 9473, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "New York City", + "orderDate": 2020-06-25T00:00:00.000Z, + "orderId": "CA-2017-116127", + "rowId": 9584, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-25T00:00:00.000Z, + "orderId": "CA-2017-116127", + "rowId": 9584, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "New York City", + "orderDate": 2020-06-25T00:00:00.000Z, + "orderId": null, + "rowId": 9584, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-25T00:00:00.000Z, + "orderId": null, + "rowId": 9584, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-11-16T00:00:00.000Z, + "orderId": "CA-2017-160633", + "rowId": 9618, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-16T00:00:00.000Z, + "orderId": "CA-2017-160633", + "rowId": 9618, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-11-16T00:00:00.000Z, + "orderId": null, + "rowId": 9618, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-16T00:00:00.000Z, + "orderId": null, + "rowId": 9618, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Bowling", + "orderDate": 2020-11-16T00:00:00.000Z, + "orderId": "CA-2017-160633", + "rowId": 9619, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-16T00:00:00.000Z, + "orderId": "CA-2017-160633", + "rowId": 9619, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Bowling", + "orderDate": 2020-11-16T00:00:00.000Z, + "orderId": null, + "rowId": 9619, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-16T00:00:00.000Z, + "orderId": null, + "rowId": 9619, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Lorain", + "orderDate": 2020-01-01T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-01-01T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Detroit", + "orderDate": 2020-01-23T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-01-23T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Decatur", + "orderDate": 2020-02-16T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-02-16T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "New York City", + "orderDate": 2020-03-17T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-03-17T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Houston", + "orderDate": 2020-03-26T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-03-26T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Philadelphia", + "orderDate": 2020-04-10T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-04-10T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-05-13T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-05-13T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Baltimore", + "orderDate": 2020-05-14T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "New York City", + "orderDate": 2020-05-14T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "2", + "city": null, + "orderDate": 2020-05-14T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Louisville", + "orderDate": 2020-05-27T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-05-27T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Omaha", + "orderDate": 2020-05-29T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-05-29T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Los Angeles", + "orderDate": 2020-06-03T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-03T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "New York City", + "orderDate": 2020-06-10T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-10T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Auburn", + "orderDate": 2020-06-11T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-11T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-06-15T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-15T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Olympia", + "orderDate": 2020-06-17T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-06-17T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-06-25T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "New York City", + "orderDate": 2020-06-25T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "2", + "city": null, + "orderDate": 2020-06-25T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Detroit", + "orderDate": 2020-09-01T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-09-01T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Bakersfield", + "orderDate": 2020-09-02T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-09-02T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Arlington", + "orderDate": 2020-09-08T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-09-08T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Morristown", + "orderDate": 2020-09-17T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Provo", + "orderDate": 2020-09-17T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "2", + "city": null, + "orderDate": 2020-09-17T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-09-23T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-09-23T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Lakewood", + "orderDate": 2020-10-12T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-10-12T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "2", + "city": "San Francisco", + "orderDate": 2020-10-19T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "2", + "city": null, + "orderDate": 2020-10-19T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Vancouver", + "orderDate": 2020-10-30T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-10-30T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-11-02T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-02T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "New York City", + "orderDate": 2020-11-05T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-05T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Dallas", + "orderDate": 2020-11-06T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-06T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-11-11T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-11T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Glendale", + "orderDate": 2020-11-12T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-12T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Bowling", + "orderDate": 2020-11-16T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-11-16T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "2", + "city": null, + "orderDate": 2020-11-16T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Philadelphia", + "orderDate": 2020-11-21T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-21T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-11-28T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-11-28T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Marion", + "orderDate": 2020-12-01T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-01T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Oakland", + "orderDate": 2020-12-02T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-02T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-12-04T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-04T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "2", + "city": "Columbus", + "orderDate": 2020-12-14T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "2", + "city": null, + "orderDate": 2020-12-14T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Lafayette", + "orderDate": 2020-12-24T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-24T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": "Columbus", + "orderDate": 2020-12-25T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, + Object { + "SUM(ECommerce.count)": "1", + "city": null, + "orderDate": 2020-12-25T00:00:00.000Z, + "orderId": null, + "rowId": null, + }, +] +`; + +exports[`Queries with the @cubejs-backend/postgres-driver SQL API: Nested Rollup: nested_rollup 1`] = ` +Array [ + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-01-23T00:00:00.000Z, + "orderId": "CA-2017-145142", + "rowId": 523, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-145142", + "rowId": 523, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 523, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-01-01T00:00:00.000Z, + "orderId": "CA-2017-107503", + "rowId": 849, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-107503", + "rowId": 849, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 849, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-06-17T00:00:00.000Z, + "orderId": "CA-2017-118437", + "rowId": 1013, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-118437", + "rowId": 1013, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 1013, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-10-30T00:00:00.000Z, + "orderId": "CA-2017-139661", + "rowId": 1494, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-139661", + "rowId": 1494, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 1494, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-06-25T00:00:00.000Z, + "orderId": "CA-2017-133648", + "rowId": 1995, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-133648", + "rowId": 1995, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 1995, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-09-23T00:00:00.000Z, + "orderId": "CA-2017-138422", + "rowId": 2329, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-138422", + "rowId": 2329, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 2329, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-03-17T00:00:00.000Z, + "orderId": "CA-2017-140949", + "rowId": 2455, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-140949", + "rowId": 2455, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 2455, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-05-13T00:00:00.000Z, + "orderId": "CA-2017-149048", + "rowId": 2595, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-149048", + "rowId": 2595, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 2595, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-09-17T00:00:00.000Z, + "orderId": "CA-2017-112515", + "rowId": 2655, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-112515", + "rowId": 2655, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 2655, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-11-28T00:00:00.000Z, + "orderId": "CA-2017-123372", + "rowId": 2661, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-123372", + "rowId": 2661, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 2661, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-11-12T00:00:00.000Z, + "orderId": "CA-2017-134915", + "rowId": 2952, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-134915", + "rowId": 2952, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 2952, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-10-19T00:00:00.000Z, + "orderId": "CA-2017-131492", + "rowId": 3059, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-131492", + "rowId": 3059, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 3059, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-10-19T00:00:00.000Z, + "orderId": "CA-2017-131492", + "rowId": 3060, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-131492", + "rowId": 3060, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 3060, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-05-27T00:00:00.000Z, + "orderId": "US-2017-132297", + "rowId": 3083, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "US-2017-132297", + "rowId": 3083, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 3083, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-06-11T00:00:00.000Z, + "orderId": "CA-2017-102554", + "rowId": 3448, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-102554", + "rowId": 3448, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 3448, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-05-29T00:00:00.000Z, + "orderId": "CA-2017-144568", + "rowId": 3717, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-144568", + "rowId": 3717, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 3717, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-09-02T00:00:00.000Z, + "orderId": "CA-2017-123001", + "rowId": 3934, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-123001", + "rowId": 3934, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 3934, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-11-21T00:00:00.000Z, + "orderId": "CA-2017-100811", + "rowId": 4012, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-100811", + "rowId": 4012, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 4012, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-12-24T00:00:00.000Z, + "orderId": "CA-2017-124296", + "rowId": 4031, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-124296", + "rowId": 4031, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 4031, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-05-14T00:00:00.000Z, + "orderId": "CA-2017-115546", + "rowId": 4161, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-115546", + "rowId": 4161, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 4161, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-11-11T00:00:00.000Z, + "orderId": "CA-2017-120327", + "rowId": 4227, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-120327", + "rowId": 4227, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 4227, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-11-02T00:00:00.000Z, + "orderId": "CA-2017-143567", + "rowId": 4882, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-143567", + "rowId": 4882, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 4882, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-09-01T00:00:00.000Z, + "orderId": "CA-2017-145653", + "rowId": 5220, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-145653", + "rowId": 5220, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 5220, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-12-14T00:00:00.000Z, + "orderId": "CA-2017-147333", + "rowId": 5277, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-147333", + "rowId": 5277, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 5277, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-06-03T00:00:00.000Z, + "orderId": "CA-2017-145772", + "rowId": 6125, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-145772", + "rowId": 6125, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 6125, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-12-01T00:00:00.000Z, + "orderId": "CA-2017-145660", + "rowId": 6205, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-145660", + "rowId": 6205, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 6205, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-12-02T00:00:00.000Z, + "orderId": "CA-2017-102379", + "rowId": 6272, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-102379", + "rowId": 6272, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 6272, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-05-14T00:00:00.000Z, + "orderId": "US-2017-133361", + "rowId": 6459, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "US-2017-133361", + "rowId": 6459, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 6459, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-09-08T00:00:00.000Z, + "orderId": "US-2017-124779", + "rowId": 6651, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "US-2017-124779", + "rowId": 6651, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 6651, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-03-26T00:00:00.000Z, + "orderId": "US-2017-141677", + "rowId": 7174, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "US-2017-141677", + "rowId": 7174, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 7174, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-12-04T00:00:00.000Z, + "orderId": "CA-2017-109183", + "rowId": 7293, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-109183", + "rowId": 7293, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 7293, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-06-10T00:00:00.000Z, + "orderId": "CA-2017-112172", + "rowId": 7310, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-112172", + "rowId": 7310, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 7310, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-04-10T00:00:00.000Z, + "orderId": "CA-2017-135069", + "rowId": 7425, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-135069", + "rowId": 7425, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 7425, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-12-14T00:00:00.000Z, + "orderId": "CA-2017-151799", + "rowId": 7698, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-151799", + "rowId": 7698, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 7698, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-10-12T00:00:00.000Z, + "orderId": "CA-2017-150091", + "rowId": 8425, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-150091", + "rowId": 8425, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 8425, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-11-06T00:00:00.000Z, + "orderId": "US-2017-119319", + "rowId": 8621, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "US-2017-119319", + "rowId": 8621, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 8621, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-02-16T00:00:00.000Z, + "orderId": "CA-2017-163265", + "rowId": 8673, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-163265", + "rowId": 8673, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 8673, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-06-15T00:00:00.000Z, + "orderId": "CA-2017-119284", + "rowId": 8697, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-119284", + "rowId": 8697, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 8697, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-09-17T00:00:00.000Z, + "orderId": "CA-2017-126928", + "rowId": 8878, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-126928", + "rowId": 8878, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 8878, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-12-25T00:00:00.000Z, + "orderId": "CA-2017-105620", + "rowId": 8958, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-105620", + "rowId": 8958, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 8958, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-11-05T00:00:00.000Z, + "orderId": "CA-2017-102925", + "rowId": 9473, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-102925", + "rowId": 9473, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 9473, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-06-25T00:00:00.000Z, + "orderId": "CA-2017-116127", + "rowId": 9584, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-116127", + "rowId": 9584, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 9584, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-11-16T00:00:00.000Z, + "orderId": "CA-2017-160633", + "rowId": 9618, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-160633", + "rowId": 9618, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 9618, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": 2020-11-16T00:00:00.000Z, + "orderId": "CA-2017-160633", + "rowId": 9619, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": "CA-2017-160633", + "rowId": 9619, + }, + Object { + "SUM(a.cnt)": "1", + "orderDate": null, + "orderId": null, + "rowId": 9619, + }, + Object { + "SUM(a.cnt)": "44", + "orderDate": null, + "orderId": null, + "rowId": null, + }, +] +`; + +exports[`Queries with the @cubejs-backend/postgres-driver SQL API: Simple Rollup: simple_rollup 1`] = ` +Array [ + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-01-23T00:00:00.000Z, + "orderId": "CA-2017-145142", + "rowId": 523, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-145142", + "rowId": 523, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 523, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-01-01T00:00:00.000Z, + "orderId": "CA-2017-107503", + "rowId": 849, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-107503", + "rowId": 849, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 849, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-06-17T00:00:00.000Z, + "orderId": "CA-2017-118437", + "rowId": 1013, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-118437", + "rowId": 1013, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 1013, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-10-30T00:00:00.000Z, + "orderId": "CA-2017-139661", + "rowId": 1494, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-139661", + "rowId": 1494, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 1494, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-06-25T00:00:00.000Z, + "orderId": "CA-2017-133648", + "rowId": 1995, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-133648", + "rowId": 1995, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 1995, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-09-23T00:00:00.000Z, + "orderId": "CA-2017-138422", + "rowId": 2329, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-138422", + "rowId": 2329, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 2329, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-03-17T00:00:00.000Z, + "orderId": "CA-2017-140949", + "rowId": 2455, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-140949", + "rowId": 2455, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 2455, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-05-13T00:00:00.000Z, + "orderId": "CA-2017-149048", + "rowId": 2595, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-149048", + "rowId": 2595, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 2595, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-09-17T00:00:00.000Z, + "orderId": "CA-2017-112515", + "rowId": 2655, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-112515", + "rowId": 2655, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 2655, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-11-28T00:00:00.000Z, + "orderId": "CA-2017-123372", + "rowId": 2661, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-123372", + "rowId": 2661, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 2661, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-11-12T00:00:00.000Z, + "orderId": "CA-2017-134915", + "rowId": 2952, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-134915", + "rowId": 2952, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 2952, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-10-19T00:00:00.000Z, + "orderId": "CA-2017-131492", + "rowId": 3059, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-131492", + "rowId": 3059, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 3059, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-10-19T00:00:00.000Z, + "orderId": "CA-2017-131492", + "rowId": 3060, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-131492", + "rowId": 3060, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 3060, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-05-27T00:00:00.000Z, + "orderId": "US-2017-132297", + "rowId": 3083, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "US-2017-132297", + "rowId": 3083, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 3083, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-06-11T00:00:00.000Z, + "orderId": "CA-2017-102554", + "rowId": 3448, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-102554", + "rowId": 3448, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 3448, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-05-29T00:00:00.000Z, + "orderId": "CA-2017-144568", + "rowId": 3717, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-144568", + "rowId": 3717, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 3717, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-09-02T00:00:00.000Z, + "orderId": "CA-2017-123001", + "rowId": 3934, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-123001", + "rowId": 3934, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 3934, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-11-21T00:00:00.000Z, + "orderId": "CA-2017-100811", + "rowId": 4012, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-100811", + "rowId": 4012, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 4012, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-12-24T00:00:00.000Z, + "orderId": "CA-2017-124296", + "rowId": 4031, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-124296", + "rowId": 4031, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 4031, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-05-14T00:00:00.000Z, + "orderId": "CA-2017-115546", + "rowId": 4161, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-115546", + "rowId": 4161, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 4161, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-11-11T00:00:00.000Z, + "orderId": "CA-2017-120327", + "rowId": 4227, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-120327", + "rowId": 4227, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 4227, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-11-02T00:00:00.000Z, + "orderId": "CA-2017-143567", + "rowId": 4882, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-143567", + "rowId": 4882, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 4882, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-09-01T00:00:00.000Z, + "orderId": "CA-2017-145653", + "rowId": 5220, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-145653", + "rowId": 5220, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 5220, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-12-14T00:00:00.000Z, + "orderId": "CA-2017-147333", + "rowId": 5277, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-147333", + "rowId": 5277, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 5277, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-06-03T00:00:00.000Z, + "orderId": "CA-2017-145772", + "rowId": 6125, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-145772", + "rowId": 6125, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 6125, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-12-01T00:00:00.000Z, + "orderId": "CA-2017-145660", + "rowId": 6205, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-145660", + "rowId": 6205, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 6205, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-12-02T00:00:00.000Z, + "orderId": "CA-2017-102379", + "rowId": 6272, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-102379", + "rowId": 6272, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 6272, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-05-14T00:00:00.000Z, + "orderId": "US-2017-133361", + "rowId": 6459, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "US-2017-133361", + "rowId": 6459, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 6459, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-09-08T00:00:00.000Z, + "orderId": "US-2017-124779", + "rowId": 6651, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "US-2017-124779", + "rowId": 6651, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 6651, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-03-26T00:00:00.000Z, + "orderId": "US-2017-141677", + "rowId": 7174, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "US-2017-141677", + "rowId": 7174, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 7174, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-12-04T00:00:00.000Z, + "orderId": "CA-2017-109183", + "rowId": 7293, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-109183", + "rowId": 7293, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 7293, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-06-10T00:00:00.000Z, + "orderId": "CA-2017-112172", + "rowId": 7310, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-112172", + "rowId": 7310, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 7310, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-04-10T00:00:00.000Z, + "orderId": "CA-2017-135069", + "rowId": 7425, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-135069", + "rowId": 7425, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 7425, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-12-14T00:00:00.000Z, + "orderId": "CA-2017-151799", + "rowId": 7698, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-151799", + "rowId": 7698, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 7698, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-10-12T00:00:00.000Z, + "orderId": "CA-2017-150091", + "rowId": 8425, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-150091", + "rowId": 8425, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 8425, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-11-06T00:00:00.000Z, + "orderId": "US-2017-119319", + "rowId": 8621, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "US-2017-119319", + "rowId": 8621, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 8621, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-02-16T00:00:00.000Z, + "orderId": "CA-2017-163265", + "rowId": 8673, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-163265", + "rowId": 8673, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 8673, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-06-15T00:00:00.000Z, + "orderId": "CA-2017-119284", + "rowId": 8697, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-119284", + "rowId": 8697, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 8697, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-09-17T00:00:00.000Z, + "orderId": "CA-2017-126928", + "rowId": 8878, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-126928", + "rowId": 8878, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 8878, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-12-25T00:00:00.000Z, + "orderId": "CA-2017-105620", + "rowId": 8958, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-105620", + "rowId": 8958, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 8958, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-11-05T00:00:00.000Z, + "orderId": "CA-2017-102925", + "rowId": 9473, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-102925", + "rowId": 9473, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 9473, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-06-25T00:00:00.000Z, + "orderId": "CA-2017-116127", + "rowId": 9584, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-116127", + "rowId": 9584, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 9584, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-11-16T00:00:00.000Z, + "orderId": "CA-2017-160633", + "rowId": 9618, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-160633", + "rowId": 9618, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 9618, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": 2020-11-16T00:00:00.000Z, + "orderId": "CA-2017-160633", + "rowId": 9619, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": "CA-2017-160633", + "rowId": 9619, + }, + Object { + "SUM(ECommerce.count)": "1", + "orderDate": null, + "orderId": null, + "rowId": 9619, + }, + Object { + "SUM(ECommerce.count)": "44", + "orderDate": null, + "orderId": null, + "rowId": null, + }, +] +`; + exports[`Queries with the @cubejs-backend/postgres-driver SQL API: post-aggregate percentage of total: post_aggregate_percentage_of_total 1`] = ` Array [ Object { diff --git a/rust/cubesql/Cargo.lock b/rust/cubesql/Cargo.lock index a80494401fd8..ba008181ffcb 100644 --- a/rust/cubesql/Cargo.lock +++ b/rust/cubesql/Cargo.lock @@ -834,7 +834,7 @@ dependencies = [ [[package]] name = "cube-ext" version = "1.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=554dac236d586bda9e39ea9a82f4411787f51032#554dac236d586bda9e39ea9a82f4411787f51032" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=38c8946ecb2fff7948b57e2f7151655d041a5b39#38c8946ecb2fff7948b57e2f7151655d041a5b39" dependencies = [ "arrow", "chrono", @@ -968,7 +968,7 @@ dependencies = [ [[package]] name = "datafusion" version = "7.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=554dac236d586bda9e39ea9a82f4411787f51032#554dac236d586bda9e39ea9a82f4411787f51032" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=38c8946ecb2fff7948b57e2f7151655d041a5b39#38c8946ecb2fff7948b57e2f7151655d041a5b39" dependencies = [ "ahash 0.7.6", "arrow", @@ -1001,7 +1001,7 @@ dependencies = [ [[package]] name = "datafusion-common" version = "7.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=554dac236d586bda9e39ea9a82f4411787f51032#554dac236d586bda9e39ea9a82f4411787f51032" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=38c8946ecb2fff7948b57e2f7151655d041a5b39#38c8946ecb2fff7948b57e2f7151655d041a5b39" dependencies = [ "arrow", "ordered-float 2.10.0", @@ -1012,7 +1012,7 @@ dependencies = [ [[package]] name = "datafusion-data-access" version = "1.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=554dac236d586bda9e39ea9a82f4411787f51032#554dac236d586bda9e39ea9a82f4411787f51032" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=38c8946ecb2fff7948b57e2f7151655d041a5b39#38c8946ecb2fff7948b57e2f7151655d041a5b39" dependencies = [ "async-trait", "chrono", @@ -1025,7 +1025,7 @@ dependencies = [ [[package]] name = "datafusion-expr" version = "7.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=554dac236d586bda9e39ea9a82f4411787f51032#554dac236d586bda9e39ea9a82f4411787f51032" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=38c8946ecb2fff7948b57e2f7151655d041a5b39#38c8946ecb2fff7948b57e2f7151655d041a5b39" dependencies = [ "ahash 0.7.6", "arrow", @@ -1036,7 +1036,7 @@ dependencies = [ [[package]] name = "datafusion-physical-expr" version = "7.0.0" -source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=554dac236d586bda9e39ea9a82f4411787f51032#554dac236d586bda9e39ea9a82f4411787f51032" +source = "git+https://github.com/cube-js/arrow-datafusion.git?rev=38c8946ecb2fff7948b57e2f7151655d041a5b39#38c8946ecb2fff7948b57e2f7151655d041a5b39" dependencies = [ "ahash 0.7.6", "arrow", diff --git a/rust/cubesql/cubesql/Cargo.toml b/rust/cubesql/cubesql/Cargo.toml index c99e10cc970e..6c33807414cb 100644 --- a/rust/cubesql/cubesql/Cargo.toml +++ b/rust/cubesql/cubesql/Cargo.toml @@ -10,7 +10,7 @@ homepage = "https://cube.dev" [dependencies] arc-swap = "1" -datafusion = { git = 'https://github.com/cube-js/arrow-datafusion.git', rev = "554dac236d586bda9e39ea9a82f4411787f51032", default-features = false, features = ["regex_expressions", "unicode_expressions"] } +datafusion = { git = 'https://github.com/cube-js/arrow-datafusion.git', rev = "38c8946ecb2fff7948b57e2f7151655d041a5b39", default-features = false, features = ["regex_expressions", "unicode_expressions"] } anyhow = "1.0" thiserror = "1.0.50" cubeclient = { path = "../cubeclient" } diff --git a/rust/cubesql/cubesql/src/compile/engine/df/optimizers/utils.rs b/rust/cubesql/cubesql/src/compile/engine/df/optimizers/utils.rs index 9fd8f47ec233..459a7525b524 100644 --- a/rust/cubesql/cubesql/src/compile/engine/df/optimizers/utils.rs +++ b/rust/cubesql/cubesql/src/compile/engine/df/optimizers/utils.rs @@ -316,6 +316,7 @@ pub fn rewrite(expr: &Expr, map: &HashMap>) -> Result None, + Expr::GroupingSet(..) => None, Expr::InSubquery { expr, subquery, diff --git a/rust/cubesql/cubesql/src/compile/engine/df/wrapper.rs b/rust/cubesql/cubesql/src/compile/engine/df/wrapper.rs index 306c34439c13..275f67a168cb 100644 --- a/rust/cubesql/cubesql/src/compile/engine/df/wrapper.rs +++ b/rust/cubesql/cubesql/src/compile/engine/df/wrapper.rs @@ -1,7 +1,7 @@ use crate::{ compile::{ engine::df::scan::{CubeScanNode, DataType, MemberField, WrappedSelectNode}, - rewrite::WrappedSelectType, + rewrite::{extract_exprlist_from_groupping_set, WrappedSelectType}, }, config::ConfigObj, sql::AuthContextRef, @@ -16,8 +16,8 @@ use cubeclient::models::V1LoadRequestQuery; use datafusion::{ error::{DataFusionError, Result}, logical_plan::{ - plan::Extension, replace_col, Column, DFSchema, DFSchemaRef, Expr, LogicalPlan, - UserDefinedLogicalNode, + plan::Extension, replace_col, Column, DFSchema, DFSchemaRef, Expr, GroupingSet, + LogicalPlan, UserDefinedLogicalNode, }, physical_plan::{aggregates::AggregateFunction, functions::BuiltinScalarFunction}, scalar::ScalarValue, @@ -26,7 +26,7 @@ use itertools::Itertools; use regex::{Captures, Regex}; use serde_derive::*; use std::{ - any::Any, collections::HashMap, convert::TryInto, fmt, future::Future, pin::Pin, result, + any::Any, collections::HashMap, convert::TryInto, fmt, future::Future, iter, pin::Pin, result, sync::Arc, }; @@ -42,6 +42,64 @@ struct UngrouppedMemberDef { alias: String, cube_params: Vec, expr: String, + grouping_set: Option, +} + +#[derive(Clone, Serialize, Debug, PartialEq, Eq)] +pub enum GroupingSetType { + Rollup, + Cube, +} + +#[derive(Clone, Serialize, Debug, PartialEq, Eq)] +pub struct GroupingSetDesc { + pub group_type: GroupingSetType, + pub id: u64, + pub sub_id: Option, +} + +impl GroupingSetDesc { + pub fn new(group_type: GroupingSetType, id: u64) -> Self { + Self { + group_type, + id, + sub_id: None, + } + } +} + +fn extract_group_type_from_groupping_set( + exprs: &Vec, +) -> Result>> { + let mut result = Vec::new(); + let mut id = 0; + for expr in exprs { + match expr { + Expr::GroupingSet(groupping_set) => match groupping_set { + GroupingSet::Rollup(exprs) => { + result.extend( + iter::repeat(Some(GroupingSetDesc::new(GroupingSetType::Rollup, id))) + .take(exprs.len()), + ); + id += 1; + } + GroupingSet::Cube(exprs) => { + result.extend( + iter::repeat(Some(GroupingSetDesc::new(GroupingSetType::Cube, id))) + .take(exprs.len()), + ); + id += 1; + } + GroupingSet::GroupingSets(_) => { + return Err(DataFusionError::Internal(format!( + "SQL generation for GroupingSet is not supported" + ))) + } + }, + _ => result.push(None), + } + } + Ok(result) } impl SqlQuery { @@ -572,7 +630,7 @@ impl CubeScanWrapperNode { let (group_by, sql) = Self::generate_column_expr( plan.clone(), schema.clone(), - group_expr.clone(), + extract_exprlist_from_groupping_set(&group_expr), sql, generator.clone(), &column_remapping, @@ -583,6 +641,7 @@ impl CubeScanWrapperNode { subqueries_sql.clone(), ) .await?; + let group_descs = extract_group_type_from_groupping_set(&group_expr)?; let (aggregate, sql) = Self::generate_column_expr( plan.clone(), schema.clone(), @@ -673,10 +732,12 @@ impl CubeScanWrapperNode { load_request.dimensions = Some( group_by .iter() - .map(|m| { - Self::ungrouped_member_def( + .zip(group_descs.iter()) + .map(|(m, t)| { + Self::dimension_member_def( m, &ungrouped_scan_node.used_cubes, + t, ) }) .collect::>()?, @@ -792,6 +853,7 @@ impl CubeScanWrapperNode { sql.sql.to_string(), projection, group_by, + group_descs, aggregate, // TODO from_alias.unwrap_or("".to_string()), @@ -989,7 +1051,10 @@ impl CubeScanWrapperNode { Ok((aliased_columns, sql)) } - fn ungrouped_member_def(column: &AliasedColumn, used_cubes: &Vec) -> Result { + fn make_member_def( + column: &AliasedColumn, + used_cubes: &Vec, + ) -> Result { let res = UngrouppedMemberDef { cube_name: used_cubes .iter() @@ -1004,7 +1069,23 @@ impl CubeScanWrapperNode { alias: column.alias.clone(), cube_params: used_cubes.clone(), expr: column.expr.clone(), + grouping_set: None, }; + Ok(res) + } + + fn ungrouped_member_def(column: &AliasedColumn, used_cubes: &Vec) -> Result { + let res = Self::make_member_def(column, used_cubes)?; + Ok(serde_json::json!(res).to_string()) + } + + fn dimension_member_def( + column: &AliasedColumn, + used_cubes: &Vec, + grouping_type: &Option, + ) -> Result { + let mut res = Self::make_member_def(column, used_cubes)?; + res.grouping_set = grouping_type.clone(); Ok(serde_json::json!(res).to_string()) } @@ -1770,6 +1851,70 @@ impl CubeScanWrapperNode { sql_query, )) } + Expr::GroupingSet(grouping_set) => match grouping_set { + datafusion::logical_plan::GroupingSet::Rollup(exprs) => { + let mut sql_exprs = Vec::new(); + for expr in exprs { + let (sql, query) = Self::generate_sql_for_expr( + plan.clone(), + sql_query, + sql_generator.clone(), + expr, + ungrouped_scan_node.clone(), + subqueries.clone(), + ) + .await?; + sql_query = query; + sql_exprs.push(sql); + } + Ok(( + sql_generator + .get_sql_templates() + .rollup_expr(sql_exprs) + .map_err(|e| { + DataFusionError::Internal(format!( + "Can't generate SQL for rollup expression: {}", + e + )) + })?, + sql_query, + )) + } + datafusion::logical_plan::GroupingSet::Cube(exprs) => { + let mut sql_exprs = Vec::new(); + for expr in exprs { + let (sql, query) = Self::generate_sql_for_expr( + plan.clone(), + sql_query, + sql_generator.clone(), + expr, + ungrouped_scan_node.clone(), + subqueries.clone(), + ) + .await?; + sql_query = query; + sql_exprs.push(sql); + } + Ok(( + sql_generator + .get_sql_templates() + .cube_expr(sql_exprs) + .map_err(|e| { + DataFusionError::Internal(format!( + "Can't generate SQL for rollup expression: {}", + e + )) + })?, + sql_query, + )) + } + datafusion::logical_plan::GroupingSet::GroupingSets(_) => { + Err(DataFusionError::Internal(format!( + "SQL generation for GroupingSet is not supported" + ))) + } + }, + Expr::WindowFunction { fun, args, diff --git a/rust/cubesql/cubesql/src/compile/mod.rs b/rust/cubesql/cubesql/src/compile/mod.rs index 7ec81fc86dad..4661ff80b596 100644 --- a/rust/cubesql/cubesql/src/compile/mod.rs +++ b/rust/cubesql/cubesql/src/compile/mod.rs @@ -19940,6 +19940,158 @@ ORDER BY "source"."str0" ASC let _physical_plan = query_plan.as_physical_plan().await.unwrap(); } + #[tokio::test] + async fn test_wrapper_group_by_rollup() { + if !Rewriter::sql_push_down_enabled() { + return; + } + init_logger(); + + let query_plan = convert_select_to_query_plan( + "SELECT customer_gender, notes, AVG(avgPrice) mp FROM KibanaSampleDataEcommerce a GROUP BY 1, ROLLUP(2)" + .to_string(), + DatabaseProtocol::PostgreSQL, + ) + .await; + + let logical_plan = query_plan.as_logical_plan(); + let sql = logical_plan + .find_cube_scan_wrapper() + .wrapped_sql + .unwrap() + .sql; + assert!(sql.contains("Rollup")); + + let _physical_plan = query_plan.as_physical_plan().await.unwrap(); + } + + #[tokio::test] + async fn test_wrapper_group_by_rollup_nested() { + if !Rewriter::sql_push_down_enabled() { + return; + } + init_logger(); + + let query_plan = convert_select_to_query_plan( + "SELECT customer_gender, notes, avg(mp) from (SELECT customer_gender, notes, avg(avgPrice) mp FROM KibanaSampleDataEcommerce a GROUP BY 1, 2) b GROUP BY ROLLUP(1, 2)" + .to_string(), + DatabaseProtocol::PostgreSQL, + ) + .await; + + let logical_plan = query_plan.as_logical_plan(); + let sql = logical_plan + .find_cube_scan_wrapper() + .wrapped_sql + .unwrap() + .sql; + assert!(sql.contains("ROLLUP(1, 2)")); + + let _physical_plan = query_plan.as_physical_plan().await.unwrap(); + } + + #[tokio::test] + async fn test_wrapper_group_by_rollup_nested_complex() { + if !Rewriter::sql_push_down_enabled() { + return; + } + init_logger(); + + let query_plan = convert_select_to_query_plan( + "SELECT customer_gender, notes, order_date, last_mod, avg(mp) from \ + (SELECT customer_gender, notes, order_date, last_mod, avg(avgPrice) mp FROM KibanaSampleDataEcommerce a GROUP BY 1, 2, 3, 4) b \ + GROUP BY ROLLUP(1), ROLLUP(2), 3, CUBE(4)" + .to_string(), + DatabaseProtocol::PostgreSQL, + ) + .await; + + let logical_plan = query_plan.as_logical_plan(); + let sql = logical_plan + .find_cube_scan_wrapper() + .wrapped_sql + .unwrap() + .sql; + assert!(sql.contains("ROLLUP(1), ROLLUP(2), 3, CUBE(4)")); + + let _physical_plan = query_plan.as_physical_plan().await.unwrap(); + } + + #[tokio::test] + async fn test_wrapper_group_by_rollup_placeholders() { + if !Rewriter::sql_push_down_enabled() { + return; + } + init_logger(); + + let query_plan = convert_select_to_query_plan( + "SELECT customer_gender, notes, AVG(avgPrice) mp FROM KibanaSampleDataEcommerce a GROUP BY ROLLUP(1, 2)" + .to_string(), + DatabaseProtocol::PostgreSQL, + ) + .await; + + let logical_plan = query_plan.as_logical_plan(); + let sql = logical_plan + .find_cube_scan_wrapper() + .wrapped_sql + .unwrap() + .sql; + assert!(sql.contains("Rollup")); + + let _physical_plan = query_plan.as_physical_plan().await.unwrap(); + } + + #[tokio::test] + async fn test_wrapper_group_by_cube() { + if !Rewriter::sql_push_down_enabled() { + return; + } + init_logger(); + + let query_plan = convert_select_to_query_plan( + "SELECT customer_gender, notes, AVG(avgPrice) mp FROM KibanaSampleDataEcommerce a GROUP BY CUBE(customer_gender, notes)" + .to_string(), + DatabaseProtocol::PostgreSQL, + ) + .await; + + let logical_plan = query_plan.as_logical_plan(); + let sql = logical_plan + .find_cube_scan_wrapper() + .wrapped_sql + .unwrap() + .sql; + assert!(sql.contains("Cube")); + + let _physical_plan = query_plan.as_physical_plan().await.unwrap(); + } + + #[tokio::test] + async fn test_wrapper_group_by_rollup_complex() { + if !Rewriter::sql_push_down_enabled() { + return; + } + init_logger(); + + let query_plan = convert_select_to_query_plan( + "SELECT customer_gender, notes, has_subscription, AVG(avgPrice) mp FROM KibanaSampleDataEcommerce a GROUP BY ROLLUP(customer_gender, notes), has_subscription" + .to_string(), + DatabaseProtocol::PostgreSQL, + ) + .await; + + let logical_plan = query_plan.as_logical_plan(); + let sql = logical_plan + .find_cube_scan_wrapper() + .wrapped_sql + .unwrap() + .sql; + assert!(sql.contains("Rollup")); + + let _physical_plan = query_plan.as_physical_plan().await.unwrap(); + } + #[tokio::test] async fn test_simple_subquery_wrapper_projection_empty_source() { if !Rewriter::sql_push_down_enabled() { diff --git a/rust/cubesql/cubesql/src/compile/rewrite/analysis.rs b/rust/cubesql/cubesql/src/compile/rewrite/analysis.rs index 0dff087f02c3..8bd9c26090b7 100644 --- a/rust/cubesql/cubesql/src/compile/rewrite/analysis.rs +++ b/rust/cubesql/cubesql/src/compile/rewrite/analysis.rs @@ -874,6 +874,10 @@ impl LogicalPlanAnalysis { push_referenced_columns(params[1], &mut vec)?; Some(vec) } + LogicalPlanLanguage::GroupingSetExpr(params) => { + push_referenced_columns(params[0], &mut vec)?; + Some(vec) + } LogicalPlanLanguage::LiteralExpr(_) => Some(vec), LogicalPlanLanguage::QueryParam(_) => Some(vec), LogicalPlanLanguage::SortExpr(params) => { @@ -902,6 +906,14 @@ impl LogicalPlanAnalysis { Some(vec) } + + LogicalPlanLanguage::GroupingSetExprMembers(params) => { + for p in params.iter() { + vec.extend(referenced_columns(*p)?.into_iter()); + } + + Some(vec) + } _ => None, } } diff --git a/rust/cubesql/cubesql/src/compile/rewrite/converter.rs b/rust/cubesql/cubesql/src/compile/rewrite/converter.rs index f3a02a1a04f2..3eaf637447ad 100644 --- a/rust/cubesql/cubesql/src/compile/rewrite/converter.rs +++ b/rust/cubesql/cubesql/src/compile/rewrite/converter.rs @@ -8,27 +8,27 @@ use crate::{ provider::CubeContext, }, rewrite::{ - analysis::LogicalPlanAnalysis, rewriter::Rewriter, AggregateFunctionExprDistinct, - AggregateFunctionExprFun, AggregateSplit, AggregateUDFExprFun, AliasExprAlias, - AnyExprAll, AnyExprOp, BetweenExprNegated, BinaryExprOp, CastExprDataType, - ChangeUserMemberValue, ColumnExprColumn, CubeScanAliasToCube, CubeScanLimit, - CubeScanOffset, CubeScanUngrouped, CubeScanWrapped, DimensionName, - EmptyRelationDerivedSourceTableName, EmptyRelationIsWrappable, + analysis::LogicalPlanAnalysis, extract_exprlist_from_groupping_set, rewriter::Rewriter, + AggregateFunctionExprDistinct, AggregateFunctionExprFun, AggregateSplit, + AggregateUDFExprFun, AliasExprAlias, AnyExprAll, AnyExprOp, BetweenExprNegated, + BinaryExprOp, CastExprDataType, ChangeUserMemberValue, ColumnExprColumn, + CubeScanAliasToCube, CubeScanLimit, CubeScanOffset, CubeScanUngrouped, CubeScanWrapped, + DimensionName, EmptyRelationDerivedSourceTableName, EmptyRelationIsWrappable, EmptyRelationProduceOneRow, FilterMemberMember, FilterMemberOp, FilterMemberValues, - FilterOpOp, InListExprNegated, InSubqueryExprNegated, JoinJoinConstraint, JoinJoinType, - JoinLeftOn, JoinRightOn, LikeExprEscapeChar, LikeExprLikeType, LikeExprNegated, - LikeType, LimitFetch, LimitSkip, LiteralExprValue, LiteralMemberRelation, - LiteralMemberValue, LogicalPlanLanguage, MeasureName, MemberErrorError, OrderAsc, - OrderMember, OuterColumnExprColumn, OuterColumnExprDataType, ProjectionAlias, - ProjectionSplit, QueryParamIndex, ScalarFunctionExprFun, ScalarUDFExprFun, - ScalarVariableExprDataType, ScalarVariableExprVariable, SegmentMemberMember, - SortExprAsc, SortExprNullsFirst, SubqueryTypes, TableScanFetch, TableScanProjection, - TableScanSourceTableName, TableScanTableName, TableUDFExprFun, TimeDimensionDateRange, - TimeDimensionGranularity, TimeDimensionName, TryCastExprDataType, UnionAlias, - WindowFunctionExprFun, WindowFunctionExprWindowFrame, WrappedSelectAlias, - WrappedSelectDistinct, WrappedSelectJoinJoinType, WrappedSelectLimit, - WrappedSelectOffset, WrappedSelectSelectType, WrappedSelectType, - WrappedSelectUngrouped, + FilterOpOp, GroupingSetExprType, GroupingSetType, InListExprNegated, + InSubqueryExprNegated, JoinJoinConstraint, JoinJoinType, JoinLeftOn, JoinRightOn, + LikeExprEscapeChar, LikeExprLikeType, LikeExprNegated, LikeType, LimitFetch, LimitSkip, + LiteralExprValue, LiteralMemberRelation, LiteralMemberValue, LogicalPlanLanguage, + MeasureName, MemberErrorError, OrderAsc, OrderMember, OuterColumnExprColumn, + OuterColumnExprDataType, ProjectionAlias, ProjectionSplit, QueryParamIndex, + ScalarFunctionExprFun, ScalarUDFExprFun, ScalarVariableExprDataType, + ScalarVariableExprVariable, SegmentMemberMember, SortExprAsc, SortExprNullsFirst, + SubqueryTypes, TableScanFetch, TableScanProjection, TableScanSourceTableName, + TableScanTableName, TableUDFExprFun, TimeDimensionDateRange, TimeDimensionGranularity, + TimeDimensionName, TryCastExprDataType, UnionAlias, WindowFunctionExprFun, + WindowFunctionExprWindowFrame, WrappedSelectAlias, WrappedSelectDistinct, + WrappedSelectJoinJoinType, WrappedSelectLimit, WrappedSelectOffset, + WrappedSelectSelectType, WrappedSelectType, WrappedSelectUngrouped, }, }, sql::AuthContextRef, @@ -43,10 +43,11 @@ use datafusion::{ catalog::TableReference, error::DataFusionError, logical_plan::{ - build_join_schema, build_table_udf_schema, exprlist_to_fields, normalize_cols, + build_join_schema, build_table_udf_schema, exprlist_to_fields, + exprlist_to_fields_from_schema, normalize_cols, plan::{Aggregate, Extension, Filter, Join, Projection, Sort, TableUDFs, Window}, replace_col_to_expr, Column, CrossJoin, DFField, DFSchema, DFSchemaRef, Distinct, - EmptyRelation, Expr, ExprRewritable, ExprRewriter, Like, Limit, LogicalPlan, + EmptyRelation, Expr, ExprRewritable, ExprRewriter, GroupingSet, Like, Limit, LogicalPlan, LogicalPlanBuilder, TableScan, Union, }, physical_plan::planner::DefaultPhysicalPlanner, @@ -522,6 +523,33 @@ impl LogicalPlanToLanguageConverter { let key = Self::add_expr_replace_params(graph, key, query_params, flat_list)?; graph.add(LogicalPlanLanguage::GetIndexedFieldExpr([expr, key])) } + Expr::GroupingSet(groupping_set) => match groupping_set { + GroupingSet::Rollup(members) => { + let members = add_expr_flat_list_node!( + graph, + members, + query_params, + GroupingSetExprMembers, + flat_list + ); + let expr_type = + add_expr_data_node!(graph, GroupingSetType::Rollup, GroupingSetExprType); + graph.add(LogicalPlanLanguage::GroupingSetExpr([members, expr_type])) + } + GroupingSet::Cube(members) => { + let members = add_binary_expr_list_node!( + graph, + members, + query_params, + GroupingSetExprMembers, + false + ); + let expr_type = + add_expr_data_node!(graph, GroupingSetType::Cube, GroupingSetExprType); + graph.add(LogicalPlanLanguage::GroupingSetExpr([members, expr_type])) + } + _ => unimplemented!("Unsupported grouping set type: {:?}", expr), + }, // TODO: Support all _ => unimplemented!("Unsupported node type: {:?}", expr), }) @@ -1200,6 +1228,16 @@ pub fn node_to_expr( negated, } } + LogicalPlanLanguage::GroupingSetExpr(params) => { + let members = + match_expr_list_node!(node_by_id, to_expr, params[0], GroupingSetExprMembers); + let expr_type = match_data_node!(node_by_id, params[1], GroupingSetExprType); + + match expr_type { + GroupingSetType::Rollup => Expr::GroupingSet(GroupingSet::Rollup(members)), + GroupingSetType::Cube => Expr::GroupingSet(GroupingSet::Cube(members)), + } + } x => panic!("Unexpected expression node: {:?}", x), }) } @@ -1237,7 +1275,7 @@ impl LanguageToLogicalPlanConverter { replace_qualified_col_with_flat_name_if_missing(expr, input.schema(), true)?; let alias = match_data_node!(node_by_id, params[2], ProjectionAlias); let input_schema = DFSchema::new_with_metadata( - exprlist_to_fields(&expr, input.schema())?, + exprlist_to_fields(&expr, &input)?, HashMap::new(), )?; let schema = match alias { @@ -1268,7 +1306,7 @@ impl LanguageToLogicalPlanConverter { true, )?; let mut window_fields: Vec = - exprlist_to_fields(window_expr.iter(), input.schema())?; + exprlist_to_fields(window_expr.iter(), &input)?; window_fields.extend_from_slice(input.schema().fields()); LogicalPlan::Window(Window { @@ -1301,7 +1339,7 @@ impl LanguageToLogicalPlanConverter { )?; let all_expr = group_expr.iter().chain(aggr_expr.iter()); let schema = Arc::new(DFSchema::new_with_metadata( - exprlist_to_fields(all_expr, input.schema())?, + exprlist_to_fields(all_expr, &input)?, HashMap::new(), )?); @@ -2136,7 +2174,11 @@ impl LanguageToLogicalPlanConverter { let all_expr_without_window = match select_type { WrappedSelectType::Projection => projection_expr.clone(), WrappedSelectType::Aggregate => { - group_expr.iter().chain(aggr_expr.iter()).cloned().collect() + extract_exprlist_from_groupping_set(&group_expr) + .iter() + .chain(aggr_expr.iter()) + .cloned() + .collect() } }; // TODO support asterisk query? @@ -2156,8 +2198,10 @@ impl LanguageToLogicalPlanConverter { } let schema_with_subqueries = from.schema().join(&subqueries_schema)?; - let without_window_fields = - exprlist_to_fields(all_expr_without_window.iter(), &schema_with_subqueries)?; + let without_window_fields = exprlist_to_fields_from_schema( + all_expr_without_window.iter(), + &schema_with_subqueries, + )?; let replace_map = all_expr_without_window .iter() .zip(without_window_fields.iter()) @@ -2216,7 +2260,7 @@ impl LanguageToLogicalPlanConverter { without_window_fields .into_iter() .chain( - exprlist_to_fields( + exprlist_to_fields_from_schema( window_expr_rebased.iter(), &schema_with_subqueries, )? diff --git a/rust/cubesql/cubesql/src/compile/rewrite/cost.rs b/rust/cubesql/cubesql/src/compile/rewrite/cost.rs index cf1c2bbd321b..bac35efd19b1 100644 --- a/rust/cubesql/cubesql/src/compile/rewrite/cost.rs +++ b/rust/cubesql/cubesql/src/compile/rewrite/cost.rs @@ -43,6 +43,7 @@ pub struct CubePlanCost { member_errors: i64, // TODO if pre-aggregation can be used for window functions, then it'd be suboptimal non_pushed_down_window: i64, + non_pushed_down_grouping_sets: i64, ungrouped_aggregates: usize, wrapper_nodes: i64, wrapped_select_ungrouped_scan: usize, @@ -127,6 +128,8 @@ impl CubePlanCost { }) + other.non_detected_cube_scans, filter_members: self.filter_members + other.filter_members, non_pushed_down_window: self.non_pushed_down_window + other.non_pushed_down_window, + non_pushed_down_grouping_sets: self.non_pushed_down_grouping_sets + + other.non_pushed_down_grouping_sets, member_errors: self.member_errors + other.member_errors, cube_members: self.cube_members + other.cube_members, errors: self.errors + other.errors, @@ -165,6 +168,11 @@ impl CubePlanCost { filter_members: self.filter_members, member_errors: self.member_errors, non_pushed_down_window: self.non_pushed_down_window, + non_pushed_down_grouping_sets: match state { + CubePlanState::Wrapped => 0, + CubePlanState::Unwrapped(_) => self.non_pushed_down_grouping_sets, + CubePlanState::Wrapper => 0, + }, cube_members: self.cube_members, errors: self.errors, structure_points: self.structure_points, @@ -253,6 +261,11 @@ impl CostFunction for BestCubePlan { _ => 0, }; + let non_pushed_down_grouping_sets = match enode { + LogicalPlanLanguage::GroupingSetExpr(_) => 1, + _ => 0, + }; + let ast_size_inside_wrapper = match enode { LogicalPlanLanguage::WrappedSelect(_) => 1, _ => 0, @@ -395,6 +408,7 @@ impl CostFunction for BestCubePlan { non_detected_cube_scans, member_errors, non_pushed_down_window, + non_pushed_down_grouping_sets, cube_members, errors: this_errors, time_dimensions_used_as_dimensions, diff --git a/rust/cubesql/cubesql/src/compile/rewrite/language.rs b/rust/cubesql/cubesql/src/compile/rewrite/language.rs index c3e3ad1d1df4..1bae74089193 100644 --- a/rust/cubesql/cubesql/src/compile/rewrite/language.rs +++ b/rust/cubesql/cubesql/src/compile/rewrite/language.rs @@ -469,6 +469,15 @@ macro_rules! variant_field_struct { ); }; + ($variant:ident, $var_field:ident, GroupingSetType) => { + $crate::variant_field_struct!( + @enum_struct $variant, $var_field, { GroupingSetType } -> { + GroupingSetType::Rollup => "Rollup", + GroupingSetType::Cube => "Cube", + } + ); + }; + (@enum_struct $variant:ident, $var_field:ident, { $var_field_type:ty } -> {$($variant_type:ty => $name:literal,)*}) => { paste::item! { #[derive(Debug, Clone)] diff --git a/rust/cubesql/cubesql/src/compile/rewrite/mod.rs b/rust/cubesql/cubesql/src/compile/rewrite/mod.rs index 10bfb49ca013..66859fa07361 100644 --- a/rust/cubesql/cubesql/src/compile/rewrite/mod.rs +++ b/rust/cubesql/cubesql/src/compile/rewrite/mod.rs @@ -14,7 +14,7 @@ use datafusion::{ error::DataFusionError, logical_plan::{ plan::SubqueryType, window_frames::WindowFrame, Column, DFSchema, Expr, ExprRewritable, - ExprRewriter, JoinConstraint, JoinType, Operator, RewriteRecursion, + ExprRewriter, GroupingSet, JoinConstraint, JoinType, Operator, RewriteRecursion, }, physical_plan::{ aggregates::AggregateFunction, functions::BuiltinScalarFunction, windows::WindowFunction, @@ -62,6 +62,12 @@ pub enum WrappedSelectType { Aggregate, } +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Hash)] +pub enum GroupingSetType { + Rollup, + Cube, +} + crate::plan_to_language! { pub enum LogicalPlanLanguage { Projection { @@ -476,6 +482,10 @@ crate::plan_to_language! { members: Vec, meta: Option>, }, + GroupingSetExpr { + members: Vec, + type: GroupingSetType, + }, QueryParam { index: usize, }, @@ -736,6 +746,7 @@ pub enum ListType { AggregateGroupExpr, AggregateAggrExpr, ScalarFunctionExprArgs, + GroupingSetExprMembers, WrappedSelectProjectionExpr, WrappedSelectGroupExpr, WrappedSelectAggrExpr, @@ -750,6 +761,7 @@ impl ListType { Self::WindowWindowExpr => window_window_expr_empty_tail(), Self::AggregateGroupExpr => aggr_group_expr_empty_tail(), Self::AggregateAggrExpr => aggr_aggr_expr_empty_tail(), + Self::GroupingSetExprMembers => grouping_set_expr_members_empty_tail(), Self::ScalarFunctionExprArgs => scalar_fun_expr_args_empty_tail(), Self::WrappedSelectProjectionExpr => wrapped_select_projection_expr_empty_tail(), Self::WrappedSelectGroupExpr => wrapped_select_group_expr_empty_tail(), @@ -818,6 +830,9 @@ impl ListNodeSearcher { ListType::WrappedSelectProjectionExpr => { matches!(node, LogicalPlanLanguage::WrappedSelectProjectionExpr(_)) } + ListType::GroupingSetExprMembers => { + matches!(node, LogicalPlanLanguage::GroupingSetExprMembers(_)) + } ListType::WrappedSelectGroupExpr => { matches!(node, LogicalPlanLanguage::WrappedSelectGroupExpr(_)) } @@ -925,6 +940,7 @@ impl ListNodeApplierList { ListType::WrappedSelectProjectionExpr => { LogicalPlanLanguage::WrappedSelectProjectionExpr(list) } + ListType::GroupingSetExprMembers => LogicalPlanLanguage::GroupingSetExprMembers(list), ListType::WrappedSelectGroupExpr => LogicalPlanLanguage::WrappedSelectGroupExpr(list), ListType::WrappedSelectAggrExpr => LogicalPlanLanguage::WrappedSelectAggrExpr(list), ListType::WrappedSelectWindowExpr => LogicalPlanLanguage::WrappedSelectWindowExpr(list), @@ -1398,6 +1414,14 @@ fn aggr_aggr_expr_empty_tail() -> String { aggr_aggr_expr(Vec::::new()) } +fn grouping_set_expr(members: impl Display, expr_type: impl Display) -> String { + format!("(GroupingSetExpr {} {})", members, expr_type) +} + +fn grouping_set_expr_members_empty_tail() -> String { + format!("GroupingSetExprMembers") +} + fn aggr_aggr_expr_legacy(left: impl Display, right: impl Display) -> String { format!("(AggregateAggrExpr {} {})", left, right) } @@ -2152,3 +2176,20 @@ pub fn add_root_original_expr_alias( false } } + +pub fn extract_exprlist_from_groupping_set(exprs: &Vec) -> Vec { + let mut result = Vec::new(); + for expr in exprs { + match expr { + Expr::GroupingSet(groupping_set) => match groupping_set { + GroupingSet::Rollup(exprs) => result.extend(exprs.iter().cloned()), + GroupingSet::Cube(exprs) => result.extend(exprs.iter().cloned()), + GroupingSet::GroupingSets(sets) => { + result.extend(sets.iter().flat_map(|s| s.iter().cloned())) + } + }, + _ => result.push(expr.clone()), + } + } + result +} diff --git a/rust/cubesql/cubesql/src/compile/rewrite/rules/wrapper/aggregate.rs b/rust/cubesql/cubesql/src/compile/rewrite/rules/wrapper/aggregate.rs index 07a1d95e5292..85b8f45879a4 100644 --- a/rust/cubesql/cubesql/src/compile/rewrite/rules/wrapper/aggregate.rs +++ b/rust/cubesql/cubesql/src/compile/rewrite/rules/wrapper/aggregate.rs @@ -2,7 +2,8 @@ use crate::{ compile::rewrite::{ aggregate, analysis::LogicalPlanAnalysis, - column_name_to_member_vec, cube_scan_wrapper, original_expr_name, + column_name_to_member_vec, cube_scan_wrapper, grouping_set_expr, original_expr_name, + rewrite, rules::{members::MemberRules, wrapper::WrapperRules}, subquery, transforming_chain_rewrite, transforming_rewrite, wrapped_select, wrapped_select_filter_expr_empty_tail, wrapped_select_having_expr_empty_tail, @@ -10,7 +11,8 @@ use crate::{ wrapped_select_projection_expr_empty_tail, wrapped_select_subqueries_empty_tail, wrapped_select_window_expr_empty_tail, wrapper_pullup_replacer, wrapper_pushdown_replacer, AggregateFunctionExprDistinct, AggregateFunctionExprFun, AliasExprAlias, ColumnExprColumn, - ListType, LogicalPlanLanguage, WrappedSelectUngrouped, WrapperPullupReplacerUngrouped, + ListType, LogicalPlanLanguage, WrappedSelectUngrouped, WrapperPullupReplacerAliasToCube, + WrapperPullupReplacerUngrouped, }, transport::V1CubeMetaMeasureExt, var, var_iter, @@ -23,100 +25,143 @@ impl WrapperRules { &self, rules: &mut Vec>, ) { - rules.extend(vec![transforming_rewrite( - "wrapper-push-down-aggregate-to-cube-scan", - aggregate( + rules.extend(vec![ + transforming_rewrite( + "wrapper-push-down-aggregate-to-cube-scan", + aggregate( + cube_scan_wrapper( + wrapper_pullup_replacer( + "?cube_scan_input", + "?alias_to_cube", + "?ungrouped", + "?in_projection", + "?cube_members", + ), + "CubeScanWrapperFinalized:false", + ), + "?group_expr", + "?aggr_expr", + "AggregateSplit:false", + ), cube_scan_wrapper( - wrapper_pullup_replacer( - "?cube_scan_input", - "?alias_to_cube", - "?ungrouped", - "?in_projection", - "?cube_members", + wrapped_select( + "WrappedSelectSelectType:Aggregate", + wrapper_pullup_replacer( + wrapped_select_projection_expr_empty_tail(), + "?alias_to_cube", + "?ungrouped", + "WrapperPullupReplacerInProjection:false", + "?cube_members", + ), + wrapper_pullup_replacer( + wrapped_select_subqueries_empty_tail(), + "?alias_to_cube", + "?ungrouped", + "WrapperPullupReplacerInProjection:false", + "?cube_members", + ), + wrapper_pushdown_replacer( + "?group_expr", + "?alias_to_cube", + "?ungrouped", + "WrapperPullupReplacerInProjection:false", + "?cube_members", + ), + wrapper_pushdown_replacer( + "?aggr_expr", + "?alias_to_cube", + "?ungrouped", + "WrapperPullupReplacerInProjection:false", + "?cube_members", + ), + wrapper_pullup_replacer( + wrapped_select_window_expr_empty_tail(), + "?alias_to_cube", + "?ungrouped", + "WrapperPullupReplacerInProjection:false", + "?cube_members", + ), + wrapper_pullup_replacer( + "?cube_scan_input", + "?alias_to_cube", + "?ungrouped", + "WrapperPullupReplacerInProjection:false", + "?cube_members", + ), + wrapped_select_joins_empty_tail(), + wrapper_pullup_replacer( + wrapped_select_filter_expr_empty_tail(), + "?alias_to_cube", + "?ungrouped", + "WrapperPullupReplacerInProjection:false", + "?cube_members", + ), + wrapped_select_having_expr_empty_tail(), + "WrappedSelectLimit:None", + "WrappedSelectOffset:None", + wrapper_pullup_replacer( + wrapped_select_order_expr_empty_tail(), + "?alias_to_cube", + "?ungrouped", + "WrapperPullupReplacerInProjection:false", + "?cube_members", + ), + "WrappedSelectAlias:None", + "WrappedSelectDistinct:false", + "?select_ungrouped", + "WrappedSelectUngroupedScan:false", ), "CubeScanWrapperFinalized:false", ), - "?group_expr", - "?aggr_expr", - "AggregateSplit:false", + self.transform_aggregate( + "?group_expr", + "?aggr_expr", + "?ungrouped", + "?select_ungrouped", + ), ), - cube_scan_wrapper( - wrapped_select( - "WrappedSelectSelectType:Aggregate", - wrapper_pullup_replacer( - wrapped_select_projection_expr_empty_tail(), - "?alias_to_cube", - "?ungrouped", - "WrapperPullupReplacerInProjection:false", - "?cube_members", - ), - wrapper_pullup_replacer( - wrapped_select_subqueries_empty_tail(), - "?alias_to_cube", - "?ungrouped", - "WrapperPullupReplacerInProjection:false", - "?cube_members", - ), - wrapper_pushdown_replacer( - "?group_expr", - "?alias_to_cube", - "?ungrouped", - "WrapperPullupReplacerInProjection:false", - "?cube_members", - ), + transforming_rewrite( + "wrapper-groupping-set-push-down", + wrapper_pushdown_replacer( + grouping_set_expr("?rollout_members", "?type"), + "?alias_to_cube", + "?ungrouped", + "WrapperPullupReplacerInProjection:false", + "?cube_members", + ), + grouping_set_expr( wrapper_pushdown_replacer( - "?aggr_expr", + "?rollout_members", "?alias_to_cube", "?ungrouped", "WrapperPullupReplacerInProjection:false", "?cube_members", ), + "?type", + ), + self.check_rollup_allowed("?alias_to_cube"), + ), + rewrite( + "wrapper-groupping-set-pull-up", + grouping_set_expr( wrapper_pullup_replacer( - wrapped_select_window_expr_empty_tail(), - "?alias_to_cube", - "?ungrouped", - "WrapperPullupReplacerInProjection:false", - "?cube_members", - ), - wrapper_pullup_replacer( - "?cube_scan_input", - "?alias_to_cube", - "?ungrouped", - "WrapperPullupReplacerInProjection:false", - "?cube_members", - ), - wrapped_select_joins_empty_tail(), - wrapper_pullup_replacer( - wrapped_select_filter_expr_empty_tail(), - "?alias_to_cube", - "?ungrouped", - "WrapperPullupReplacerInProjection:false", - "?cube_members", - ), - wrapped_select_having_expr_empty_tail(), - "WrappedSelectLimit:None", - "WrappedSelectOffset:None", - wrapper_pullup_replacer( - wrapped_select_order_expr_empty_tail(), + "?rollout_members", "?alias_to_cube", "?ungrouped", "WrapperPullupReplacerInProjection:false", "?cube_members", ), - "WrappedSelectAlias:None", - "WrappedSelectDistinct:false", - "?select_ungrouped", - "WrappedSelectUngroupedScan:false", + "?type", + ), + wrapper_pullup_replacer( + grouping_set_expr("?rollout_members", "?type"), + "?alias_to_cube", + "?ungrouped", + "WrapperPullupReplacerInProjection:false", + "?cube_members", ), - "CubeScanWrapperFinalized:false", - ), - self.transform_aggregate( - "?group_expr", - "?aggr_expr", - "?ungrouped", - "?select_ungrouped", ), - )]); + ]); // TODO add flag to disable dimension rules MemberRules::measure_rewrites( @@ -172,6 +217,12 @@ impl WrapperRules { ListType::AggregateGroupExpr, ListType::WrappedSelectGroupExpr, ); + Self::flat_list_pushdown_pullup_rules( + rules, + "wrapper-grouping-set-members", + ListType::GroupingSetExprMembers, + ListType::GroupingSetExprMembers, + ); } else { Self::list_pushdown_pullup_rules( rules, @@ -186,6 +237,12 @@ impl WrapperRules { "AggregateGroupExpr", "WrappedSelectGroupExpr", ); + Self::list_pushdown_pullup_rules( + rules, + "wrapper-grouping-set-members", + "GroupingSetExprMembers", + "GroupingSetExprMembers", + ); } } @@ -380,6 +437,33 @@ impl WrapperRules { false } + fn check_rollup_allowed( + &self, + alias_to_cube_var: &'static str, + ) -> impl Fn(&mut EGraph, &mut Subst) -> bool { + let alias_to_cube_var = var!(alias_to_cube_var); + let meta = self.meta_context.clone(); + move |egraph, subst| { + for alias_to_cube in var_iter!( + egraph[subst[alias_to_cube_var]], + WrapperPullupReplacerAliasToCube + ) + .cloned() + { + if let Some(sql_generator) = meta.sql_generator_by_alias_to_cube(&alias_to_cube) { + if sql_generator + .get_sql_templates() + .templates + .contains_key("expressions/rollup") + { + return true; + } + } + } + false + } + } + fn pushdown_measure( &self, original_expr_var: &'static str, diff --git a/rust/cubesql/cubesql/src/compile/test/mod.rs b/rust/cubesql/cubesql/src/compile/test/mod.rs index 1b8f4b98abd9..3463e328b869 100644 --- a/rust/cubesql/cubesql/src/compile/test/mod.rs +++ b/rust/cubesql/cubesql/src/compile/test/mod.rs @@ -353,11 +353,15 @@ FROM ( {{ from | indent(2) }} ) AS {{ from_alias }} {% endif %} {% if filter %} WHERE {{ filter }}{% endif %}{% if group_by %} -GROUP BY {{ group_by | map(attribute='index') | join(', ') }}{% endif %}{% if order_by %} +GROUP BY {{ group_by }}{% endif %}{% if order_by %} ORDER BY {{ order_by | map(attribute='expr') | join(', ') }}{% endif %}{% if limit %} LIMIT {{ limit }}{% endif %}{% if offset %} OFFSET {{ offset }}{% endif %}"#.to_string(), ), + ( + "statements/group_by_exprs".to_string(), + "{{ group_by | map(attribute='index') | join(', ') }}".to_string(), + ), ( "expressions/column_aliased".to_string(), "{{expr}} {{quoted_alias}}".to_string(), @@ -373,6 +377,8 @@ OFFSET {{ offset }}{% endif %}"#.to_string(), ("expressions/in_list".to_string(), "{{ expr }} {% if negated %}NOT {% endif %}IN ({{ in_exprs_concat }})".to_string()), ("expressions/subquery".to_string(), "({{ expr }})".to_string()), ("expressions/in_subquery".to_string(), "{{ expr }} {% if negated %}NOT {% endif %}IN {{ subquery_expr }}".to_string()), + ("expressions/rollup".to_string(), "ROLLUP({{ exprs_concat }})".to_string()), + ("expressions/cube".to_string(), "CUBE({{ exprs_concat }})".to_string()), ("expressions/negative".to_string(), "-({{ expr }})".to_string()), ("expressions/not".to_string(), "NOT ({{ expr }})".to_string()), ("expressions/true".to_string(), "TRUE".to_string()), diff --git a/rust/cubesql/cubesql/src/transport/service.rs b/rust/cubesql/cubesql/src/transport/service.rs index 068579eb09c8..a9b7a7b9fbdf 100644 --- a/rust/cubesql/cubesql/src/transport/service.rs +++ b/rust/cubesql/cubesql/src/transport/service.rs @@ -25,7 +25,10 @@ use uuid::Uuid; use crate::{ compile::{ - engine::df::{scan::MemberField, wrapper::SqlQuery}, + engine::df::{ + scan::MemberField, + wrapper::{GroupingSetDesc, GroupingSetType, SqlQuery}, + }, MetaContext, }, sql::{AuthContextRef, HttpAuthContext}, @@ -386,6 +389,7 @@ impl SqlTemplates { from: String, projection: Vec, group_by: Vec, + group_descs: Vec>, aggregate: Vec, alias: String, filter: Option, @@ -406,12 +410,21 @@ impl SqlTemplates { .map(|c| c.clone()) .collect::>(); let quoted_from_alias = self.quote_identifier(&alias)?; + let has_grouping_sets = group_descs.iter().any(|d| d.is_some()); + let group_by_expr = if has_grouping_sets { + self.group_by_with_grouping_sets(&group_by, &group_descs)? + } else { + self.render_template( + "statements/group_by_exprs", + context! { group_by => group_by }, + )? + }; self.render_template( "statements/select", context! { from => from, select_concat => select_concat, - group_by => group_by, + group_by => group_by_expr, aggregate => aggregate, projection => projection, order_by => order_by, @@ -424,6 +437,43 @@ impl SqlTemplates { ) } + fn group_by_with_grouping_sets( + &self, + group_by: &Vec, + group_descs: &Vec>, + ) -> Result { + let mut parts = Vec::new(); + let mut curr_set = Vec::new(); + let mut curr_set_desc = None; + for (col, desc) in group_by.iter().zip(group_descs.iter()) { + if desc != &curr_set_desc { + if let Some(curr_desc) = &curr_set_desc { + let part_expr = match curr_desc.group_type { + GroupingSetType::Rollup => self.rollup_expr(curr_set)?, + GroupingSetType::Cube => self.cube_expr(curr_set)?, + }; + parts.push(part_expr); + } + curr_set_desc = desc.clone(); + curr_set = Vec::new(); + } + if desc.is_some() { + curr_set.push(col.index.to_string()); + } else { + parts.push(col.index.to_string()) + } + } + if let Some(curr_desc) = &curr_set_desc { + let part_expr = match curr_desc.group_type { + GroupingSetType::Rollup => self.rollup_expr(curr_set)?, + GroupingSetType::Cube => self.cube_expr(curr_set)?, + }; + parts.push(part_expr); + } + + Ok(parts.join(", ")) + } + fn to_template_columns( &self, aliased_columns: Vec, @@ -698,6 +748,26 @@ impl SqlTemplates { ) } + pub fn rollup_expr(&self, exprs: Vec) -> Result { + let exprs_concat = exprs.join(", "); + self.render_template( + "expressions/rollup", + context! { + exprs_concat => exprs_concat, + }, + ) + } + + pub fn cube_expr(&self, exprs: Vec) -> Result { + let exprs_concat = exprs.join(", "); + self.render_template( + "expressions/cube", + context! { + exprs_concat => exprs_concat, + }, + ) + } + pub fn subquery_expr(&self, subquery_expr: String) -> Result { self.render_template( "expressions/subquery",