Skip to content
This repository was archived by the owner on Apr 29, 2025. It is now read-only.

Commit 3582e72

Browse files
committed
refactor(execute): use transactions and parse values
Parse each value while iterating prepared statements, ensuring objects are remapped to arrays and NULL values are properly inserted. Utilise transactions to rollback changes in the event of an error.
1 parent dea98f7 commit 3582e72

File tree

3 files changed

+31
-5
lines changed

3 files changed

+31
-5
lines changed

src/database/rawExecute.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { pool } from '.';
33
import { logQuery } from '../logger';
44
import { CFXCallback, CFXParameters, QueryResponse } from '../types';
55
import { parseResponse } from '../utils/parseResponse';
6-
import { executeType, parseExecute } from '../utils/parseExecute';
6+
import { executeType, parseExecute, parseValues } from '../utils/parseExecute';
77
import { scheduleTick } from '../utils/scheduleTick';
88

99
export const rawExecute = async (
@@ -24,10 +24,14 @@ export const rawExecute = async (
2424
let response: QueryResponse;
2525

2626
try {
27+
const placeholders = query.split('?').length - 1;
2728
const results = [] as RowDataPacket;
2829
const executionTime = process.hrtime();
2930

30-
for (const values of parameters) {
31+
await connection.beginTransaction();
32+
33+
parameters.forEach(async (values: any) => {
34+
values = parseValues(placeholders, values);
3135
const [rows] = (await connection.execute(query, values)) as RowDataPacket[][];
3236
if (rows.length > 1) {
3337
for (const row of rows) {
@@ -36,7 +40,7 @@ export const rawExecute = async (
3640
} else results.push(parseResponse(type, rows));
3741

3842
logQuery(invokingResource, query, process.hrtime(executionTime)[1] / 1e6, values as typeof parameters);
39-
}
43+
});
4044

4145
response = results;
4246

@@ -50,10 +54,14 @@ export const rawExecute = async (
5054
} else {
5155
response = results;
5256
}
57+
58+
await connection.commit();
5359
} catch (e) {
60+
await connection.rollback();
61+
5462
throw new Error(`${invokingResource} was unable to execute a query!
5563
${(e as QueryError).message}
56-
${`${query} ${JSON.stringify(parameters)}`}`);
64+
${`${(e as any).sql}`}`);
5765
} finally {
5866
connection.release();
5967
}

src/database/rawQuery.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const rawQuery = async (
1616
await scheduleTick();
1717
[query, parameters, cb] = parseArguments(invokingResource, query, parameters, cb);
1818

19+
//@ts-ignore TODO: patch mysql2 type
1920
pool.query(query, parameters, (err, result, _, executionTime) => {
2021
logQuery(invokingResource, query, executionTime, parameters);
2122
if (err)

src/utils/parseExecute.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,31 @@ export const executeType = (query: string) => {
1616
};
1717

1818
export const parseExecute = (parameters: CFXParameters | CFXParameters[]) => {
19-
if (!Array.isArray(parameters))
19+
if (!Array.isArray(parameters)) {
2020
if (typeof parameters === 'object') {
2121
const arr: unknown[] = [];
2222
Object.entries(parameters).forEach((entry) => (arr[parseInt(entry[0]) - 1] = entry[1]));
2323
parameters = arr;
2424
} else throw new Error(`Parameters expected an array but received ${typeof parameters} instead`);
25+
}
2526

2627
if (!parameters.every(Array.isArray)) parameters = [[...parameters]];
2728

2829
return parameters;
2930
};
31+
32+
export const parseValues = (placeholders: number, parameters: CFXParameters | CFXParameters[]) => {
33+
if (!Array.isArray(parameters)) {
34+
if (typeof parameters === 'object') {
35+
const arr: unknown[] = [];
36+
Object.entries(parameters).forEach((entry) => (arr[parseInt(entry[0]) - 1] = entry[1]));
37+
parameters = arr;
38+
} else throw new Error(`Parameters expected an array but received ${typeof parameters} instead`);
39+
} else if (placeholders > parameters.length) {
40+
for (let i = parameters.length; i < placeholders; i++) {
41+
parameters[i] = null;
42+
}
43+
}
44+
45+
return parameters;
46+
};

0 commit comments

Comments
 (0)