diff --git a/lattice/src/App/QueryBuilder/QueryBuilder.tsx b/lattice/src/App/QueryBuilder/QueryBuilder.tsx index d4c890324..93d92a3c4 100644 --- a/lattice/src/App/QueryBuilder/QueryBuilder.tsx +++ b/lattice/src/App/QueryBuilder/QueryBuilder.tsx @@ -100,7 +100,10 @@ export const QueryBuilder: FC = ({ } break; case 'GroupBy': - queryString = stringifyGroupBy(query); + const groupBy = stringifyGroupBy(query); + if(!groupBy.error) { + queryString = groupBy.queryString; + } break; case 'Count': const cleanCountQuery = cleanRows(); diff --git a/lattice/src/App/QueryBuilder/utils.test.ts b/lattice/src/App/QueryBuilder/utils.test.ts index d34e15ef9..daae5964d 100644 --- a/lattice/src/App/QueryBuilder/utils.test.ts +++ b/lattice/src/App/QueryBuilder/utils.test.ts @@ -746,7 +746,7 @@ describe('Query types', () => { groupByCall: { primary: 'primary' } - })).toEqual('GroupBy(Rows(primary))'); + })).toEqual({ error: false, queryString: 'GroupBy(Rows(primary))' }); }); it('stringifies GroupBy queries with secondary grouping', () => { @@ -755,7 +755,7 @@ describe('Query types', () => { primary: 'primary', secondary: 'secondary' } - })).toEqual('GroupBy(Rows(primary), Rows(secondary))'); + })).toEqual({ error: false, queryString: 'GroupBy(Rows(primary), Rows(secondary))' }); }); it('stringifies GroupBy queries with a filter', () => { @@ -764,7 +764,7 @@ describe('Query types', () => { primary: 'primary' }, filter: 'filterString' - })).toEqual('GroupBy(Rows(primary), filter=filterString)'); + })).toEqual({ error: false, queryString: 'GroupBy(Rows(primary), filter=filterString)' }); }); it('stringifies GroupBy queries with a sort', () => { @@ -773,7 +773,7 @@ describe('Query types', () => { primary: 'primary' }, sort: [{ sortValue: 'count desc' }] - })).toEqual('GroupBy(Rows(primary), sort=\"count desc\")'); + })).toEqual({ error: false, queryString: 'GroupBy(Rows(primary), sort=\"count desc\")' }); }); it('stringifies GroupBy queries with a secondary sum sort', () => { @@ -783,9 +783,20 @@ describe('Query types', () => { }, sort: [ { sortValue: 'count desc' }, - { sortValue: 'sum asc', field: 'field' } + { sortValue: 'sum asc', sum: 'field' } ] - })).toEqual('GroupBy(Rows(primary), sort=\"count desc, sum asc\", aggregate=Sum(field=field))'); + })).toEqual({ error: false, queryString: 'GroupBy(Rows(primary), sort=\"count desc, sum asc\", aggregate=Sum(field=field))' }); + }); + + it('stringifies GroupBy queries with an aggregate sort', () => { + expect(stringifyGroupBy({ + groupByCall: { + primary: 'primary' + }, + sort: [ + { sortValue: 'aggregate asc', aggregate: 'field' } + ] + })).toEqual({ error: false, queryString: 'GroupBy(Rows(primary), sort=\"aggregate asc\", aggregate=Count(Distinct(field=field)))' }); }); it('stringifies GroupBy queries with a filter and sort', () => { @@ -795,8 +806,30 @@ describe('Query types', () => { }, filter: 'filterString', sort: [ - { sortValue: 'sum asc', field: 'field' } + { sortValue: 'sum asc', sum: 'field' } ] - })).toEqual('GroupBy(Rows(primary), filter=filterString, sort=\"sum asc\", aggregate=Sum(field=field))'); + })).toEqual({ error: false, queryString: 'GroupBy(Rows(primary), filter=filterString, sort=\"sum asc\", aggregate=Sum(field=field))' }); + }); + + it('fails when stringifying a GroupBy query with sum sort when field is not set', () => { + expect(stringifyGroupBy({ + groupByCall: { + primary: 'primary' + }, + sort: [ + { sortValue: 'sum desc' } + ] + })).toEqual({ error: true, queryString: 'GroupBy(Rows(primary), sort=\"sum desc\")' }); + }); + + it('fails when stringifying a GroupBy query with aggregate sort when field is not set', () => { + expect(stringifyGroupBy({ + groupByCall: { + primary: 'primary' + }, + sort: [ + { sortValue: 'aggregate asc' } + ] + })).toEqual({ error: true, queryString: 'GroupBy(Rows(primary), sort=\"aggregate asc\")' }); }); }); diff --git a/lattice/src/App/QueryBuilder/utils.ts b/lattice/src/App/QueryBuilder/utils.ts index 570d32845..c90cafaed 100644 --- a/lattice/src/App/QueryBuilder/utils.ts +++ b/lattice/src/App/QueryBuilder/utils.ts @@ -116,22 +116,39 @@ export const stringifyRowData = (rowCalls: RowGrouping[], operator?: Operator) = export const stringifyGroupBy = (query: any) => { const { groupByCall, filter, sort } = query; + let isInvalid = false; let sortString = ''; let aggregateString = ''; if (sort?.length > 0) { sortString = sort[0].sortValue; if (sort[0].sortValue.includes('sum')) { - aggregateString = `, aggregate=Sum(field=${sort[0].sum})`; - } else if(sort[0].sortValue.includes('aggregate')) { - aggregateString = `, aggregate=Count(Distinct(field=${sort[0].aggregate}))`; + if (sort[0].sum) { + aggregateString = `, aggregate=Sum(field=${sort[0].sum})`; + } else { + isInvalid = true; + } + } else if (sort[0].sortValue.includes('aggregate')) { + if (sort[0].aggregate) { + aggregateString = `, aggregate=Count(Distinct(field=${sort[0].aggregate}))`; + } else { + isInvalid = true; + } } if (sort.length > 1) { sortString = `${sortString}, ${sort[1].sortValue}`; if (sort[1].sortValue.includes('sum')) { - aggregateString = `, aggregate=Sum(field=${sort[1].sum})`; - } else if(sort[1].sortValue.includes('aggregate')) { - aggregateString = `, aggregate=Count(Distinct(field=${sort[1].aggregate}))`; + if (sort[1].sum) { + aggregateString = `, aggregate=Sum(field=${sort[1].sum})`; + } else { + isInvalid = true; + } + } else if (sort[1].sortValue.includes('aggregate')) { + if (sort[1].aggregate) { + aggregateString = `, aggregate=Count(Distinct(field=${sort[1].aggregate}))`; + } else { + isInvalid = true; + } } } sortString = `, sort="${sortString}"`; @@ -141,7 +158,7 @@ export const stringifyGroupBy = (query: any) => { ? `GroupBy(Rows(${groupByCall.primary}), Rows(${groupByCall.secondary})${filterString}${sortString}${aggregateString})` : `GroupBy(Rows(${groupByCall.primary})${filterString}${sortString}${aggregateString})`; - return queryString; + return { error: isInvalid, queryString }; } export const cleanupRows = (rowCalls: RowGrouping[]) => {