fix(MySQL Node): Query to statements splitting fix (#9207)

This commit is contained in:
Michael Kret 2024-04-25 16:30:59 +03:00 committed by GitHub
parent 093dcefafc
commit dc844528f4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 61 additions and 8 deletions

View file

@ -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',
};
@ -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);

View file

@ -8,6 +8,7 @@ import {
addSortRules,
replaceEmptyStringsByNulls,
escapeSqlIdentifier,
splitQueryToStatements,
} from '../../v2/helpers/utils';
const mySqlMockNode: INode = {
@ -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",
]);
});
});

View file

@ -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: {

View file

@ -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,
@ -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];
@ -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);
}
const responses: IDataObject[] = [];
for (const statement of statements) {
@ -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) {