Browse Source

refactor: support nested insert in new insert api v2 - WIP

pull/6817/head
Pranav C 1 year ago
parent
commit
7ab120c38c
  1. 160
      packages/nocodb/src/db/BaseModelSqlv2.ts

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

@ -2524,75 +2524,15 @@ class BaseModelSqlv2 {
); );
let rowId = null; let rowId = null;
const postInsertOps = [];
const nestedCols = (await this.model.getColumns()).filter((c) => const nestedCols = (await this.model.getColumns()).filter((c) =>
isLinksOrLTAR(c), isLinksOrLTAR(c),
); );
const postInsertOps = await this.prepareNestedLinkQb({
for (const col of nestedCols) { nestedCols,
if (col.title in data) { data,
const colOptions = insertObj,
await col.getColOptions<LinkToAnotherRecordColumn>(); });
// parse data if it's JSON string
let nestedData;
try {
nestedData =
typeof data[col.title] === 'string'
? JSON.parse(data[col.title])
: data[col.title];
} catch {
continue;
}
switch (colOptions.type) {
case RelationTypes.BELONGS_TO:
{
const childCol = await colOptions.getChildColumn();
const parentCol = await colOptions.getParentColumn();
insertObj[childCol.column_name] = nestedData?.[parentCol.title];
}
break;
case RelationTypes.HAS_MANY:
{
const childCol = await colOptions.getChildColumn();
const childModel = await childCol.getModel();
await childModel.getColumns();
postInsertOps.push(async () => {
await this.dbDriver(this.getTnPath(childModel.table_name))
.update({
[childCol.column_name]: rowId,
})
.whereIn(
childModel.primaryKey.column_name,
nestedData?.map((r) => r[childModel.primaryKey.title]),
);
});
}
break;
case RelationTypes.MANY_TO_MANY: {
postInsertOps.push(async () => {
const parentModel = await colOptions
.getParentColumn()
.then((c) => c.getModel());
await parentModel.getColumns();
const parentMMCol = await colOptions.getMMParentColumn();
const childMMCol = await colOptions.getMMChildColumn();
const mmModel = await colOptions.getMMModel();
const rows = nestedData.map((r) => ({
[parentMMCol.column_name]: r[parentModel.primaryKey.title],
[childMMCol.column_name]: rowId,
}));
await this.dbDriver(this.getTnPath(mmModel.table_name)).insert(
rows,
);
});
}
}
}
}
await this.validate(insertObj); await this.validate(insertObj);
@ -2649,7 +2589,7 @@ class BaseModelSqlv2 {
: response?.[ai.title]; : response?.[ai.title];
} }
await Promise.all(postInsertOps.map((f) => f())); await Promise.all(postInsertOps.map((f) => f(rowId)));
response = await this.readByPk( response = await this.readByPk(
rowId, rowId,
@ -2667,6 +2607,81 @@ class BaseModelSqlv2 {
} }
} }
private async prepareNestedLinkQb({
nestedCols,
data,
insertObj,
}: {
nestedCols: Column[];
data: Record<string, any>;
insertObj: Record<string, any>;
}) {
const postInsertOps: ((rowId: any) => Promise<void>)[] = [];
for (const col of nestedCols) {
if (col.title in data) {
const colOptions = await col.getColOptions<LinkToAnotherRecordColumn>();
// parse data if it's JSON string
let nestedData;
try {
nestedData =
typeof data[col.title] === 'string'
? JSON.parse(data[col.title])
: data[col.title];
} catch {
continue;
}
switch (colOptions.type) {
case RelationTypes.BELONGS_TO:
{
const childCol = await colOptions.getChildColumn();
const parentCol = await colOptions.getParentColumn();
insertObj[childCol.column_name] = nestedData?.[parentCol.title];
}
break;
case RelationTypes.HAS_MANY:
{
const childCol = await colOptions.getChildColumn();
const childModel = await childCol.getModel();
await childModel.getColumns();
postInsertOps.push(async (rowId) => {
await this.dbDriver(this.getTnPath(childModel.table_name))
.update({
[childCol.column_name]: rowId,
})
.whereIn(
childModel.primaryKey.column_name,
nestedData?.map((r) => r[childModel.primaryKey.title]),
);
});
}
break;
case RelationTypes.MANY_TO_MANY: {
postInsertOps.push(async (rowId) => {
const parentModel = await colOptions
.getParentColumn()
.then((c) => c.getModel());
await parentModel.getColumns();
const parentMMCol = await colOptions.getMMParentColumn();
const childMMCol = await colOptions.getMMChildColumn();
const mmModel = await colOptions.getMMModel();
const rows = nestedData.map((r) => ({
[parentMMCol.column_name]: r[parentModel.primaryKey.title],
[childMMCol.column_name]: rowId,
}));
await this.dbDriver(this.getTnPath(mmModel.table_name)).insert(
rows,
);
});
}
}
}
}
return postInsertOps;
}
async bulkInsert( async bulkInsert(
datas: any[], datas: any[],
{ {
@ -2691,8 +2706,13 @@ class BaseModelSqlv2 {
try { try {
// TODO: ag column handling for raw bulk insert // TODO: ag column handling for raw bulk insert
const insertDatas = raw ? datas : []; const insertDatas = raw ? datas : [];
const postInsertOps: ((rowId: any) => Promise<void>)[][] = [];
if (!raw) { if (!raw) {
const nestedCols = (await this.model.getColumns()).filter((c) =>
isLinksOrLTAR(c),
);
await this.model.getColumns(); await this.model.getColumns();
for (const d of datas) { for (const d of datas) {
@ -2819,6 +2839,14 @@ class BaseModelSqlv2 {
await this.prepareAttachmentData(insertObj); await this.prepareAttachmentData(insertObj);
postInsertOps.push(
await this.prepareNestedLinkQb({
nestedCols,
d,
insertObj,
}),
);
insertDatas.push(insertObj); insertDatas.push(insertObj);
} }
} }

Loading…
Cancel
Save