mirror of
https://github.com/n8n-io/n8n.git
synced 2025-01-11 04:47:29 -08:00
✨ Add query parameters for CrateDB, PostgresDB, TimescaleDB and QuestDB (Parametrized Queries) (#1577)
* Adding support to ParameterizedQuery on Postgres Node * Created another parameter to toggle on replacement so it's clear to users what is happening. * Fixed lint issues * ⚡ Formatting * Improvements to questDB node so it is more consistent * Fixed lint issues * Fixed typing issue * ⚡ Apply suggestions BHesseldieck Co-authored-by: Ben Hesseldieck <1849459+BHesseldieck@users.noreply.github.com> * Standardized output for postgres and postgres-like nodes This changes the behavior of CrateDB, Postgres, QuestDB and TimescaleDB nodes. The Execute Query operation used to execute multiple queries but return the result from only one of the queries. This change causes the node output to containt results from all queries that ran, making the behavior more consistent across all n8n. * Fixing lint issues * ⚡ Minor improvements * ⚡ Fix breaking changes files Co-authored-by: Gustavo Arjones <gustavo.arjones@ank.app> Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com> Co-authored-by: Jan <janober@users.noreply.github.com> Co-authored-by: Ben Hesseldieck <1849459+BHesseldieck@users.noreply.github.com>
This commit is contained in:
parent
4cf8055224
commit
fc54f7c82b
|
@ -2,6 +2,15 @@
|
|||
|
||||
This list shows all the versions which include breaking changes and how to upgrade.
|
||||
|
||||
## 0.118.0
|
||||
|
||||
### What changed?
|
||||
In the Postgres, CrateDB, QuestDB and TimescaleDB nodes the `Execute Query` operation returns the result from all queries executed instead of just one of the results.
|
||||
|
||||
### When is action necessary?
|
||||
|
||||
If you use any of the above mentioned nodes with the `Execute Query` operation and the result is relevant to you, you are encouraged to revisit your logic. The node output may now contain more information than before. This change was made so that the behavior is more consistent across n8n where input with multiple rows should yield results acccording all input data instead of only one. Please note: n8n was already running multiple queries based on input. Only the output was changed.
|
||||
|
||||
## 0.117.0
|
||||
|
||||
### What changed?
|
||||
|
@ -50,6 +59,7 @@ If you are using a Dropbox APP with permission type, "App Folder".
|
|||
### How to upgrade:
|
||||
|
||||
Open your Dropbox node's credentials and set the "APP Access Type" parameter to "App Folder".
|
||||
>>>>>>> master
|
||||
|
||||
## 0.111.0
|
||||
|
||||
|
|
|
@ -80,9 +80,9 @@ export class CrateDb implements INodeType {
|
|||
},
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'SELECT id, name FROM product WHERE id < 40',
|
||||
placeholder: 'SELECT id, name FROM product WHERE quantity > $1 AND price <= $2',
|
||||
required: true,
|
||||
description: 'The SQL query to execute.',
|
||||
description: 'The SQL query to execute. You can use n8n expressions or $1 and $2 in conjunction with query parameters.',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
|
@ -235,6 +235,21 @@ export class CrateDb implements INodeType {
|
|||
'See the docs for more examples',
|
||||
].join('<br>'),
|
||||
},
|
||||
{
|
||||
displayName: 'Query Parameters',
|
||||
name: 'queryParams',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/operation': [
|
||||
'executeQuery',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'quantity,price',
|
||||
description: 'Comma separated list of properties which should be used as query parameters.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
@ -60,27 +60,40 @@ export async function pgQuery(
|
|||
getNodeParam: Function,
|
||||
pgp: pgPromise.IMain<{}, pg.IClient>,
|
||||
db: pgPromise.IDatabase<{}, pg.IClient>,
|
||||
input: INodeExecutionData[],
|
||||
items: INodeExecutionData[],
|
||||
continueOnFail: boolean,
|
||||
overrideMode?: string,
|
||||
): Promise<IDataObject[]> {
|
||||
const additionalFields = getNodeParam('additionalFields', 0) as IDataObject;
|
||||
|
||||
let valuesArray = [] as string[][];
|
||||
if (additionalFields.queryParams) {
|
||||
const propertiesString = additionalFields.queryParams as string;
|
||||
const properties = propertiesString.split(',').map(column => column.trim());
|
||||
const paramsItems = getItemsCopy(items, properties);
|
||||
valuesArray = paramsItems.map((row) => properties.map(col => row[col])) as string[][];
|
||||
}
|
||||
|
||||
const allQueries = [] as Array<{query: string, values?: string[]}>;
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const query = getNodeParam('query', i) as string;
|
||||
const values = valuesArray[i];
|
||||
const queryFormat = { query, values };
|
||||
allQueries.push(queryFormat);
|
||||
}
|
||||
|
||||
const mode = overrideMode ? overrideMode : (additionalFields.mode ?? 'multiple') as string;
|
||||
if (mode === 'multiple') {
|
||||
const queries: string[] = [];
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
queries.push(getNodeParam('query', i) as string);
|
||||
}
|
||||
return (await db.multi(pgp.helpers.concat(queries))).flat(1);
|
||||
return (await db.multi(pgp.helpers.concat(allQueries))).flat(1);
|
||||
} else if (mode === 'transaction') {
|
||||
return db.tx(async t => {
|
||||
const result: IDataObject[] = [];
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
for (let i = 0; i < allQueries.length; i++) {
|
||||
try {
|
||||
Array.prototype.push.apply(result, await t.any(getNodeParam('query', i) as string));
|
||||
Array.prototype.push.apply(result, await t.any(allQueries[i].query, allQueries[i].values));
|
||||
} catch (err) {
|
||||
if (continueOnFail === false) throw err;
|
||||
result.push({ ...input[i].json, code: err.code, message: err.message });
|
||||
result.push({ ...items[i].json, code: err.code, message: err.message });
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -89,12 +102,12 @@ export async function pgQuery(
|
|||
} else if (mode === 'independently') {
|
||||
return db.task(async t => {
|
||||
const result: IDataObject[] = [];
|
||||
for (let i = 0; i < input.length; i++) {
|
||||
for (let i = 0; i < allQueries.length; i++) {
|
||||
try {
|
||||
Array.prototype.push.apply(result, await t.any(getNodeParam('query', i) as string));
|
||||
Array.prototype.push.apply(result, await t.any(allQueries[i].query, allQueries[i].values));
|
||||
} catch (err) {
|
||||
if (continueOnFail === false) throw err;
|
||||
result.push({ ...input[i].json, code: err.code, message: err.message });
|
||||
result.push({ ...items[i].json, code: err.code, message: err.message });
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -73,9 +73,9 @@ export class Postgres implements INodeType {
|
|||
},
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'SELECT id, name FROM product WHERE id < 40',
|
||||
placeholder: 'SELECT id, name FROM product WHERE quantity > $1 AND price <= $2',
|
||||
required: true,
|
||||
description: 'The SQL query to execute.',
|
||||
description: 'The SQL query to execute. You can use n8n expressions or $1 and $2 in conjunction with query parameters.',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
|
@ -232,6 +232,21 @@ export class Postgres implements INodeType {
|
|||
'See the docs for more examples',
|
||||
].join('<br>'),
|
||||
},
|
||||
{
|
||||
displayName: 'Query Parameters',
|
||||
name: 'queryParams',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/operation': [
|
||||
'executeQuery',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'quantity,price',
|
||||
description: 'Comma separated list of properties which should be used as query parameters.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
|
@ -73,9 +73,9 @@ export class QuestDb implements INodeType {
|
|||
},
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'SELECT id, name FROM product WHERE id < 40',
|
||||
placeholder: 'SELECT id, name FROM product WHERE quantity > $1 AND price <= $2',
|
||||
required: true,
|
||||
description: 'The SQL query to execute.',
|
||||
description: 'The SQL query to execute. You can use n8n expressions or $1 and $2 in conjunction with query parameters.',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
|
@ -176,6 +176,21 @@ export class QuestDb implements INodeType {
|
|||
'See the docs for more examples',
|
||||
].join('<br>'),
|
||||
},
|
||||
{
|
||||
displayName: 'Query Parameters',
|
||||
name: 'queryParams',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/operation': [
|
||||
'executeQuery',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'quantity,price',
|
||||
description: 'Comma separated list of properties which should be used as query parameters.',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
@ -215,7 +230,7 @@ export class QuestDb implements INodeType {
|
|||
|
||||
const db = pgp(config);
|
||||
|
||||
let returnItems = [];
|
||||
let returnItems: INodeExecutionData[] = [];
|
||||
|
||||
const items = this.getInputData();
|
||||
const operation = this.getNodeParameter('operation', 0) as string;
|
||||
|
|
|
@ -11,7 +11,6 @@ import {
|
|||
} from 'n8n-workflow';
|
||||
|
||||
import {
|
||||
getItemCopy,
|
||||
pgInsert,
|
||||
pgQuery,
|
||||
pgUpdate,
|
||||
|
@ -77,15 +76,13 @@ export class TimescaleDb implements INodeType {
|
|||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
operation: [
|
||||
'executeQuery',
|
||||
],
|
||||
operation: ['executeQuery'],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'SELECT id, name FROM product WHERE id < 40',
|
||||
placeholder: 'SELECT id, name FROM product WHERE quantity > $1 AND price <= $2',
|
||||
required: true,
|
||||
description: 'The SQL query to execute.',
|
||||
description: 'The SQL query to execute. You can use n8n expressions or $1 and $2 in conjunction with query parameters.',
|
||||
},
|
||||
|
||||
// ----------------------------------
|
||||
|
@ -256,6 +253,21 @@ export class TimescaleDb implements INodeType {
|
|||
'See the docs for more examples',
|
||||
].join('<br>'),
|
||||
},
|
||||
{
|
||||
displayName: 'Query Parameters',
|
||||
name: 'queryParams',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
'/operation': [
|
||||
'executeQuery',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'quantity,price',
|
||||
description: 'Comma separated list of properties which should be used as query parameters.',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
|
Loading…
Reference in a new issue