Skip to content
Snippets Groups Projects
Commit 49699ae6 authored by Hedda Sofie Ulve's avatar Hedda Sofie Ulve
Browse files

Merge branch '23-give-the-user-feedback-if-the-query-had-wrong-syntax' into 'dev'

Resolve "Give the user feedback if the query had wrong syntax"

Closes #23

See merge request erlenyd/mysql-query-profiler!27
parents 2e1f754c 796732a8
Branches
No related tags found
No related merge requests found
......@@ -55,13 +55,24 @@ export default function QueryRecorder() {
console.log('not connected');
return;
}
try {
const result = await manager.record(changedQuery, explainAnalyze);
setOutput(JSON.stringify(result.queryResult, undefined, 2));
console.log(result);
if (result?.error) {
console.log(`QueryRecorder: Result: ${result}`);
setOutput(JSON.stringify(result.error.info.msg, undefined, 2));
} else {
setOutput(JSON.stringify(result?.result, undefined, 2));
const memoryPerformance = DataProcessor.processMemoryPerformance(
result.memoryPerformance
);
recordingContext?.setMemoryPerformance(memoryPerformance);
}
} catch (error) {
console.log(`QueryRecorder: Error: ${error}`);
}
}
async function doOptimizerQuery() {
if (!manager) {
......
......@@ -10,21 +10,20 @@ export interface MemoryPerformanceDataPoint {
export type MemoryPerformance = Array<MemoryPerformanceDataPoint>;
export class DataProcessor {
static processMemoryPerformance(performanceData: Result): MemoryPerformance {
static processMemoryPerformance(performanceData?: Result) {
// TODO: Add more restrictive tests
if (performanceData.labels.indexOf('geom') !== -1) {
if (!performanceData || performanceData.labels.indexOf('geom') !== -1) {
// TODO: Figure out why we need to skip the first element
const memoryPerformance: MemoryPerformance = performanceData.values
.slice(1)
.map((value: Array<ResultValue>) => {
return <MemoryPerformance>(
performanceData?.values.slice(1).map((value: Array<ResultValue>) => {
const dataPoint: MemoryPerformanceDataPoint = {
relative_time: Number(value[1]),
geom: Number(value[2]),
total: Number(value[3]),
};
return dataPoint;
});
return memoryPerformance;
})
);
}
throw new Error('DataProcessor: performanceData had wrong format');
}
......
......@@ -2,7 +2,7 @@ import { URI, Client } from '@mysql/xdevapi';
import { saveLoginDetails } from '../utils/fileutils';
import SqlRunner from './SqlRunner';
import SqlMonitor from './SqlMonitor';
import { Result } from '../utils/mysql';
import { closeConnection } from '../utils/mysql';
class SqlManager {
connection?: URI;
......@@ -15,7 +15,9 @@ class SqlManager {
monitor?: SqlMonitor;
async connect(connection: URI, database?: string) {
async connect(connection?: URI, database?: string) {
this.connection = connection;
this.database = database;
this.runner = new SqlRunner();
this.client = await this.runner.connect(connection, database);
this.monitor = new SqlMonitor();
......@@ -29,9 +31,22 @@ class SqlManager {
'SqlManager: Runner, monitor or connectionID was missing. Maybe you forgot to call connect()?'
);
this.monitor.monitorConnection(this.runner.connectionID);
const queryResult = await this.runner.executeQuery(query, explainAnalyze);
const result = await this.runner.executeQuery(query, explainAnalyze);
if (result?.error) {
await this.reset();
return { result, memoryPerformance: undefined, error: result.error };
}
const memoryPerformance = await this.monitor.dumpData();
return { queryResult, memoryPerformance };
return {
result,
memoryPerformance: memoryPerformance.results,
error: undefined,
};
}
async reset() {
await closeConnection(this.client);
await this.connect(this.connection, this.database);
}
async executeQuery(query: string) {
......
......@@ -11,7 +11,7 @@ export default class SqlMonitor {
async connect(client?: Client, database?: string) {
this.session = await createSession(client, database);
const resultSet = await runQuery(`SELECT connection_id();`, this.session);
this.connectionID = String(resultSet?.values[0]);
this.connectionID = String(resultSet?.results?.values[0]);
console.log(`SqlMonitor: ConnectionID: ${this.connectionID}`);
}
......
......@@ -11,13 +11,13 @@ export default class SqlRunner {
connectionID?: string;
async connect(connection: URI, database?: string) {
async connect(connection?: URI, database?: string) {
const client = await createConnection(connection, {
pooling: { enabled: true, maxSize: 2 },
});
this.session = await createSession(client, database);
const resultSet = await runQuery(`SELECT connection_id();`, this.session);
this.connectionID = String(resultSet?.values[0]);
this.connectionID = String(resultSet?.results?.values[0]);
console.log(`SqlRunner: ConnectionID: ${this.connectionID}`);
return client;
}
......
......@@ -37,11 +37,11 @@ export async function runQuery(query: string, session?: Session) {
console.log(
`Result from query '${query}':\n${JSON.stringify(results, undefined, 2)}`
);
return results;
return { results, error: undefined };
} catch (error) {
// TODO: Do more to handle errors
console.error(`Error while running query: ${error}`);
throw error;
return { results: undefined, error };
}
}
......@@ -141,8 +141,9 @@ export async function createSession(client?: Client, database?: string) {
* Close the connection, destroying the pool, closing and cleaning up all connections in the pool
* @param client
*/
export async function closeConnection(client: Client) {
export async function closeConnection(client?: Client) {
try {
if (!client) throw new Error('No client passed');
await client.close();
} catch (error) {
// TODO: Do more to handle errors
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment