Skip to content

Commit 983ced4

Browse files
mzinnerrennox
authored andcommitted
Extending the way code is executed
Previously we only executed SQL code in execution context. With this patch we can run code in all supported languages. It also builds on the recently added code broadcast feature and refines it. With that in place we can also clean up duplicate interfaces. Additionally, a new method on the SQLExecutionContext class allows to set new text on the underlying editor model and wait for the context until statement splitting is finished. Change-Id: I19fcaf2b5551361cb90d222e38d488f2d9437d96
1 parent b04f5e7 commit 983ced4

File tree

14 files changed

+173
-155
lines changed

14 files changed

+173
-155
lines changed

gui/extension/src/CodeBlocks.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,10 @@ import { CharStreams, CommonTokenStream } from "antlr4ng";
3333
import { PythonLexer } from "../../frontend/src/parsing/python/generated/PythonLexer.js";
3434

3535
import {
36+
ICodeBlockExecutionOptions,
3637
IRequestListEntry, IRequestTypeMap, IWebviewProvider, requisitions,
3738
} from "../../frontend/src/supplement/Requisitions.js";
3839
import { printChannelOutput } from "./extension.js";
39-
import { IDictionary } from "../../frontend/src/app-logic/Types.js";
4040

4141
/** A record of white spaces in a code block, which must be re-applied when replacing the original block. */
4242
interface IWhiteSpaces {
@@ -219,16 +219,13 @@ export class CodeBlocks {
219219
ranges[existing] = span;
220220
}
221221

222-
const data: IDictionary = {
222+
const options: ICodeBlockExecutionOptions = {
223223
caption,
224-
connectionId: String(connectionId),
225-
};
226-
void requisitions.execute("editorRunQuery", {
227-
data,
224+
connectionId,
228225
query: beautified,
229226
linkId: span.id,
230-
parameters: [],
231-
});
227+
};
228+
void requisitions.execute("executeCodeBlock", options);
232229
}
233230

234231
break;

gui/extension/src/DBEditorCommandHandler.ts

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,13 @@ import { basename } from "path";
2727
import { commands, ConfigurationTarget, TextEditor, Uri, window, workspace } from "vscode";
2828

2929
import {
30-
IRequestListEntry, IRequestTypeMap, IWebviewProvider, requisitions,
30+
ICodeBlockExecutionOptions, IRequestListEntry, IRequestTypeMap, IWebviewProvider, requisitions,
3131
} from "../../frontend/src/supplement/Requisitions.js";
3232

3333
import { ScriptTreeItem } from "./tree-providers/ScriptTreeItem.js";
3434

3535
import { EntityType, IDBEditorScriptState } from "../../frontend/src/modules/db-editor/index.js";
36-
import {
37-
EditorLanguage, INewEditorRequest, IRunQueryRequest, IScriptRequest,
38-
} from "../../frontend/src/supplement/index.js";
36+
import { EditorLanguage, INewEditorRequest, IScriptRequest } from "../../frontend/src/supplement/index.js";
3937
import { DBConnectionViewProvider } from "./WebviewProviders/DBConnectionViewProvider.js";
4038

4139
import { IMrsDbObjectData } from "../../frontend/src/communication/ProtocolMrs.js";
@@ -55,7 +53,6 @@ import {
5553
ConnectionsTreeDataProvider,
5654
} from "./tree-providers/ConnectionsTreeProvider/ConnectionsTreeProvider.js";
5755
import { ConnectionTreeItem } from "./tree-providers/ConnectionsTreeProvider/ConnectionTreeItem.js";
58-
import { SchemaEventTreeItem } from "./tree-providers/ConnectionsTreeProvider/SchemaEventTreeItem.js";
5956
import {
6057
IEditorConnectionEntry, IOpenEditorBaseEntry, IOpenEditorEntry, OpenEditorsTreeDataProvider,
6158
} from "./tree-providers/OpenEditorsTreeProvider/OpenEditorsTreeProvider.js";
@@ -136,7 +133,7 @@ export class DBEditorCommandHandler {
136133
});
137134

138135
requisitions.register("connectedToUrl", this.connectedToUrl);
139-
requisitions.register("editorRunQuery", this.editorRunQuery);
136+
requisitions.register("executeCodeBlock", this.executeCodeBlock);
140137
requisitions.register("proxyRequest", this.proxyRequest);
141138

142139
context.subscriptions.push(commands.registerCommand("msg.refreshConnections", () => {
@@ -201,11 +198,10 @@ export class DBEditorCommandHandler {
201198

202199
const item = entry.treeItem;
203200
const query = `${select} * ${from} \`${item.schema}\`.\`${item.label as string}\``;
204-
void provider?.runQuery(String(item.connectionId), {
205-
query,
206-
data: {},
201+
void provider?.runCode(String(item.connectionId), {
202+
code: query,
203+
language: "mysql",
207204
linkId: -1,
208-
parameters: [],
209205
});
210206
}
211207
}));
@@ -773,16 +769,15 @@ export class DBEditorCommandHandler {
773769
*
774770
* @param details The request to send to the app.
775771
*
776-
* @returns A promise returning a flag if the task was successfully executed or not.
772+
* @returns A promise returning a flag whether the task was successfully executed or not.
777773
*/
778-
private editorRunQuery = (details: IRunQueryRequest): Promise<boolean> => {
774+
private executeCodeBlock = (details: ICodeBlockExecutionOptions): Promise<boolean> => {
779775
const provider = this.#host.currentProvider;
780776
if (provider) {
781-
return provider.runQuery(details.data.connectionId as string, {
777+
return provider.runCode(String(details.connectionId), {
782778
linkId: details.linkId,
783-
query: details.query,
784-
data: {},
785-
parameters: [],
779+
code: details.query,
780+
language: "mysql",
786781
});
787782
}
788783

gui/extension/src/ExtensionHost.ts

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import { ShellTasksTreeDataProvider } from "./tree-providers/ShellTreeProvider/S
3939
import { IStatusbarInfo } from "../../frontend/src/app-logic/Types.js";
4040
import { IShellModuleDataCategoriesEntry, IShellProfile } from "../../frontend/src/communication/ProtocolGui.js";
4141
import {
42-
IEditorHostExecutionOptions,
42+
IEditorExtendedExecutionOptions,
4343
IRequestListEntry, IRequestTypeMap, IRequisitionCallbackValues, IWebviewProvider, requisitions,
4444
} from "../../frontend/src/supplement/Requisitions.js";
4545
import { ShellInterface } from "../../frontend/src/supplement/ShellInterface/ShellInterface.js";
@@ -57,7 +57,6 @@ import {
5757
} from "./tree-providers/ConnectionsTreeProvider/ConnectionsTreeProvider.js";
5858
import { DBConnectionViewProvider } from "./WebviewProviders/DBConnectionViewProvider.js";
5959
import { WebviewProvider } from "./WebviewProviders/WebviewProvider.js";
60-
import { IRunQueryRequest } from "../../frontend/src/supplement/index.js";
6160

6261
/** This class manages some extension wide things like authentication handling etc. */
6362
export class ExtensionHost {
@@ -680,16 +679,10 @@ export class ExtensionHost {
680679
}
681680

682681
case "editorExecuteOnHost": {
683-
const incoming = request.original.parameter as IEditorHostExecutionOptions;
684-
const data: IRunQueryRequest = {
685-
data: {},
686-
query: incoming.query,
687-
parameters: [],
688-
linkId: -1,
689-
};
682+
const incoming = request.original.parameter as IEditorExtendedExecutionOptions;
690683

691684
return new Promise((resolve) => {
692-
void requisitions.broadcastRequest(request.provider, "editorRunQuery", data).then(() => {
685+
void requisitions.broadcastRequest(request.provider, "editorRunCode", incoming).then(() => {
693686
resolve(true);
694687
});
695688
});

gui/extension/src/WebviewProviders/DBConnectionViewProvider.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,14 @@ import { readFile, writeFile } from "fs/promises";
2626
import { commands, OpenDialogOptions, SaveDialogOptions, Uri, window } from "vscode";
2727

2828
import {
29-
IEditorHostExecutionOptions,
30-
IMrsDbObjectEditRequest, IOpenDialogOptions, IOpenFileDialogResult, IRequestTypeMap, IRequisitionCallbackValues,
31-
requisitions,
29+
IEditorExtendedExecutionOptions, IMrsDbObjectEditRequest, IOpenDialogOptions, IOpenFileDialogResult,
30+
IRequestTypeMap, IRequisitionCallbackValues, requisitions,
3231
} from "../../../frontend/src/supplement/Requisitions.js";
3332

3433
import { IMySQLDbSystem } from "../../../frontend/src/communication/index.js";
3534
import { EntityType, IDBEditorScriptState } from "../../../frontend/src/modules/db-editor/index.js";
3635
import { DBEditorModuleId } from "../../../frontend/src/modules/ModuleInfo.js";
37-
import {
38-
EditorLanguage, INewEditorRequest, IRunQueryRequest, IScriptRequest,
39-
} from "../../../frontend/src/supplement/index.js";
36+
import { EditorLanguage, INewEditorRequest, IScriptRequest } from "../../../frontend/src/supplement/index.js";
4037
import { IShellSessionDetails } from "../../../frontend/src/supplement/ShellInterface/index.js";
4138
import { showMessageWithTimeout } from "../utilities.js";
4239
import { WebviewProvider } from "./WebviewProvider.js";
@@ -83,18 +80,18 @@ export class DBConnectionViewProvider extends WebviewProvider {
8380
}
8481

8582
/**
86-
* Executes a single statement in a webview tab.
83+
* Executes a piece of code in a webview tab.
8784
*
8885
* @param page The page to open in the webview tab (if not already done).
8986
* @param details Required information about the query that must be executed.
9087
*
9188
* @returns A promise which resolves after the command was executed.
9289
*/
93-
public runQuery(page: string, details: IRunQueryRequest): Promise<boolean> {
90+
public runCode(page: string, details: IEditorExtendedExecutionOptions): Promise<boolean> {
9491
return this.runCommand("job", [
9592
{ requestType: "showModule", parameter: DBEditorModuleId },
9693
{ requestType: "showPage", parameter: { module: DBEditorModuleId, page, suppressAbout: true } },
97-
{ requestType: "editorRunQuery", parameter: details },
94+
{ requestType: "editorRunCode", parameter: details },
9895
], details.linkId === -1 ? "newConnection" : "newConnectionWithEmbeddedSql");
9996
}
10097

@@ -400,7 +397,7 @@ export class DBConnectionViewProvider extends WebviewProvider {
400397
});
401398
};
402399

403-
private executeOnHost = (data: IEditorHostExecutionOptions): Promise<boolean> => {
400+
private executeOnHost = (data: IEditorExtendedExecutionOptions): Promise<boolean> => {
404401
return requisitions.execute("proxyRequest", {
405402
provider: this,
406403
original: { requestType: "editorExecuteOnHost", parameter: data },

gui/frontend/src/components/ui/CodeEditor/CodeEditor.tsx

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import { ExecutionContexts } from "../../../script-execution/ExecutionContexts.j
3939
import { PresentationInterface } from "../../../script-execution/PresentationInterface.js";
4040
import { EditorLanguage, ITextRange } from "../../../supplement/index.js";
4141
import {
42-
appParameters, IEditorExecutionOptions, IEditorHostExecutionOptions, requisitions,
42+
appParameters, IEditorCommonExecutionOptions, IEditorExtendedExecutionOptions, requisitions,
4343
} from "../../../supplement/Requisitions.js";
4444
import { Settings } from "../../../supplement/Settings/Settings.js";
4545
import { editorRangeToTextRange } from "../../../utilities/ts-helpers.js";
@@ -105,20 +105,6 @@ export interface IEditorPersistentState {
105105

106106
type WordWrapType = "off" | "on" | "wordWrapColumn" | "bounded";
107107

108-
interface ICodeExecutionOptions {
109-
/** If true then execute only the statement at the caret position. This is valid only for SQL like languages. */
110-
atCaret?: boolean;
111-
112-
/** If true, move the caret to the next block.If there's no block, create a new one first. */
113-
advance?: boolean;
114-
115-
/** Tells the executor to add a hint to SELECT statements to use the secondary engine(usually HeatWave). */
116-
forceSecondaryEngine?: boolean;
117-
118-
/** When true render the query and the result as plain text. */
119-
asText?: boolean;
120-
}
121-
122108
interface ICodeEditorProperties extends IComponentProperties {
123109
savedState?: IEditorPersistentState;
124110
initialContent?: string;
@@ -972,7 +958,7 @@ export class CodeEditor extends ComponentBase<ICodeEditorProperties> {
972958
contextMenuOrder: 5,
973959
precondition,
974960
run: () => {
975-
const options = { atCaret: true, advance: true, asText: false };
961+
const options = { atCaret: false, advance: true, asText: false };
976962
this.executeCurrentContextOnHost(options);
977963
this.executeCurrentContext(options);
978964
},
@@ -1509,7 +1495,7 @@ export class CodeEditor extends ComponentBase<ICodeEditorProperties> {
15091495
*
15101496
* @param options Options to control the execution.
15111497
*/
1512-
private executeCurrentContext(options: ICodeExecutionOptions): void {
1498+
private executeCurrentContext(options: IEditorCommonExecutionOptions): void {
15131499
const editor = this.backend;
15141500
const model = this.model;
15151501
if (editor && model) {
@@ -1553,19 +1539,17 @@ export class CodeEditor extends ComponentBase<ICodeEditorProperties> {
15531539
*
15541540
* @param options The options to control the execution.
15551541
*/
1556-
private executeCurrentContextOnHost(options: ICodeExecutionOptions): void {
1542+
private executeCurrentContextOnHost(options: IEditorCommonExecutionOptions): void {
15571543
const editor = this.backend;
15581544
const model = this.model;
15591545
if (editor && model) {
15601546
const index = this.currentBlockIndex;
15611547
if (index > -1) {
15621548
const block = model.executionContexts?.contextAt(index);
15631549
if (block) {
1564-
const data: IEditorHostExecutionOptions = {
1565-
startNewBlock: options.advance ?? true,
1566-
forceSecondaryEngine: options.forceSecondaryEngine ?? false,
1567-
asText: options.asText ?? false,
1568-
query: block.code,
1550+
const data: IEditorExtendedExecutionOptions = {
1551+
...options,
1552+
code: block.code,
15691553
language: block.language,
15701554
};
15711555
void requisitions.executeRemote("editorExecuteOnHost", data);
@@ -2048,14 +2032,14 @@ export class CodeEditor extends ComponentBase<ICodeEditorProperties> {
20482032
return "unhandled";
20492033
}
20502034

2051-
private executeSelectedOrAll = (options: IEditorExecutionOptions): Promise<boolean> => {
2035+
private executeSelectedOrAll = (options: IEditorCommonExecutionOptions): Promise<boolean> => {
20522036
const { language } = this.mergedProps;
20532037

20542038
const editor = this.backend;
20552039
const model = this.model;
20562040
const terminalMode = model?.editorMode === CodeEditorMode.Terminal;
20572041

2058-
const advance = (language === "msg") && options.startNewBlock;
2042+
const advance = (language === "msg") && options.advance;
20592043
this.executeCurrentContext(
20602044
{
20612045
advance: advance || terminalMode,
@@ -2067,14 +2051,14 @@ export class CodeEditor extends ComponentBase<ICodeEditorProperties> {
20672051
return Promise.resolve(true);
20682052
};
20692053

2070-
private executeCurrent = (options: IEditorExecutionOptions): Promise<boolean> => {
2054+
private executeCurrent = (options: IEditorCommonExecutionOptions): Promise<boolean> => {
20712055
const { language } = this.mergedProps;
20722056

20732057
const editor = this.backend;
20742058
const model = this.model;
20752059
const terminalMode = model?.editorMode === CodeEditorMode.Terminal;
20762060

2077-
const advance = (language === "msg") && options.startNewBlock;
2061+
const advance = (language === "msg") && options.advance;
20782062
this.executeCurrentContext(
20792063
{
20802064
atCaret: true,

gui/frontend/src/components/ui/CodeEditor/index.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,10 @@ export interface IScriptExecutionOptions {
147147

148148
/**
149149
* Determines where the SQL code comes from that must be executed. If that's a position it means
150-
* to run only the code at that (caret) position. If a string is specified then it means to run
151-
* this (single) query only. If not given at all run the statements touched by the editor selection
152-
* or all statements, if there's no selection.
150+
* to run only the code at that (caret) position. If not given at all run the statements touched by the editor
151+
* selection or all statements, if there's no selection.
153152
*/
154-
source?: IPosition | string;
153+
source?: IPosition;
155154

156155
/** When true render the query and the result as plain text. */
157156
asText?: boolean;

0 commit comments

Comments
 (0)