From 646aa1db5e8789992bb6ad0ca1dfc649c256dfdb Mon Sep 17 00:00:00 2001 From: Pranav C Date: Thu, 16 Nov 2023 12:24:10 +0000 Subject: [PATCH] feat: lookup support - mm/hm lookup - WIP --- docker-compose/mysql/docker-compose.yml | 1 + packages/nocodb/src/db/BaseModelSqlv2.ts | 7 +- .../src/db/generateMMLookupSelectQuery.ts | 140 ++++++++++-------- 3 files changed, 83 insertions(+), 65 deletions(-) diff --git a/docker-compose/mysql/docker-compose.yml b/docker-compose/mysql/docker-compose.yml index 76e2e232cc..7ed99b7ee8 100644 --- a/docker-compose/mysql/docker-compose.yml +++ b/docker-compose/mysql/docker-compose.yml @@ -37,3 +37,4 @@ services: volumes: db_data: {} nc_data: {} + diff --git a/packages/nocodb/src/db/BaseModelSqlv2.ts b/packages/nocodb/src/db/BaseModelSqlv2.ts index 9302691854..80f6fcfd78 100644 --- a/packages/nocodb/src/db/BaseModelSqlv2.ts +++ b/packages/nocodb/src/db/BaseModelSqlv2.ts @@ -64,6 +64,7 @@ import { } from '~/utils/globals'; import { extractProps } from '~/helpers/extractProps'; import { defaultLimitConfig } from '~/helpers/extractLimitAndOffset'; +import generateMMLookupSelectQuery from "~/db/generateMMLookupSelectQuery"; dayjs.extend(utc); @@ -600,7 +601,7 @@ class BaseModelSqlv2 { break; case UITypes.Lookup: { - const _selectQb = await generateBTLookupSelectQuery({ + const _selectQb = await generateMMLookupSelectQuery({ baseModelSqlv2: this, column, alias: null, @@ -695,6 +696,10 @@ class BaseModelSqlv2 { qb.groupBy(...groupBySelectors); applyPaginate(qb, rest); + + console.log('========') + console.log(qb.toQuery()) + console.log('========') return await this.execAndParse(qb); } diff --git a/packages/nocodb/src/db/generateMMLookupSelectQuery.ts b/packages/nocodb/src/db/generateMMLookupSelectQuery.ts index 767ec5e6e9..0af42ea1ef 100644 --- a/packages/nocodb/src/db/generateMMLookupSelectQuery.ts +++ b/packages/nocodb/src/db/generateMMLookupSelectQuery.ts @@ -11,23 +11,21 @@ import type { import formulaQueryBuilderv2 from '~/db/formulav2/formulaQueryBuilderv2'; import genRollupSelectv2 from '~/db/genRollupSelectv2'; import { NcError } from '~/helpers/catchError'; -import {getAliasGenerator} from "~/utils"; +import { getAliasGenerator } from '~/utils'; -export default async function generateBTLookupSelectQuery({ +export default async function generateMMLookupSelectQuery({ column, baseModelSqlv2, alias, model, - getAlias = getAliasGenerator('__lk_slt_') + getAlias = getAliasGenerator('__lk_slt_'), }: { column: Column; baseModelSqlv2: BaseModelSqlv2; alias: string; model: Model; - getAlias: ReturnType + getAlias: ReturnType; }): Promise { - - const knex = baseModelSqlv2.dbDriver; const rootAlias = alias; @@ -53,9 +51,9 @@ export default async function generateBTLookupSelectQuery({ const parentModel = await parentColumn.getModel(); await parentModel.getColumns(); - `${baseModelSqlv2.getTnPath(parentModel.table_name)} as ${alias}`, - ).where( selectQb = knex( + `${baseModelSqlv2.getTnPath(parentModel.table_name)} as ${alias}`, + ).where( `${alias}.${parentColumn.column_name}`, knex.raw(`??`, [ `${rootAlias || baseModelSqlv2.getTnPath(childModel.table_name)}.${ @@ -76,65 +74,79 @@ 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) { - - 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}`, - ); - - } else if (relation.type === RelationTypes.HAS_MANY) { - - }else if (relation.type === RelationTypes.MANY_TO_MANY) { - const mmTableAlias = getAlias() - - const mmModel = await relation.getMMModel(); - const mmChildCol = await relation.getMMChildColumn(); - const mmParentCol = await relation.getMMParentColumn(); - - knex( - `${baseModelSqlv2.getTnPath( - parentModel?.table_name, - )} as ${refTableAlias}`, + 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}`, + ); + } else if (relation.type === RelationTypes.HAS_MANY) { + 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( + childModel.table_name, + )} as ${nestedAlias}`, + `${nestedAlias}.${parentColumn.column_name}`, + `${prevAlias}.${childColumn.column_name}`, + ); + } else if (relation.type === RelationTypes.MANY_TO_MANY) { + 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(); + + const mmTableAlias = getAlias(); + + const mmModel = await relation.getMMModel(); + const mmChildCol = await relation.getMMChildColumn(); + const mmParentCol = await relation.getMMParentColumn(); + + knex( + `${baseModelSqlv2.getTnPath( + parentModel?.table_name, + )} as ${nestedAlias}`, + ) + .innerJoin( + baseModelSqlv2.getTnPath(mmModel.table_name), + knex.ref( + `${baseModelSqlv2.getTnPath(mmModel.table_name)}.${ + mmParentCol.column_name + }`, + ), + '=', + knex.ref(`${nestedAlias}.${parentColumn.column_name}`), ) - [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 - }`, - ), - ) + .where( + knex.ref( + `${baseModelSqlv2.getTnPath(mmModel.table_name)}.${ + mmChildCol.column_name + }`, + ), + '=', + knex.ref( + `${alias || baseModelSqlv2.getTnPath(childModel.table_name)}.${ + childColumn.column_name + }`, + ), + ); } - - - lookupColumn = await nestedLookup.getLookupColumn(); prevAlias = nestedAlias; }