diff --git a/packages/nodes-base/nodes/HttpRequest.node.ts b/packages/nodes-base/nodes/HttpRequest.node.ts index 43989cd73f..dfd7dff69a 100644 --- a/packages/nodes-base/nodes/HttpRequest.node.ts +++ b/packages/nodes-base/nodes/HttpRequest.node.ts @@ -829,7 +829,7 @@ export class HttpRequest implements INodeType { // Add Content Type if any are set if (options.bodyContentCustomMimeType) { - if(requestOptions.headers === undefined) { + if (requestOptions.headers === undefined) { requestOptions.headers = {}; } requestOptions.headers['Content-Type'] = options.bodyContentCustomMimeType; @@ -929,7 +929,7 @@ export class HttpRequest implements INodeType { if (property === 'body') { continue; } - returnItem[property] = response![property]; + returnItem[property] = response![property]; } newItem.json = returnItem; diff --git a/packages/nodes-base/nodes/Postgres/Postgres.node.functions.ts b/packages/nodes-base/nodes/Postgres/Postgres.node.functions.ts index eaeebe313e..df1f10cbbc 100644 --- a/packages/nodes-base/nodes/Postgres/Postgres.node.functions.ts +++ b/packages/nodes-base/nodes/Postgres/Postgres.node.functions.ts @@ -68,19 +68,22 @@ export async function pgInsert( const schema = getNodeParam('schema', 0) as string; let returnFields = (getNodeParam('returnFields', 0) as string).split(',') as string[]; const columnString = getNodeParam('columns', 0) as string; - const columns = columnString.split(',').map(column => column.trim()); - - const cs = new pgp.helpers.ColumnSet(columns); + const columns = columnString.split(',') + .map(column => column.trim().split(':')) + .map(([name, cast]) => ({ name, cast })); const te = new pgp.helpers.TableName({ table, schema }); // Prepare the data to insert and copy it to be returned - const insertItems = getItemCopy(items, columns); + const columnNames = columns.map(column => column.name); + const insertItems = getItemCopy(items, columnNames); + + const columnSet = new pgp.helpers.ColumnSet(columns); // Generate the multi-row insert query and return the id of new row returnFields = returnFields.map(value => value.trim()).filter(value => !!value); const query = - pgp.helpers.insert(insertItems, cs, te) + + pgp.helpers.insert(insertItems, columnSet, te) + (returnFields.length ? ` RETURNING ${returnFields.join(',')}` : ''); // Executing the query to insert the data @@ -109,21 +112,36 @@ export async function pgUpdate( const updateKey = getNodeParam('updateKey', 0) as string; const columnString = getNodeParam('columns', 0) as string; - const columns = columnString.split(',').map(column => column.trim()); + const [updateColumnName, updateColumnCast] = updateKey.split(':'); + const updateColumn = { + name: updateColumnName, + cast: updateColumnCast, + }; + + const columns = columnString.split(',') + .map(column => column.trim().split(':')) + .map(([name, cast]) => ({ name, cast })); const te = new pgp.helpers.TableName({ table, schema }); // Make sure that the updateKey does also get queried - if (!columns.includes(updateKey)) { - columns.unshift(updateKey); + const targetCol = columns.find((column) => column.name === updateColumn.name); + if (!targetCol) { + columns.unshift(updateColumn); + } + else if (!targetCol.cast) { + targetCol.cast = updateColumn.cast || targetCol.cast; } // Prepare the data to update and copy it to be returned - const updateItems = getItemCopy(items, columns); + const columnNames = columns.map(column => column.name); + const updateItems = getItemCopy(items, columnNames); + + const columnSet = new pgp.helpers.ColumnSet(columns); // Generate the multi-row update query const query = - pgp.helpers.update(updateItems, columns, te) + ' WHERE v.' + updateKey + ' = t.' + updateKey; + pgp.helpers.update(updateItems, columnSet, te) + ' WHERE v.' + updateColumn.name + ' = t.' + updateColumn.name; // Executing the query to update the data await db.none(query); diff --git a/packages/nodes-base/nodes/Postgres/Postgres.node.ts b/packages/nodes-base/nodes/Postgres/Postgres.node.ts index 1628510841..1250236d78 100644 --- a/packages/nodes-base/nodes/Postgres/Postgres.node.ts +++ b/packages/nodes-base/nodes/Postgres/Postgres.node.ts @@ -116,9 +116,9 @@ export class Postgres implements INodeType { }, }, default: '', - placeholder: 'id,name,description', + placeholder: 'id:int,name:text,description', description: - 'Comma separated list of the properties which should used as columns for the new rows.', + 'Comma separated list of the properties which should used as columns for the new rows.
You can use type casting with colons (:) like id:int.', }, { displayName: 'Return Fields', @@ -186,9 +186,9 @@ export class Postgres implements INodeType { }, }, default: '', - placeholder: 'name,description', + placeholder: 'name:text,description', description: - 'Comma separated list of the properties which should used as columns for rows to update.', + 'Comma separated list of the properties which should used as columns for rows to update.
You can use type casting with colons (:) like id:int.', }, ], }; diff --git a/packages/nodes-base/nodes/QuestDb/QuestDb.node.ts b/packages/nodes-base/nodes/QuestDb/QuestDb.node.ts index 15e7bcb2a5..c4b9036f0e 100644 --- a/packages/nodes-base/nodes/QuestDb/QuestDb.node.ts +++ b/packages/nodes-base/nodes/QuestDb/QuestDb.node.ts @@ -107,22 +107,6 @@ export class QuestDb implements INodeType { required: true, description: 'Name of the table in which to insert data to.', }, - { - displayName: 'Columns', - name: 'columns', - type: 'string', - displayOptions: { - show: { - operation: [ - 'insert', - ], - }, - }, - default: '', - placeholder: 'id,name,description', - description: - 'Comma separated list of the properties which should used as columns for the new rows.', - }, { displayName: 'Return Fields', name: 'returnFields', @@ -194,7 +178,7 @@ export class QuestDb implements INodeType { }).join(','); const query = `INSERT INTO ${tableName} (${columns.join(',')}) VALUES (${values});`; - queries.push(query); + queries.push(query); }); await db.any(pgp.helpers.concat(queries)); diff --git a/packages/nodes-base/test/nodes/Postgres/Postgres.node.functions.test.js b/packages/nodes-base/test/nodes/Postgres/Postgres.node.functions.test.js new file mode 100644 index 0000000000..bc3bcbb758 --- /dev/null +++ b/packages/nodes-base/test/nodes/Postgres/Postgres.node.functions.test.js @@ -0,0 +1,158 @@ +const PostgresFun = require('../../../nodes/Postgres/Postgres.node.functions') +const pgPromise = require('pg-promise'); + +describe('pgUpdate', () => { + it('runs query to update db', async () => { + const updateItem = {id: 1234, name: 'test'}; + const nodeParams = { + table: 'mytable', + schema: 'myschema', + updateKey: 'id', + columns: 'id,name' + }; + const getNodeParam = (key) => nodeParams[key]; + const pgp = pgPromise(); + const none = jest.fn(); + const db = {none}; + + const items = [ + { + json: updateItem + } + ]; + + const results = await PostgresFun.pgUpdate(getNodeParam, pgp, db, items) + + expect(db.none).toHaveBeenCalledWith(`update \"myschema\".\"mytable\" as t set \"id\"=v.\"id\",\"name\"=v.\"name\" from (values(1234,'test')) as v(\"id\",\"name\") WHERE v.id = t.id`); + expect(results).toEqual([updateItem]); + }); + + it('runs query to update db if updateKey is not in columns', async () => { + const updateItem = {id: 1234, name: 'test'}; + const nodeParams = { + table: 'mytable', + schema: 'myschema', + updateKey: 'id', + columns: 'name' + }; + const getNodeParam = (key) => nodeParams[key]; + const pgp = pgPromise(); + const none = jest.fn(); + const db = {none}; + + const items = [ + { + json: updateItem + } + ]; + + const results = await PostgresFun.pgUpdate(getNodeParam, pgp, db, items) + + expect(db.none).toHaveBeenCalledWith(`update \"myschema\".\"mytable\" as t set \"id\"=v.\"id\",\"name\"=v.\"name\" from (values(1234,'test')) as v(\"id\",\"name\") WHERE v.id = t.id`); + expect(results).toEqual([updateItem]); + }); + + it('runs query to update db with cast as updateKey', async () => { + const updateItem = {id: '1234', name: 'test'}; + const nodeParams = { + table: 'mytable', + schema: 'myschema', + updateKey: 'id:uuid', + columns: 'name' + }; + const getNodeParam = (key) => nodeParams[key]; + const pgp = pgPromise(); + const none = jest.fn(); + const db = {none}; + + const items = [ + { + json: updateItem + } + ]; + + const results = await PostgresFun.pgUpdate(getNodeParam, pgp, db, items) + + expect(db.none).toHaveBeenCalledWith(`update \"myschema\".\"mytable\" as t set \"id\"=v.\"id\",\"name\"=v.\"name\" from (values('1234'::uuid,'test')) as v(\"id\",\"name\") WHERE v.id = t.id`); + expect(results).toEqual([updateItem]); + }); + + it('runs query to update db with cast in target columns', async () => { + const updateItem = {id: '1234', name: 'test'}; + const nodeParams = { + table: 'mytable', + schema: 'myschema', + updateKey: 'id', + columns: 'id:uuid,name' + }; + const getNodeParam = (key) => nodeParams[key]; + const pgp = pgPromise(); + const none = jest.fn(); + const db = {none}; + + const items = [ + { + json: updateItem + } + ]; + + const results = await PostgresFun.pgUpdate(getNodeParam, pgp, db, items) + + expect(db.none).toHaveBeenCalledWith(`update \"myschema\".\"mytable\" as t set \"id\"=v.\"id\",\"name\"=v.\"name\" from (values('1234'::uuid,'test')) as v(\"id\",\"name\") WHERE v.id = t.id`); + expect(results).toEqual([updateItem]); + }); +}); + + + +describe('pgInsert', () => { + it('runs query to insert', async () => { + const insertItem = {id: 1234, name: 'test', age: 34}; + const nodeParams = { + table: 'mytable', + schema: 'myschema', + columns: 'id,name,age', + returnFields: '*', + }; + const getNodeParam = (key) => nodeParams[key]; + const pgp = pgPromise(); + const manyOrNone = jest.fn(); + const db = {manyOrNone}; + + const items = [ + { + json: insertItem, + }, + ]; + + const results = await PostgresFun.pgInsert(getNodeParam, pgp, db, items); + + expect(db.manyOrNone).toHaveBeenCalledWith(`insert into \"myschema\".\"mytable\"(\"id\",\"name\",\"age\") values(1234,'test',34) RETURNING *`); + expect(results).toEqual([undefined, [insertItem]]); + }); + + it('runs query to insert with type casting', async () => { + const insertItem = {id: 1234, name: 'test', age: 34}; + const nodeParams = { + table: 'mytable', + schema: 'myschema', + columns: 'id:int,name:text,age', + returnFields: '*', + }; + const getNodeParam = (key) => nodeParams[key]; + const pgp = pgPromise(); + const manyOrNone = jest.fn(); + const db = {manyOrNone}; + + const items = [ + { + json: insertItem, + }, + ]; + + const results = await PostgresFun.pgInsert(getNodeParam, pgp, db, items); + + expect(db.manyOrNone).toHaveBeenCalledWith(`insert into \"myschema\".\"mytable\"(\"id\",\"name\",\"age\") values(1234::int,'test'::text,34) RETURNING *`); + expect(results).toEqual([undefined, [insertItem]]); + }); +});