From 1b0ba2c02885a0dd9f548133efadcfc7485d666d Mon Sep 17 00:00:00 2001 From: Elias Meire Date: Fri, 19 Jan 2024 14:31:44 +0100 Subject: [PATCH] fix(Microsoft SQL Node): Prevent MSSQL max parameters error by chunking (#8390) --- .../nodes/Microsoft/Sql/GenericFunctions.ts | 25 ++++++++++++++++++- .../nodes/Microsoft/Sql/test/utils.test.ts | 12 +++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/packages/nodes-base/nodes/Microsoft/Sql/GenericFunctions.ts b/packages/nodes-base/nodes/Microsoft/Sql/GenericFunctions.ts index 86276979bf..14e880bb04 100644 --- a/packages/nodes-base/nodes/Microsoft/Sql/GenericFunctions.ts +++ b/packages/nodes-base/nodes/Microsoft/Sql/GenericFunctions.ts @@ -120,11 +120,34 @@ const escapeTableName = (table: string) => { } }; +const MSSQL_PARAMETER_LIMIT = 2100; + +export function mssqlChunk(rows: IDataObject[]): IDataObject[][] { + const chunked: IDataObject[][] = [[]]; + let currentParamCount = 0; + + for (const row of rows) { + const rowValues = Object.values(row); + const valueCount = rowValues.length; + + if (currentParamCount + valueCount >= MSSQL_PARAMETER_LIMIT) { + chunked.push([]); + currentParamCount = 0; + } + + chunked[chunked.length - 1].push(row); + + currentParamCount += valueCount; + } + + return chunked; +} + export async function insertOperation(tables: ITables, pool: mssql.ConnectionPool) { return await executeQueryQueue( tables, ({ table, columnString, items }: OperationInputData): Array> => { - return chunk(items, 1000).map(async (insertValues) => { + return mssqlChunk(items).map(async (insertValues) => { const request = pool.request(); const valuesPlaceholder = []; diff --git a/packages/nodes-base/nodes/Microsoft/Sql/test/utils.test.ts b/packages/nodes-base/nodes/Microsoft/Sql/test/utils.test.ts index 15686bbaf6..12ecdd7998 100644 --- a/packages/nodes-base/nodes/Microsoft/Sql/test/utils.test.ts +++ b/packages/nodes-base/nodes/Microsoft/Sql/test/utils.test.ts @@ -4,6 +4,7 @@ import { configurePool, deleteOperation, insertOperation, + mssqlChunk, updateOperation, } from '../GenericFunctions'; @@ -142,4 +143,15 @@ describe('MSSQL tests', () => { expect(querySpy).toHaveBeenCalledWith('DELETE FROM [users] WHERE [id] IN (@v0);'); assertParameters({ v0: 2 }); }); + + describe('mssqlChunk', () => { + it('should chunk insert values correctly', () => { + const chunks = mssqlChunk( + new Array(3000) + .fill(null) + .map((_, index) => ({ id: index, name: 'John Doe', verified: true })), + ); + expect(chunks.map((chunk) => chunk.length)).toEqual([699, 699, 699, 699, 204]); + }); + }); });