Skip to content

Commit 9370039

Browse files
authored
Merge pull request #434 from codefori/feature/output_parameters
Feature/output parameters
2 parents 2a0c512 + ffd330e commit 9370039

File tree

6 files changed

+102
-6
lines changed

6 files changed

+102
-6
lines changed

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,11 @@
149149
"type": "boolean",
150150
"description": "Make larger cells collapsed by default",
151151
"default": false
152+
},
153+
"vscode-db2i.resultsets.outputDecorations": {
154+
"type": "boolean",
155+
"description": "Show INOUT and OUT parameters inside the editor",
156+
"default": true
152157
}
153158
}
154159
},

src/views/results/contributes.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
"type": "boolean",
2424
"description": "Make larger cells collapsed by default",
2525
"default": false
26+
},
27+
"vscode-db2i.resultsets.outputDecorations": {
28+
"type": "boolean",
29+
"description": "Show INOUT and OUT parameters inside the editor",
30+
"default": true
2631
}
2732
}
2833
},

src/views/results/editorUi.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { ParsedStatementInfo } from ".";
2+
import crypto from "crypto";
3+
import { ParameterResult } from "@ibm/mapepire-js";
4+
import { DecorationOptions, ThemeColor, window, Range, MarkdownString, DecorationRangeBehavior } from "vscode";
5+
import Configuration from "../../configuration";
6+
7+
let priorStatements: { [uniqueHash: string]: ParsedStatementInfo } = {};
8+
9+
const outputParameters = window.createTextEditorDecorationType({
10+
after: {
11+
color: new ThemeColor(`editorGhostText.foreground`),
12+
fontStyle: `italic`,
13+
margin: `0 0 0 1em`
14+
},
15+
rangeBehavior: DecorationRangeBehavior.ClosedClosed
16+
});
17+
18+
export function registerRunStatement(stmt: ParsedStatementInfo) {
19+
const uniqueUiId = crypto.randomBytes(16).toString("hex");
20+
priorStatements[uniqueUiId] = stmt;
21+
return uniqueUiId;
22+
}
23+
24+
export function statementDone(uniqueId: string, options: { paramsOut?: ParameterResult[] } = {}) {
25+
const existingStatement = priorStatements[uniqueId];
26+
const activeEditor = window.activeTextEditor;
27+
28+
const shortValue = (v: any, short = true) => {
29+
if (typeof v === "string") {
30+
return short && v.length > 10 ? `${v.substring(0, 10)}...` : v;
31+
}
32+
return v || `-`;
33+
};
34+
35+
if (existingStatement) {
36+
// Huge assumption here the statement is in the active editor
37+
38+
// TODO: feature flag
39+
if (Configuration.get(`resultsets.outputDecorations`)) {
40+
if (activeEditor) {
41+
const document = activeEditor.document;
42+
const startPosition = document.positionAt(existingStatement.group.range.start);
43+
const endPosition = document.positionAt(existingStatement.group.range.end + 1);
44+
45+
if (options.paramsOut && options.paramsOut.length > 0) {
46+
const markdownString = new MarkdownString();
47+
options.paramsOut.forEach((p, i) => {
48+
markdownString.appendMarkdown(`**Parameter ${i + 1}${p.name ? ` - ${p.name}` : ``}**:\n\n\`\`\`\n${p.value !== undefined ? p.value : `-`}\n\`\`\``);
49+
50+
if (i !== options.paramsOut.length - 1) {
51+
markdownString.appendMarkdown(`\n\n---\n\n`);
52+
}
53+
});
54+
55+
const shouldBeShort = options.paramsOut.length > 1;
56+
const values = `=> ` + options.paramsOut.map((p) => shortValue(p.value, shouldBeShort)).join(", ");
57+
58+
const decoration: DecorationOptions = {
59+
range: new Range(startPosition, endPosition),
60+
hoverMessage: markdownString,
61+
renderOptions: {
62+
after: {
63+
contentText: values,
64+
}
65+
}
66+
};
67+
68+
activeEditor.setDecorations(outputParameters, [decoration]);
69+
}
70+
}
71+
}
72+
73+
delete priorStatements[uniqueId];
74+
}
75+
}

src/views/results/html.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ document.getElementById('resultset').onclick = function(e){
295295
};
296296
`;
297297

298-
export function generateScroller(basicSelect: string, parameters: SqlParameter[] = [], isCL: boolean = false, withCancel: boolean = false, updatable?: UpdatableInfo): string {
298+
export function generateScroller(uiId: string, basicSelect: string, parameters: SqlParameter[] = [], isCL: boolean = false, withCancel: boolean = false, updatable?: UpdatableInfo): string {
299299
const withCollapsed = Configuration.get<boolean>('collapsedResultSet');
300300

301301
return /*html*/`
@@ -417,6 +417,7 @@ export function generateScroller(basicSelect: string, parameters: SqlParameter[]
417417
function fetchNextPage() {
418418
isFetching = true;
419419
vscode.postMessage({
420+
uiId: ${JSON.stringify(uiId)},
420421
query: basicSelect,
421422
parameters: ${JSON.stringify(parameters)},
422423
isCL: ${isCL},

src/views/results/index.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import * as vscode from "vscode";
2+
import crypto from "crypto";
23
import { SnippetString, ViewColumn, TreeView, window } from "vscode"
34

45
import * as csv from "csv/sync";
56

6-
77
import { JobManager } from "../../config";
88
import Document from "../../language/sql/document";
99
import { ObjectRef, ParsedEmbeddedStatement, StatementGroup, StatementType } from "../../language/sql/types";
@@ -21,6 +21,7 @@ import { queryResultToRpgDs } from "./codegen";
2121
import Configuration from "../../configuration";
2222
import { getSqlDocument } from "../../language/providers/logic/parse";
2323
import { getLiteralsFromStatement, getPriorBindableStatement } from "./binding";
24+
import { registerRunStatement } from "./editorUi";
2425

2526
export type StatementQualifier = "statement" | "bind" | "update" | "explain" | "onlyexplain" | "json" | "csv" | "cl" | "sql" | "rpg";
2627

@@ -57,7 +58,7 @@ let doveResultsView = new DoveResultsView();
5758
let doveResultsTreeView: TreeView<ExplainTreeItem> = doveResultsView.getTreeView();
5859
let doveNodeView = new DoveNodeView();
5960
let doveNodeTreeView: TreeView<PropertyNode> = doveNodeView.getTreeView();
60-
let doveTreeDecorationProvider = new DoveTreeDecorationProvider(); // Self-registers as a tree decoration providor
61+
let doveTreeDecorationProvider = new DoveTreeDecorationProvider(); // Self-registers as a tree decoration provider
6162

6263
export function initialise(context: vscode.ExtensionContext) {
6364
setCancelButtonVisibility(false);
@@ -378,13 +379,15 @@ async function runHandler(options?: StatementInfo) {
378379
updatableTable = refs[0];
379380
}
380381

382+
const uiId = registerRunStatement(statementDetail);
381383
const basicSelect = statementDetail.content.split(eol).filter(line => !line.trimStart().startsWith(`--`)).join(eol);
382384

383385
chosenView.setScrolling({ // Never errors
384386
basicSelect: basicSelect,
385387
withCancel: inWindow,
386388
ref: updatableTable,
387389
parameters,
390+
uiId
388391
})
389392
}
390393

src/views/results/resultSetPanelProvider.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ import { ObjectRef } from "../../language/sql/types";
1010
import Table from "../../database/table";
1111
import Statement from "../../database/statement";
1212
import { TableColumn } from "../../types";
13+
import { statementDone } from "./editorUi";
14+
import { QueryResult } from "@ibm/mapepire-js";
1315

1416
export type SqlParameter = string|number;
1517

1618
export interface ScrollerOptions {
19+
uiId?: string;
1720
basicSelect: string;
1821
parameters?: SqlParameter[];
1922
isCL?: boolean;
@@ -106,7 +109,7 @@ export class ResultSetPanelProvider implements WebviewViewProvider {
106109

107110
if (this.currentQuery.getState() !== "RUN_DONE") {
108111
setCancelButtonVisibility(true);
109-
let queryResults = undefined;
112+
let queryResults: QueryResult<any> = undefined;
110113
let startTime = 0;
111114
let endTime = 0;
112115
let executionTime: number|undefined;
@@ -118,7 +121,11 @@ export class ResultSetPanelProvider implements WebviewViewProvider {
118121
startTime = performance.now();
119122
queryResults = await this.currentQuery.execute();
120123
endTime = performance.now();
121-
executionTime = (endTime - startTime)
124+
executionTime = (endTime - startTime);
125+
126+
if (message.uiId) {
127+
statementDone(message.uiId, {paramsOut: queryResults.output_parms});
128+
}
122129
}
123130
const jobId = this.currentQuery.getHostJob().id;
124131

@@ -285,7 +292,7 @@ export class ResultSetPanelProvider implements WebviewViewProvider {
285292
}
286293
}
287294

288-
this._view.webview.html = html.generateScroller(options.basicSelect, options.parameters, options.isCL, options.withCancel, updatable);
295+
this._view.webview.html = html.generateScroller(options.uiId, options.basicSelect, options.parameters, options.isCL, options.withCancel, updatable);
289296

290297
this._view.webview.postMessage({
291298
command: `fetch`,

0 commit comments

Comments
 (0)