mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-19 11:01:15 +00:00
feat(Merge Node): Option in combineBySql operation to return either confirmation of succes or empty result (#15509)
This commit is contained in:
@@ -14,7 +14,7 @@ export class Merge extends VersionedNodeType {
|
|||||||
group: ['transform'],
|
group: ['transform'],
|
||||||
subtitle: '={{$parameter["mode"]}}',
|
subtitle: '={{$parameter["mode"]}}',
|
||||||
description: 'Merges data of multiple streams once data from both is available',
|
description: 'Merges data of multiple streams once data from both is available',
|
||||||
defaultVersion: 3.1,
|
defaultVersion: 3.2,
|
||||||
};
|
};
|
||||||
|
|
||||||
const nodeVersions: IVersionedNodeType['nodeVersions'] = {
|
const nodeVersions: IVersionedNodeType['nodeVersions'] = {
|
||||||
@@ -23,6 +23,7 @@ export class Merge extends VersionedNodeType {
|
|||||||
2.1: new MergeV2(baseDescription),
|
2.1: new MergeV2(baseDescription),
|
||||||
3: new MergeV3(baseDescription),
|
3: new MergeV3(baseDescription),
|
||||||
3.1: new MergeV3(baseDescription),
|
3.1: new MergeV3(baseDescription),
|
||||||
|
3.2: new MergeV3(baseDescription),
|
||||||
};
|
};
|
||||||
|
|
||||||
super(nodeVersions, baseDescription);
|
super(nodeVersions, baseDescription);
|
||||||
|
|||||||
@@ -396,6 +396,59 @@ describe('Test MergeV3, combineBySql operation', () => {
|
|||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Empty successful query should return [{ success: true }] at version <= 3.1', async () => {
|
||||||
|
const nodeParameters: IDataObject = {
|
||||||
|
operation: 'combineBySql',
|
||||||
|
query: 'SELECT id from input1',
|
||||||
|
};
|
||||||
|
|
||||||
|
const returnData = await mode.combineBySql.execute.call(
|
||||||
|
createMockExecuteFunction(nodeParameters, { ...node, typeVersion: 3.1 }),
|
||||||
|
[[]],
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(returnData.length).toEqual(1);
|
||||||
|
expect(returnData[0].length).toEqual(1);
|
||||||
|
expect(returnData[0][0].json).toEqual({
|
||||||
|
success: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Empty successful query should return [] at version >= 3.2 if no option set', async () => {
|
||||||
|
const nodeParameters: IDataObject = {
|
||||||
|
operation: 'combineBySql',
|
||||||
|
query: 'SELECT id from input1',
|
||||||
|
};
|
||||||
|
|
||||||
|
const returnData = await mode.combineBySql.execute.call(
|
||||||
|
createMockExecuteFunction(nodeParameters, { ...node, typeVersion: 3.2 }),
|
||||||
|
[[]],
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(returnData).toEqual([[]]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Empty successful query should return [{ success: true }] at version >= 3.2 if option set', async () => {
|
||||||
|
const nodeParameters: IDataObject = {
|
||||||
|
operation: 'combineBySql',
|
||||||
|
query: 'SELECT id from input1',
|
||||||
|
options: {
|
||||||
|
emptyQueryResult: 'success',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const returnData = await mode.combineBySql.execute.call(
|
||||||
|
createMockExecuteFunction(nodeParameters, { ...node, typeVersion: 3.2 }),
|
||||||
|
[[]],
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(returnData.length).toEqual(1);
|
||||||
|
expect(returnData[0].length).toEqual(1);
|
||||||
|
expect(returnData[0][0].json).toEqual({
|
||||||
|
success: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Test MergeV3, append operation', () => {
|
describe('Test MergeV3, append operation', () => {
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ import { getResolvables, updateDisplayOptions } from '@utils/utilities';
|
|||||||
import { numberInputsProperty } from '../../helpers/descriptions';
|
import { numberInputsProperty } from '../../helpers/descriptions';
|
||||||
import { modifySelectQuery, rowToExecutionData } from '../../helpers/utils';
|
import { modifySelectQuery, rowToExecutionData } from '../../helpers/utils';
|
||||||
|
|
||||||
|
type OperationOptions = {
|
||||||
|
emptyQueryResult: 'success' | 'empty';
|
||||||
|
};
|
||||||
|
|
||||||
export const properties: INodeProperties[] = [
|
export const properties: INodeProperties[] = [
|
||||||
numberInputsProperty,
|
numberInputsProperty,
|
||||||
{
|
{
|
||||||
@@ -33,6 +37,37 @@ export const properties: INodeProperties[] = [
|
|||||||
editor: 'sqlEditor',
|
editor: 'sqlEditor',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
displayName: 'Options',
|
||||||
|
name: 'options',
|
||||||
|
type: 'collection',
|
||||||
|
placeholder: 'Add option',
|
||||||
|
default: {},
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
displayName: 'Empty Query Result',
|
||||||
|
name: 'emptyQueryResult',
|
||||||
|
type: 'options',
|
||||||
|
description: 'What to return if the query executed successfully but returned no results',
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'Success',
|
||||||
|
value: 'success',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Empty Result',
|
||||||
|
value: 'empty',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
default: 'empty',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
displayOptions: {
|
||||||
|
show: {
|
||||||
|
'@version': [3.2],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const displayOptions = {
|
const displayOptions = {
|
||||||
@@ -61,6 +96,7 @@ async function executeSelectWithMappedPairedItems(
|
|||||||
node: INode,
|
node: INode,
|
||||||
inputsData: INodeExecutionData[][],
|
inputsData: INodeExecutionData[][],
|
||||||
query: string,
|
query: string,
|
||||||
|
returnSuccessItemIfEmpty: boolean,
|
||||||
): Promise<INodeExecutionData[][]> {
|
): Promise<INodeExecutionData[][]> {
|
||||||
const returnData: INodeExecutionData[] = [];
|
const returnData: INodeExecutionData[] = [];
|
||||||
|
|
||||||
@@ -95,7 +131,7 @@ async function executeSelectWithMappedPairedItems(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!returnData.length) {
|
if (!returnData.length && returnSuccessItemIfEmpty) {
|
||||||
returnData.push({ json: { success: true } });
|
returnData.push({ json: { success: true } });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -114,6 +150,7 @@ export async function execute(
|
|||||||
const node = this.getNode();
|
const node = this.getNode();
|
||||||
const returnData: INodeExecutionData[] = [];
|
const returnData: INodeExecutionData[] = [];
|
||||||
const pairedItem: IPairedItemData[] = [];
|
const pairedItem: IPairedItemData[] = [];
|
||||||
|
const options = this.getNodeParameter('options', 0, {}) as OperationOptions;
|
||||||
|
|
||||||
let query = this.getNodeParameter('query', 0) as string;
|
let query = this.getNodeParameter('query', 0) as string;
|
||||||
|
|
||||||
@@ -122,10 +159,17 @@ export async function execute(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const isSelectQuery = node.typeVersion >= 3.1 ? query.toLowerCase().startsWith('select') : false;
|
const isSelectQuery = node.typeVersion >= 3.1 ? query.toLowerCase().startsWith('select') : false;
|
||||||
|
const returnSuccessItemIfEmpty =
|
||||||
|
node.typeVersion <= 3.1 ? true : options.emptyQueryResult === 'success';
|
||||||
|
|
||||||
if (isSelectQuery) {
|
if (isSelectQuery) {
|
||||||
try {
|
try {
|
||||||
return await executeSelectWithMappedPairedItems(node, inputsData, query);
|
return await executeSelectWithMappedPairedItems(
|
||||||
|
node,
|
||||||
|
inputsData,
|
||||||
|
query,
|
||||||
|
returnSuccessItemIfEmpty,
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Container.get(ErrorReporter).error(error, {
|
Container.get(ErrorReporter).error(error, {
|
||||||
extra: {
|
extra: {
|
||||||
@@ -199,7 +243,7 @@ export async function execute(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!returnData.length) {
|
if (!returnData.length && returnSuccessItemIfEmpty) {
|
||||||
returnData.push({ json: { success: true }, pairedItem });
|
returnData.push({ json: { success: true }, pairedItem });
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export const versionDescription: INodeTypeDescription = {
|
|||||||
name: 'merge',
|
name: 'merge',
|
||||||
group: ['transform'],
|
group: ['transform'],
|
||||||
description: 'Merges data of multiple streams once data from both is available',
|
description: 'Merges data of multiple streams once data from both is available',
|
||||||
version: [3, 3.1],
|
version: [3, 3.1, 3.2],
|
||||||
defaults: {
|
defaults: {
|
||||||
name: 'Merge',
|
name: 'Merge',
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user