From 72d041102f12c8f941eb4202fe39f2e44cc05467 Mon Sep 17 00:00:00 2001 From: Pranav C Date: Tue, 26 Sep 2023 19:53:23 +0530 Subject: [PATCH] feat: Group by on lookup column, Links and formula Signed-off-by: Pranav C --- packages/nc-gui/composables/useViewGroupBy.ts | 22 +++---- packages/nocodb/src/db/BaseModelSqlv2.ts | 60 +++++++++++-------- 2 files changed, 47 insertions(+), 35 deletions(-) diff --git a/packages/nc-gui/composables/useViewGroupBy.ts b/packages/nc-gui/composables/useViewGroupBy.ts index cd0c84df79..798cb738b1 100644 --- a/packages/nc-gui/composables/useViewGroupBy.ts +++ b/packages/nc-gui/composables/useViewGroupBy.ts @@ -161,12 +161,10 @@ export const useViewGroupBy = (view: Ref, where?: Computed if (group.nestedIn.length > groupBy.value.length) return if (group.nestedIn.length === 0) nextGroupColor.value = colors.value[0] - const groupby = groupBy.value[group.nestedIn.length] const nestedWhere = calculateNestedWhere(group.nestedIn, where?.value) - - if (!groupby || !groupby.column.column_name) return + if (!groupby || !(groupby.column.column_name || groupby.column.title)) return if (isPublic.value && !sharedView.value?.uuid) { return @@ -181,7 +179,7 @@ export const useViewGroupBy = (view: Ref, where?: Computed ...(isUIAllowed('filterSync') ? {} : { filterArrJson: JSON.stringify(nestedFilters.value) }), where: `${nestedWhere}`, sort: `${groupby.sort === 'desc' ? '-' : ''}${groupby.column.title}`, - column_name: groupby.column.column_name, + column_name: groupby.column.column_name || groupby.column.title, } as any) : await api.public.dataGroupBy(sharedView.value!.uuid!, { offset: ((group.paginationData.page ?? 0) - 1) * (group.paginationData.pageSize ?? groupByLimit), @@ -189,30 +187,32 @@ export const useViewGroupBy = (view: Ref, where?: Computed ...params, where: nestedWhere, sort: `${groupby.sort === 'desc' ? '-' : ''}${groupby.column.title}`, - column_name: groupby.column.column_name, + column_name: groupby.column.column_name || groupby.column.title, sortsArr: sorts.value, filtersArr: nestedFilters.value, }) const tempList: Group[] = response.list.reduce((acc: Group[], curr: Record) => { - const keyExists = acc.find((a) => a.key === valueToTitle(curr[groupby.column.column_name!], groupby.column)) + const keyExists = acc.find( + (a) => a.key === valueToTitle(curr[groupby.column.column_name!] ?? curr[groupby.column.title!], groupby.column), + ) if (keyExists) { keyExists.count += +curr.count keyExists.paginationData = { page: 1, pageSize: groupByLimit, totalRows: keyExists.count } return acc } - if (groupby.column.title && groupby.column.column_name && groupby.column.uidt) { + if (groupby.column.title && groupby.column.uidt) { acc.push({ - key: valueToTitle(curr[groupby.column.column_name!], groupby.column), + key: valueToTitle(curr[(groupby.column.column_name || groupby.column.title)!], groupby.column), column: groupby.column, count: +curr.count, - color: findKeyColor(curr[groupby.column.column_name!], groupby.column), + color: findKeyColor(curr[(groupby.column.column_name || groupby.column.title)!], groupby.column), nestedIn: [ ...group!.nestedIn, { title: groupby.column.title, - column_name: groupby.column.column_name!, - key: valueToTitle(curr[groupby.column.column_name!], groupby.column), + column_name: (groupby.column.column_name || groupby.column.title)!, + key: valueToTitle(curr[(groupby.column.column_name || groupby.column.title)!], groupby.column), column_uidt: groupby.column.uidt, }, ], diff --git a/packages/nocodb/src/db/BaseModelSqlv2.ts b/packages/nocodb/src/db/BaseModelSqlv2.ts index bfd9e4164c..560c690a0c 100644 --- a/packages/nocodb/src/db/BaseModelSqlv2.ts +++ b/packages/nocodb/src/db/BaseModelSqlv2.ts @@ -339,6 +339,12 @@ class BaseModelSqlv2 { let data; + console.log(` + +${qb.toQuery()} + + `); + try { data = await this.execAndParse(qb); } catch (e) { @@ -499,6 +505,7 @@ class BaseModelSqlv2 { args.column_name = args.column_name || ''; const cols = await this.model.getColumns(); + const groupByColumns: Record = {}; const selectors = []; const groupBySelectors = []; @@ -508,11 +515,13 @@ class BaseModelSqlv2 { const column = cols.find( (c) => c.column_name === col || c.title === col, ); + groupByColumns[column.id] = column; if (!column) { throw NcError.notFound('Column not found'); } switch (column.uidt) { + case UITypes.Links: case UITypes.Rollup: selectors.push( ( @@ -554,34 +563,25 @@ class BaseModelSqlv2 { break; case UITypes.Lookup: { - let selectQb; - try { - const _selectQb = await generateBTLookupSelectQuery({ - baseModelSqlv2: this, - column, - alias: null, - model: this.model, - }); + const _selectQb = await generateBTLookupSelectQuery({ + baseModelSqlv2: this, + column, + alias: null, + model: this.model, + }); - selectQb = this.dbDriver.raw(`?? as ??`, [ - this.dbDriver.raw(_selectQb.builder).wrap('(', ')'), - sanitize(column.title), - ]); - } catch (e) { - console.log(e); - // return dummy select - selectQb = this.dbDriver.raw(`'ERR' as ??`, [ - sanitize(column.title), - ]); - } + const selectQb = this.dbDriver.raw(`?? as ??`, [ + this.dbDriver.raw(_selectQb.builder).wrap('(', ')'), + sanitize(column.title), + ]); selectors.push(selectQb); - groupBySelectors.push(column.title); + groupBySelectors.push(sanitize(column.title)); } break; default: selectors.push(column.column_name); - groupBySelectors.push(sanitize(column.title)); + groupBySelectors.push(sanitize(column.column_name)); break; } }), @@ -634,6 +634,17 @@ class BaseModelSqlv2 { ? args.sortArr : await Sort.list({ viewId: this.viewId }); + sorts = sorts.filter((sort) => { + if (!groupByColumns[sort.fk_column_id]) { + return true; + } + + qb.orderBy( + groupByColumns[sort.fk_column_id].column_name || + groupByColumns[sort.fk_column_id].title, + ); + }); + if (sorts) await sortV2(this, sorts, qb); applyPaginate(qb, rest); return await qb; @@ -668,6 +679,7 @@ class BaseModelSqlv2 { switch (column.uidt) { case UITypes.Rollup: + case UITypes.Links: selectors.push( ( await genRollupSelectv2({ @@ -725,7 +737,7 @@ class BaseModelSqlv2 { break; default: selectors.push(column.column_name); - groupBySelectors.push(sanitize(column.title)); + groupBySelectors.push(sanitize(column.column_name)); break; } }), @@ -4894,7 +4906,7 @@ async function generateBTLookupSelectQuery({ { let aliasCount = 0, selectQb; - const alias = `__nc_lookup${aliasCount++}`; + const alias = `__nc_lk_${aliasCount++}`; const lookup = await column.getColOptions(); { const relationCol = await lookup.getRelationColumn(); @@ -4925,7 +4937,7 @@ async function generateBTLookupSelectQuery({ let lookupColumn = await lookup.getLookupColumn(); let prevAlias = alias; while (lookupColumn.uidt === UITypes.Lookup) { - const nestedAlias = `__nc_sort${aliasCount++}`; + const nestedAlias = `__nc_lk_nested_${aliasCount++}`; const nestedLookup = await lookupColumn.getColOptions(); const relationCol = await nestedLookup.getRelationColumn(); const relation =