Browse Source

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

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

Loading…
Cancel
Save