Browse Source

feat: lookup support - mm/hm lookup

pull/6987/head
Pranav C 10 months ago
parent
commit
d422b729e0
  1. 12
      packages/nc-gui/components/smartsheet/toolbar/GroupByMenu.vue
  2. 11
      packages/nocodb/src/db/generateBTLookupSelectQuery.ts
  3. 204
      packages/nocodb/src/db/generateMMLookupSelectQuery.ts

12
packages/nc-gui/components/smartsheet/toolbar/GroupByMenu.vue

@ -68,11 +68,11 @@ const fieldsToGroupBy = computed(() => {
const fields = meta.value?.columns || []
return fields.filter((field) => {
if (!groupingUidt.includes(field.uidt as UITypes)) return false
if (field.uidt === UITypes.Lookup) {
return btLookups.value.includes(field.id)
}
// if (!groupingUidt.includes(field.uidt as UITypes)) return false
//
// if (field.uidt === UITypes.Lookup) {
// return btLookups.value.includes(field.id)
// }
return true
})
@ -243,7 +243,7 @@ onMounted(async () => {
v-model="group.fk_column_id"
class="caption nc-sort-field-select"
:columns="
fieldsToGroupBy.filter((f) => (f.id && !groupedByColumnIds.includes(f.id)) || f.id === group.fk_column_id)
fieldsToGroupBy
"
:allow-empty="true"
@change="saveGroupBy"

11
packages/nocodb/src/db/generateBTLookupSelectQuery.ts

@ -38,9 +38,9 @@ export default async function generateBTLookupSelectQuery({
await relationCol.getColOptions<LinkToAnotherRecordColumn>();
// if not belongs to then throw error as we don't support
if (relation.type !== RelationTypes.BELONGS_TO)
NcError.badRequest('HasMany/ManyToMany lookup is not supported');
if (relation.type !== RelationTypes.BELONGS_TO) {
// NcError.badRequest('HasMany/ManyToMany lookup is not supported');
}
const childColumn = await relation.getChildColumn();
const parentColumn = await relation.getParentColumn();
const childModel = await childColumn.getModel();
@ -70,8 +70,9 @@ export default async function generateBTLookupSelectQuery({
// if any of the relation in nested lookup is
// not belongs to then throw error as we don't support
if (relation.type !== RelationTypes.BELONGS_TO)
NcError.badRequest('HasMany/ManyToMany lookup is not supported');
if (relation.type !== RelationTypes.BELONGS_TO) {
// NcError.badRequest('HasMany/ManyToMany lookup is not supported');
}
const childColumn = await relation.getChildColumn();
const parentColumn = await relation.getParentColumn();

204
packages/nocodb/src/db/generateMMLookupSelectQuery.ts

@ -0,0 +1,204 @@
import { RelationTypes, UITypes } from 'nocodb-sdk';
import type LookupColumn from '../models/LookupColumn';
import type { BaseModelSqlv2 } from '~/db/BaseModelSqlv2';
import type {
Column,
FormulaColumn,
LinkToAnotherRecordColumn,
Model,
RollupColumn,
} from '~/models';
import formulaQueryBuilderv2 from '~/db/formulav2/formulaQueryBuilderv2';
import genRollupSelectv2 from '~/db/genRollupSelectv2';
import { NcError } from '~/helpers/catchError';
export default async function generateBTLookupSelectQuery({
column,
baseModelSqlv2,
alias,
model,
}: {
column: Column;
baseModelSqlv2: BaseModelSqlv2;
alias: string;
model: Model;
}): Promise<any> {
const knex = baseModelSqlv2.dbDriver;
const rootAlias = alias;
{
let aliasCount = 0,
selectQb;
const alias = `__nc_lk_${aliasCount++}`;
const lookup = await column.getColOptions<LookupColumn>();
{
const relationCol = await lookup.getRelationColumn();
const relation =
await relationCol.getColOptions<LinkToAnotherRecordColumn>();
// if not belongs to then throw error as we don't support
if (relation.type !== RelationTypes.BELONGS_TO) {
// NcError.badRequest('HasMany/ManyToMany lookup is not supported');
}
const childColumn = await relation.getChildColumn();
const parentColumn = await relation.getParentColumn();
const childModel = await childColumn.getModel();
await childModel.getColumns();
const parentModel = await parentColumn.getModel();
await parentModel.getColumns();
`${baseModelSqlv2.getTnPath(parentModel.table_name)} as ${alias}`,
).where(
selectQb = knex(
`${alias}.${parentColumn.column_name}`,
knex.raw(`??`, [
`${rootAlias || baseModelSqlv2.getTnPath(childModel.table_name)}.${
childColumn.column_name
}`,
]),
);
}
let lookupColumn = await lookup.getLookupColumn();
let prevAlias = alias;
while (lookupColumn.uidt === UITypes.Lookup) {
const nestedAlias = `__nc_lk_nested_${aliasCount++}`;
const nestedLookup = await lookupColumn.getColOptions<LookupColumn>();
const relationCol = await nestedLookup.getRelationColumn();
const relation =
await relationCol.getColOptions<LinkToAnotherRecordColumn>();
// if any of the relation in nested lookup is
// not belongs to then throw error as we don't support
if (relation.type !== RelationTypes.BELONGS_TO) {
// NcError.badRequest('HasMany/ManyToMany lookup is not supported');
}
const childColumn = await relation.getChildColumn();
const parentColumn = await relation.getParentColumn();
const childModel = await childColumn.getModel();
await childModel.getColumns();
const parentModel = await parentColumn.getModel();
await parentModel.getColumns();
selectQb.join(
`${baseModelSqlv2.getTnPath(parentModel.table_name)} as ${nestedAlias}`,
`${nestedAlias}.${parentColumn.column_name}`,
`${prevAlias}.${childColumn.column_name}`,
);
const mmModel = await relationColumnOption.getMMModel();
const mmChildCol = await relationColumnOption.getMMChildColumn();
const mmParentCol = await relationColumnOption.getMMParentColumn();
knex(
`${baseModelSqlv2.getTnPath(
parentModel?.table_name,
)} as ${refTableAlias}`,
)
[columnOptions.rollup_function as string]?.(
knex.ref(`${refTableAlias}.${rollupColumn.column_name}`),
)
.innerJoin(
baseModelSqlv2.getTnPath(mmModel.table_name),
knex.ref(
`${baseModelSqlv2.getTnPath(mmModel.table_name)}.${
mmParentCol.column_name
}`,
),
'=',
knex.ref(`${refTableAlias}.${parentCol.column_name}`),
)
.where(
knex.ref(
`${baseModelSqlv2.getTnPath(mmModel.table_name)}.${
mmChildCol.column_name
}`,
),
'=',
knex.ref(
`${alias || baseModelSqlv2.getTnPath(childModel.table_name)}.${
childCol.column_name
}`,
),
)
lookupColumn = await nestedLookup.getLookupColumn();
prevAlias = nestedAlias;
}
switch (lookupColumn.uidt) {
case UITypes.Links:
case UITypes.Rollup:
{
const builder = (
await genRollupSelectv2({
baseModelSqlv2,
knex,
columnOptions:
(await lookupColumn.getColOptions()) as RollupColumn,
alias: prevAlias,
})
).builder;
selectQb.select(builder);
}
break;
case UITypes.LinkToAnotherRecord:
{
const nestedAlias = `__nc_sort${aliasCount++}`;
const relation =
await lookupColumn.getColOptions<LinkToAnotherRecordColumn>();
if (relation.type !== 'bt') return;
const colOptions =
(await column.getColOptions()) as LinkToAnotherRecordColumn;
const childColumn = await colOptions.getChildColumn();
const parentColumn = await colOptions.getParentColumn();
const childModel = await childColumn.getModel();
await childModel.getColumns();
const parentModel = await parentColumn.getModel();
await parentModel.getColumns();
selectQb
.join(
`${baseModelSqlv2.getTnPath(
parentModel.table_name,
)} as ${nestedAlias}`,
`${nestedAlias}.${parentColumn.column_name}`,
`${prevAlias}.${childColumn.column_name}`,
)
.select(parentModel?.displayValue?.column_name);
}
break;
case UITypes.Formula:
{
const builder = (
await formulaQueryBuilderv2(
baseModelSqlv2,
(
await column.getColOptions<FormulaColumn>()
).formula,
null,
model,
column,
)
).builder;
selectQb.select(builder);
}
break;
default:
{
selectQb.select(`${prevAlias}.${lookupColumn.column_name}`);
}
break;
}
return { builder: selectQb };
}
}
Loading…
Cancel
Save