Browse Source

feat: add LTAR group by support

pull/6987/head
Pranav C 10 months ago
parent
commit
2d48363cff
  1. 21
      packages/nocodb/src/db/BaseModelSqlv2.ts
  2. 5
      packages/nocodb/src/db/conditionV2.ts
  3. 66
      packages/nocodb/src/db/generateLookupSelectQuery.ts

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

@ -63,7 +63,8 @@ import {
} from '~/utils/globals';
import { extractProps } from '~/helpers/extractProps';
import { defaultLimitConfig } from '~/helpers/extractLimitAndOffset';
import generateLookupSelectQuery from "~/db/generateLookupSelectQuery";
import generateLookupSelectQuery from '~/db/generateLookupSelectQuery';
import { getAliasGenerator } from '~/utils';
dayjs.extend(utc);
@ -387,9 +388,9 @@ class BaseModelSqlv2 {
});
}
console.log('=======data')
console.log(qb.toQuery())
console.log('=======data')
console.log('=======data');
console.log(qb.toQuery());
console.log('=======data');
return data?.map((d) => {
d.__proto__ = proto;
@ -554,6 +555,7 @@ class BaseModelSqlv2 {
const selectors = [];
const groupBySelectors = [];
const getAlias = getAliasGenerator('__nc_gb');
await Promise.all(
args.column_name.split(',').map(async (col) => {
@ -604,12 +606,14 @@ class BaseModelSqlv2 {
}
break;
case UITypes.Lookup:
case UITypes.LinkToAnotherRecord:
{
const _selectQb = await generateLookupSelectQuery({
baseModelSqlv2: this,
column,
alias: null,
model: this.model,
getAlias,
});
const selectQb = this.dbDriver.raw(`?? as ??`, [
@ -701,9 +705,9 @@ class BaseModelSqlv2 {
applyPaginate(qb, rest);
console.log('========')
console.log(qb.toQuery())
console.log('========')
console.log('========');
console.log(qb.toQuery());
console.log('========');
return await this.execAndParse(qb);
}
@ -720,6 +724,7 @@ class BaseModelSqlv2 {
const selectors = [];
const groupBySelectors = [];
const getAlias = getAliasGenerator('__nc_gb');
await this.model.getColumns().then((cols) =>
Promise.all(
@ -773,12 +778,14 @@ class BaseModelSqlv2 {
break;
}
case UITypes.Lookup:
case UITypes.LinkToAnotherRecord:
{
const _selectQb = await generateLookupSelectQuery({
baseModelSqlv2: this,
column,
alias: null,
model: this.model,
getAlias,
});
const selectQb = this.dbDriver.raw(`?? as ??`, [

5
packages/nocodb/src/db/conditionV2.ts

@ -118,7 +118,10 @@ const parseConditionV2 = async (
// handle group by filter separately
if (filter.comparison_op === 'gb_val') {
const column = await filter.getColumn();
if (column.uidt === UITypes.Lookup) {
if (
column.uidt === UITypes.Lookup ||
column.uidt === UITypes.LinkToAnotherRecord
) {
const model = await column.getModel();
const lkQb = await generateLookupSelectQuery({
baseModelSqlv2,

66
packages/nocodb/src/db/generateLookupSelectQuery.ts

@ -16,6 +16,16 @@ import { NcError } from '~/helpers/catchError';
const LOOKUP_VAL_SEPARATOR = '___';
export async function getDisplayValueOfRefTable(
relationCol: Column<LinkToAnotherRecordColumn | LinksColumn>,
) {
return await relationCol
.getColOptions()
.then((colOpt) => colOpt.getRelatedTable())
.then((model) => model.getColumns())
.then((cols) => cols.find((col) => col.pv));
}
export default async function generateLookupSelectQuery({
column,
baseModelSqlv2,
@ -36,9 +46,18 @@ export default async function generateLookupSelectQuery({
{
let selectQb;
const alias = getAlias();
const lookup = await column.getColOptions<LookupColumn>();
let lookupColOpt: LookupColumn;
if (column.uidt === UITypes.Lookup) {
lookupColOpt = await column.getColOptions<LookupColumn>();
} else if (column.uidt !== UITypes.LinkToAnotherRecord) {
NcError.badRequest('Invalid column type');
}
await column.getColOptions<LookupColumn>();
{
const relationCol = await lookup.getRelationColumn();
const relationCol = lookupColOpt
? await lookupColOpt.getRelationColumn()
: column;
const relation =
await relationCol.getColOptions<LinkToAnotherRecordColumn>();
@ -121,7 +140,9 @@ export default async function generateLookupSelectQuery({
);
}
}
let lookupColumn = await lookup.getLookupColumn();
let lookupColumn = lookupColOpt
? await lookupColOpt.getLookupColumn()
: await getDisplayValueOfRefTable(column);
let prevAlias = alias;
while (
lookupColumn.uidt === UITypes.Lookup ||
@ -142,7 +163,7 @@ export default async function generateLookupSelectQuery({
const relation =
await relationCol.getColOptions<LinkToAnotherRecordColumn>();
// if any of the relation in nested lookup is
// if any of the relation in nested lookupColOpt is
// not belongs to then throw error as we don't support
if (relation.type === RelationTypes.BELONGS_TO) {
const childColumn = await relation.getChildColumn();
@ -222,12 +243,7 @@ export default async function generateLookupSelectQuery({
if (lookupColumn.uidt === UITypes.Lookup)
lookupColumn = await nestedLookupColOpt.getLookupColumn();
else
lookupColumn = await relationCol
.getColOptions()
.then((colOpt) => colOpt.getRelatedTable())
.then((model) => model.getColumns())
.then((cols) => cols.find((col) => col.pv));
else lookupColumn = await getDisplayValueOfRefTable(relationCol);
prevAlias = nestedAlias;
}
@ -301,12 +317,14 @@ export default async function generateLookupSelectQuery({
break;
}
const subQueryAlias = getAlias();
if (baseModelSqlv2.isPg) {
// alternate approach with array_agg
return {
builder: selectQb.select(
knex.raw('json_agg(??)::text', [lookupColumn.title]),
),
builder: knex
.select(knex.raw('json_agg(??)::text', [lookupColumn.title]))
.from(selectQb.as(subQueryAlias)),
};
/*
// alternate approach with array_agg
@ -329,9 +347,11 @@ export default async function generateLookupSelectQuery({
} else if (baseModelSqlv2.isMySQL) {
// alternate approach with JSON_ARRAYAGG
return {
builder: selectQb.select(
knex.raw('cast(JSON_ARRAYAGG(??) as NCHAR)', [lookupColumn.title]),
),
builder: knex
.select(
knex.raw('cast(JSON_ARRAYAGG(??) as NCHAR)', [lookupColumn.title]),
)
.from(selectQb.as(subQueryAlias)),
};
// return {
@ -349,12 +369,14 @@ export default async function generateLookupSelectQuery({
// ref: https://stackoverflow.com/questions/13382856/sqlite3-join-group-concat-using-distinct-with-custom-separator
// selectQb.orderBy(`${lookupColumn.title}`, 'asc');
return {
builder: selectQb.select(
knex.raw(`group_concat(??, ?)`, [
lookupColumn.title,
LOOKUP_VAL_SEPARATOR,
]),
),
builder: knex
.select(
knex.raw(`group_concat(??, ?)`, [
lookupColumn.title,
LOOKUP_VAL_SEPARATOR,
]),
)
.from(selectQb.as(subQueryAlias)),
};
}

Loading…
Cancel
Save