From 42cda59ee5f175b2b9f887b8a5fbdd60fda8184b Mon Sep 17 00:00:00 2001 From: RomanDavydchuk Date: Fri, 28 Nov 2025 19:03:01 +0200 Subject: [PATCH] fix(PostgreSQL Node): Input items with array being modified (#22426) --- .../nodes/Postgres/test/v2/utils.test.ts | 29 +++++++++++++++++-- .../v2/actions/database/insert.operation.ts | 2 +- .../v2/actions/database/update.operation.ts | 2 +- .../v2/actions/database/upsert.operation.ts | 2 +- .../nodes/Postgres/v2/helpers/utils.ts | 14 +++++---- 5 files changed, 39 insertions(+), 10 deletions(-) diff --git a/packages/nodes-base/nodes/Postgres/test/v2/utils.test.ts b/packages/nodes-base/nodes/Postgres/test/v2/utils.test.ts index 43320a8bdd8..29dbacce10d 100644 --- a/packages/nodes-base/nodes/Postgres/test/v2/utils.test.ts +++ b/packages/nodes-base/nodes/Postgres/test/v2/utils.test.ts @@ -535,9 +535,9 @@ describe('Test PostgresV2, convertArraysToPostgresFormat', () => { }, ]; - convertArraysToPostgresFormat(item, schema, node, 0); + const result = convertArraysToPostgresFormat(item, schema, node, 0); - expect(item).toEqual({ + expect(result).toEqual({ jsonb_array: '{"{\\"key\\":\\"value44\\"}"}', json_array: '{"{\\"key\\":\\"value54\\"}"}', int_array: '{1,2,5}', @@ -545,4 +545,29 @@ describe('Test PostgresV2, convertArraysToPostgresFormat', () => { bool_array: '{"true","false"}', }); }); + + it('should not modify the original data object', () => { + const referenceItem = { + arr: [1, 2, 3], + }; + const item = { + arr: [1, 2, 3], + }; + const schema: ColumnInfo[] = [ + { + column_name: 'arr', + data_type: 'ARRAY', + is_nullable: 'YES', + udt_name: '_int4', + column_default: null, + }, + ]; + + const result = convertArraysToPostgresFormat(item, schema, node, 0); + + expect(result).toEqual({ + arr: '{1,2,3}', + }); + expect(item).toEqual(referenceItem); + }); }); diff --git a/packages/nodes-base/nodes/Postgres/v2/actions/database/insert.operation.ts b/packages/nodes-base/nodes/Postgres/v2/actions/database/insert.operation.ts index df00fd94b61..6f52d45a8fa 100644 --- a/packages/nodes-base/nodes/Postgres/v2/actions/database/insert.operation.ts +++ b/packages/nodes-base/nodes/Postgres/v2/actions/database/insert.operation.ts @@ -234,7 +234,7 @@ export async function execute( tableSchema = await updateTableSchema(db, tableSchema, schema, table); if (nodeVersion >= 2.4) { - convertArraysToPostgresFormat(item, tableSchema, this.getNode(), i); + item = convertArraysToPostgresFormat(item, tableSchema, this.getNode(), i); } values.push(checkItemAgainstSchema(this.getNode(), item, tableSchema, i)); diff --git a/packages/nodes-base/nodes/Postgres/v2/actions/database/update.operation.ts b/packages/nodes-base/nodes/Postgres/v2/actions/database/update.operation.ts index e15169b0d24..df7e4e43413 100644 --- a/packages/nodes-base/nodes/Postgres/v2/actions/database/update.operation.ts +++ b/packages/nodes-base/nodes/Postgres/v2/actions/database/update.operation.ts @@ -302,7 +302,7 @@ export async function execute( tableSchema = await updateTableSchema(db, tableSchema, schema, table); if (nodeVersion >= 2.4) { - convertArraysToPostgresFormat(item, tableSchema, this.getNode(), i); + item = convertArraysToPostgresFormat(item, tableSchema, this.getNode(), i); } item = checkItemAgainstSchema(this.getNode(), item, tableSchema, i); diff --git a/packages/nodes-base/nodes/Postgres/v2/actions/database/upsert.operation.ts b/packages/nodes-base/nodes/Postgres/v2/actions/database/upsert.operation.ts index 4a9567e5c22..d47ad46acca 100644 --- a/packages/nodes-base/nodes/Postgres/v2/actions/database/upsert.operation.ts +++ b/packages/nodes-base/nodes/Postgres/v2/actions/database/upsert.operation.ts @@ -271,7 +271,7 @@ export async function execute( tableSchema = await updateTableSchema(db, tableSchema, schema, table); if (nodeVersion >= 2.4) { - convertArraysToPostgresFormat(item, tableSchema, this.getNode(), i); + item = convertArraysToPostgresFormat(item, tableSchema, this.getNode(), i); } item = checkItemAgainstSchema(this.getNode(), item, tableSchema, i); diff --git a/packages/nodes-base/nodes/Postgres/v2/helpers/utils.ts b/packages/nodes-base/nodes/Postgres/v2/helpers/utils.ts index d8e8ee7e04f..a8321c60202 100644 --- a/packages/nodes-base/nodes/Postgres/v2/helpers/utils.ts +++ b/packages/nodes-base/nodes/Postgres/v2/helpers/utils.ts @@ -6,7 +6,7 @@ import type { INodePropertyOptions, NodeParameterValueType, } from 'n8n-workflow'; -import { NodeOperationError, jsonParse } from 'n8n-workflow'; +import { NodeOperationError, deepCopy, jsonParse } from 'n8n-workflow'; import type { ColumnInfo, @@ -570,6 +570,7 @@ export const configureTableSchemaUpdater = (initialSchema: string, initialTable: * @param schema table schema * @param node INode * @param itemIndex the index of the current item + * @returns a new data object with the arrays converted to postgres format */ export const convertArraysToPostgresFormat = ( data: IDataObject, @@ -577,10 +578,11 @@ export const convertArraysToPostgresFormat = ( node: INode, itemIndex = 0, ) => { + const newData = deepCopy(data); for (const columnInfo of schema) { - //in case column type is array we need to convert it to fornmat that postgres understands + // in case column type is array we need to convert it to fornmat that postgres understands if (columnInfo.data_type.toUpperCase() === 'ARRAY') { - let columnValue = data[columnInfo.column_name]; + let columnValue = newData[columnInfo.column_name]; if (typeof columnValue === 'string') { columnValue = jsonParse(columnValue); @@ -607,8 +609,8 @@ export const convertArraysToPostgresFormat = ( return entry; }); - //wrap in {} instead of [] as postgres does and join with , - data[columnInfo.column_name] = `{${arrayEntries.join(',')}}`; + // wrap in {} instead of [] as postgres does and join with , + newData[columnInfo.column_name] = `{${arrayEntries.join(',')}}`; } else { if (columnInfo.is_nullable === 'NO') { throw new NodeOperationError( @@ -622,4 +624,6 @@ export const convertArraysToPostgresFormat = ( } } } + + return newData; };