mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 20:24:05 -08:00
fix(Postgres Node): Empty return data fix for Postgres and MySQL (#7016)
This commit is contained in:
parent
f02f6b659a
commit
176ccd62bc
|
@ -11,7 +11,7 @@ export class MySql extends VersionedNodeType {
|
|||
name: 'mySql',
|
||||
icon: 'file:mysql.svg',
|
||||
group: ['input'],
|
||||
defaultVersion: 2.1,
|
||||
defaultVersion: 2.2,
|
||||
description: 'Get, add and update data in MySQL',
|
||||
};
|
||||
|
||||
|
@ -19,6 +19,7 @@ export class MySql extends VersionedNodeType {
|
|||
1: new MySqlV1(baseDescription),
|
||||
2: new MySqlV2(baseDescription),
|
||||
2.1: new MySqlV2(baseDescription),
|
||||
2.2: new MySqlV2(baseDescription),
|
||||
};
|
||||
|
||||
super(nodeVersions, baseDescription);
|
||||
|
|
|
@ -305,7 +305,7 @@ describe('Test MySql V2, operations', () => {
|
|||
|
||||
const runQueries: QueryRunner = configureQueryRunner.call(
|
||||
fakeExecuteFunction,
|
||||
nodeOptions,
|
||||
{ ...nodeOptions, nodeVersion: 2 },
|
||||
pool,
|
||||
);
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ describe('Test MySql V2, runQueries', () => {
|
|||
});
|
||||
|
||||
it('should execute in "Single" mode, should return success true', async () => {
|
||||
const nodeOptions: IDataObject = { queryBatching: BATCH_MODE.SINGLE };
|
||||
const nodeOptions: IDataObject = { queryBatching: BATCH_MODE.SINGLE, nodeVersion: 2 };
|
||||
|
||||
const pool = createFakePool(fakeConnection);
|
||||
const fakeExecuteFunction = createMockExecuteFunction({}, mySqlMockNode);
|
||||
|
@ -81,7 +81,7 @@ describe('Test MySql V2, runQueries', () => {
|
|||
});
|
||||
|
||||
it('should execute in "independently" mode, should return success true', async () => {
|
||||
const nodeOptions: IDataObject = { queryBatching: BATCH_MODE.INDEPENDENTLY };
|
||||
const nodeOptions: IDataObject = { queryBatching: BATCH_MODE.INDEPENDENTLY, nodeVersion: 2 };
|
||||
|
||||
const pool = createFakePool(fakeConnection);
|
||||
|
||||
|
@ -126,7 +126,7 @@ describe('Test MySql V2, runQueries', () => {
|
|||
});
|
||||
|
||||
it('should execute in "transaction" mode, should return success true', async () => {
|
||||
const nodeOptions: IDataObject = { queryBatching: BATCH_MODE.TRANSACTION };
|
||||
const nodeOptions: IDataObject = { queryBatching: BATCH_MODE.TRANSACTION, nodeVersion: 2 };
|
||||
|
||||
const pool = createFakePool(fakeConnection);
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ export const versionDescription: INodeTypeDescription = {
|
|||
name: 'mySql',
|
||||
icon: 'file:mysql.svg',
|
||||
group: ['input'],
|
||||
version: [2, 2.1],
|
||||
version: [2, 2.1, 2.2],
|
||||
subtitle: '={{ $parameter["operation"] }}',
|
||||
description: 'Get, add and update data in MySQL',
|
||||
defaults: {
|
||||
|
|
|
@ -167,7 +167,23 @@ export function prepareOutput(
|
|||
}
|
||||
|
||||
if (!returnData.length) {
|
||||
returnData.push({ json: { success: true } });
|
||||
if ((options?.nodeVersion as number) < 2.2) {
|
||||
returnData.push({ json: { success: true } });
|
||||
} else {
|
||||
const isSelectQuery = statements
|
||||
.filter((statement) => !statement.startsWith('--'))
|
||||
.every((statement) =>
|
||||
statement
|
||||
.replace(/\/\*.*?\*\//g, '') // remove multiline comments
|
||||
.replace(/\n/g, '')
|
||||
.toLowerCase()
|
||||
.startsWith('select'),
|
||||
);
|
||||
|
||||
if (!isSelectQuery) {
|
||||
returnData.push({ json: { success: true } });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return returnData;
|
||||
|
|
|
@ -11,7 +11,7 @@ export class Postgres extends VersionedNodeType {
|
|||
name: 'postgres',
|
||||
icon: 'file:postgres.svg',
|
||||
group: ['input'],
|
||||
defaultVersion: 2.2,
|
||||
defaultVersion: 2.3,
|
||||
description: 'Get, add and update data in Postgres',
|
||||
};
|
||||
|
||||
|
@ -20,6 +20,7 @@ export class Postgres extends VersionedNodeType {
|
|||
2: new PostgresV2(baseDescription),
|
||||
2.1: new PostgresV2(baseDescription),
|
||||
2.2: new PostgresV2(baseDescription),
|
||||
2.3: new PostgresV2(baseDescription),
|
||||
};
|
||||
|
||||
super(nodeVersions, baseDescription);
|
||||
|
|
|
@ -44,7 +44,9 @@ describe('Test PostgresV2, runQueries', () => {
|
|||
const thisArg = mock<IExecuteFunctions>();
|
||||
const runQueries = configureQueryRunner.call(thisArg, node, false, pgp, db);
|
||||
|
||||
const result = await runQueries([{ query: 'SELECT * FROM table', values: [] }], [], {});
|
||||
const result = await runQueries([{ query: 'SELECT * FROM table', values: [] }], [], {
|
||||
nodeVersion: 2.2,
|
||||
});
|
||||
|
||||
expect(result).toBeDefined();
|
||||
expect(result).toHaveLength(1);
|
||||
|
|
|
@ -8,7 +8,7 @@ export const versionDescription: INodeTypeDescription = {
|
|||
name: 'postgres',
|
||||
icon: 'file:postgres.svg',
|
||||
group: ['input'],
|
||||
version: [2, 2.1, 2.2],
|
||||
version: [2, 2.1, 2.2, 2.3],
|
||||
subtitle: '={{ $parameter["operation"] }}',
|
||||
description: 'Get, add and update data in Postgres',
|
||||
defaults: {
|
||||
|
|
|
@ -199,6 +199,15 @@ export function addReturning(
|
|||
return [`${query} RETURNING $${replacementIndex}:name`, [...replacements, outputColumns]];
|
||||
}
|
||||
|
||||
const isSelectQuery = (query: string) => {
|
||||
return query
|
||||
.replace(/\/\*.*?\*\//g, '') // remove multiline comments
|
||||
.replace(/\n/g, '')
|
||||
.split(';')
|
||||
.filter((statement) => statement && !statement.startsWith('--')) // remove comments and empty statements
|
||||
.every((statement) => statement.trim().toLowerCase().startsWith('select'));
|
||||
};
|
||||
|
||||
export function configureQueryRunner(
|
||||
this: IExecuteFunctions,
|
||||
node: INode,
|
||||
|
@ -221,7 +230,16 @@ export function configureQueryRunner(
|
|||
});
|
||||
})
|
||||
.flat();
|
||||
returnData = returnData.length ? returnData : emptyReturnData;
|
||||
|
||||
if (!returnData.length) {
|
||||
if ((options?.nodeVersion as number) < 2.3) {
|
||||
returnData = emptyReturnData;
|
||||
} else {
|
||||
returnData = queries.every((query) => isSelectQuery(query.query))
|
||||
? []
|
||||
: [{ json: { success: true } }];
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
const error = parsePostgresError(node, err, queries);
|
||||
if (!continueOnFail) throw error;
|
||||
|
@ -242,13 +260,26 @@ export function configureQueryRunner(
|
|||
const result: INodeExecutionData[] = [];
|
||||
for (let i = 0; i < queries.length; i++) {
|
||||
try {
|
||||
const transactionResult: IDataObject[] = await transaction.any(
|
||||
queries[i].query,
|
||||
queries[i].values,
|
||||
);
|
||||
const query = queries[i].query;
|
||||
const values = queries[i].values;
|
||||
|
||||
let transactionResults;
|
||||
if ((options?.nodeVersion as number) < 2.3) {
|
||||
transactionResults = await transaction.any(query, values);
|
||||
} else {
|
||||
transactionResults = (await transaction.multi(query, values)).flat();
|
||||
}
|
||||
|
||||
if (!transactionResults.length) {
|
||||
if ((options?.nodeVersion as number) < 2.3) {
|
||||
transactionResults = emptyReturnData;
|
||||
} else {
|
||||
transactionResults = isSelectQuery(query) ? [] : [{ success: true }];
|
||||
}
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
wrapData(transactionResult.length ? transactionResult : emptyReturnData),
|
||||
wrapData(transactionResults),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
|
||||
|
@ -265,17 +296,30 @@ export function configureQueryRunner(
|
|||
}
|
||||
|
||||
if (queryBatching === 'independently') {
|
||||
returnData = await db.task(async (t) => {
|
||||
returnData = await db.task(async (task) => {
|
||||
const result: INodeExecutionData[] = [];
|
||||
for (let i = 0; i < queries.length; i++) {
|
||||
try {
|
||||
const transactionResult: IDataObject[] = await t.any(
|
||||
queries[i].query,
|
||||
queries[i].values,
|
||||
);
|
||||
const query = queries[i].query;
|
||||
const values = queries[i].values;
|
||||
|
||||
let transactionResults;
|
||||
if ((options?.nodeVersion as number) < 2.3) {
|
||||
transactionResults = await task.any(query, values);
|
||||
} else {
|
||||
transactionResults = (await task.multi(query, values)).flat();
|
||||
}
|
||||
|
||||
if (!transactionResults.length) {
|
||||
if ((options?.nodeVersion as number) < 2.3) {
|
||||
transactionResults = emptyReturnData;
|
||||
} else {
|
||||
transactionResults = isSelectQuery(query) ? [] : [{ success: true }];
|
||||
}
|
||||
}
|
||||
|
||||
const executionData = this.helpers.constructExecutionMetaData(
|
||||
wrapData(transactionResult.length ? transactionResult : emptyReturnData),
|
||||
wrapData(transactionResults),
|
||||
{ itemData: { item: i } },
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in a new issue