Compile the whole buffer
This commit is contained in:
22
package.json
22
package.json
@@ -23,15 +23,31 @@
|
|||||||
"title": "Execute SQL Snippet"
|
"title": "Execute SQL Snippet"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"command": "selectConnection",
|
"command": "frog.compileFile",
|
||||||
|
"title": "Compiles the current file"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "frog.selectConnection",
|
||||||
"title": "Selects the connection to use"
|
"title": "Selects the connection to use"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "frog.setRowLimit",
|
||||||
|
"title": "Sets the row limit"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"keybindings": [{
|
"keybindings": [
|
||||||
|
{
|
||||||
"command": "frog.executeSnippet",
|
"command": "frog.executeSnippet",
|
||||||
"key": "ctrl+enter",
|
"key": "ctrl+enter",
|
||||||
"mac": "ctrl+enter"
|
"mac": "ctrl+enter"
|
||||||
}],
|
},
|
||||||
|
{
|
||||||
|
"command": "frog.compileFile",
|
||||||
|
"key": "ctrl+alt+c",
|
||||||
|
"mac": "ctrl+alt+c"
|
||||||
|
}
|
||||||
|
|
||||||
|
],
|
||||||
"views": {
|
"views": {
|
||||||
"explorer": [
|
"explorer": [
|
||||||
{
|
{
|
||||||
|
@@ -16,7 +16,7 @@ export class FolderNode {
|
|||||||
|
|
||||||
export class ConnectionNode {
|
export class ConnectionNode {
|
||||||
|
|
||||||
constructor(public name:string, public host:string, public port:Number, public schema:String, public username:String, public password:String) {
|
constructor(public name:string, public host:string, public port:number, public schema:string, public username:string, public password:string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ export class ConnectionProvider implements TreeDataProvider<TreeNode>, TextDocum
|
|||||||
label: element.name,
|
label: element.name,
|
||||||
collapsibleState: void 0,
|
collapsibleState: void 0,
|
||||||
command: {
|
command: {
|
||||||
command: 'selectConnection',
|
command: 'frog.selectConnection',
|
||||||
arguments: [element],
|
arguments: [element],
|
||||||
title: 'Open Connection'
|
title: 'Open Connection'
|
||||||
}
|
}
|
||||||
|
150
src/extension.ts
150
src/extension.ts
@@ -5,43 +5,20 @@ import * as vscode from 'vscode';
|
|||||||
import { ConnectionProvider, ConnectionNode } from './connections'
|
import { ConnectionProvider, ConnectionNode } from './connections'
|
||||||
import { TextDocumentContentProvider } from './resultsetview'
|
import { TextDocumentContentProvider } from './resultsetview'
|
||||||
import { BlockDetector } from './editorsupport'
|
import { BlockDetector } from './editorsupport'
|
||||||
|
import { SessionManager } from './sessionmanager'
|
||||||
|
|
||||||
const { spawn } = require('child_process');
|
let sessionManager : SessionManager = null;
|
||||||
const extensionName = "frog";
|
let rowLimit = 50;
|
||||||
|
|
||||||
let currentConnection : ConnectionNode = null;
|
|
||||||
let dbSession = null;
|
|
||||||
|
|
||||||
|
|
||||||
// this method is called when your extension is activated
|
// this method is called when your extension is activated
|
||||||
// your extension is activated the very first time the command is executed
|
// your extension is activated the very first time the command is executed
|
||||||
export function activate(context: vscode.ExtensionContext) {
|
export function activate(context: vscode.ExtensionContext) {
|
||||||
let previewUri = vscode.Uri.parse('frog-view://authority/resultset');
|
sessionManager = new SessionManager(context);
|
||||||
|
|
||||||
let statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
|
|
||||||
statusBarItem.text = 'Frog: No connection'
|
|
||||||
statusBarItem.show()
|
|
||||||
context.subscriptions.push(statusBarItem);
|
|
||||||
|
|
||||||
const connectionProvider = new ConnectionProvider();
|
const connectionProvider = new ConnectionProvider();
|
||||||
let myOutputChannel = vscode.window.createOutputChannel('SQL Query Results');
|
|
||||||
context.subscriptions.push(myOutputChannel);
|
|
||||||
|
|
||||||
let diagnosticCollection = vscode.languages.createDiagnosticCollection(extensionName);
|
|
||||||
context.subscriptions.push(diagnosticCollection);
|
|
||||||
|
|
||||||
vscode.window.registerTreeDataProvider('connections', connectionProvider);
|
vscode.window.registerTreeDataProvider('connections', connectionProvider);
|
||||||
|
|
||||||
let provider = new TextDocumentContentProvider();
|
|
||||||
let registration = vscode.workspace.registerTextDocumentContentProvider('frog-view', provider);
|
|
||||||
|
|
||||||
// Use the console to output diagnostic information (console.log) and errors (console.error)
|
|
||||||
// This line of code will only be executed once when your extension is activated
|
|
||||||
console.log('Congratulations, your extension "frog" is now active!');
|
|
||||||
|
|
||||||
let disposable = vscode.commands.registerCommand('frog.executeSnippet', () => {
|
let disposable = vscode.commands.registerCommand('frog.executeSnippet', () => {
|
||||||
// The code you place here will be executed every time your command is executed
|
|
||||||
|
|
||||||
let editor = vscode.window.activeTextEditor;
|
let editor = vscode.window.activeTextEditor;
|
||||||
|
|
||||||
if (!editor) return;
|
if (!editor) return;
|
||||||
@@ -54,117 +31,42 @@ export function activate(context: vscode.ExtensionContext) {
|
|||||||
|
|
||||||
let text = editor.document.getText(editor.selection);
|
let text = editor.document.getText(editor.selection);
|
||||||
|
|
||||||
if (!dbSession) {
|
|
||||||
if (!currentConnection) {
|
|
||||||
vscode.window.showWarningMessage('No connection selected');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let extPath = vscode.extensions.getExtension("todie.frog").extensionPath;
|
|
||||||
dbSession = spawn("java", ['-jar', extPath + '/frog-runner.jar', currentConnection.host, currentConnection.port, currentConnection.schema, currentConnection.username, currentConnection.password]);
|
|
||||||
|
|
||||||
let outputBuffer = "";
|
|
||||||
|
|
||||||
dbSession.stdout.on('data', (data) => {
|
|
||||||
outputBuffer += data.toString();
|
|
||||||
|
|
||||||
try {
|
|
||||||
let json = JSON.parse(outputBuffer);
|
|
||||||
|
|
||||||
//console.log(json);
|
|
||||||
|
|
||||||
const diagnostics = [];
|
|
||||||
let cd = json['columnDefinitions']
|
|
||||||
|
|
||||||
if (!json['rows']) {
|
|
||||||
if ('dbOutput' in json) {
|
|
||||||
myOutputChannel.append(json['dbOutput'].map((x) => `DB: ${x}\n`).join(''));
|
|
||||||
}
|
|
||||||
if (json['userErrors']) {
|
|
||||||
myOutputChannel.append("Errors found:\n");
|
|
||||||
|
|
||||||
const document = vscode.window.activeTextEditor.document;
|
|
||||||
|
|
||||||
for (let error of json['userErrors'][0]['lines']) {
|
|
||||||
let range = document.lineAt(selection.start.line + error['line'] - 1).range;
|
|
||||||
let diagnostic = new vscode.Diagnostic(range, error['text'], vscode.DiagnosticSeverity.Error);
|
|
||||||
diagnostic.source = extensionName;
|
|
||||||
diagnostic.code = "code";
|
|
||||||
diagnostics.push(diagnostic);
|
|
||||||
myOutputChannel.append(error['line'] + ": " + error['text'] + "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
diagnosticCollection.set(document.uri, diagnostics);
|
|
||||||
} else if (json['exception']) {
|
|
||||||
myOutputChannel.append("Exception caught: " + json['exceptionMessage'] + "\n");
|
|
||||||
} else if ("affectedRows" in json) {
|
|
||||||
myOutputChannel.append(json['affectedRows'] + " rows affected.\n");
|
|
||||||
} else {
|
|
||||||
myOutputChannel.append("SQL executed successfully.\n");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
provider.setData(json);
|
|
||||||
provider.update(previewUri);
|
|
||||||
|
|
||||||
vscode.commands.executeCommand('vscode.previewHtml', previewUri, vscode.ViewColumn.Two, 'Result Set View').then((success) => {
|
|
||||||
}, (reason) => {
|
|
||||||
vscode.window.showErrorMessage(reason);
|
|
||||||
});
|
|
||||||
|
|
||||||
myOutputChannel.append("Query successful.\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
myOutputChannel.append("-- " + new Date() + " -------------------------------\n");
|
|
||||||
outputBuffer = "";
|
|
||||||
statusBarItem.text = currentConnection.name + " (Connected)";
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
statusBarItem.text = currentConnection.name + " (Connected)";
|
|
||||||
});
|
|
||||||
|
|
||||||
dbSession.stderr.on('data', (data) => {
|
|
||||||
myOutputChannel.show(true);
|
|
||||||
myOutputChannel.append(data.toString());
|
|
||||||
});
|
|
||||||
|
|
||||||
dbSession.on('close', (code) => {
|
|
||||||
console.log(`child process exited with code ${code}`);
|
|
||||||
dbSession = null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!text) {
|
if (!text) {
|
||||||
vscode.window.showInformationMessage('No text selected');
|
vscode.window.showInformationMessage('No text selected');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sessionManager.execute(text, rowLimit);
|
||||||
myOutputChannel.append("-- " + new Date() + " -------------------------------\n"); //Executing: '" + text + "'\n");
|
|
||||||
let input = { "sql": text, "rowLimit": 30 };
|
|
||||||
dbSession.stdin.write(JSON.stringify(input) + "\n--- END ---\n");
|
|
||||||
statusBarItem.text = currentConnection.name + " (Connected, Query running...)";
|
|
||||||
});
|
});
|
||||||
|
context.subscriptions.push(disposable);
|
||||||
|
|
||||||
context.subscriptions.push(disposable, registration);
|
disposable = vscode.commands.registerCommand('frog.compileFile', () => {
|
||||||
|
let editor = vscode.window.activeTextEditor;
|
||||||
|
|
||||||
|
const text = editor.document.getText();
|
||||||
|
|
||||||
|
sessionManager.execute(text, rowLimit);
|
||||||
|
});
|
||||||
|
context.subscriptions.push(disposable);
|
||||||
|
|
||||||
function changeSession(node: ConnectionNode) {
|
function changeSession(node: ConnectionNode) {
|
||||||
currentConnection = node;
|
sessionManager.currentConnection = node;
|
||||||
statusBarItem.text = node.name;
|
|
||||||
if (dbSession) {
|
|
||||||
dbSession.stdin.end();
|
|
||||||
dbSession = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vscode.commands.registerCommand('selectConnection', (node: ConnectionNode) => {
|
disposable = vscode.commands.registerCommand('frog.setRowLimit', (args : Object) => {
|
||||||
if (!dbSession) {
|
rowLimit = args['rowLimit'];
|
||||||
changeSession(node)
|
vscode.window.showInformationMessage(`Row limit set to ${args['rowLimit']}`);
|
||||||
|
});
|
||||||
|
context.subscriptions.push(disposable);
|
||||||
|
|
||||||
|
vscode.commands.registerCommand('frog.selectConnection', (node: ConnectionNode) => {
|
||||||
|
if (!sessionManager.isSessionActive()) {
|
||||||
|
sessionManager.currentConnection = node;
|
||||||
} else {
|
} else {
|
||||||
vscode.window.showInformationMessage(`You want to change the connection to '${node.name}'. Sure?`, 'Yes')
|
vscode.window.showInformationMessage(`You want to change the connection to '${node.name}'. Sure?`, 'Yes')
|
||||||
.then( (selection) => {
|
.then( (selection) => {
|
||||||
if (selection == 'Yes') {
|
if (selection == 'Yes') {
|
||||||
changeSession(node);
|
sessionManager.currentConnection = node;
|
||||||
}
|
}
|
||||||
}, (reason) => {})
|
}, (reason) => {})
|
||||||
}
|
}
|
||||||
@@ -173,5 +75,5 @@ export function activate(context: vscode.ExtensionContext) {
|
|||||||
|
|
||||||
// this method is called when your extension is deactivated
|
// this method is called when your extension is deactivated
|
||||||
export function deactivate() {
|
export function deactivate() {
|
||||||
if (dbSession) dbSession.stdin.end();
|
sessionManager.closeSession();
|
||||||
}
|
}
|
@@ -16,9 +16,18 @@ export class TextDocumentContentProvider implements vscode.TextDocumentContentPr
|
|||||||
border: solid 1px white;
|
border: solid 1px white;
|
||||||
padding: 3px;
|
padding: 3px;
|
||||||
}
|
}
|
||||||
|
#limitBox a {
|
||||||
|
color: white;
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
</style>`
|
</style>`
|
||||||
|
|
||||||
let text = `<body>${styles}<table><tr>`
|
const choosableLimits = [2,10,50]
|
||||||
|
let limitBox = '<div id="limitBox"><p>Limit Results: '
|
||||||
|
+ choosableLimits.map((limit) =>
|
||||||
|
`<a href="${encodeURI('command:frog.setRowLimit?{"rowLimit": ' + limit + '}')}">${limit}</a>`).join('') + '</p></div>'
|
||||||
|
|
||||||
|
let text = `<body>${styles}${limitBox}<table><tr>`
|
||||||
text += this._data['columnDefinitions'].map((x) => `<th>${x['name']}</th>`).join('')
|
text += this._data['columnDefinitions'].map((x) => `<th>${x['name']}</th>`).join('')
|
||||||
text += '</tr>'
|
text += '</tr>'
|
||||||
text += this._data['rows'].map((r) =>
|
text += this._data['rows'].map((r) =>
|
||||||
|
142
src/sessionmanager.ts
Normal file
142
src/sessionmanager.ts
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
import * as vscode from 'vscode';
|
||||||
|
import { ConnectionNode } from './connections'
|
||||||
|
import { spawn } from 'child_process'
|
||||||
|
import { TextDocumentContentProvider } from './resultsetview'
|
||||||
|
|
||||||
|
const extensionName = "frog";
|
||||||
|
const previewUri = vscode.Uri.parse('frog-view://authority/resultset');
|
||||||
|
|
||||||
|
export class SessionManager {
|
||||||
|
private _currentConnection : ConnectionNode
|
||||||
|
private outputChannel
|
||||||
|
private diagnosticCollection;
|
||||||
|
private statusBarItem
|
||||||
|
private dbSession
|
||||||
|
private provider
|
||||||
|
|
||||||
|
constructor(context: vscode.ExtensionContext) {
|
||||||
|
|
||||||
|
this.outputChannel = vscode.window.createOutputChannel('SQL Query Results');
|
||||||
|
context.subscriptions.push(this.outputChannel);
|
||||||
|
|
||||||
|
this.diagnosticCollection = vscode.languages.createDiagnosticCollection(extensionName);
|
||||||
|
context.subscriptions.push(this.diagnosticCollection);
|
||||||
|
|
||||||
|
this.statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
|
||||||
|
this.statusBarItem.text = 'Frog: No connection'
|
||||||
|
this.statusBarItem.show()
|
||||||
|
context.subscriptions.push(this.statusBarItem);
|
||||||
|
|
||||||
|
this.provider = new TextDocumentContentProvider();
|
||||||
|
let registration = vscode.workspace.registerTextDocumentContentProvider('frog-view', this.provider);
|
||||||
|
}
|
||||||
|
|
||||||
|
public set currentConnection(c : ConnectionNode) {
|
||||||
|
this.statusBarItem.text = c.name;
|
||||||
|
if (this.dbSession) this.closeSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
public get currentConnection() : ConnectionNode {
|
||||||
|
return this.currentConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public isSessionActive() : boolean {
|
||||||
|
return this.dbSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
public closeSession() {
|
||||||
|
if (!this.dbSession) return;
|
||||||
|
|
||||||
|
this.dbSession.stdin.end();
|
||||||
|
this.dbSession = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public check() {
|
||||||
|
if (!this.currentConnection) {
|
||||||
|
vscode.window.showWarningMessage('No connection selected');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let extPath = vscode.extensions.getExtension("todie.frog").extensionPath;
|
||||||
|
this.dbSession = spawn("java", ['-jar', extPath + '/frog-runner.jar', this.currentConnection.host, this.currentConnection.port.toString(), this.currentConnection.schema, this.currentConnection.username, this.currentConnection.password]);
|
||||||
|
|
||||||
|
let outputBuffer = "";
|
||||||
|
|
||||||
|
this.dbSession.stdout.on('data', (data) => {
|
||||||
|
outputBuffer += data.toString();
|
||||||
|
|
||||||
|
try {
|
||||||
|
let json = JSON.parse(outputBuffer);
|
||||||
|
|
||||||
|
const diagnostics = [];
|
||||||
|
let cd = json['columnDefinitions']
|
||||||
|
|
||||||
|
if (!json['rows']) {
|
||||||
|
if ('dbOutput' in json) {
|
||||||
|
this.outputChannel.append(json['dbOutput'].map((x) => `DB: ${x}\n`).join(''));
|
||||||
|
}
|
||||||
|
if (json['userErrors']) {
|
||||||
|
this.outputChannel.append("Errors found:\n");
|
||||||
|
|
||||||
|
const editor = vscode.window.activeTextEditor;
|
||||||
|
const document = editor.document;
|
||||||
|
|
||||||
|
for (let error of json['userErrors'][0]['lines']) {
|
||||||
|
let range = document.lineAt(editor.selection.start.line + error['line'] - 1).range;
|
||||||
|
let diagnostic = new vscode.Diagnostic(range, error['text'], vscode.DiagnosticSeverity.Error);
|
||||||
|
diagnostic.source = extensionName;
|
||||||
|
diagnostic.code = "code";
|
||||||
|
diagnostics.push(diagnostic);
|
||||||
|
this.outputChannel.append(error['line'] + ": " + error['text'] + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.diagnosticCollection.set(document.uri, diagnostics);
|
||||||
|
} else if (json['exception']) {
|
||||||
|
this.outputChannel.append("Exception caught: " + json['exceptionMessage'] + "\n");
|
||||||
|
} else if ("affectedRows" in json) {
|
||||||
|
this.outputChannel.append(json['affectedRows'] + " rows affected.\n");
|
||||||
|
} else {
|
||||||
|
this.outputChannel.append("SQL executed successfully.\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.provider.setData(json);
|
||||||
|
this.provider.update(previewUri);
|
||||||
|
|
||||||
|
vscode.commands.executeCommand('vscode.previewHtml', previewUri, vscode.ViewColumn.Two, 'Result Set View').then((success) => {
|
||||||
|
}, (reason) => {
|
||||||
|
vscode.window.showErrorMessage(reason);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.outputChannel.append("Query successful.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.outputChannel.append("-- " + new Date() + " -------------------------------\n");
|
||||||
|
outputBuffer = "";
|
||||||
|
this.statusBarItem.text = this.currentConnection.name + " (Connected)";
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
this.statusBarItem.text = this.currentConnection.name + " (Connected)";
|
||||||
|
});
|
||||||
|
|
||||||
|
this.dbSession.stderr.on('data', (data) => {
|
||||||
|
this.outputChannel.show(true);
|
||||||
|
this.outputChannel.append(data.toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
this.dbSession.on('close', (code) => {
|
||||||
|
console.log(`child process exited with code ${code}`);
|
||||||
|
this.dbSession = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public execute(text : string, rowLimit : number) {
|
||||||
|
this.check();
|
||||||
|
|
||||||
|
this.outputChannel.append("-- " + new Date() + " -------------------------------\n"); //Executing: '" + text + "'\n");
|
||||||
|
let input = { "sql": text, "rowLimit": rowLimit };
|
||||||
|
this.dbSession.stdin.write(JSON.stringify(input) + "\n--- END ---\n");
|
||||||
|
this.statusBarItem.text = this.currentConnection.name + " (Connected, Query running...)";
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user