Browse Source

Merge pull request #7508 from nocodb/nc-fix/nested-lookup

Nc fix/nested lookup
pull/7510/head
Raju Udava 10 months ago committed by GitHub
parent
commit
fb8df6bdd9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 103
      packages/nocodb/src/db/BaseModelSqlv2.ts

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

@ -1033,7 +1033,10 @@ class BaseModelSqlv2 {
// console.log(childQb.toQuery()) // console.log(childQb.toQuery())
const children = await this.execAndParse(childQb, childTable); const children = await this.execAndParse(
childQb,
await childTable.getColumns(),
);
const proto = await ( const proto = await (
await Model.getBaseModelSQL({ await Model.getBaseModelSQL({
id: childTable.id, id: childTable.id,
@ -1165,7 +1168,10 @@ class BaseModelSqlv2 {
await childModel.selectObject({ qb, fieldsSet: args.fieldSet }); await childModel.selectObject({ qb, fieldsSet: args.fieldSet });
const children = await this.execAndParse(qb, childTable); const children = await this.execAndParse(
qb,
await childTable.getColumns(),
);
const proto = await ( const proto = await (
await Model.getBaseModelSQL({ await Model.getBaseModelSQL({
@ -1292,7 +1298,10 @@ class BaseModelSqlv2 {
!this.isSqlite, !this.isSqlite,
); );
const children = await this.execAndParse(finalQb, childTable); const children = await this.execAndParse(
finalQb,
await childTable.getColumns(),
);
const proto = await ( const proto = await (
await Model.getBaseModelSQL({ await Model.getBaseModelSQL({
@ -1361,7 +1370,7 @@ class BaseModelSqlv2 {
qb.limit(+rest?.limit || 25); qb.limit(+rest?.limit || 25);
qb.offset(+rest?.offset || 0); qb.offset(+rest?.offset || 0);
const children = await this.execAndParse(qb, childTable); const children = await this.execAndParse(qb, await childTable.getColumns());
const proto = await ( const proto = await (
await Model.getBaseModelSQL({ id: rtnId, dbDriver: this.dbDriver }) await Model.getBaseModelSQL({ id: rtnId, dbDriver: this.dbDriver })
).getProto(); ).getProto();
@ -1595,7 +1604,7 @@ class BaseModelSqlv2 {
applyPaginate(qb, rest); applyPaginate(qb, rest);
const proto = await childModel.getProto(); const proto = await childModel.getProto();
const data = await this.execAndParse(qb, childTable); const data = await this.execAndParse(qb, await childTable.getColumns());
return data.map((c) => { return data.map((c) => {
c.__proto__ = proto; c.__proto__ = proto;
return c; return c;
@ -1710,7 +1719,7 @@ class BaseModelSqlv2 {
applyPaginate(qb, rest); applyPaginate(qb, rest);
const proto = await childModel.getProto(); const proto = await childModel.getProto();
const data = await this.execAndParse(qb, childTable); const data = await this.execAndParse(qb, await childTable.getColumns());
return data.map((c) => { return data.map((c) => {
c.__proto__ = proto; c.__proto__ = proto;
@ -1829,7 +1838,7 @@ class BaseModelSqlv2 {
applyPaginate(qb, rest); applyPaginate(qb, rest);
const proto = await parentModel.getProto(); const proto = await parentModel.getProto();
const data = await this.execAndParse(qb, parentTable); const data = await this.execAndParse(qb, await parentTable.getColumns());
return data.map((c) => { return data.map((c) => {
c.__proto__ = proto; c.__proto__ = proto;
@ -4547,7 +4556,7 @@ class BaseModelSqlv2 {
public async execAndParse( public async execAndParse(
qb: Knex.QueryBuilder | string, qb: Knex.QueryBuilder | string,
childTable?: Model, dependencyColumns?: Column[],
options: { options: {
skipDateConversion?: boolean; skipDateConversion?: boolean;
skipAttachmentConversion?: boolean; skipAttachmentConversion?: boolean;
@ -4591,23 +4600,30 @@ class BaseModelSqlv2 {
) )
: await this.dbDriver.raw(query); : await this.dbDriver.raw(query);
if (!this.model?.columns) {
await this.model.getColumns();
}
// update attachment fields // update attachment fields
if (!options.skipAttachmentConversion) { if (!options.skipAttachmentConversion) {
data = await this.convertAttachmentType(data, childTable); data = await this.convertAttachmentType(data, dependencyColumns);
} }
// update date time fields // update date time fields
if (!options.skipDateConversion) { if (!options.skipDateConversion) {
data = this.convertDateFormat(data, childTable); data = this.convertDateFormat(data, dependencyColumns);
} }
// update user fields // update user fields
if (!options.skipUserConversion) { if (!options.skipUserConversion) {
data = await this.convertUserFormat(data, childTable); data = await this.convertUserFormat(data, dependencyColumns);
} }
if (!options.skipSubstitutingColumnIds) { if (!options.skipSubstitutingColumnIds) {
data = await this.substituteColumnIdsWithColumnTitles(data, childTable); data = await this.substituteColumnIdsWithColumnTitles(
data,
dependencyColumns,
);
} }
if (options.first) { if (options.first) {
@ -4619,9 +4635,10 @@ class BaseModelSqlv2 {
protected async substituteColumnIdsWithColumnTitles( protected async substituteColumnIdsWithColumnTitles(
data: Record<string, any>[], data: Record<string, any>[],
childTable?: Model, dependencyColumns?: Column[],
aliasColumns?: Record<string, Column>,
) { ) {
const modelColumns = this.model?.columns.concat(childTable?.columns ?? []); const modelColumns = this.model?.columns.concat(dependencyColumns ?? []);
if (!modelColumns || !data.length) { if (!modelColumns || !data.length) {
return data; return data;
@ -4632,6 +4649,12 @@ class BaseModelSqlv2 {
const btMap: Record<string, boolean> = {}; const btMap: Record<string, boolean> = {};
modelColumns.forEach((col) => { modelColumns.forEach((col) => {
if (aliasColumns && col.id in aliasColumns) {
aliasColumns[col.id].id = col.id;
aliasColumns[col.id].title = col.title;
col = aliasColumns[col.id];
}
idToAliasMap[col.id] = col.title; idToAliasMap[col.id] = col.title;
if (col.colOptions?.type === 'bt') { if (col.colOptions?.type === 'bt') {
btMap[col.id] = true; btMap[col.id] = true;
@ -4701,26 +4724,20 @@ class BaseModelSqlv2 {
protected async convertUserFormat( protected async convertUserFormat(
data: Record<string, any>, data: Record<string, any>,
childTable?: Model, dependencyColumns?: Column[],
) { ) {
// user is stored as id within the database // user is stored as id within the database
// convertUserFormat is used to convert the response in id to user object in API response // convertUserFormat is used to convert the response in id to user object in API response
if (data) { if (data) {
if (childTable && !childTable?.columns) {
await childTable.getColumns();
} else if (!this.model?.columns) {
await this.model.getColumns();
}
let userColumns = []; let userColumns = [];
const columns = childTable ? childTable.columns : this.model.columns; const columns = this.model?.columns.concat(dependencyColumns ?? []);
for (const col of columns) { for (const col of columns) {
if (col.uidt === UITypes.Lookup) { if (col.uidt === UITypes.Lookup) {
if ( if (
[UITypes.User, UITypes.CreatedBy, UITypes.LastModifiedBy].includes( [UITypes.User, UITypes.CreatedBy, UITypes.LastModifiedBy].includes(
(await this.getNestedUidt(col)) as UITypes, (await this.getNestedColumn(col))?.uidt as UITypes,
) )
) { ) {
userColumns.push(col); userColumns.push(col);
@ -4751,7 +4768,7 @@ class BaseModelSqlv2 {
// process user columns that are present in data // process user columns that are present in data
if (userColumns.length) { if (userColumns.length) {
const baseUsers = await BaseUser.getUsersList({ const baseUsers = await BaseUser.getUsersList({
base_id: childTable ? childTable.base_id : this.model.base_id, base_id: this.model.base_id,
}); });
if (Array.isArray(data)) { if (Array.isArray(data)) {
@ -4870,34 +4887,28 @@ class BaseModelSqlv2 {
return d; return d;
} }
public async getNestedUidt(column: Column) { public async getNestedColumn(column: Column) {
if (column.uidt !== UITypes.Lookup) { if (column.uidt !== UITypes.Lookup) {
return column.uidt; return column;
} }
const colOptions = await column.getColOptions<LookupColumn>(); const colOptions = await column.getColOptions<LookupColumn>();
return this.getNestedUidt(await colOptions?.getLookupColumn()); return this.getNestedColumn(await colOptions?.getLookupColumn());
} }
public async convertAttachmentType( public async convertAttachmentType(
data: Record<string, any>, data: Record<string, any>,
childTable?: Model, dependencyColumns?: Column[],
) { ) {
// attachment is stored in text and parse in UI // attachment is stored in text and parse in UI
// convertAttachmentType is used to convert the response in string to array of object in API response // convertAttachmentType is used to convert the response in string to array of object in API response
if (data) { if (data) {
if (childTable && !childTable?.columns) {
await childTable.getColumns();
} else if (!this.model?.columns) {
await this.model.getColumns();
}
const attachmentColumns = []; const attachmentColumns = [];
const columns = childTable ? childTable.columns : this.model.columns; const columns = this.model?.columns.concat(dependencyColumns ?? []);
for (const col of columns) { for (const col of columns) {
if (col.uidt === UITypes.Lookup) { if (col.uidt === UITypes.Lookup) {
if ((await this.getNestedUidt(col)) === UITypes.Attachment) { if ((await this.getNestedColumn(col))?.uidt === UITypes.Attachment) {
attachmentColumns.push(col); attachmentColumns.push(col);
} }
} else { } else {
@ -5051,13 +5062,15 @@ class BaseModelSqlv2 {
return d; return d;
} }
public convertDateFormat(data: Record<string, any>, childTable?: Model) { public convertDateFormat(
data: Record<string, any>,
dependencyColumns?: Column[],
) {
// Show the date time in UTC format in API response // Show the date time in UTC format in API response
// e.g. 2022-01-01 04:30:00+00:00 // e.g. 2022-01-01 04:30:00+00:00
if (data) { if (data) {
const dateTimeColumns = ( const columns = this.model?.columns.concat(dependencyColumns ?? []);
childTable ? childTable.columns : this.model.columns const dateTimeColumns = columns.filter(
).filter(
(c) => (c) =>
c.uidt === UITypes.DateTime || c.uidt === UITypes.DateTime ||
c.uidt === UITypes.Date || c.uidt === UITypes.Date ||
@ -5701,9 +5714,13 @@ class BaseModelSqlv2 {
await parentModel.selectObject({ qb, fieldsSet: args.fieldSet }); await parentModel.selectObject({ qb, fieldsSet: args.fieldSet });
const parent = await this.execAndParse(qb, parentTable, { const parent = await this.execAndParse(
first: true, qb,
}); await parentTable.getColumns(),
{
first: true,
},
);
const proto = await parentModel.getProto(); const proto = await parentModel.getProto();

Loading…
Cancel
Save