Skip to content

Commit f21ad82

Browse files
lorefnoncmoog
authored andcommitted
Add json output so that other nb renderer plugins can present it as structured tree/table etc.
1 parent 82b8b87 commit f21ad82

2 files changed

Lines changed: 75 additions & 71 deletions

File tree

src/controller.ts

Lines changed: 15 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as vscode from 'vscode';
2-
import { ExecutionResult, Row, TabularResult } from './driver';
2+
import { ExecutionResult } from './driver';
33
import { globalConnPool, notebookType } from './main';
4+
import { resultToMarkdownTable } from './markdown';
45

56
export class SQLNotebookController {
67
readonly controllerId = 'sql-notebook-executor';
@@ -77,19 +78,22 @@ export class SQLNotebookController {
7778
}
7879

7980
if (typeof result === 'string') {
80-
writeSuccess(execution, result);
81+
writeSuccess(execution, [[text(result)]]);
8182
return;
8283
}
8384

8485
if (
8586
result.length === 0 ||
8687
(result.length === 1 && result[0].length === 0)
8788
) {
88-
writeSuccess(execution, 'Successfully executed query');
89+
writeSuccess(execution, [[text('Successfully executed query')]]);
8990
return;
9091
}
91-
const tables = result.map(resultToMarkdownTable);
92-
writeSuccess(execution, tables, 'text/markdown');
92+
93+
writeSuccess(execution, result.map(item => [
94+
text(resultToMarkdownTable(item), "text/markdown"),
95+
json(item)
96+
]));
9397
}
9498
}
9599

@@ -100,77 +104,17 @@ function writeErr(execution: vscode.NotebookCellExecution, err: string) {
100104
execution.end(false, Date.now());
101105
}
102106

107+
const { text, json } = vscode.NotebookCellOutputItem;
108+
103109
function writeSuccess(
104110
execution: vscode.NotebookCellExecution,
105-
text: string | string[],
106-
mimeType?: string
111+
outputs: vscode.NotebookCellOutputItem[][]
107112
) {
108-
const items = typeof text === 'string' ? [text] : text;
109113
execution.replaceOutput(
110-
items.map(
111-
(item) =>
112-
new vscode.NotebookCellOutput([
113-
vscode.NotebookCellOutputItem.text(item, mimeType),
114-
])
114+
outputs.map(
115+
(items) =>
116+
new vscode.NotebookCellOutput(items)
115117
)
116118
);
117119
execution.end(true, Date.now());
118120
}
119-
120-
function resultToMarkdownTable(result: TabularResult): string {
121-
if (result.length < 1) {
122-
return '*Empty Results Table*';
123-
}
124-
125-
const maxRows = getMaxRows();
126-
if (result.length > maxRows) {
127-
result = result.slice(0, maxRows);
128-
result.push(
129-
Object.fromEntries(Object.entries(result).map((pair) => [pair[0], '...']))
130-
);
131-
}
132-
return `${markdownHeader(result[0])}\n${result.map(markdownRow).join('\n')}`;
133-
}
134-
135-
function getMaxRows(): number {
136-
const fallbackMaxRows = 25;
137-
const maxRows: number | undefined = vscode.workspace
138-
.getConfiguration('SQLNotebook')
139-
.get('maxResultRows');
140-
return maxRows ?? fallbackMaxRows;
141-
}
142-
143-
function serializeCell(a: any): any {
144-
try {
145-
// serialize buffers as hex strings
146-
if (Buffer.isBuffer(a)) {
147-
return `0x${a.toString('hex')}`;
148-
}
149-
// attempt to serialize all remaining "object" values as JSON
150-
if (typeof a === 'object') {
151-
return JSON.stringify(a);
152-
}
153-
if (typeof a === 'string') {
154-
return a.replace(/\n/g, '\\n').replace(/\r/g, '\\r');
155-
}
156-
return a;
157-
} catch {
158-
return a;
159-
}
160-
}
161-
162-
function markdownRow(row: Row): string {
163-
const middle = Object.entries(row)
164-
.map((pair) => pair[1])
165-
.map(serializeCell)
166-
.join(' | ');
167-
return `| ${middle} |`;
168-
}
169-
170-
function markdownHeader(obj: Row): string {
171-
const keys = Object.keys(obj).join(' | ');
172-
const divider = Object.keys(obj)
173-
.map(() => '--')
174-
.join(' | ');
175-
return `| ${keys} |\n| ${divider} |`;
176-
}

src/markdown.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import * as vscode from 'vscode';
2+
import { Row, TabularResult } from './driver';
3+
4+
export function resultToMarkdownTable(result: TabularResult): string {
5+
if (result.length < 1) {
6+
return '*Empty Results Table*';
7+
}
8+
9+
const maxRows = getMaxRows();
10+
if (result.length > maxRows) {
11+
result = result.slice(0, maxRows);
12+
result.push(
13+
Object.fromEntries(Object.entries(result).map((pair) => [pair[0], '...']))
14+
);
15+
}
16+
return `${markdownHeader(result[0])}\n${result.map(markdownRow).join('\n')}`;
17+
}
18+
19+
function getMaxRows(): number {
20+
const fallbackMaxRows = 25;
21+
const maxRows: number | undefined = vscode.workspace
22+
.getConfiguration('SQLNotebook')
23+
.get('maxResultRows');
24+
return maxRows ?? fallbackMaxRows;
25+
}
26+
27+
function serializeCell(a: any): any {
28+
try {
29+
// serialize buffers as hex strings
30+
if (Buffer.isBuffer(a)) {
31+
return `0x${a.toString('hex')}`;
32+
}
33+
// attempt to serialize all remaining "object" values as JSON
34+
if (typeof a === 'object') {
35+
return JSON.stringify(a);
36+
}
37+
if (typeof a === 'string') {
38+
return a.replace(/\n/g, '\\n').replace(/\r/g, '\\r');
39+
}
40+
return a;
41+
} catch {
42+
return a;
43+
}
44+
}
45+
46+
function markdownRow(row: Row): string {
47+
const middle = Object.entries(row)
48+
.map((pair) => pair[1])
49+
.map(serializeCell)
50+
.join(' | ');
51+
return `| ${middle} |`;
52+
}
53+
54+
function markdownHeader(obj: Row): string {
55+
const keys = Object.keys(obj).join(' | ');
56+
const divider = Object.keys(obj)
57+
.map(() => '--')
58+
.join(' | ');
59+
return `| ${keys} |\n| ${divider} |`;
60+
}

0 commit comments

Comments
 (0)