From 66aa73939e0b9782fdcdb13635614bf0524f2b2f Mon Sep 17 00:00:00 2001 From: mertmit Date: Tue, 18 Apr 2023 17:26:08 +0300 Subject: [PATCH] feat: foreign_key_checks and raw option for bulkInsert operation Signed-off-by: mertmit --- packages/nocodb-nest/src/db/BaseModelSqlv2.ts | 55 ++++++++++++++----- .../src/services/bulk-data-alias.service.ts | 12 +++- 2 files changed, 51 insertions(+), 16 deletions(-) diff --git a/packages/nocodb-nest/src/db/BaseModelSqlv2.ts b/packages/nocodb-nest/src/db/BaseModelSqlv2.ts index 846a95f9c1..377dc50124 100644 --- a/packages/nocodb-nest/src/db/BaseModelSqlv2.ts +++ b/packages/nocodb-nest/src/db/BaseModelSqlv2.ts @@ -2097,23 +2097,32 @@ class BaseModelSqlv2 { { chunkSize: _chunkSize = 100, cookie, + foreign_key_checks = true, + raw = false, }: { chunkSize?: number; cookie?: any; + foreign_key_checks?: boolean; + raw?: boolean; } = {}, ) { try { - const insertDatas = await Promise.all( - datas.map(async (d) => { - await populatePk(this.model, d); - return this.model.mapAliasToColumn(d); - }), - ); + // TODO: ag column handling for raw bulk insert + const insertDatas = raw + ? datas + : await Promise.all( + datas.map(async (d) => { + await populatePk(this.model, d); + return this.model.mapAliasToColumn(d); + }), + ); // await this.beforeInsertb(insertDatas, null); - for (const data of datas) { - await this.validate(data); + if (!raw) { + for (const data of datas) { + await this.validate(data); + } } // fallbacks to `10` if database client is sqlite @@ -2121,18 +2130,34 @@ class BaseModelSqlv2 { // refer : https://www.sqlite.org/limits.html const chunkSize = this.isSqlite ? 10 : _chunkSize; + const trx = await this.dbDriver.transaction(); + + if (!foreign_key_checks) { + if (this.isPg) { + await trx.raw('set session_replication_role to replica;'); + } else if (this.isMySQL) { + await trx.raw('SET foreign_key_checks = 0;'); + } + } + const response = this.isPg || this.isMssql - ? await this.dbDriver + ? await trx .batchInsert(this.tnPath, insertDatas, chunkSize) .returning(this.model.primaryKey?.column_name) - : await this.dbDriver.batchInsert( - this.tnPath, - insertDatas, - chunkSize, - ); + : await trx.batchInsert(this.tnPath, insertDatas, chunkSize); + + if (!foreign_key_checks) { + if (this.isPg) { + await trx.raw('set session_replication_role to origin;'); + } else if (this.isMySQL) { + await trx.raw('SET foreign_key_checks = 1;'); + } + } + + await trx.commit(); - await this.afterBulkInsert(insertDatas, this.dbDriver, cookie); + if (!raw) await this.afterBulkInsert(insertDatas, this.dbDriver, cookie); return response; } catch (e) { diff --git a/packages/nocodb-nest/src/services/bulk-data-alias.service.ts b/packages/nocodb-nest/src/services/bulk-data-alias.service.ts index 21201b879b..d61556254c 100644 --- a/packages/nocodb-nest/src/services/bulk-data-alias.service.ts +++ b/packages/nocodb-nest/src/services/bulk-data-alias.service.ts @@ -44,12 +44,22 @@ export class BulkDataAliasService { param: PathParams & { body: any; cookie: any; + chunkSize?: number; + foreign_key_checks?: boolean; + raw?: boolean; }, ) { return await this.executeBulkOperation({ ...param, operation: 'bulkInsert', - options: [param.body, { cookie: param.cookie }], + options: [ + param.body, + { + cookie: param.cookie, + foreign_key_checks: param.foreign_key_checks, + raw: param.raw, + }, + ], }); }