Browse Source

refactor: use composite key extraction in bulk api implementations

pull/7649/head
Pranav C 10 months ago
parent
commit
0ef551b853
  1. 100
      packages/nocodb/src/db/BaseModelSqlv2.ts

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

@ -2449,7 +2449,11 @@ class BaseModelSqlv2 {
if (ag) {
if (!response) await this.execAndParse(query);
response = await this.readByPk(
insertObj[ag.column_name],
this.extractCompositePK({
rowId: insertObj[ag.column_name],
insertObj,
ag,
}),
false,
{},
{ ignoreView: true, getHiddenColumn: true },
@ -2492,7 +2496,7 @@ class BaseModelSqlv2 {
).id;
}
response = await this.readByPk(
id,
this.extractCompositePK({ rowId: id, insertObj, ag }),
false,
{},
{ ignoreView: true, getHiddenColumn: true },
@ -2505,7 +2509,7 @@ class BaseModelSqlv2 {
? response?.[0]?.[ai.id]
: response?.[ai.id];
response = await this.readByPk(
id,
this.extractCompositePK({ rowId: id, insertObj, ag }),
false,
{},
{ ignoreView: true, getHiddenColumn: true },
@ -2869,22 +2873,7 @@ class BaseModelSqlv2 {
? response?.[0]?.[ai.id]
: response?.[ai.id];
}
// handle if composite primary key is used along with ai or ag
if ((ai || ag) && this.model.primaryKeys?.length > 1) {
// generate object with ai column and rest of the primary keys
const pkObj = {};
for (const pk of this.model.primaryKeys) {
if (ai && pk.id === ai.id) {
pkObj[pk.id] = rowId;
} else if (ag && pk.id === ag.id) {
pkObj[pk.id] = rowId;
} else {
pkObj[pk.id] = insertObj[pk.column_name] ?? null;
}
}
rowId = pkObj;
}
rowId = this.extractCompositePK({ ai, ag, rowId, insertObj });
await Promise.all(postInsertOps.map((f) => f(rowId)));
@ -2905,6 +2894,35 @@ class BaseModelSqlv2 {
}
}
private extractCompositePK({
ai,
ag,
rowId,
insertObj,
}: {
ai?: Column<any>;
ag?: Column<any>;
rowId;
insertObj: Record<string, any>;
}) {
// handle if composite primary key is used along with ai or ag
if ((ai || ag) && this.model.primaryKeys?.length > 1) {
// generate object with ai column and rest of the primary keys
const pkObj = {};
for (const pk of this.model.primaryKeys) {
if (ai && pk.id === ai.id) {
pkObj[pk.id] = rowId;
} else if (ag && pk.id === ag.id) {
pkObj[pk.id] = rowId;
} else {
pkObj[pk.id] = insertObj[pk.column_name] ?? null;
}
}
rowId = pkObj;
}
return rowId;
}
private async prepareNestedLinkQb({
nestedCols,
data,
@ -3198,27 +3216,43 @@ class BaseModelSqlv2 {
let responses;
const aiPkCol = this.model.primaryKeys.find((pk) => pk.ai);
const agPkCol = this.model.primaryKeys.find((pk) => pk.meta?.ag);
// insert one by one as fallback to get ids for sqlite and mysql
if (insertOneByOneAsFallback && (this.isSqlite || this.isMySQL)) {
// sqlite and mysql doesn't support returning, so insert one by one and return ids
responses = [];
const aiPkCol = this.model.primaryKeys.find((pk) => pk.ai);
for (const insertData of insertDatas) {
const query = trx(this.tnPath).insert(insertData);
const id = (await query)[0];
responses.push(aiPkCol ? { [aiPkCol.title]: id } : id);
let id = (await query)[0];
if (agPkCol) {
id = insertData[agPkCol.column_name];
}
responses.push(
this.extractCompositePK({
rowId: id,
ai: aiPkCol,
ag: agPkCol,
insertObj: insertData,
}) || insertData,
);
}
} else {
const returningObj: Record<string, string> = {};
for (const col of this.model.primaryKeys) {
returningObj[col.title] = col.column_name;
}
responses =
!raw && (this.isPg || this.isMssql)
? await trx
.batchInsert(this.tnPath, insertDatas, chunkSize)
.returning({
[this.model.primaryKey?.title]:
this.model.primaryKey?.column_name,
})
.returning(returningObj)
: await trx.batchInsert(this.tnPath, insertDatas, chunkSize);
}
@ -3232,7 +3266,17 @@ class BaseModelSqlv2 {
// insert nested link data for single record insertion
if (isSingleRecordInsertion) {
const rowId = responses[0][this.model.primaryKey?.title];
let rowId = responses[0][this.model.primaryKey?.title];
if (aiPkCol || agPkCol) {
rowId = this.extractCompositePK({
rowId,
ai: aiPkCol,
ag: agPkCol,
insertObj: insertDatas[0],
});
}
await Promise.all(postInsertOps.map((f) => f(rowId, trx)));
}

Loading…
Cancel
Save