Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(MySQL Node): Resolve expressions in v1 #7464

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions packages/nodes-base/nodes/MySql/test/v1/executeQuery.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import type { INodeTypes } from 'n8n-workflow';

import nock from 'nock';
import { getResultNodeData, setup, workflowToTests } from '@test/nodes/Helpers';
import type { WorkflowTestData } from '@test/nodes/types';
import { executeWorkflow } from '@test/nodes/ExecuteWorkflow';

const queryMock = jest.fn(async function () {
return [{ success: true }];
});

jest.mock('../../v1/GenericFunctions', () => {
const originalModule = jest.requireActual('../../v1/GenericFunctions');
return {
...originalModule,
createConnection: jest.fn(async function () {
return {
query: queryMock,
end: jest.fn(),
};
}),
};
});

describe('Test MySqlV1, executeQuery', () => {
const workflows = ['nodes/MySql/test/v1/executeQuery.workflow.json'];
const tests = workflowToTests(workflows);

beforeAll(() => {
nock.disableNetConnect();
});

afterAll(() => {
nock.restore();
jest.unmock('../../v1/GenericFunctions');
});

const nodeTypes = setup(tests);

const testNode = async (testData: WorkflowTestData, types: INodeTypes) => {
const { result } = await executeWorkflow(testData, types);

const resultNodeData = getResultNodeData(result, testData);

resultNodeData.forEach(({ nodeName, resultData }) => {
return expect(resultData).toEqual(testData.output.nodeData[nodeName]);
});

expect(queryMock).toHaveBeenCalledTimes(1);
expect(queryMock).toHaveBeenCalledWith(
"select * from family_parents where (parent_email = '[email protected]' or parent_email = '[email protected]') and parent_email <> '';",
);

expect(result.finished).toEqual(true);
};

for (const testData of tests) {
test(testData.description, async () => testNode(testData, nodeTypes));
}
});
127 changes: 127 additions & 0 deletions packages/nodes-base/nodes/MySql/test/v1/executeQuery.workflow.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
{
"name": "mysql v1 resolve expression copy",
"nodes": [
{
"parameters": {},
"id": "d6d9fbcc-d8bc-4f79-8e00-3acf8ffb12de",
"name": "When clicking \"Execute Workflow\"",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
460,
460
]
},
{
"parameters": {
"operation": "executeQuery",
"query": "select * from family_parents where (parent_email = {{ \"'\" + $json['Parent 1 email'] + \"'\" }} or parent_email = {{ \"'\" + $json['Parent 2 email'] + \"'\"}}) and parent_email <> '';\n"
},
"id": "faefc24c-91b4-4b10-85a6-b3cecbceee08",
"name": "Get matching families",
"type": "n8n-nodes-base.mySql",
"typeVersion": 1,
"position": [
900,
460
],
"credentials": {
"mySql": {
"id": "93",
"name": "MySQL account"
}
}
},
{
"parameters": {},
"id": "29c30f6e-9f5f-4b3a-80c4-2da762e96bd9",
"name": "No Operation, do nothing1",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [
1120,
460
]
},
{
"parameters": {
"fields": {
"values": [
{
"name": "Parent 1 email",
"stringValue": "[email protected]"
},
{
"name": "Parent 2 email",
"stringValue": "[email protected]"
}
]
},
"include": "none",
"options": {}
},
"id": "54c7bbf9-dabc-421b-85b2-7c3006f5ee61",
"name": "Edit Fields",
"type": "n8n-nodes-base.set",
"typeVersion": 3.2,
"position": [
680,
460
]
}
],
"pinData": {
"No Operation, do nothing1": [
{
"json": {
"success": true
}
}
]
},
"connections": {
"When clicking \"Execute Workflow\"": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"Get matching families": {
"main": [
[
{
"node": "No Operation, do nothing1",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields": {
"main": [
[
{
"node": "Get matching families",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "aeb01d24-c117-405a-875f-909ea8ccdc16",
"id": "GlTwlHZfQwNjbeqv",
"meta": {
"instanceId": "b888bd11cd1ddbb95450babf3e199556799d999b896f650de768b8370ee50363"
},
"tags": []
}
12 changes: 10 additions & 2 deletions packages/nodes-base/nodes/MySql/v1/MySqlV1.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type mysql2 from 'mysql2/promise';
import { createConnection, searchTables } from './GenericFunctions';

import { oldVersionNotice } from '@utils/descriptions';
import { getResolvables } from '@utils/utilities';

const versionDescription: INodeTypeDescription = {
displayName: 'MySQL',
Expand Down Expand Up @@ -306,8 +307,15 @@ export class MySqlV1 implements INodeType {
// ----------------------------------

try {
const queryQueue = items.map(async (item, index) => {
const rawQuery = this.getNodeParameter('query', index) as string;
const queryQueue = items.map(async (_, index) => {
let rawQuery = (this.getNodeParameter('query', index) as string).trim();

for (const resolvable of getResolvables(rawQuery)) {
rawQuery = rawQuery.replace(
resolvable,
this.evaluateExpression(resolvable, index) as string,
);
}

return connection.query(rawQuery);
});
Expand Down
Loading