
18 changed files with 11322 additions and 157 deletions
-
2package.json
-
48resources/webview/changeTable.html
-
48resources/webview/createTable.html
-
49resources/webview/result.html
-
3resources/webview/test.css
-
10947resources/webview/vue.js
-
2src/common/appInsightsClient.ts
-
4src/database/DatabaseCache.ts
-
69src/database/SqlViewManager.ts
-
278src/database/utility.ts
-
7src/extension.ts
-
4src/model/columnNode.ts
-
4src/model/connectionNode.ts
-
4src/model/databaseNode.ts
-
4src/model/tableNode.ts
-
2src/provider/CompletionManager.ts
-
2src/provider/CompletionProvider.ts
-
2src/provider/mysqlTreeDataProvider.ts
@ -0,0 +1,48 @@ |
|||
<html> |
|||
|
|||
<head> |
|||
<title>result</title> |
|||
<link rel="stylesheet" href="${webviewPath}/test.css"> |
|||
<script src="${webviewPath}/vue.js"></script> |
|||
</head> |
|||
|
|||
<body> |
|||
<div id="app"> |
|||
<div v-for="str in list" v-text="str"><br></div> |
|||
<span class="test">hello</span> |
|||
</div> |
|||
</body> |
|||
<script> |
|||
const vue=new Vue({ |
|||
el:'#app', |
|||
data:{ |
|||
list:["test",'hehe'] |
|||
} |
|||
}) |
|||
const vscode = acquireVsCodeApi(); |
|||
document.write("test") |
|||
document.write("${webviewPath}/style.css") |
|||
console.log('test') |
|||
vscode.postMessage({ |
|||
command: 'webview.table.change', |
|||
text: "test text" |
|||
}) |
|||
|
|||
window.addEventListener('message', event => { |
|||
|
|||
const message = event.data; // The JSON data our extension sent |
|||
vue.list.push(message) |
|||
// console.log(message) |
|||
// document.write(message) |
|||
|
|||
// switch (message.command) { |
|||
// case 'mysql.newQuery': |
|||
// count = Math.ceil(count * 0.5); |
|||
// counter.textContent = count; |
|||
// document.write(count) |
|||
// break; |
|||
// } |
|||
}); |
|||
</script> |
|||
|
|||
</html> |
@ -0,0 +1,48 @@ |
|||
<html> |
|||
|
|||
<head> |
|||
<title>result</title> |
|||
<link rel="stylesheet" href="${webviewPath}/test.css"> |
|||
<script src="${webviewPath}/vue.js"></script> |
|||
</head> |
|||
|
|||
<body> |
|||
<div id="app"> |
|||
<div v-for="str in list" v-text="str"><br></div> |
|||
<span class="test">hello</span> |
|||
</div> |
|||
</body> |
|||
<script> |
|||
const vue=new Vue({ |
|||
el:'#app', |
|||
data:{ |
|||
list:["test",'hehe'] |
|||
} |
|||
}) |
|||
const vscode = acquireVsCodeApi(); |
|||
document.write("test") |
|||
document.write("${webviewPath}/style.css") |
|||
console.log('test') |
|||
vscode.postMessage({ |
|||
command: 'webview.table.change', |
|||
text: "test text" |
|||
}) |
|||
|
|||
window.addEventListener('message', event => { |
|||
|
|||
const message = event.data; // The JSON data our extension sent |
|||
vue.list.push(message) |
|||
// console.log(message) |
|||
// document.write(message) |
|||
|
|||
// switch (message.command) { |
|||
// case 'mysql.newQuery': |
|||
// count = Math.ceil(count * 0.5); |
|||
// counter.textContent = count; |
|||
// document.write(count) |
|||
// break; |
|||
// } |
|||
}); |
|||
</script> |
|||
|
|||
</html> |
@ -0,0 +1,49 @@ |
|||
<html> |
|||
|
|||
<head> |
|||
<title>result</title> |
|||
<link rel="stylesheet" href="${webviewPath}/test.css"> |
|||
<script src="${webviewPath}/vue.js"></script> |
|||
</head> |
|||
|
|||
<body> |
|||
<div id="app"> |
|||
<div v-for="str in list" v-text="str"><br></div> |
|||
<span class="test">hello</span> |
|||
</div> |
|||
</body> |
|||
<script> |
|||
const vue=new Vue({ |
|||
el:'#app', |
|||
data:{ |
|||
list:["test",'hehe'] |
|||
} |
|||
}) |
|||
const vscode = acquireVsCodeApi(); |
|||
document.write("test") |
|||
document.write("${webviewPath}/style.css") |
|||
console.log('test') |
|||
vscode.postMessage({ |
|||
command: 'webview.table.change', |
|||
text: "test text" |
|||
}) |
|||
|
|||
window.addEventListener('message', event => { |
|||
// vscode.setState({ count }); |
|||
// vscode.getState() |
|||
const message = event.data; // The JSON data our extension sent |
|||
vue.list.push(message) |
|||
// console.log(message) |
|||
// document.write(message) |
|||
|
|||
// switch (message.command) { |
|||
// case 'mysql.newQuery': |
|||
// count = Math.ceil(count * 0.5); |
|||
// counter.textContent = count; |
|||
// document.write(count) |
|||
// break; |
|||
// } |
|||
}); |
|||
</script> |
|||
|
|||
</html> |
@ -0,0 +1,3 @@ |
|||
.test{ |
|||
color: red; |
|||
} |
10947
resources/webview/vue.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,69 @@ |
|||
import { WebviewPanel } from "vscode"; |
|||
"use strict"; |
|||
import * as fs from "fs"; |
|||
import * as vscode from "vscode"; |
|||
import { OutputChannel } from "../common/outputChannel"; |
|||
|
|||
export class ViewOption { |
|||
viewPath: string; |
|||
viewTitle: string; |
|||
viewId: string; |
|||
/** |
|||
* receive webview send message |
|||
*/ |
|||
receiveListener?: (message: any) => {} |
|||
|
|||
disposeListener?: (message: any) => {} |
|||
} |
|||
|
|||
|
|||
export class SqlViewManager { |
|||
static resultWebviewPanel: WebviewPanel |
|||
static tableEditWebviewPanel: WebviewPanel |
|||
static tableCreateWebviewPanel: WebviewPanel |
|||
static extensionPath: string |
|||
public static initExtesnsionPath(extensionPath: string) { |
|||
this.extensionPath = extensionPath |
|||
} |
|||
|
|||
|
|||
public static showQueueResult(data:any,title:string){ |
|||
|
|||
this.createWebviewPanel({ |
|||
viewId: "queryResult", |
|||
viewPath: "result", |
|||
viewTitle: title |
|||
}).then(webviewPanel=>{ |
|||
webviewPanel.webview.postMessage({data:data}) |
|||
}) |
|||
} |
|||
|
|||
private static createWebviewPanel(viewOption: ViewOption): Promise<WebviewPanel> { |
|||
|
|||
return new Promise((resolve, reject) => { |
|||
fs.readFile(`${this.extensionPath}/resources/webview/${viewOption.viewPath}.html`, 'utf8', async (err, data) => { |
|||
if (err) { |
|||
OutputChannel.appendLine(err) |
|||
reject(err) |
|||
return; |
|||
} |
|||
const webviewPanel = await vscode.window.createWebviewPanel( |
|||
viewOption.viewId, |
|||
viewOption.viewTitle, |
|||
vscode.ViewColumn.One, |
|||
{ enableScripts: true } |
|||
); |
|||
webviewPanel.webview.html = data.replace(/\$\{webviewPath\}/gi, |
|||
vscode.Uri.file(`${this.extensionPath}/resources/webview`) |
|||
.with({ scheme: 'vscode-resource' }).toString()) |
|||
webviewPanel.webview.onDidReceiveMessage(viewOption.receiveListener); |
|||
webviewPanel.onDidDispose(viewOption.disposeListener) |
|||
|
|||
resolve(webviewPanel) |
|||
}) |
|||
|
|||
}) |
|||
|
|||
} |
|||
|
|||
} |
@ -1,140 +1,138 @@ |
|||
"use strict"; |
|||
import * as fs from "fs"; |
|||
import * as mysql from "mysql"; |
|||
import * as vscode from "vscode"; |
|||
import { IConnection } from "../model/connection"; |
|||
import { AppInsightsClient } from "./appInsightsClient"; |
|||
import { Global } from "./global"; |
|||
import { OutputChannel } from "./outputChannel"; |
|||
|
|||
export class Utility { |
|||
public static readonly maxTableCount = Utility.getConfiguration().get<number>("maxTableCount"); |
|||
|
|||
public static getConfiguration(): vscode.WorkspaceConfiguration { |
|||
return vscode.workspace.getConfiguration("vscode-mysql"); |
|||
} |
|||
|
|||
public static queryPromise<T>(connection, sql: string): Promise<T> { |
|||
return new Promise((resolve, reject) => { |
|||
OutputChannel.appendLine(`Execute SQL:${sql}`) |
|||
connection.query(sql, (err, rows) => { |
|||
if (err) { |
|||
OutputChannel.appendLine(err) |
|||
reject("Error: " + err.message); |
|||
} else { |
|||
resolve(rows); |
|||
} |
|||
}); |
|||
connection.end(); |
|||
}); |
|||
} |
|||
|
|||
public static async runQuery(sql?: string, connectionOptions?: IConnection) { |
|||
AppInsightsClient.sendEvent("runQuery.start"); |
|||
if (!sql && !vscode.window.activeTextEditor) { |
|||
vscode.window.showWarningMessage("No SQL file selected"); |
|||
AppInsightsClient.sendEvent("runQuery.noFile"); |
|||
return; |
|||
} |
|||
if (!connectionOptions && !Global.activeConnection) { |
|||
const hasActiveConnection = await Utility.hasActiveConnection(); |
|||
if (!hasActiveConnection) { |
|||
vscode.window.showWarningMessage("No MySQL Server or Database selected"); |
|||
AppInsightsClient.sendEvent("runQuery.noMySQL"); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
if (!sql) { |
|||
const activeTextEditor = vscode.window.activeTextEditor; |
|||
const selection = activeTextEditor.selection; |
|||
if (selection.isEmpty) { |
|||
sql = activeTextEditor.document.getText(); |
|||
} else { |
|||
sql = activeTextEditor.document.getText(selection); |
|||
} |
|||
} |
|||
|
|||
connectionOptions = connectionOptions ? connectionOptions : Global.activeConnection; |
|||
connectionOptions.multipleStatements = true; |
|||
const connection = Utility.createConnection(connectionOptions); |
|||
|
|||
connection.query(sql, (err, rows) => { |
|||
if (Array.isArray(rows)) { |
|||
if (rows.some(((row) => Array.isArray(row)))) { |
|||
rows.forEach((row, index) => { |
|||
if (Array.isArray(row)) { |
|||
Utility.showQueryResult(row); |
|||
} else { |
|||
OutputChannel.appendLine(JSON.stringify(row)); |
|||
} |
|||
}); |
|||
} else { |
|||
Utility.showQueryResult(rows); |
|||
} |
|||
|
|||
} else { |
|||
OutputChannel.appendLine(JSON.stringify(rows)); |
|||
} |
|||
|
|||
if (err) { |
|||
OutputChannel.appendLine(err); |
|||
AppInsightsClient.sendEvent("runQuery.end", { Result: "Fail", ErrorMessage: err }); |
|||
} else { |
|||
AppInsightsClient.sendEvent("runQuery.end", { Result: "Success" }); |
|||
} |
|||
}); |
|||
connection.end(); |
|||
} |
|||
|
|||
public static async createSQLTextDocument(sql: string = "") { |
|||
const textDocument = await vscode.workspace.openTextDocument({ content: sql, language: "sql" }); |
|||
return vscode.window.showTextDocument(textDocument); |
|||
} |
|||
|
|||
public static createConnection(connectionOptions: IConnection): any { |
|||
const newConnectionOptions: any = Object.assign({}, connectionOptions); |
|||
if (connectionOptions.certPath && fs.existsSync(connectionOptions.certPath)) { |
|||
newConnectionOptions.ssl = { |
|||
ca: fs.readFileSync(connectionOptions.certPath), |
|||
}; |
|||
} |
|||
return mysql.createConnection(newConnectionOptions); |
|||
} |
|||
|
|||
private static getPreviewUri(data) { |
|||
const uri = vscode.Uri.parse("sqlresult://mysql/data"); |
|||
|
|||
return uri.with({ query: data }); |
|||
} |
|||
|
|||
private static showQueryResult(data) { |
|||
|
|||
// const panel = vscode.window.createWebviewPanel(
|
|||
// 'catCoding',
|
|||
// 'Cat Coding',
|
|||
// vscode.ViewColumn.One,
|
|||
// {}
|
|||
// );
|
|||
|
|||
const uri = Utility.getPreviewUri(JSON.stringify(data)) |
|||
vscode.commands.executeCommand('markdown.showPreview', uri) |
|||
vscode.commands.executeCommand('m2arkdown.preview.refresh', uri); |
|||
|
|||
} |
|||
|
|||
private static async hasActiveConnection(): Promise<boolean> { |
|||
let count = 5; |
|||
while (!Global.activeConnection && count > 0) { |
|||
await Utility.sleep(100); |
|||
count--; |
|||
} |
|||
return !!Global.activeConnection; |
|||
} |
|||
|
|||
private static sleep(ms) { |
|||
return new Promise((resolve) => { |
|||
setTimeout(resolve, ms); |
|||
}); |
|||
} |
|||
} |
|||
"use strict"; |
|||
import * as fs from "fs"; |
|||
import * as mysql from "mysql"; |
|||
import * as path from 'path'; |
|||
import * as vscode from "vscode"; |
|||
import { IConnection } from "../model/connection"; |
|||
import { AppInsightsClient } from "../common/appInsightsClient"; |
|||
import { Global } from "../common/global"; |
|||
import { OutputChannel } from "../common/outputChannel"; |
|||
import { resolve } from "url"; |
|||
import { SqlViewManager } from "./SqlViewManager"; |
|||
|
|||
export class Utility { |
|||
public static readonly maxTableCount = Utility.getConfiguration().get<number>("maxTableCount"); |
|||
|
|||
public static getConfiguration(): vscode.WorkspaceConfiguration { |
|||
return vscode.workspace.getConfiguration("vscode-mysql"); |
|||
} |
|||
|
|||
public static queryPromise<T>(connection, sql: string): Promise<T> { |
|||
return new Promise((resolve, reject) => { |
|||
OutputChannel.appendLine(`Execute SQL:${sql}`) |
|||
connection.query(sql, (err, rows) => { |
|||
if (err) { |
|||
OutputChannel.appendLine(err) |
|||
reject("Error: " + err.message); |
|||
} else { |
|||
resolve(rows); |
|||
} |
|||
}); |
|||
connection.end(); |
|||
}); |
|||
} |
|||
|
|||
public static async runQuery(sql?: string, connectionOptions?: IConnection) { |
|||
AppInsightsClient.sendEvent("runQuery.start"); |
|||
if (!sql && !vscode.window.activeTextEditor) { |
|||
vscode.window.showWarningMessage("No SQL file selected"); |
|||
AppInsightsClient.sendEvent("runQuery.noFile"); |
|||
return; |
|||
} |
|||
if (!connectionOptions && !Global.activeConnection) { |
|||
const hasActiveConnection = await Utility.hasActiveConnection(); |
|||
if (!hasActiveConnection) { |
|||
vscode.window.showWarningMessage("No MySQL Server or Database selected"); |
|||
AppInsightsClient.sendEvent("runQuery.noMySQL"); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
if (!sql) { |
|||
const activeTextEditor = vscode.window.activeTextEditor; |
|||
const selection = activeTextEditor.selection; |
|||
if (selection.isEmpty) { |
|||
sql = activeTextEditor.document.getText(); |
|||
} else { |
|||
sql = activeTextEditor.document.getText(selection); |
|||
} |
|||
} |
|||
|
|||
connectionOptions = connectionOptions ? connectionOptions : Global.activeConnection; |
|||
connectionOptions.multipleStatements = true; |
|||
const connection = Utility.createConnection(connectionOptions); |
|||
|
|||
connection.query(sql, (err, rows) => { |
|||
if (Array.isArray(rows)) { |
|||
if (rows.some(((row) => Array.isArray(row)))) { |
|||
rows.forEach((row, index) => { |
|||
if (Array.isArray(row)) { |
|||
Utility.showQueryResult(row); |
|||
} else { |
|||
OutputChannel.appendLine(JSON.stringify(row)); |
|||
} |
|||
}); |
|||
} else { |
|||
Utility.showQueryResult(rows); |
|||
} |
|||
|
|||
} else { |
|||
OutputChannel.appendLine(JSON.stringify(rows)); |
|||
} |
|||
|
|||
if (err) { |
|||
OutputChannel.appendLine(err); |
|||
AppInsightsClient.sendEvent("runQuery.end", { Result: "Fail", ErrorMessage: err }); |
|||
} else { |
|||
AppInsightsClient.sendEvent("runQuery.end", { Result: "Success" }); |
|||
} |
|||
}); |
|||
connection.end(); |
|||
} |
|||
|
|||
public static async createSQLTextDocument(sql: string = "") { |
|||
const textDocument = await vscode.workspace.openTextDocument({ content: sql, language: "sql" }); |
|||
return vscode.window.showTextDocument(textDocument); |
|||
} |
|||
|
|||
public static createConnection(connectionOptions: IConnection): any { |
|||
const newConnectionOptions: any = Object.assign({}, connectionOptions); |
|||
if (connectionOptions.certPath && fs.existsSync(connectionOptions.certPath)) { |
|||
newConnectionOptions.ssl = { |
|||
ca: fs.readFileSync(connectionOptions.certPath), |
|||
}; |
|||
} |
|||
return mysql.createConnection(newConnectionOptions); |
|||
} |
|||
|
|||
private static getPreviewUri(data) { |
|||
const uri = vscode.Uri.parse("sqlresult://mysql/data"); |
|||
|
|||
return uri.with({ query: data }); |
|||
} |
|||
|
|||
static webviewPanel: vscode.WebviewPanel; |
|||
|
|||
private static showQueryResult(data) { |
|||
|
|||
SqlViewManager.showQueueResult(data,"test") |
|||
|
|||
}; |
|||
|
|||
|
|||
|
|||
private static async hasActiveConnection(): Promise<boolean> { |
|||
let count = 5; |
|||
while (!Global.activeConnection && count > 0) { |
|||
await Utility.sleep(100); |
|||
count--; |
|||
} |
|||
return !!Global.activeConnection; |
|||
} |
|||
|
|||
private static sleep(ms) { |
|||
return new Promise((resolve) => { |
|||
setTimeout(resolve, ms); |
|||
}); |
|||
} |
|||
} |
@ -1,5 +1,5 @@ |
|||
import * as vscode from "vscode"; |
|||
import { DatabaseCache } from "./DatabaseCache"; |
|||
import { DatabaseCache } from "../database/DatabaseCache"; |
|||
|
|||
export class CompletionManager { |
|||
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue