Browse Source

feat: Group by on lookup column, Links and formula

Signed-off-by: Pranav C <pranavxc@gmail.com>
pull/6489/head
Pranav C 1 year ago
parent
commit
72d041102f
  1. 22
      packages/nc-gui/composables/useViewGroupBy.ts
  2. 60
      packages/nocodb/src/db/BaseModelSqlv2.ts

22
packages/nc-gui/composables/useViewGroupBy.ts

@ -161,12 +161,10 @@ export const useViewGroupBy = (view: Ref<ViewType | undefined>, where?: Computed
if (group.nestedIn.length > groupBy.value.length) return if (group.nestedIn.length > groupBy.value.length) return
if (group.nestedIn.length === 0) nextGroupColor.value = colors.value[0] if (group.nestedIn.length === 0) nextGroupColor.value = colors.value[0]
const groupby = groupBy.value[group.nestedIn.length] const groupby = groupBy.value[group.nestedIn.length]
const nestedWhere = calculateNestedWhere(group.nestedIn, where?.value) const nestedWhere = calculateNestedWhere(group.nestedIn, where?.value)
if (!groupby || !(groupby.column.column_name || groupby.column.title)) return
if (!groupby || !groupby.column.column_name) return
if (isPublic.value && !sharedView.value?.uuid) { if (isPublic.value && !sharedView.value?.uuid) {
return return
@ -181,7 +179,7 @@ export const useViewGroupBy = (view: Ref<ViewType | undefined>, where?: Computed
...(isUIAllowed('filterSync') ? {} : { filterArrJson: JSON.stringify(nestedFilters.value) }), ...(isUIAllowed('filterSync') ? {} : { filterArrJson: JSON.stringify(nestedFilters.value) }),
where: `${nestedWhere}`, where: `${nestedWhere}`,
sort: `${groupby.sort === 'desc' ? '-' : ''}${groupby.column.title}`, sort: `${groupby.sort === 'desc' ? '-' : ''}${groupby.column.title}`,
column_name: groupby.column.column_name, column_name: groupby.column.column_name || groupby.column.title,
} as any) } as any)
: await api.public.dataGroupBy(sharedView.value!.uuid!, { : await api.public.dataGroupBy(sharedView.value!.uuid!, {
offset: ((group.paginationData.page ?? 0) - 1) * (group.paginationData.pageSize ?? groupByLimit), offset: ((group.paginationData.page ?? 0) - 1) * (group.paginationData.pageSize ?? groupByLimit),
@ -189,30 +187,32 @@ export const useViewGroupBy = (view: Ref<ViewType | undefined>, where?: Computed
...params, ...params,
where: nestedWhere, where: nestedWhere,
sort: `${groupby.sort === 'desc' ? '-' : ''}${groupby.column.title}`, 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, sortsArr: sorts.value,
filtersArr: nestedFilters.value, filtersArr: nestedFilters.value,
}) })
const tempList: Group[] = response.list.reduce((acc: Group[], curr: Record<string, any>) => { const tempList: Group[] = response.list.reduce((acc: Group[], curr: Record<string, any>) => {
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) { if (keyExists) {
keyExists.count += +curr.count keyExists.count += +curr.count
keyExists.paginationData = { page: 1, pageSize: groupByLimit, totalRows: keyExists.count } keyExists.paginationData = { page: 1, pageSize: groupByLimit, totalRows: keyExists.count }
return acc return acc
} }
if (groupby.column.title && groupby.column.column_name && groupby.column.uidt) { if (groupby.column.title && groupby.column.uidt) {
acc.push({ 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, column: groupby.column,
count: +curr.count, 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: [ nestedIn: [
...group!.nestedIn, ...group!.nestedIn,
{ {
title: groupby.column.title, title: groupby.column.title,
column_name: groupby.column.column_name!, column_name: (groupby.column.column_name || groupby.column.title)!,
key: valueToTitle(curr[groupby.column.column_name!], groupby.column), key: valueToTitle(curr[(groupby.column.column_name || groupby.column.title)!], groupby.column),
column_uidt: groupby.column.uidt, column_uidt: groupby.column.uidt,
}, },
], ],

60
packages/nocodb/src/db/BaseModelSqlv2.ts

@ -339,6 +339,12 @@ class BaseModelSqlv2 {
let data; let data;
console.log(`
${qb.toQuery()}
`);
try { try {
data = await this.execAndParse(qb); data = await this.execAndParse(qb);
} catch (e) { } catch (e) {
@ -499,6 +505,7 @@ class BaseModelSqlv2 {
args.column_name = args.column_name || ''; args.column_name = args.column_name || '';
const cols = await this.model.getColumns(); const cols = await this.model.getColumns();
const groupByColumns: Record<string, Column> = {};
const selectors = []; const selectors = [];
const groupBySelectors = []; const groupBySelectors = [];
@ -508,11 +515,13 @@ class BaseModelSqlv2 {
const column = cols.find( const column = cols.find(
(c) => c.column_name === col || c.title === col, (c) => c.column_name === col || c.title === col,
); );
groupByColumns[column.id] = column;
if (!column) { if (!column) {
throw NcError.notFound('Column not found'); throw NcError.notFound('Column not found');
} }
switch (column.uidt) { switch (column.uidt) {
case UITypes.Links:
case UITypes.Rollup: case UITypes.Rollup:
selectors.push( selectors.push(
( (
@ -554,34 +563,25 @@ class BaseModelSqlv2 {
break; break;
case UITypes.Lookup: case UITypes.Lookup:
{ {
let selectQb; const _selectQb = await generateBTLookupSelectQuery({
try { baseModelSqlv2: this,
const _selectQb = await generateBTLookupSelectQuery({ column,
baseModelSqlv2: this, alias: null,
column, model: this.model,
alias: null, });
model: this.model,
});
selectQb = this.dbDriver.raw(`?? as ??`, [ const selectQb = this.dbDriver.raw(`?? as ??`, [
this.dbDriver.raw(_selectQb.builder).wrap('(', ')'), this.dbDriver.raw(_selectQb.builder).wrap('(', ')'),
sanitize(column.title), sanitize(column.title),
]); ]);
} catch (e) {
console.log(e);
// return dummy select
selectQb = this.dbDriver.raw(`'ERR' as ??`, [
sanitize(column.title),
]);
}
selectors.push(selectQb); selectors.push(selectQb);
groupBySelectors.push(column.title); groupBySelectors.push(sanitize(column.title));
} }
break; break;
default: default:
selectors.push(column.column_name); selectors.push(column.column_name);
groupBySelectors.push(sanitize(column.title)); groupBySelectors.push(sanitize(column.column_name));
break; break;
} }
}), }),
@ -634,6 +634,17 @@ class BaseModelSqlv2 {
? args.sortArr ? args.sortArr
: await Sort.list({ viewId: this.viewId }); : 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); if (sorts) await sortV2(this, sorts, qb);
applyPaginate(qb, rest); applyPaginate(qb, rest);
return await qb; return await qb;
@ -668,6 +679,7 @@ class BaseModelSqlv2 {
switch (column.uidt) { switch (column.uidt) {
case UITypes.Rollup: case UITypes.Rollup:
case UITypes.Links:
selectors.push( selectors.push(
( (
await genRollupSelectv2({ await genRollupSelectv2({
@ -725,7 +737,7 @@ class BaseModelSqlv2 {
break; break;
default: default:
selectors.push(column.column_name); selectors.push(column.column_name);
groupBySelectors.push(sanitize(column.title)); groupBySelectors.push(sanitize(column.column_name));
break; break;
} }
}), }),
@ -4894,7 +4906,7 @@ async function generateBTLookupSelectQuery({
{ {
let aliasCount = 0, let aliasCount = 0,
selectQb; selectQb;
const alias = `__nc_lookup${aliasCount++}`; const alias = `__nc_lk_${aliasCount++}`;
const lookup = await column.getColOptions<LookupColumn>(); const lookup = await column.getColOptions<LookupColumn>();
{ {
const relationCol = await lookup.getRelationColumn(); const relationCol = await lookup.getRelationColumn();
@ -4925,7 +4937,7 @@ async function generateBTLookupSelectQuery({
let lookupColumn = await lookup.getLookupColumn(); let lookupColumn = await lookup.getLookupColumn();
let prevAlias = alias; let prevAlias = alias;
while (lookupColumn.uidt === UITypes.Lookup) { while (lookupColumn.uidt === UITypes.Lookup) {
const nestedAlias = `__nc_sort${aliasCount++}`; const nestedAlias = `__nc_lk_nested_${aliasCount++}`;
const nestedLookup = await lookupColumn.getColOptions<LookupColumn>(); const nestedLookup = await lookupColumn.getColOptions<LookupColumn>();
const relationCol = await nestedLookup.getRelationColumn(); const relationCol = await nestedLookup.getRelationColumn();
const relation = const relation =

Loading…
Cancel
Save