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): Query to statements splitting fix #9207

Merged
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
3 changes: 2 additions & 1 deletion packages/nodes-base/nodes/MySql/MySql.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class MySql extends VersionedNodeType {
name: 'mySql',
icon: 'file:mysql.svg',
group: ['input'],
defaultVersion: 2.3,
defaultVersion: 2.4,
description: 'Get, add and update data in MySQL',
parameterPane: 'wide',
};
Expand All @@ -22,6 +22,7 @@ export class MySql extends VersionedNodeType {
2.1: new MySqlV2(baseDescription),
2.2: new MySqlV2(baseDescription),
2.3: new MySqlV2(baseDescription),
2.4: new MySqlV2(baseDescription),
};

super(nodeVersions, baseDescription);
Expand Down
27 changes: 27 additions & 0 deletions packages/nodes-base/nodes/MySql/test/v2/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
addSortRules,
replaceEmptyStringsByNulls,
escapeSqlIdentifier,
splitQueryToStatements,
} from '../../v2/helpers/utils';

const mySqlMockNode: INode = {
Expand Down Expand Up @@ -175,3 +176,29 @@ describe('Test MySql V2, escapeSqlIdentifier', () => {
expect(escapedIdentifier).toEqual('`db_name`.`some.dotted.tbl_name`');
});
});

describe('Test MySql V2, splitQueryToStatements', () => {
it('should split query into statements', () => {
const query =
"insert into models (`created_at`, custom_ship_time, id) values ('2023-09-07 10:26:20', 'some random; data with a semicolon', 1); insert into models (`created_at`, custom_ship_time, id) values ('2023-09-07 10:27:55', 'random data without semicolon\n', 2);";

const statements = splitQueryToStatements(query);

expect(statements).toBeDefined();
expect(statements).toEqual([
"insert into models (`created_at`, custom_ship_time, id) values ('2023-09-07 10:26:20', 'some random; data with a semicolon', 1)",
"insert into models (`created_at`, custom_ship_time, id) values ('2023-09-07 10:27:55', 'random data without semicolon', 2)",
]);
});
it('should not split by ; inside string literal', () => {
const query =
"SELECT custom_ship_time FROM models WHERE models.custom_ship_time LIKE CONCAT('%', ';', '%') LIMIT 10";

const statements = splitQueryToStatements(query);

expect(statements).toBeDefined();
expect(statements).toEqual([
"SELECT custom_ship_time FROM models WHERE models.custom_ship_time LIKE CONCAT('%', ';', '%') LIMIT 10",
]);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const versionDescription: INodeTypeDescription = {
name: 'mySql',
icon: 'file:mysql.svg',
group: ['input'],
version: [2, 2.1, 2.2, 2.3],
version: [2, 2.1, 2.2, 2.3, 2.4],
subtitle: '={{ $parameter["operation"] }}',
description: 'Get, add and update data in MySQL',
defaults: {
Expand Down
37 changes: 31 additions & 6 deletions packages/nodes-base/nodes/MySql/v2/helpers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,14 @@ export function prepareOutput(

return returnData;
}
const END_OF_STATEMENT = /;(?=(?:[^'\\]|'[^']*?'|\\[\s\S])*?$)/g;
export const splitQueryToStatements = (query: string, filterOutEmpty = true) => {
const statements = query
.replace(/\n/g, '')
.split(END_OF_STATEMENT)
.map((statement) => statement.trim());
return filterOutEmpty ? statements.filter((statement) => statement !== '') : statements;
};

export function configureQueryRunner(
this: IExecuteFunctions,
Expand Down Expand Up @@ -225,10 +233,15 @@ export function configureQueryRunner(

if (!response) return [];

const statements = singleQuery
.replace(/\n/g, '')
.split(';')
.filter((statement) => statement !== '');
let statements;
if ((options?.nodeVersion as number) <= 2.3) {
statements = singleQuery
.replace(/\n/g, '')
.split(';')
.filter((statement) => statement !== '');
} else {
statements = splitQueryToStatements(singleQuery);
}

if (Array.isArray(response)) {
if (statements.length === 1) response = [response];
Expand Down Expand Up @@ -261,7 +274,13 @@ export function configureQueryRunner(
try {
const { query, values } = queryWithValues;
formatedQuery = connection.format(query, values);
const statements = formatedQuery.split(';').map((q) => q.trim());

let statements;
if ((options?.nodeVersion as number) <= 2.3) {
statements = formatedQuery.split(';').map((q) => q.trim());
} else {
statements = splitQueryToStatements(formatedQuery, false);
elsmr marked this conversation as resolved.
Show resolved Hide resolved
}

const responses: IDataObject[] = [];
for (const statement of statements) {
Expand Down Expand Up @@ -300,7 +319,13 @@ export function configureQueryRunner(
try {
const { query, values } = queryWithValues;
formatedQuery = connection.format(query, values);
const statements = formatedQuery.split(';').map((q) => q.trim());

let statements;
if ((options?.nodeVersion as number) <= 2.3) {
statements = formatedQuery.split(';').map((q) => q.trim());
} else {
statements = splitQueryToStatements(formatedQuery, false);
}

const responses: IDataObject[] = [];
for (const statement of statements) {
Expand Down
Loading