Skip to content

Commit

Permalink
sql: abort queries
Browse files Browse the repository at this point in the history
  • Loading branch information
joacoc committed Dec 13, 2023
1 parent da69383 commit cb76cae
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 9 deletions.
15 changes: 15 additions & 0 deletions src/context/asyncContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,21 @@ export default class AsyncContext extends Context {
}
}

/**
* Cancels a query by reconnecting the SQL client.
*
* This action will release the private client
* and create a new pool of clients.
*
*/
async cancelQuery() {
try {
await this.clients.sql?.reconnect();
} catch (err) {
throw new ExtensionError(Errors.cancelQueryError, err);
}
}

/**
* Adds a new profile.
*
Expand Down
30 changes: 23 additions & 7 deletions src/providers/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,17 @@ export const buildRunSQLCommand = (context: AsyncContext) => {
// the results from one query can overlap the results
// from another. We only want to display the last results.
const id = randomUUID();
let queryCanceled = false;
try {
resultsProvider.setQueryId(id);
const cancelHandler = () => {
console.log("[RunSQLCommand]", "Canceling query.");
queryCanceled = true;
context.cancelQuery();
}
resultsProvider.setQuery(
id,
cancelHandler
);
try {
const statements = await context.parseSql(query);
console.log("[RunSQLCommand]", "Running statements: ", statements);
Expand Down Expand Up @@ -78,13 +87,20 @@ export const buildRunSQLCommand = (context: AsyncContext) => {
sql: statement.sql
});

resultsProvider.setResults(id,
undefined,
{
message: error.toString(),
position: error.position,
if (!queryCanceled) {
resultsProvider.setResults(id,
undefined,
{
message: error.toString(),
position: error.position,
query,
});
} else {
resultsProvider.setResults(id, undefined, {
message: "Query canceled.",
query,
});
});
}

// Break for-loop.
break;
Expand Down
17 changes: 16 additions & 1 deletion src/providers/results.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ export default class ResultsProvider implements vscode.WebviewViewProvider {
// It is used to display the results and not overlap them from the results of a laggy query.
private lastQueryId: string | undefined;

// Handles query cancelation. After running this function
// the context will reconnect the SQL client.
private cancelHandler: undefined | (() => void);

// The provider can be invoked from `materialize.run`.
// When this happens, the inner rendering script will not be ready
// to listen changes. This variable holds the pending data to render
Expand All @@ -34,14 +38,19 @@ export default class ResultsProvider implements vscode.WebviewViewProvider {
constructor(private readonly _extensionUri: vscode.Uri) {
this._extensionUri = _extensionUri;
this.isScriptReady = false;
this.cancelHandler = undefined;
}

/**
* Cleans the results and sets a latest query id.
* @param id
*/
public setQueryId(id: string) {
public setQuery(
id: string,
cancelHandler: () => void,
) {
this.lastQueryId = id;
this.cancelHandler = cancelHandler;

if (this._view) {
console.log("[ResultsProvider]", "New query.");
Expand Down Expand Up @@ -113,6 +122,12 @@ export default class ResultsProvider implements vscode.WebviewViewProvider {
console.error("[ResultsProvider]", error);
break;
}
case "cancelQuery": {
if (this.cancelHandler) {
this.cancelHandler();
}
break;
}
case "ready": {
console.log("[ResultsProvider]", "The script is now ready.");
this.isScriptReady = true;
Expand Down
17 changes: 17 additions & 0 deletions src/providers/scripts/results.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ import {
timerElement.style.paddingTop = "0.5rem";
document.body.appendChild(timerElement);
}

// Reset and show the timer content
timerElement.textContent = 'Time elapsed:';
timerElement.style.display = 'block';
Expand Down Expand Up @@ -131,6 +132,18 @@ import {
}, 500);
}
}, 103);

const cancelQuery = () => {
vscode.postMessage({ type: "cancelQuery" });
};
const cancelElement = document.createElement('vscode-button');
cancelElement.innerHTML = "Cancel";
cancelElement.style.float = "right";
cancelElement.id = "cancelButton";
cancelElement.setAttribute("appearance", "secondary");
cancelElement.onclick = cancelQuery;
container.appendChild(cancelElement);

break;
}

Expand All @@ -139,6 +152,10 @@ import {
if (progressRing) {
progressRing.style.display = "none";
}
const cancelButton = document.getElementById("cancelButton");
if (cancelButton) {
cancelButton.style.display = "none";
}

const { data: results } = message;
console.log("[Results.js]", "New message - Results: ", results);
Expand Down
6 changes: 5 additions & 1 deletion src/utilities/error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,9 @@ export enum Errors {
/**
* Raises when a fetch failes after a minute.
*/
fetchTimeoutError = "Failed to fetch after a minute."
fetchTimeoutError = "Failed to fetch after a minute.",
/**
* Raises when trying to cancel a query.
*/
cancelQueryError = "Failed to cancel the query."
}

0 comments on commit cb76cae

Please sign in to comment.