SQL Operations Studio Public Preview 1 (0.23) release source code

This commit is contained in:
Karl Burtram
2017-11-09 14:30:27 -08:00
parent b88ecb8d93
commit 3cdac41339
8829 changed files with 759707 additions and 286 deletions

View File

@@ -0,0 +1,110 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as data from 'data';
import {TPromise} from 'vs/base/common/winjs.base';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {Disposable} from 'vs/workbench/api/node/extHostTypes';
import {
ExtHostAccountManagementShape,
MainThreadAccountManagementShape,
SqlMainContext,
} from 'sql/workbench/api/node/sqlExtHost.protocol';
export class ExtHostAccountManagement extends ExtHostAccountManagementShape {
private _handlePool: number = 0;
private _proxy: MainThreadAccountManagementShape;
private _providers: {[handle: number]: AccountProviderWithMetadata} = {};
constructor(threadService: IThreadService) {
super();
this._proxy = threadService.get(SqlMainContext.MainThreadAccountManagement);
}
// PUBLIC METHODS //////////////////////////////////////////////////////
// - MAIN THREAD AVAILABLE METHODS /////////////////////////////////////
public $clear(handle: number, accountKey: data.AccountKey): Thenable<void> {
return this._withProvider(handle, (provider: data.AccountProvider) => provider.clear(accountKey));
}
public $getSecurityToken(handle: number, account: data.Account): Thenable<{}> {
return this._withProvider(handle, (provider: data.AccountProvider) => provider.getSecurityToken(account));
}
public $initialize(handle: number, restoredAccounts: data.Account[]): Thenable<data.Account[]> {
return this._withProvider(handle, (provider: data.AccountProvider) => provider.initialize(restoredAccounts));
}
public $prompt(handle: number): Thenable<data.Account> {
return this._withProvider(handle, (provider: data.AccountProvider) => provider.prompt());
}
public $refresh(handle: number, account: data.Account): Thenable<data.Account> {
return this._withProvider(handle, (provider: data.AccountProvider) => provider.refresh(account));
}
// - EXTENSION HOST AVAILABLE METHODS //////////////////////////////////
public $performOAuthAuthorization(url: string, silent: boolean): Thenable<string> {
return this._proxy.$performOAuthAuthorization(url, silent);
}
public $registerAccountProvider(providerMetadata: data.AccountProviderMetadata, provider: data.AccountProvider): Disposable {
let self = this;
// Look for any account providers that have the same provider ID
let matchingProviderIndex = Object.values(this._providers).findIndex((provider: AccountProviderWithMetadata) => {
return provider.metadata.id === providerMetadata.id;
});
if (matchingProviderIndex >= 0) {
throw new Error(`Account Provider with ID '${providerMetadata.id}' has already been registered`);
}
// Create the handle for the provider
let handle: number = this._nextHandle();
this._providers[handle] = {
metadata: providerMetadata,
provider: provider
};
// Register the provider in the main thread via the proxy
this._proxy.$registerAccountProvider(providerMetadata, handle);
// Return a disposable to cleanup the provider
return new Disposable(() => {
delete self._providers[handle];
self._proxy.$unregisterAccountProvider(handle);
});
}
/**
* This method is for testing only, it is not exposed via the shape.
* @return {number} Number of providers that are currently registered
*/
public getProviderCount(): number {
return Object.keys(this._providers).length;
}
// PRIVATE METHODS /////////////////////////////////////////////////////
private _nextHandle(): number {
return this._handlePool++;
}
private _withProvider<R>(handle: number, callback: (provider: data.AccountProvider) => Thenable<R>): Thenable<R> {
let provider = this._providers[handle];
if (provider === undefined) {
return TPromise.wrapError(new Error(`Provider ${handle} not found.`));
}
return callback(provider.provider);
}
}
interface AccountProviderWithMetadata {
metadata: data.AccountProviderMetadata;
provider: data.AccountProvider;
}

View File

@@ -0,0 +1,146 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { SqlMainContext, MainThreadCredentialManagementShape, ExtHostCredentialManagementShape } from 'sql/workbench/api/node/sqlExtHost.protocol';
import * as vscode from 'vscode';
import * as data from 'data';
import { Disposable } from 'vs/workbench/api/node/extHostTypes';
class CredentialAdapter {
public provider: data.CredentialProvider;
constructor(provider: data.CredentialProvider) {
this.provider = provider;
}
public saveCredential(credentialId: string, password: string): Thenable<boolean> {
return this.provider.saveCredential(credentialId, password);
}
public readCredential(credentialId: string): Thenable<data.Credential> {
return this.provider.readCredential(credentialId);
}
public deleteCredential(credentialId: string): Thenable<boolean> {
return this.provider.deleteCredential(credentialId);
}
}
type Adapter = CredentialAdapter;
export class ExtHostCredentialManagement extends ExtHostCredentialManagementShape {
// MEMBER VARIABLES ////////////////////////////////////////////////////
private _adapter: { [handle: number]: Adapter } = Object.create(null);
private _handlePool: number = 0;
private _proxy: MainThreadCredentialManagementShape;
private _registrationPromise: Promise<void>;
private _registrationPromiseResolve;
constructor(threadService: IThreadService) {
super();
let self = this;
this._proxy = threadService.get(SqlMainContext.MainThreadCredentialManagement);
// Create a promise to resolve when a credential provider has been registered.
// HACK: this gives us a deferred promise
this._registrationPromise = new Promise((resolve) => { self._registrationPromiseResolve = resolve; });
}
// PUBLIC METHODS //////////////////////////////////////////////////////
public $registerCredentialProvider(provider: data.CredentialProvider): vscode.Disposable {
// Store the credential provider
provider.handle = this._nextHandle();
this._adapter[provider.handle] = new CredentialAdapter(provider);
// Register the credential provider with the main thread
this._proxy.$registerCredentialProvider(provider.handle);
// Resolve the credential provider registration promise
this._registrationPromiseResolve();
return this._createDisposable(provider.handle);
}
public $getCredentialProvider(namespaceId: string): Thenable<data.CredentialProvider> {
let self = this;
if (!namespaceId) {
return TPromise.wrapError(new Error('A namespace must be provided when retrieving a credential provider'));
}
// When the registration promise has finished successfully,
return this._registrationPromise.then(() =>
self._withAdapter(0, CredentialAdapter, adapter => self._createNamespacedCredentialProvider(namespaceId, adapter))
);
}
public $saveCredential(credentialId: string, password: string): Thenable<boolean> {
return this._withAdapter(0, CredentialAdapter, adapter => adapter.saveCredential(credentialId, password));
}
public $readCredential(credentialId: string): Thenable<data.Credential> {
return this._withAdapter(0, CredentialAdapter, adapter => adapter.readCredential(credentialId));
}
public $deleteCredential(credentialId: string): Thenable<boolean> {
return this._withAdapter(0, CredentialAdapter, adapter => adapter.deleteCredential(credentialId));
}
/**
* Helper method for tests. Not exposed via shape.
* @return {number} Number of providers registered
*/
public getProviderCount(): number {
return Object.keys(this._adapter).length;
}
// PRIVATE HELPERS /////////////////////////////////////////////////////
private static _getNamespacedCredentialId(namespaceId: string, credentialId: string) {
return `${namespaceId}|${credentialId}`;
}
private _createNamespacedCredentialProvider(namespaceId: string, adapter: CredentialAdapter): Thenable<data.CredentialProvider> {
// Create a provider that wraps the methods in a namespace
let provider: data.CredentialProvider = {
handle: adapter.provider.handle,
deleteCredential: (credentialId: string) => {
let namespacedId = ExtHostCredentialManagement._getNamespacedCredentialId(namespaceId, credentialId);
return adapter.provider.deleteCredential(namespacedId);
},
readCredential: (credentialId: string) => {
let namespacedId = ExtHostCredentialManagement._getNamespacedCredentialId(namespaceId, credentialId);
return adapter.provider.readCredential(namespacedId);
},
saveCredential: (credentialId: string, credential: string) => {
let namespacedId = ExtHostCredentialManagement._getNamespacedCredentialId(namespaceId, credentialId);
return adapter.provider.saveCredential(namespacedId, credential);
}
};
return Promise.resolve(provider);
}
private _createDisposable(handle: number): Disposable {
return new Disposable(() => {
delete this._adapter[handle];
this._proxy.$unregisterCredentialProvider(handle);
});
}
private _nextHandle(): number {
return this._handlePool++;
}
private _withAdapter<A, R>(handle: number, ctor: { new (...args: any[]): A }, callback: (adapter: A) => Thenable<R>): Thenable<R> {
let adapter = this._adapter[handle];
if (!(adapter instanceof ctor)) {
return TPromise.wrapError(new Error('no adapter found'));
}
return callback(<any>adapter);
}
}

View File

@@ -0,0 +1,541 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import Event, { Emitter } from 'vs/base/common/event';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { SqlMainContext, MainThreadDataProtocolShape, ExtHostDataProtocolShape } from 'sql/workbench/api/node/sqlExtHost.protocol';
import * as vscode from 'vscode';
import * as data from 'data';
import { Disposable } from 'vs/workbench/api/node/extHostTypes';
export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
private readonly _onDidChangeLanguageFlavor = new Emitter<data.DidChangeLanguageFlavorParams>();
readonly onDidChangeLanguageFlavor: Event<data.DidChangeLanguageFlavorParams> = this._onDidChangeLanguageFlavor.event;
private _proxy: MainThreadDataProtocolShape;
private static _handlePool: number = 0;
private _adapter = new Map<number, data.DataProtocolProvider>();
constructor(
threadService: IThreadService
) {
super();
this._proxy = threadService.get(SqlMainContext.MainThreadDataProtocol);
}
private _createDisposable(handle: number): Disposable {
return new Disposable(() => {
this._adapter.delete(handle);
this._proxy.$unregisterProvider(handle);
});
}
private _nextHandle(): number {
return ExtHostDataProtocol._handlePool++;
}
private _runWithProvider<T>(handle: number, action: (p: data.DataProtocolProvider) => Thenable<T>): Thenable<T> {
let provider = this._adapter.get(handle);
return provider !== undefined
? action(provider)
: undefined;
}
$registerProvider(provider: data.DataProtocolProvider): vscode.Disposable {
provider.handle = this._nextHandle();
this._adapter.set(provider.handle, provider);
this._proxy.$registerProvider(provider.providerId, provider.handle);
return this._createDisposable(provider.handle);
}
// Capabilities Discovery handlers
$getServerCapabilities(handle: number, client: data.DataProtocolClientCapabilities): Thenable<data.DataProtocolServerCapabilities> {
return this._runWithProvider(handle, provider => {
return provider.capabilitiesProvider ? provider.capabilitiesProvider.getServerCapabilities(client)
: undefined;
});
}
// Connection Management handlers
$connect(handle: number, connectionUri: string, connection: data.ConnectionInfo): Thenable<boolean> {
return this._runWithProvider(handle, provider => {
return provider.connectionProvider ? provider.connectionProvider.connect(connectionUri, connection)
: undefined;
});
}
$disconnect(handle: number, connectionUri: string): Thenable<boolean> {
return this._runWithProvider(handle, provider => {
return provider.connectionProvider ? provider.connectionProvider.disconnect(connectionUri)
: undefined;
});
}
$cancelConnect(handle: number, connectionUri: string): Thenable<boolean> {
return this._runWithProvider(handle, provider => {
return provider.connectionProvider ? provider.connectionProvider.cancelConnect(connectionUri)
: undefined;
});
}
$changeDatabase(handle: number, connectionUri: string, newDatabase: string): Thenable<boolean> {
return this._runWithProvider(handle, provider => {
return provider.connectionProvider ? provider.connectionProvider.changeDatabase(connectionUri, newDatabase)
: undefined;
});
}
$listDatabases(handle: number, connectionUri: string): Thenable<data.ListDatabasesResult> {
return this._runWithProvider(handle, provider => {
return provider.connectionProvider ? provider.connectionProvider.listDatabases(connectionUri)
: undefined;
});
}
$rebuildIntelliSenseCache(handle: number, connectionUri: string): Thenable<void> {
return this._runWithProvider(handle, provider => {
return provider.connectionProvider ? provider.connectionProvider.rebuildIntelliSenseCache(connectionUri)
: undefined;
});
}
$onConnectComplete(handle: number, connectionInfoSummary: data.ConnectionInfoSummary): void {
this._proxy.$onConnectionComplete(handle, connectionInfoSummary);
}
public $onIntelliSenseCacheComplete(handle: number, connectionUri: string): void {
this._proxy.$onIntelliSenseCacheComplete(handle, connectionUri);
}
public $onConnectionChanged(handle: number, changedConnInfo: data.ChangedConnectionInfo): void {
this._proxy.$onConnectionChangeNotification(handle, changedConnInfo);
}
// Protocol-wide Event Handlers
public $languageFlavorChanged(params: data.DidChangeLanguageFlavorParams): void {
this._onDidChangeLanguageFlavor.fire(params);
}
// Query Management handlers
$cancelQuery(handle: number, ownerUri: string): Thenable<data.QueryCancelResult> {
return this._runWithProvider(handle, provider => {
return provider.queryProvider.cancelQuery(ownerUri);
});
}
$runQuery(handle: number, ownerUri: string, selection: data.ISelectionData, runOptions?: data.ExecutionPlanOptions): Thenable<void> {
return this._runWithProvider(handle, provider => {
return provider.queryProvider.runQuery(ownerUri, selection, runOptions);
});
}
$runQueryStatement(handle: number, ownerUri: string, line: number, column: number): Thenable<void> {
return this._runWithProvider(handle, provider => {
return provider.queryProvider.runQueryStatement(ownerUri, line, column);
});
}
$runQueryString(handle: number, ownerUri: string, queryString: string): Thenable<void> {
return this._runWithProvider(handle, provider => {
return provider.queryProvider.runQueryString(ownerUri, queryString);
});
}
$runQueryAndReturn(handle: number, ownerUri: string, queryString: string): Thenable<data.SimpleExecuteResult> {
return this._runWithProvider(handle, provider => {
return provider.queryProvider.runQueryAndReturn(ownerUri, queryString);
});
}
$getQueryRows(handle: number, rowData: data.QueryExecuteSubsetParams): Thenable<data.QueryExecuteSubsetResult> {
return this._runWithProvider(handle, (provider) => {
return provider.queryProvider.getQueryRows(rowData);
});
}
$disposeQuery(handle: number, ownerUri: string): Thenable<void> {
return this._runWithProvider(handle, (provider) => {
return provider.queryProvider.disposeQuery(ownerUri);
});
}
$onQueryComplete(handle: number, result: data.QueryExecuteCompleteNotificationResult): void {
this._proxy.$onQueryComplete(handle, result);
}
$onBatchStart(handle: number, batchInfo: data.QueryExecuteBatchNotificationParams): void {
this._proxy.$onBatchStart(handle, batchInfo);
}
$onBatchComplete(handle: number, batchInfo: data.QueryExecuteBatchNotificationParams): void {
this._proxy.$onBatchComplete(handle, batchInfo);
}
$onResultSetComplete(handle: number, resultSetInfo: data.QueryExecuteResultSetCompleteNotificationParams): void {
this._proxy.$onResultSetComplete(handle, resultSetInfo);
}
$onQueryMessage(handle: number, message: data.QueryExecuteMessageParams): void {
this._proxy.$onQueryMessage(handle, message);
}
$saveResults(handle: number, requestParams: data.SaveResultsRequestParams): Thenable<data.SaveResultRequestResult> {
return this._runWithProvider(handle, (provider) => {
return provider.queryProvider.saveResults(requestParams);
});
}
// Edit Data handlers
$commitEdit(handle: number, ownerUri: string): Thenable<void> {
return this._runWithProvider(handle, provider => {
return provider.queryProvider.commitEdit(ownerUri);
});
}
$createRow(handle: number, ownerUri: string): Thenable<data.EditCreateRowResult> {
return this._runWithProvider(handle, provider => {
return provider.queryProvider.createRow(ownerUri);
});
}
$deleteRow(handle: number, ownerUri: string, rowId: number): Thenable<void> {
return this._runWithProvider(handle, provider => {
return provider.queryProvider.deleteRow(ownerUri, rowId);
});
}
$disposeEdit(handle: number, ownerUri: string): Thenable<void> {
return this._runWithProvider(handle, provider => {
return provider.queryProvider.disposeEdit(ownerUri);
});
}
$initializeEdit(handle: number, ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): Thenable<void> {
return this._runWithProvider(handle, provider => {
return provider.queryProvider.initializeEdit(ownerUri, schemaName, objectName, objectType, rowLimit);
});
}
$revertCell(handle: number, ownerUri: string, rowId: number, columnId: number): Thenable<data.EditRevertCellResult> {
return this._runWithProvider(handle, provider => {
return provider.queryProvider.revertCell(ownerUri, rowId, columnId);
});
}
$revertRow(handle: number, ownerUri: string, rowId: number): Thenable<void> {
return this._runWithProvider(handle, provider => {
return provider.queryProvider.revertRow(ownerUri, rowId);
});
}
$updateCell(handle: number, ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<data.EditUpdateCellResult> {
return this._runWithProvider(handle, provider => {
return provider.queryProvider.updateCell(ownerUri, rowId, columnId, newValue);
});
}
$getEditRows(handle: number, rowData: data.EditSubsetParams): Thenable<data.EditSubsetResult> {
return this._runWithProvider(handle, (provider) => {
return provider.queryProvider.getEditRows(rowData);
});
}
$onEditSessionReady(handle: number, ownerUri: string, success: boolean, message: string): void {
this._proxy.$onEditSessionReady(handle, ownerUri, success, message);
}
// Metadata handlers
public $getMetadata(handle: number, connectionUri: string): Thenable<data.ProviderMetadata> {
return this._runWithProvider(handle, provider => {
return provider.metadataProvider ? provider.metadataProvider.getMetadata(connectionUri)
: Promise.resolve(undefined);
});
}
// Object Explorer Service
public $createObjectExplorerSession(handle: number, connInfo: data.ConnectionInfo): Thenable<data.ObjectExplorerSessionResponse> {
return this._runWithProvider(handle, provider => {
return provider.objectExplorerProvider ? provider.objectExplorerProvider.createNewSession(connInfo)
: Promise.resolve(undefined);
});
}
public $expandObjectExplorerNode(handle: number, nodeInfo: data.ExpandNodeInfo): Thenable<boolean> {
return this._runWithProvider(handle, provider => {
return provider.objectExplorerProvider ? provider.objectExplorerProvider.expandNode(nodeInfo)
: Promise.resolve(undefined);
});
}
public $refreshObjectExplorerNode(handle: number, nodeInfo: data.ExpandNodeInfo): Thenable<boolean> {
return this._runWithProvider(handle, provider => {
return provider.objectExplorerProvider ? provider.objectExplorerProvider.refreshNode(nodeInfo)
: Promise.resolve(undefined);
});
}
public $closeObjectExplorerSession(handle: number, closeSessionInfo: data.ObjectExplorerCloseSessionInfo): Thenable<data.ObjectExplorerCloseSessionResponse> {
return this._runWithProvider(handle, provider => {
return provider.objectExplorerProvider ? provider.objectExplorerProvider.closeSession(closeSessionInfo)
: Promise.resolve(undefined);
});
}
public $onObjectExplorerSessionCreated(handle: number, response: data.ObjectExplorerSession): void {
this._proxy.$onObjectExplorerSessionCreated(handle, response);
}
public $onObjectExplorerNodeExpanded(handle: number, response: data.ObjectExplorerExpandInfo): void {
this._proxy.$onObjectExplorerNodeExpanded(handle, response);
}
// Task Service
public $getAllTasks(handle: number, listTasksParams: data.ListTasksParams): Thenable<data.ListTasksResponse> {
return this._runWithProvider(handle, provider => {
return provider.taskServicesProvider ? provider.taskServicesProvider.getAllTasks(listTasksParams)
: Promise.resolve(undefined);
});
}
public $cancelTask(handle: number, cancelTaskParams: data.CancelTaskParams): Thenable<boolean> {
return this._runWithProvider(handle, provider => {
return provider.taskServicesProvider ? provider.taskServicesProvider.cancelTask(cancelTaskParams)
: Promise.resolve(undefined);
});
}
public $onTaskStatusChanged(handle: number, response: data.TaskProgressInfo): void {
this._proxy.$onTaskStatusChanged(handle, response);
}
public $onTaskCreated(handle: number, response: data.TaskInfo): void {
this._proxy.$onTaskCreated(handle, response);
}
public $getDatabases(handle: number, connectionUri: string): Thenable<string[]> {
return this._runWithProvider(handle, provider => {
return provider.metadataProvider ? provider.metadataProvider.getDatabases(connectionUri)
: Promise.resolve(undefined);
});
}
public $getTableInfo(handle: number, connectionUri: string, metadata: data.ObjectMetadata): Thenable<data.ColumnMetadata[]> {
return this._runWithProvider(handle, provider => {
return provider.metadataProvider ? provider.metadataProvider.getTableInfo(connectionUri, metadata)
: Promise.resolve(undefined);
});
}
public $getViewInfo(handle: number, connectionUri: string, metadata: data.ObjectMetadata): Thenable<data.ColumnMetadata[]> {
return this._runWithProvider(handle, provider => {
return provider.metadataProvider ? provider.metadataProvider.getViewInfo(connectionUri, metadata)
: Promise.resolve(undefined);
});
}
// Scripting handlers
public $scriptAsSelect(handle: number, connectionUri: string, metadata: data.ObjectMetadata, paramDetails: data.ScriptingParamDetails): Thenable<data.ScriptingResult> {
return this._runWithProvider(handle, provider => {
return provider.scriptingProvider ? provider.scriptingProvider.scriptAsSelect(connectionUri, metadata, paramDetails)
: Promise.resolve(undefined);
});
}
public $scriptAsCreate(handle: number, connectionUri: string, metadata: data.ObjectMetadata, paramDetails: data.ScriptingParamDetails): Thenable<data.ScriptingResult> {
return this._runWithProvider(handle, provider => {
return provider.scriptingProvider ? provider.scriptingProvider.scriptAsCreate(connectionUri, metadata, paramDetails)
: Promise.resolve(undefined);
});
}
public $scriptAsUpdate(handle: number, connectionUri: string, metadata: data.ObjectMetadata, paramDetails: data.ScriptingParamDetails): Thenable<data.ScriptingResult> {
return this._runWithProvider(handle, provider => {
return provider.scriptingProvider ? provider.scriptingProvider.scriptAsUpdate(connectionUri, metadata, paramDetails)
: Promise.resolve(undefined);
});
}
public $scriptAsInsert(handle: number, connectionUri: string, metadata: data.ObjectMetadata, paramDetails: data.ScriptingParamDetails): Thenable<data.ScriptingResult> {
return this._runWithProvider(handle, provider => {
return provider.scriptingProvider ? provider.scriptingProvider.scriptAsInsert(connectionUri, metadata, paramDetails)
: Promise.resolve(undefined);
});
}
public $scriptAsDelete(handle: number, connectionUri: string, metadata: data.ObjectMetadata, paramDetails: data.ScriptingParamDetails): Thenable<data.ScriptingResult> {
return this._runWithProvider(handle, provider => {
return provider.scriptingProvider ? provider.scriptingProvider.scriptAsDelete(connectionUri, metadata, paramDetails)
: Promise.resolve(undefined);
});
}
public $onScriptingComplete(handle: number, scriptingCompleteResult: data.ScriptingCompleteResult): void {
this._proxy.$onScriptingComplete(handle, scriptingCompleteResult);
}
/**
* Create a new database on the provided connection
*/
public $createDatabase(handle: number, connectionUri: string, database: data.DatabaseInfo): Thenable<data.CreateDatabaseResponse> {
return this._runWithProvider(handle, provider => {
return provider.adminServicesProvider ? provider.adminServicesProvider.createDatabase(connectionUri, database)
: Promise.resolve(undefined);
});
}
/**
* Create a new database on the provided connection
*/
public $getDefaultDatabaseInfo(handle: number, connectionUri: string): Thenable<data.DatabaseInfo> {
return this._runWithProvider(handle, provider => {
return provider.adminServicesProvider ? provider.adminServicesProvider.getDefaultDatabaseInfo(connectionUri)
: Promise.resolve(undefined);
});
}
/**
* Get the info on a database
*/
public $getDatabaseInfo(handle: number, connectionUri: string): Thenable<data.DatabaseInfo> {
return this._runWithProvider(handle, provider => {
return provider.adminServicesProvider ? provider.adminServicesProvider.getDatabaseInfo(connectionUri)
: Promise.resolve(undefined);
});
}
/**
* Create a new login on the provided connection
*/
public $createLogin(handle: number, connectionUri: string, login: data.LoginInfo): Thenable<data.CreateLoginResponse> {
return this._runWithProvider(handle, provider => {
return provider.adminServicesProvider ? provider.adminServicesProvider.createLogin(connectionUri, login)
: Promise.resolve(undefined);
});
}
/**
* Backup a database
*/
public $backup(handle: number, connectionUri: string, backupInfo: { [key: string]: any }, taskExecutionMode: data.TaskExecutionMode): Thenable<data.BackupResponse> {
return this._runWithProvider(handle, provider => {
return provider.disasterRecoveryProvider ? provider.disasterRecoveryProvider.backup(connectionUri, backupInfo, taskExecutionMode)
: Promise.resolve(undefined);
});
}
/**
* Create a new database on the provided connection
*/
public $getBackupConfigInfo(handle: number, connectionUri: string): Thenable<data.BackupConfigInfo> {
return this._runWithProvider(handle, provider => {
return provider.disasterRecoveryProvider ? provider.disasterRecoveryProvider.getBackupConfigInfo(connectionUri)
: Promise.resolve(undefined);
});
}
/**
* Restores a database
*/
public $restore(handle: number, connectionUri: string, restoreInfo: data.RestoreInfo): Thenable<data.RestoreResponse> {
return this._runWithProvider(handle, provider => {
return provider.disasterRecoveryProvider ? provider.disasterRecoveryProvider.restore(connectionUri, restoreInfo)
: Promise.resolve(undefined);
});
}
/**
* Gets a plan for restoring a database
*/
public $getRestorePlan(handle: number, connectionUri: string, restoreInfo: data.RestoreInfo): Thenable<data.RestorePlanResponse> {
return this._runWithProvider(handle, provider => {
return provider.disasterRecoveryProvider ? provider.disasterRecoveryProvider.getRestorePlan(connectionUri, restoreInfo)
: Promise.resolve(undefined);
});
}
/**
* cancels a restore plan
*/
public $cancelRestorePlan(handle: number, connectionUri: string, restoreInfo: data.RestoreInfo): Thenable<boolean> {
return this._runWithProvider(handle, provider => {
return provider.disasterRecoveryProvider ? provider.disasterRecoveryProvider.cancelRestorePlan(connectionUri, restoreInfo)
: Promise.resolve(undefined);
});
}
/**
* Gets restore config Info
*/
public $getRestoreConfigInfo(handle: number, connectionUri: string): Thenable<data.RestoreConfigInfo> {
return this._runWithProvider(handle, provider => {
return provider.disasterRecoveryProvider ? provider.disasterRecoveryProvider.getRestoreConfigInfo(connectionUri)
: Promise.resolve(undefined);
});
}
/**
* Open a file browser
*/
public $openFileBrowser(handle: number, ownerUri: string, expandPath: string, fileFilters: string[], changeFilter: boolean): Thenable<boolean> {
return this._runWithProvider(handle, provider => {
return provider.fileBrowserProvider ? provider.fileBrowserProvider.openFileBrowser(ownerUri, expandPath, fileFilters, changeFilter)
: Promise.resolve(undefined);
});
}
/**
* Send event when opening browser is complete
*/
public $onFileBrowserOpened(handle: number, response: data.FileBrowserOpenedParams): void {
this._proxy.$onFileBrowserOpened(handle, response);
}
/**
* Expand a folder node
*/
public $expandFolderNode(handle: number, ownerUri: string, expandPath: string): Thenable<boolean> {
return this._runWithProvider(handle, provider => {
return provider.fileBrowserProvider ? provider.fileBrowserProvider.expandFolderNode(ownerUri, expandPath)
: Promise.resolve(undefined);
});
}
/**
* Send event when expansion is complete
*/
public $onFolderNodeExpanded(handle: number, response: data.FileBrowserExpandedParams): void {
this._proxy.$onFolderNodeExpanded(handle, response);
}
/**
* Validate selected file path
*/
public $validateFilePaths(handle: number, ownerUri: string, serviceType: string, selectedFiles: string[]): Thenable<boolean> {
return this._runWithProvider(handle, provider => {
return provider.fileBrowserProvider ? provider.fileBrowserProvider.validateFilePaths(ownerUri, serviceType, selectedFiles)
: Promise.resolve(undefined);
});
}
/**
* Send event when validation is complete
*/
public $onFilePathsValidated(handle: number, response: data.FileBrowserValidatedParams) {
this._proxy.$onFilePathsValidated(handle, response);
}
/**
* Close file browser
*/
public $closeFileBrowser(handle: number, ownerUri: string): Thenable<data.FileBrowserCloseResponse> {
return this._runWithProvider(handle, provider => {
return provider.fileBrowserProvider ? provider.fileBrowserProvider.closeFileBrowser(ownerUri)
: Promise.resolve(undefined);
});
}
}

View File

@@ -0,0 +1,93 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as data from 'data';
import {TPromise} from 'vs/base/common/winjs.base';
import {IThreadService} from 'vs/workbench/services/thread/common/threadService';
import {Disposable} from 'vs/workbench/api/node/extHostTypes';
import {
ExtHostResourceProviderShape,
MainThreadResourceProviderShape,
SqlMainContext,
} from 'sql/workbench/api/node/sqlExtHost.protocol';
export class ExtHostResourceProvider extends ExtHostResourceProviderShape {
private _handlePool: number = 0;
private _proxy: MainThreadResourceProviderShape;
private _providers: {[handle: number]: ResourceProviderWithMetadata} = {};
constructor(threadService: IThreadService) {
super();
this._proxy = threadService.get(SqlMainContext.MainThreadResourceProvider);
}
// PUBLIC METHODS //////////////////////////////////////////////////////
// - MAIN THREAD AVAILABLE METHODS /////////////////////////////////////
public $createFirewallRule(handle: number, account: data.Account, firewallRuleInfo: data.FirewallRuleInfo): Thenable<data.CreateFirewallRuleResponse> {
return this._withProvider(handle, (provider: data.ResourceProvider) => provider.createFirewallRule(account, firewallRuleInfo));
}
public $handleFirewallRule(handle: number, errorCode: number, errorMessage: string, connectionTypeId: string): Thenable<data.HandleFirewallRuleResponse> {
return this._withProvider(handle, (provider: data.ResourceProvider) => provider.handleFirewallRule(errorCode, errorMessage, connectionTypeId));
}
// - EXTENSION HOST AVAILABLE METHODS //////////////////////////////////
public $registerResourceProvider(providerMetadata: data.ResourceProviderMetadata, provider: data.ResourceProvider): Disposable {
let self = this;
// Look for any account providers that have the same provider ID
let matchingProviderIndex = Object.values(this._providers).findIndex((provider: ResourceProviderWithMetadata) => {
return provider.metadata.id === providerMetadata.id;
});
if (matchingProviderIndex >= 0) {
throw new Error(`Resource Provider with ID '${providerMetadata.id}' has already been registered`);
}
// Create the handle for the provider
let handle: number = this._nextHandle();
this._providers[handle] = {
metadata: providerMetadata,
provider: provider
};
// Register the provider in the main thread via the proxy
this._proxy.$registerResourceProvider(providerMetadata, handle);
// Return a disposable to cleanup the provider
return new Disposable(() => {
delete self._providers[handle];
self._proxy.$unregisterResourceProvider(handle);
});
}
/**
* This method is for testing only, it is not exposed via the shape.
* @return {number} Number of providers that are currently registered
*/
public getProviderCount(): number {
return Object.keys(this._providers).length;
}
// PRIVATE METHODS /////////////////////////////////////////////////////
private _nextHandle(): number {
return this._handlePool++;
}
private _withProvider<R>(handle: number, callback: (provider: data.ResourceProvider) => Thenable<R>): Thenable<R> {
let provider = this._providers[handle];
if (provider === undefined) {
return TPromise.wrapError(new Error(`Provider ${handle} not found.`));
}
return callback(provider.provider);
}
}
interface ResourceProviderWithMetadata {
metadata: data.ResourceProviderMetadata;
provider: data.ResourceProvider;
}

View File

@@ -0,0 +1,73 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { SqlMainContext, MainThreadSerializationProviderShape, ExtHostSerializationProviderShape } from 'sql/workbench/api/node/sqlExtHost.protocol';
import * as vscode from 'vscode';
import * as data from 'data';
import { Disposable } from 'vs/workbench/api/node/extHostTypes';
class SerializationAdapter {
private _provider: data.SerializationProvider;
constructor(provider: data.SerializationProvider) {
this._provider = provider;
}
public saveAs(saveFormat: string, savePath: string, results: string, appendToFile: boolean): Thenable<data.SaveResultRequestResult> {
return this._provider.saveAs(saveFormat, savePath, results, appendToFile);
}
}
type Adapter = SerializationAdapter;
export class ExtHostSerializationProvider extends ExtHostSerializationProviderShape {
private _proxy: MainThreadSerializationProviderShape;
private static _handlePool: number = 0;
private _adapter: { [handle: number]: Adapter } = Object.create(null);
private _createDisposable(handle: number): Disposable {
return new Disposable(() => {
delete this._adapter[handle];
this._proxy.$unregisterSerializationProvider(handle);
});
}
private _nextHandle(): number {
return ExtHostSerializationProvider._handlePool++;
}
private _withAdapter<A, R>(handle: number, ctor: { new (...args: any[]): A }, callback: (adapter: A) => Thenable<R>): Thenable<R> {
let adapter = this._adapter[handle];
if (!(adapter instanceof ctor)) {
return TPromise.wrapError(new Error('no adapter found'));
}
return callback(<any>adapter);
}
constructor(
threadService: IThreadService
) {
super();
this._proxy = threadService.get(SqlMainContext.MainThreadSerializationProvider);
}
public $registerSerializationProvider(provider: data.SerializationProvider): vscode.Disposable {
provider.handle = this._nextHandle();
this._adapter[provider.handle] = new SerializationAdapter(provider);
this._proxy.$registerSerializationProvider(provider.handle);
return this._createDisposable(provider.handle);
}
public $saveAs(saveFormat: string, savePath: string, results: string, appendToFile: boolean): Thenable<data.SaveResultRequestResult> {
return this._withAdapter(0, SerializationAdapter, adapter => adapter.saveAs(saveFormat, savePath, results, appendToFile));
}
}

View File

@@ -0,0 +1,78 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as data from 'data';
import {TPromise} from 'vs/base/common/winjs.base';
import {IAccountManagementService} from 'sql/services/accountManagement/interfaces';
import {dispose, IDisposable} from 'vs/base/common/lifecycle';
import {
ExtHostAccountManagementShape,
MainThreadAccountManagementShape,
SqlExtHostContext,
SqlMainContext
} from 'sql/workbench/api/node/sqlExtHost.protocol';
import { IExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
@extHostNamedCustomer(SqlMainContext.MainThreadAccountManagement)
export class MainThreadAccountManagement extends MainThreadAccountManagementShape {
private _providerMetadata: {[handle: number]: data.AccountProviderMetadata};
private _proxy: ExtHostAccountManagementShape;
private _toDispose: IDisposable[];
constructor(
extHostContext: IExtHostContext,
@IAccountManagementService private _accountManagementService: IAccountManagementService
) {
super();
this._providerMetadata = {};
if (extHostContext) {
this._proxy = extHostContext.get(SqlExtHostContext.ExtHostAccountManagement);
}
this._toDispose = [];
}
public $performOAuthAuthorization(url, silent: boolean): Thenable<string> {
return this._accountManagementService.performOAuthAuthorization(url, silent);
}
public $registerAccountProvider(providerMetadata: data.AccountProviderMetadata, handle: number): Thenable<any> {
let self = this;
// Create the account provider that interfaces with the extension via the proxy and register it
let accountProvider: data.AccountProvider = {
clear(accountKey: data.AccountKey): Thenable<void> {
return self._proxy.$clear(handle, accountKey);
},
getSecurityToken(account: data.Account): Thenable<{}> {
return self._proxy.$getSecurityToken(handle, account);
},
initialize(restoredAccounts: data.Account[]): Thenable<data.Account[]> {
return self._proxy.$initialize(handle, restoredAccounts);
},
prompt(): Thenable<data.Account> {
return self._proxy.$prompt(handle);
},
refresh(account: data.Account): Thenable<data.Account> {
return self._proxy.$refresh(handle, account);
}
};
this._accountManagementService.registerProvider(providerMetadata, accountProvider);
this._providerMetadata[handle] = providerMetadata;
return TPromise.as(null);
}
public $unregisterAccountProvider(handle: number): Thenable<any> {
this._accountManagementService.unregisterProvider(this._providerMetadata[handle]);
return TPromise.as(null);
}
public dispose(): void {
this._toDispose = dispose(this._toDispose);
}
}

View File

@@ -0,0 +1,66 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import {
SqlExtHostContext, ExtHostCredentialManagementShape,
MainThreadCredentialManagementShape, SqlMainContext } from 'sql/workbench/api/node/sqlExtHost.protocol';
import { ICredentialsService } from 'sql/services/credentials/credentialsService';
import * as data from 'data';
import { IExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
@extHostNamedCustomer(SqlMainContext.MainThreadCredentialManagement)
export class MainThreadCredentialManagement extends MainThreadCredentialManagementShape {
private _proxy: ExtHostCredentialManagementShape;
private _toDispose: IDisposable[];
private _registrations: { [handle: number]: IDisposable; } = Object.create(null);
constructor(
extHostContext: IExtHostContext,
@ICredentialsService private credentialService: ICredentialsService
) {
super();
if (extHostContext) {
this._proxy = extHostContext.get(SqlExtHostContext.ExtHostCredentialManagement);
}
}
public dispose(): void {
this._toDispose = dispose(this._toDispose);
}
public $registerCredentialProvider(handle: number): TPromise<any> {
let self = this;
this._registrations[handle] = this.credentialService.addEventListener(handle, {
onSaveCredential(credentialId: string, password: string): Thenable<boolean> {
return self._proxy.$saveCredential(credentialId, password);
},
onReadCredential(credentialId: string): Thenable<data.Credential> {
return self._proxy.$readCredential(credentialId);
},
onDeleteCredential(credentialId: string): Thenable<boolean> {
return self._proxy.$deleteCredential(credentialId);
}
});
return undefined;
}
public $unregisterCredentialProvider(handle: number): TPromise<any> {
let registration = this._registrations[handle];
if (registration) {
registration.dispose();
delete this._registrations[handle];
}
return undefined;
}
}

View File

@@ -0,0 +1,353 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import {
SqlExtHostContext, ExtHostDataProtocolShape,
MainThreadDataProtocolShape, SqlMainContext
} from 'sql/workbench/api/node/sqlExtHost.protocol';
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
import { IQueryManagementService } from 'sql/parts/query/common/queryManagement';
import * as data from 'data';
import { IMetadataService } from 'sql/services/metadata/metadataService';
import { IObjectExplorerService } from 'sql/parts/registeredServer/common/objectExplorerService';
import { IScriptingService } from 'sql/services/scripting/scriptingService';
import { IAdminService } from 'sql/parts/admin/common/adminService';
import { IDisasterRecoveryService } from 'sql/parts/disasterRecovery/common/interfaces';
import { ITaskService } from 'sql/parts/taskHistory/common/taskService';
import { IProfilerService } from 'sql/parts/profiler/service/interfaces';
import { ISerializationService } from 'sql/services/serialization/serializationService';
import { IFileBrowserService } from 'sql/parts/fileBrowser/common/interfaces';
import { IExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
/**
* Main thread class for handling data protocol management registration.
*/
@extHostNamedCustomer(SqlMainContext.MainThreadDataProtocol)
export class MainThreadDataProtocol extends MainThreadDataProtocolShape {
private _proxy: ExtHostDataProtocolShape;
private _toDispose: IDisposable[];
private _capabilitiesRegistrations: { [handle: number]: IDisposable; } = Object.create(null);
constructor(
extHostContext: IExtHostContext,
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
@ICapabilitiesService private _capabilitiesService: ICapabilitiesService,
@IQueryManagementService private _queryManagementService: IQueryManagementService,
@IMetadataService private _metadataService: IMetadataService,
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
@IScriptingService private _scriptingService: IScriptingService,
@IAdminService private _adminService: IAdminService,
@IDisasterRecoveryService private _disasterRecoveryService: IDisasterRecoveryService,
@ITaskService private _taskService: ITaskService,
@IProfilerService private _profilerService: IProfilerService,
@ISerializationService private _serializationService: ISerializationService,
@IFileBrowserService private _fileBrowserService: IFileBrowserService
) {
super();
if (extHostContext) {
this._proxy = extHostContext.get(SqlExtHostContext.ExtHostDataProtocol);
}
if (this._connectionManagementService) {
this._connectionManagementService.onLanguageFlavorChanged(e => this._proxy.$languageFlavorChanged(e), this, this._toDispose);
}
}
public dispose(): void {
this._toDispose = dispose(this._toDispose);
}
public $registerProvider(providerId: string, handle: number): TPromise<any> {
let self = this;
// register connection management provider
this._connectionManagementService.registerProvider(providerId, <data.ConnectionProvider>{
connect(connectionUri: string, connectionInfo: data.ConnectionInfo): Thenable<boolean> {
return self._proxy.$connect(handle, connectionUri, connectionInfo);
},
disconnect(connectionUri: string): Thenable<boolean> {
return self._proxy.$disconnect(handle, connectionUri);
},
changeDatabase(connectionUri: string, newDatabase: string): Thenable<boolean> {
return self._proxy.$changeDatabase(handle, connectionUri, newDatabase);
},
cancelConnect(connectionUri: string): Thenable<boolean> {
return self._proxy.$cancelConnect(handle, connectionUri);
},
listDatabases(connectionUri: string): Thenable<data.ListDatabasesResult> {
return self._proxy.$listDatabases(handle, connectionUri);
},
rebuildIntelliSenseCache(connectionUri: string): Thenable<void> {
return self._proxy.$rebuildIntelliSenseCache(handle, connectionUri);
}
});
this._capabilitiesService.registerProvider(<data.CapabilitiesProvider>{
getServerCapabilities(client: data.DataProtocolClientCapabilities): Thenable<data.DataProtocolServerCapabilities> {
return self._proxy.$getServerCapabilities(handle, client);
}
});
// register query provider
this._queryManagementService.addQueryRequestHandler(providerId, {
cancelQuery(ownerUri: string): Thenable<data.QueryCancelResult> {
return self._proxy.$cancelQuery(handle, ownerUri);
},
runQuery(ownerUri: string, selection: data.ISelectionData, runOptions?: data.ExecutionPlanOptions): Thenable<void> {
return self._proxy.$runQuery(handle, ownerUri, selection, runOptions);
},
runQueryStatement(ownerUri: string, line: number, column: number): Thenable<void> {
return self._proxy.$runQueryStatement(handle, ownerUri, line, column);
},
runQueryString(ownerUri: string, queryString: string): Thenable<void> {
return self._proxy.$runQueryString(handle, ownerUri, queryString);
},
runQueryAndReturn(ownerUri: string, queryString: string): Thenable<data.SimpleExecuteResult> {
return self._proxy.$runQueryAndReturn(handle, ownerUri, queryString);
},
getQueryRows(rowData: data.QueryExecuteSubsetParams): Thenable<data.QueryExecuteSubsetResult> {
return self._proxy.$getQueryRows(handle, rowData);
},
disposeQuery(ownerUri: string): Thenable<void> {
return self._proxy.$disposeQuery(handle, ownerUri);
},
saveResults(requestParams: data.SaveResultsRequestParams): Thenable<data.SaveResultRequestResult> {
let serializationProvider = self._serializationService.getSerializationFeatureMetadataProvider(requestParams.ownerUri);
if (serializationProvider && serializationProvider.enabled) {
return self._proxy.$saveResults(handle, requestParams);
}
else if (serializationProvider && !serializationProvider.enabled) {
return self._serializationService.disabledSaveAs();
}
else {
return self._serializationService.saveAs(requestParams.resultFormat, requestParams.filePath, undefined, true);
}
},
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): Thenable<void> {
return self._proxy.$initializeEdit(handle, ownerUri, schemaName, objectName, objectType, rowLimit);
},
updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<data.EditUpdateCellResult> {
return self._proxy.$updateCell(handle, ownerUri, rowId, columnId, newValue);
},
commitEdit(ownerUri): Thenable<void> {
return self._proxy.$commitEdit(handle, ownerUri);
},
createRow(ownerUri: string): Thenable<data.EditCreateRowResult> {
return self._proxy.$createRow(handle, ownerUri);
},
deleteRow(ownerUri: string, rowId: number): Thenable<void> {
return self._proxy.$deleteRow(handle, ownerUri, rowId);
},
disposeEdit(ownerUri: string): Thenable<void> {
return self._proxy.$disposeEdit(handle, ownerUri);
},
revertCell(ownerUri: string, rowId: number, columnId: number): Thenable<data.EditRevertCellResult> {
return self._proxy.$revertCell(handle, ownerUri, rowId, columnId);
},
revertRow(ownerUri: string, rowId: number): Thenable<void> {
return self._proxy.$revertRow(handle, ownerUri, rowId);
},
getEditRows(rowData: data.EditSubsetParams): Thenable<data.EditSubsetResult> {
return self._proxy.$getEditRows(handle, rowData);
}
});
this._metadataService.registerProvider(providerId, <data.MetadataProvider>{
getMetadata(connectionUri: string): Thenable<data.ProviderMetadata> {
return self._proxy.$getMetadata(handle, connectionUri);
},
getDatabases(connectionUri: string): Thenable<string[]> {
return self._proxy.$getDatabases(handle, connectionUri);
},
getTableInfo(connectionUri: string, metadata: data.ObjectMetadata): Thenable<data.ColumnMetadata[]> {
return self._proxy.$getTableInfo(handle, connectionUri, metadata);
},
getViewInfo(connectionUri: string, metadata: data.ObjectMetadata): Thenable<data.ColumnMetadata[]> {
return self._proxy.$getViewInfo(handle, connectionUri, metadata);
}
});
this._objectExplorerService.registerProvider(providerId, <data.ObjectExplorerProvider>{
createNewSession(connection: data.ConnectionInfo): Thenable<data.ObjectExplorerSessionResponse> {
return self._proxy.$createObjectExplorerSession(handle, connection);
},
expandNode(nodeInfo: data.ExpandNodeInfo): Thenable<boolean> {
return self._proxy.$expandObjectExplorerNode(handle, nodeInfo);
},
refreshNode(nodeInfo: data.ExpandNodeInfo): Thenable<boolean> {
return self._proxy.$refreshObjectExplorerNode(handle, nodeInfo);
},
closeSession(closeSessionInfo: data.ObjectExplorerCloseSessionInfo): Thenable<data.ObjectExplorerCloseSessionResponse> {
return self._proxy.$closeObjectExplorerSession(handle, closeSessionInfo);
}
});
this._taskService.registerProvider(providerId, <data.TaskServicesProvider>{
getAllTasks(listTasksParams: data.ListTasksParams): Thenable<data.ListTasksResponse> {
return self._proxy.$getAllTasks(handle, listTasksParams);
},
cancelTask(cancelTaskParams: data.CancelTaskParams): Thenable<boolean> {
return self._proxy.$cancelTask(handle, cancelTaskParams);
}
});
this._scriptingService.registerProvider(providerId, <data.ScriptingProvider>{
scriptAsSelect(connectionUri: string, metadata: data.ObjectMetadata, paramDetails: data.ScriptingParamDetails): Thenable<data.ScriptingResult> {
return self._proxy.$scriptAsSelect(handle, connectionUri, metadata, paramDetails);
},
scriptAsCreate(connectionUri: string, metadata: data.ObjectMetadata, paramDetails: data.ScriptingParamDetails): Thenable<data.ScriptingResult> {
return self._proxy.$scriptAsCreate(handle, connectionUri, metadata, paramDetails);
},
scriptAsInsert(connectionUri: string, metadata: data.ObjectMetadata, paramDetails: data.ScriptingParamDetails): Thenable<data.ScriptingResult> {
return self._proxy.$scriptAsInsert(handle, connectionUri, metadata, paramDetails);
},
scriptAsUpdate(connectionUri: string, metadata: data.ObjectMetadata, paramDetails: data.ScriptingParamDetails): Thenable<data.ScriptingResult> {
return self._proxy.$scriptAsUpdate(handle, connectionUri, metadata, paramDetails);
},
scriptAsDelete(connectionUri: string, metadata: data.ObjectMetadata, paramDetails: data.ScriptingParamDetails): Thenable<data.ScriptingResult> {
return self._proxy.$scriptAsDelete(handle, connectionUri, metadata, paramDetails);
}
});
this._adminService.registerProvider(providerId, <data.AdminServicesProvider>{
createDatabase(connectionUri: string, database: data.DatabaseInfo): Thenable<data.CreateDatabaseResponse> {
return self._proxy.$createDatabase(handle, connectionUri, database);
},
getDefaultDatabaseInfo(connectionUri: string): Thenable<data.DatabaseInfo> {
return self._proxy.$getDefaultDatabaseInfo(handle, connectionUri);
},
getDatabaseInfo(connectionUri: string): Thenable<data.DatabaseInfo> {
return self._proxy.$getDatabaseInfo(handle, connectionUri);
},
createLogin(connectionUri: string, login: data.LoginInfo): Thenable<data.CreateLoginResponse> {
return self._proxy.$createLogin(handle, connectionUri, login);
}
});
this._disasterRecoveryService.registerProvider(providerId, <data.DisasterRecoveryProvider>{
backup(connectionUri: string, backupInfo: { [key: string]: any }, taskExecutionMode: data.TaskExecutionMode): Thenable<data.BackupResponse> {
return self._proxy.$backup(handle, connectionUri, backupInfo, taskExecutionMode);
},
getBackupConfigInfo(connectionUri: string): Thenable<data.BackupConfigInfo> {
return self._proxy.$getBackupConfigInfo(handle, connectionUri);
},
getRestorePlan(connectionUri: string, restoreInfo: data.RestoreInfo): Thenable<data.RestorePlanResponse> {
return self._proxy.$getRestorePlan(handle, connectionUri, restoreInfo);
},
cancelRestorePlan(connectionUri: string, restoreInfo: data.RestoreInfo): Thenable<boolean> {
return self._proxy.$cancelRestorePlan(handle, connectionUri, restoreInfo);
},
restore(connectionUri: string, restoreInfo: data.RestoreInfo): Thenable<data.RestoreResponse> {
return self._proxy.$restore(handle, connectionUri, restoreInfo);
},
getRestoreConfigInfo(connectionUri: string): Thenable<data.RestoreConfigInfo> {
return self._proxy.$getRestoreConfigInfo(handle, connectionUri);
}
});
this._fileBrowserService.registerProvider(providerId, <data.FileBrowserProvider>{
openFileBrowser(ownerUri: string, expandPath: string, fileFilters: string[], changeFilter: boolean): Thenable<boolean> {
return self._proxy.$openFileBrowser(handle, ownerUri, expandPath, fileFilters, changeFilter);
},
expandFolderNode(ownerUri: string, expandPath: string): Thenable<boolean> {
return self._proxy.$expandFolderNode(handle, ownerUri, expandPath);
},
validateFilePaths(ownerUri: string, serviceType: string, selectedFiles: string[]): Thenable<boolean> {
return self._proxy.$validateFilePaths(handle, ownerUri, serviceType, selectedFiles);
},
closeFileBrowser(ownerUri: string): Thenable<data.FileBrowserCloseResponse> {
return self._proxy.$closeFileBrowser(handle, ownerUri);
}
});
return undefined;
}
// Connection Management handlers
public $onConnectionComplete(handle: number, connectionInfoSummary: data.ConnectionInfoSummary): void {
this._connectionManagementService.onConnectionComplete(handle, connectionInfoSummary);
}
public $onIntelliSenseCacheComplete(handle: number, connectionUri: string): void {
this._connectionManagementService.onIntelliSenseCacheComplete(handle, connectionUri);
}
public $onConnectionChangeNotification(handle: number, changedConnInfo: data.ChangedConnectionInfo): void {
this._connectionManagementService.onConnectionChangedNotification(handle, changedConnInfo);
}
// Query Management handlers
public $onQueryComplete(handle: number, result: data.QueryExecuteCompleteNotificationResult): void {
this._queryManagementService.onQueryComplete(result);
}
public $onBatchStart(handle: number, batchInfo: data.QueryExecuteBatchNotificationParams): void {
this._queryManagementService.onBatchStart(batchInfo);
}
public $onBatchComplete(handle: number, batchInfo: data.QueryExecuteBatchNotificationParams): void {
this._queryManagementService.onBatchComplete(batchInfo);
}
public $onResultSetComplete(handle: number, resultSetInfo: data.QueryExecuteResultSetCompleteNotificationParams): void {
this._queryManagementService.onResultSetComplete(resultSetInfo);
}
public $onQueryMessage(handle: number, message: data.QueryExecuteMessageParams): void {
this._queryManagementService.onMessage(message);
}
public $onEditSessionReady(handle: number, ownerUri: string, success: boolean, message: string): void {
this._queryManagementService.onEditSessionReady(ownerUri, success, message);
}
// Script Handlers
public $onScriptingComplete(handle: number, scriptingCompleteResult: data.ScriptingCompleteResult): void {
this._scriptingService.onScriptingComplete(handle, scriptingCompleteResult);
}
//OE handlers
public $onObjectExplorerSessionCreated(handle: number, sessionResponse: data.ObjectExplorerSession): void {
this._objectExplorerService.onSessionCreated(handle, sessionResponse);
}
public $onObjectExplorerNodeExpanded(handle: number, expandResponse: data.ObjectExplorerExpandInfo): void {
this._objectExplorerService.onNodeExpanded(handle, expandResponse);
}
//Tasks handlers
public $onTaskCreated(handle: number, taskInfo: data.TaskInfo): void {
this._taskService.onNewTaskCreated(handle, taskInfo);
}
public $onTaskStatusChanged(handle: number, taskProgressInfo: data.TaskProgressInfo): void {
this._taskService.onTaskStatusChanged(handle, taskProgressInfo);
}
//File browser handlers
public $onFileBrowserOpened(handle: number, response: data.FileBrowserOpenedParams): void {
this._fileBrowserService.onFileBrowserOpened(handle, response);
}
public $onFolderNodeExpanded(handle: number, response: data.FileBrowserExpandedParams): void {
this._fileBrowserService.onFolderNodeExpanded(handle, response);
}
public $onFilePathsValidated(handle: number, response: data.FileBrowserValidatedParams): void {
this._fileBrowserService.onFilePathsValidated(handle, response);
}
public $unregisterProvider(handle: number): TPromise<any> {
let capabilitiesRegistration = this._capabilitiesRegistrations[handle];
if (capabilitiesRegistration) {
capabilitiesRegistration.dispose();
delete this._capabilitiesRegistrations[handle];
}
return undefined;
}
}

View File

@@ -0,0 +1,65 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as data from 'data';
import {TPromise} from 'vs/base/common/winjs.base';
import { IResourceProviderService } from 'sql/parts/accountManagement/common/interfaces';
import {dispose, IDisposable} from 'vs/base/common/lifecycle';
import {
ExtHostResourceProviderShape,
MainThreadResourceProviderShape,
SqlExtHostContext,
SqlMainContext
} from 'sql/workbench/api/node/sqlExtHost.protocol';
import { IExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
@extHostNamedCustomer(SqlMainContext.MainThreadResourceProvider)
export class MainThreadResourceProvider extends MainThreadResourceProviderShape {
private _providerMetadata: {[handle: number]: data.AccountProviderMetadata};
private _proxy: ExtHostResourceProviderShape;
private _toDispose: IDisposable[];
constructor(
extHostContext: IExtHostContext,
@IResourceProviderService private _resourceProviderService: IResourceProviderService
) {
super();
this._providerMetadata = {};
if (extHostContext) {
this._proxy = extHostContext.get(SqlExtHostContext.ExtHostResourceProvider);
}
this._toDispose = [];
}
public $registerResourceProvider(providerMetadata: data.ResourceProviderMetadata, handle: number): Thenable<any> {
let self = this;
// Create the account provider that interfaces with the extension via the proxy and register it
let resourceProvider: data.ResourceProvider = {
createFirewallRule(account: data.Account, firewallruleInfo: data.FirewallRuleInfo): Thenable<data.CreateFirewallRuleResponse> {
return self._proxy.$createFirewallRule(handle, account, firewallruleInfo);
},
handleFirewallRule(errorCode: number, errorMessage: string, connectionTypeId: string): Thenable<data.HandleFirewallRuleResponse> {
return self._proxy.$handleFirewallRule(handle, errorCode, errorMessage, connectionTypeId);
}
};
this._resourceProviderService.registerProvider(providerMetadata.id, resourceProvider);
this._providerMetadata[handle] = providerMetadata;
return TPromise.as(null);
}
public $unregisterResourceProvider(handle: number): Thenable<any> {
this._resourceProviderService.unregisterProvider(this._providerMetadata[handle].id);
return TPromise.as(null);
}
public dispose(): void {
this._toDispose = dispose(this._toDispose);
}
}

View File

@@ -0,0 +1,62 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import {
SqlExtHostContext, ExtHostSerializationProviderShape,
MainThreadSerializationProviderShape, SqlMainContext } from 'sql/workbench/api/node/sqlExtHost.protocol';
import { ISerializationService } from 'sql/services/serialization/serializationService';
import * as data from 'data';
import { IExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
@extHostNamedCustomer(SqlMainContext.MainThreadSerializationProvider)
export class MainThreadSerializationProvider extends MainThreadSerializationProviderShape {
private _proxy: ExtHostSerializationProviderShape;
private _toDispose: IDisposable[];
private _registrations: { [handle: number]: IDisposable; } = Object.create(null);
constructor(
extHostContext: IExtHostContext,
@ISerializationService private serializationService: ISerializationService
) {
super();
if (extHostContext) {
this._proxy = extHostContext.get(SqlExtHostContext.ExtHostSerializationProvider);
}
}
public dispose(): void {
this._toDispose = dispose(this._toDispose);
}
public $registerSerializationProvider(handle: number): TPromise<any> {
let self = this;
this._registrations[handle] = this.serializationService.addEventListener(handle, {
onSaveAs(saveFormat: string, savePath: string, results: string, appendToFile: boolean): Thenable<data.SaveResultRequestResult> {
return self._proxy.$saveAs(saveFormat, savePath, results, appendToFile);
}
});
return undefined;
}
public $unregisterSerializationProvider(handle: number): TPromise<any> {
let registration = this._registrations[handle];
if (registration) {
registration.dispose();
delete this._registrations[handle];
}
return undefined;
}
}

View File

@@ -0,0 +1,288 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as extHostApi from 'vs/workbench/api/node/extHost.api.impl';
import { TrieMap } from 'vs/base/common/map';
import { TPromise } from 'vs/base/common/winjs.base';
import { IInitData } from 'vs/workbench/api/node/extHost.protocol';
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { realpath } from 'fs';
import * as extHostTypes from 'vs/workbench/api/node/extHostTypes';
import * as data from 'data';
import * as vscode from 'vscode';
import { SqlExtHostContext } from 'sql/workbench/api/node/sqlExtHost.protocol';
import { ExtHostAccountManagement } from 'sql/workbench/api/node/extHostAccountManagement';
import { ExtHostCredentialManagement } from 'sql/workbench/api/node/extHostCredentialManagement';
import { ExtHostDataProtocol } from 'sql/workbench/api/node/extHostDataProtocol';
import { ExtHostSerializationProvider } from 'sql/workbench/api/node/extHostSerializationProvider';
import { ExtHostResourceProvider } from 'sql/workbench/api/node/extHostResourceProvider';
import { ExtHostThreadService } from 'vs/workbench/services/thread/node/extHostThreadService';
import * as sqlExtHostTypes from 'sql/workbench/api/node/sqlExtHostTypes';
export interface ISqlExtensionApiFactory {
vsCodeFactory(extension: IExtensionDescription): typeof vscode;
dataFactory(extension: IExtensionDescription): typeof data;
}
/**
* This method instantiates and returns the extension API surface. This overrides the default ApiFactory by extending it to add Carbon-related functions
*/
export function createApiFactory(
initData: IInitData,
threadService: ExtHostThreadService,
extensionService: ExtHostExtensionService
): ISqlExtensionApiFactory {
let vsCodeFactory = extHostApi.createApiFactory(initData, threadService, extensionService);
// Addressable instances
const extHostAccountManagement = threadService.set(SqlExtHostContext.ExtHostAccountManagement, new ExtHostAccountManagement(threadService));
const extHostCredentialManagement = threadService.set(SqlExtHostContext.ExtHostCredentialManagement, new ExtHostCredentialManagement(threadService));
const extHostDataProvider = threadService.set(SqlExtHostContext.ExtHostDataProtocol, new ExtHostDataProtocol(threadService));
const extHostSerializationProvider = threadService.set(SqlExtHostContext.ExtHostSerializationProvider, new ExtHostSerializationProvider(threadService));
const extHostResourceProvider = threadService.set(SqlExtHostContext.ExtHostResourceProvider, new ExtHostResourceProvider(threadService));
return {
vsCodeFactory: vsCodeFactory,
dataFactory: function (extension: IExtensionDescription): typeof data {
// namespace: accounts
const accounts: typeof data.accounts = {
performOAuthAuthorization(url: string, silent: boolean): Thenable<string> {
return extHostAccountManagement.$performOAuthAuthorization(url, silent);
},
registerAccountProvider(providerMetadata: data.AccountProviderMetadata, provider: data.AccountProvider): vscode.Disposable {
return extHostAccountManagement.$registerAccountProvider(providerMetadata, provider);
},
};
// namespace: credentials
const credentials: typeof data.credentials = {
registerProvider(provider: data.CredentialProvider): vscode.Disposable {
return extHostCredentialManagement.$registerCredentialProvider(provider);
},
getProvider(namespaceId: string): Thenable<data.CredentialProvider> {
return extHostCredentialManagement.$getCredentialProvider(namespaceId);
}
};
// namespace: serialization
const serialization: typeof data.serialization = {
registerProvider(provider: data.SerializationProvider): vscode.Disposable {
return extHostSerializationProvider.$registerSerializationProvider(provider);
},
};
// namespace: serialization
const resources: typeof data.resources = {
registerResourceProvider(providerMetadata: data.ResourceProviderMetadata, provider: data.ResourceProvider): vscode.Disposable {
return extHostResourceProvider.$registerResourceProvider(providerMetadata, provider);
}
};
// namespace: dataprotocol
const dataprotocol: typeof data.dataprotocol = {
registerProvider(provider: data.DataProtocolProvider): vscode.Disposable {
// Connection callbacks
provider.connectionProvider.registerOnConnectionComplete((connSummary: data.ConnectionInfoSummary) => {
extHostDataProvider.$onConnectComplete(provider.handle, connSummary);
});
provider.connectionProvider.registerOnIntelliSenseCacheComplete((connectionUri: string) => {
extHostDataProvider.$onIntelliSenseCacheComplete(provider.handle, connectionUri);
});
provider.connectionProvider.registerOnConnectionChanged((changedConnInfo: data.ChangedConnectionInfo) => {
extHostDataProvider.$onConnectionChanged(provider.handle, changedConnInfo);
});
// Query callbacks
provider.queryProvider.registerOnQueryComplete((result: data.QueryExecuteCompleteNotificationResult) => {
extHostDataProvider.$onQueryComplete(provider.handle, result);
});
provider.queryProvider.registerOnBatchStart((batchInfo: data.QueryExecuteBatchNotificationParams) => {
extHostDataProvider.$onBatchStart(provider.handle, batchInfo);
});
provider.queryProvider.registerOnBatchComplete((batchInfo: data.QueryExecuteBatchNotificationParams) => {
extHostDataProvider.$onBatchComplete(provider.handle, batchInfo);
});
provider.queryProvider.registerOnResultSetComplete((resultSetInfo: data.QueryExecuteResultSetCompleteNotificationParams) => {
extHostDataProvider.$onResultSetComplete(provider.handle, resultSetInfo);
});
provider.queryProvider.registerOnMessage((message: data.QueryExecuteMessageParams) => {
extHostDataProvider.$onQueryMessage(provider.handle, message);
});
//OE callbacks
provider.objectExplorerProvider.registerOnSessionCreated((response: data.ObjectExplorerSession) => {
extHostDataProvider.$onObjectExplorerSessionCreated(provider.handle, response);
});
provider.objectExplorerProvider.registerOnExpandCompleted((response: data.ObjectExplorerExpandInfo) => {
extHostDataProvider.$onObjectExplorerNodeExpanded(provider.handle, response);
});
//Tasks callbacks
provider.taskServicesProvider.registerOnTaskCreated((response: data.TaskInfo) => {
extHostDataProvider.$onTaskCreated(provider.handle, response);
});
provider.taskServicesProvider.registerOnTaskStatusChanged((response: data.TaskProgressInfo) => {
extHostDataProvider.$onTaskStatusChanged(provider.handle, response);
});
// Edit Data callbacks
provider.queryProvider.registerOnEditSessionReady((ownerUri: string, success: boolean, message: string) => {
extHostDataProvider.$onEditSessionReady(provider.handle, ownerUri, success, message);
});
// File browser callbacks
provider.fileBrowserProvider.registerOnFileBrowserOpened((response: data.FileBrowserOpenedParams) => {
extHostDataProvider.$onFileBrowserOpened(provider.handle, response);
});
provider.fileBrowserProvider.registerOnFolderNodeExpanded((response: data.FileBrowserExpandedParams) => {
extHostDataProvider.$onFolderNodeExpanded(provider.handle, response);
});
provider.fileBrowserProvider.registerOnFilePathsValidated((response: data.FileBrowserValidatedParams) => {
extHostDataProvider.$onFilePathsValidated(provider.handle, response);
});
// Scripting callbacks
provider.scriptingProvider.registerOnScriptingComplete((response: data.ScriptingCompleteResult) => {
extHostDataProvider.$onScriptingComplete(provider.handle, response);
});
// Complete registration
return extHostDataProvider.$registerProvider(provider);
},
onDidChangeLanguageFlavor(listener: (e: data.DidChangeLanguageFlavorParams) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) {
return extHostDataProvider.onDidChangeLanguageFlavor(listener, thisArgs, disposables);
}
};
return {
accounts,
credentials,
resources,
serialization,
dataprotocol,
ServiceOptionType: sqlExtHostTypes.ServiceOptionType,
ConnectionOptionSpecialType: sqlExtHostTypes.ConnectionOptionSpecialType,
EditRowState: sqlExtHostTypes.EditRowState,
MetadataType: sqlExtHostTypes.MetadataType,
TaskStatus: sqlExtHostTypes.TaskStatus,
TaskExecutionMode: sqlExtHostTypes.TaskExecutionMode
};
}
};
}
export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: ISqlExtensionApiFactory): TPromise<void> {
return createExtensionPathIndex(extensionService).then(trie => defineAPI(apiFactory, trie));
}
function createExtensionPathIndex(extensionService: ExtHostExtensionService): TPromise<TrieMap<IExtensionDescription>> {
// create trie to enable fast 'filename -> extension id' look up
const trie = new TrieMap<IExtensionDescription>(TrieMap.PathSplitter);
const extensions = extensionService.getAllExtensionDescriptions().map(ext => {
if (!ext.main) {
return undefined;
}
return new TPromise((resolve, reject) => {
realpath(ext.extensionFolderPath, (err, path) => {
if (err) {
reject(err);
} else {
trie.insert(path, ext);
resolve(void 0);
}
});
});
});
return TPromise.join(extensions).then(() => trie);
}
function defineAPI(factory: ISqlExtensionApiFactory, extensionPaths: TrieMap<IExtensionDescription>): void {
type ApiImpl = typeof vscode | typeof data;
// each extension is meant to get its own api implementation
const extApiImpl = new Map<string, typeof vscode>();
const dataExtApiImpl = new Map<string, typeof data>();
let defaultApiImpl: typeof vscode;
let defaultDataApiImpl: typeof data;
// The module factory looks for an entry in the API map for an extension. If found, it reuses this.
// If not, it loads it & saves it in the map
let getModuleFactory = function (apiMap: Map<string, any>,
createApi: (extensionDescription: IExtensionDescription) => ApiImpl,
defaultImpl: ApiImpl,
setDefaultApiImpl: (defaultImpl: ApiImpl) => void,
parent: any): ApiImpl {
// get extension id from filename and api for extension
const ext = extensionPaths.findSubstr(parent.filename);
if (ext) {
let apiImpl = apiMap.get(ext.id);
if (!apiImpl) {
apiImpl = createApi(ext);
apiMap.set(ext.id, apiImpl);
}
return apiImpl;
}
// fall back to a default implementation
if (!defaultImpl) {
defaultImpl = createApi(nullExtensionDescription);
setDefaultApiImpl(defaultImpl);
}
return defaultImpl;
};
const node_module = <any>require.__$__nodeRequire('module');
const original = node_module._load;
// TODO look into de-duplicating this code
node_module._load = function load(request, parent, isMain) {
if (request === 'vscode') {
return getModuleFactory(extApiImpl, (ext) => factory.vsCodeFactory(ext),
defaultApiImpl,
(impl) => defaultApiImpl = <typeof vscode>impl,
parent);
} else if (request === 'data') {
return getModuleFactory(dataExtApiImpl,
(ext) => factory.dataFactory(ext),
defaultDataApiImpl,
(impl) => defaultDataApiImpl = <typeof data>impl,
parent);
} else {
// Allow standard node_module load to occur
return original.apply(this, arguments);
}
};
}
const nullExtensionDescription: IExtensionDescription = {
id: 'nullExtensionDescription',
name: 'Null Extension Description',
publisher: 'vscode',
activationEvents: undefined,
contributes: undefined,
enableProposedApi: false,
engines: undefined,
extensionDependencies: undefined,
extensionFolderPath: undefined,
isBuiltin: false,
main: undefined,
version: undefined
};

View File

@@ -0,0 +1,34 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { Registry } from 'vs/platform/registry/common/platform';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
// --- SQL contributions
import 'sql/workbench/api/node/mainThreadCredentialManagement';
import 'sql/workbench/api/node/mainThreadDataProtocol';
import 'sql/workbench/api/node/mainThreadSerializationProvider';
import 'sql/workbench/api/node/mainThreadResourceProvider';
import './mainThreadAccountManagement';
export class SqlExtHostContribution implements IWorkbenchContribution {
constructor(
@IInstantiationService private instantiationService: IInstantiationService
) {
}
public getId(): string {
return 'sql.api.sqlExtHost';
}
}
// Register File Tracker
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).registerWorkbenchContribution(
SqlExtHostContribution
);

View File

@@ -0,0 +1,430 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {
createMainContextProxyIdentifier as createMainId,
createExtHostContextProxyIdentifier as createExtId,
ProxyIdentifier, IThreadService
} from 'vs/workbench/services/thread/common/threadService';
import * as data from 'data';
import { TPromise } from 'vs/base/common/winjs.base';
export abstract class ExtHostAccountManagementShape {
$clear(handle: number, accountKey: data.AccountKey): Thenable<void> { throw ni(); }
$getSecurityToken(handle: number, account: data.Account): Thenable<{}> { throw ni(); }
$initialize(handle: number, restoredAccounts: data.Account[]): Thenable<data.Account[]> { throw ni(); }
$prompt(handle: number): Thenable<data.Account> { throw ni(); }
$refresh(handle: number, account: data.Account): Thenable<data.Account> { throw ni(); }
}
export abstract class ExtHostDataProtocolShape {
/**
* Establish a connection to a data source using the provided ConnectionInfo instance.
*/
$connect(handle: number, connectionUri: string, connection: data.ConnectionInfo): Thenable<boolean> { throw ni(); }
/**
* Disconnect from a data source using the provided connectionUri string.
*/
$disconnect(handle: number, connectionUri: string): Thenable<boolean> { throw ni(); }
/**
* Cancel a connection to a data source using the provided connectionUri string.
*/
$cancelConnect(handle: number, connectionUri: string): Thenable<boolean> { throw ni(); }
/**
* Change the database for the connection.
*/
$changeDatabase(handle: number, connectionUri: string, newDatabase: string): Thenable<boolean> { throw ni(); }
/**
* List databases for a data source using the provided connectionUri string.
* @param handle the handle to use when looking up a provider
* @param connectionUri URI identifying a connected resource
*/
$listDatabases(handle: number, connectionUri: string): Thenable<data.ListDatabasesResult> { throw ni(); }
/**
* Notifies all listeners on the Extension Host side that a language change occurred
* for a dataprotocol language. The sub-flavor is the specific implementation used for query
* and other events
* @param params information on what URI was changed and the new language
*/
$languageFlavorChanged(params: data.DidChangeLanguageFlavorParams): void { throw ni(); }
/**
* Callback when a connection request has completed
*/
$onConnectComplete(handle: number, connectionInfoSummary: data.ConnectionInfoSummary): void { throw ni(); }
/**
* Callback when a IntelliSense cache has been built
*/
$onIntelliSenseCacheComplete(handle: number, connectionUri: string): void { throw ni(); }
$getServerCapabilities(handle: number, client: data.DataProtocolClientCapabilities): Thenable<data.DataProtocolServerCapabilities> { throw ni(); }
/**
* Metadata service methods
*
*/
$getMetadata(handle: number, connectionUri: string): Thenable<data.ProviderMetadata> { throw ni(); }
$getDatabases(handle: number, connectionUri: string): Thenable<string[]> { throw ni(); }
$getTableInfo(handle: number, connectionUri: string, metadata: data.ObjectMetadata): Thenable<data.ColumnMetadata[]> { throw ni(); }
$getViewInfo(handle: number, connectionUri: string, metadata: data.ObjectMetadata): Thenable<data.ColumnMetadata[]> { throw ni(); }
/**
* Object Explorer
*/
$createObjectExplorerSession(handle: number, connInfo: data.ConnectionInfo): Thenable<data.ObjectExplorerSessionResponse> { throw ni(); }
$expandObjectExplorerNode(handle: number, nodeInfo: data.ExpandNodeInfo): Thenable<boolean> { throw ni(); }
$refreshObjectExplorerNode(handle: number, nodeInfo: data.ExpandNodeInfo): Thenable<boolean> { throw ni(); }
$closeObjectExplorerSession(handle: number, closeSessionInfo: data.ObjectExplorerCloseSessionInfo): Thenable<data.ObjectExplorerCloseSessionResponse> { throw ni(); }
/**
* Tasks
*/
$getAllTasks(handle: number, listTasksParams: data.ListTasksParams): Thenable<data.ListTasksResponse> { throw ni(); }
$cancelTask(handle: number, cancelTaskParams: data.CancelTaskParams): Thenable<boolean> { throw ni(); }
/**
* Scripting methods
*/
$scriptAsSelect(handle: number, connectionUri: string, metadata: data.ObjectMetadata, paramDetails: data.ScriptingParamDetails): Thenable<data.ScriptingResult> { throw ni(); }
$scriptAsCreate(handle: number, connectionUri: string, metadata: data.ObjectMetadata, paramDetails: data.ScriptingParamDetails): Thenable<data.ScriptingResult> { throw ni(); }
$scriptAsUpdate(handle: number, connectionUri: string, metadata: data.ObjectMetadata, paramDetails: data.ScriptingParamDetails): Thenable<data.ScriptingResult> { throw ni(); }
$scriptAsInsert(handle: number, connectionUri: string, metadata: data.ObjectMetadata, paramDetails: data.ScriptingParamDetails): Thenable<data.ScriptingResult> { throw ni(); }
$scriptAsDelete(handle: number, connectionUri: string, metadata: data.ObjectMetadata, paramDetails: data.ScriptingParamDetails): Thenable<data.ScriptingResult> { throw ni(); }
/**
* Cancels the currently running query for a URI
*/
$cancelQuery(handle: number, ownerUri: string): Thenable<data.QueryCancelResult> { throw ni(); }
/**
* Runs a query for a text selection inside a document
*/
$runQuery(handle: number, ownerUri: string, selection: data.ISelectionData, runOptions?: data.ExecutionPlanOptions): Thenable<void> { throw ni(); }
/**
* Runs the current SQL statement query for a text document
*/
$runQueryStatement(handle: number, ownerUri: string, line: number, column: number): Thenable<void> { throw ni(); }
/**
* Runs a query for a provided query
*/
$runQueryString(handle: number, ownerUri: string, queryString: string): Thenable<void> { throw ni(); }
/**
* Runs a query for a provided query and returns result
*/
$runQueryAndReturn(handle: number, ownerUri: string, queryString: string): Thenable<data.SimpleExecuteResult> { throw ni(); }
/**
* Gets a subset of rows in a result set in order to display in the UI
*/
$getQueryRows(handle: number, rowData: data.QueryExecuteSubsetParams): Thenable<data.QueryExecuteSubsetResult> { throw ni(); }
/**
* Disposes the cached information regarding a query
*/
$disposeQuery(handle: number, ownerUri: string): Thenable<void> { throw ni(); }
/**
* Refreshes the IntelliSense cache
*/
$rebuildIntelliSenseCache(handle: number, ownerUri: string): Thenable<void> { throw ni(); }
/**
* Callback when a query has completed
*/
$onQueryComplete(handle: number, result: data.QueryExecuteCompleteNotificationResult): void { throw ni(); }
/**
* Callback when a batch has started. This enables the UI to display when batch execution has started
*/
$onBatchStart(handle: number, batchInfo: data.QueryExecuteBatchNotificationParams): void { throw ni(); }
/**
* Callback when a batch is complete. This includes updated information on result sets, time to execute, and
* other relevant batch information
*/
$onBatchComplete(handle: number, batchInfo: data.QueryExecuteBatchNotificationParams): void { throw ni(); }
/**
* Callback when a result set has been returned from query execution and can be displayed
*/
$onResultSetComplete(handle: number, resultSetInfo: data.QueryExecuteResultSetCompleteNotificationParams): void { throw ni(); }
/**
* Callback when a message generated during query execution is issued
*/
$onQueryMessage(handle: number, message: data.QueryExecuteMessageParams): void { throw ni(); }
/**
* Requests saving of the results from a result set into a specific format (CSV, JSON, Excel)
*/
$saveResults(handle: number, requestParams: data.SaveResultsRequestParams): Thenable<data.SaveResultRequestResult> { throw ni(); }
/**
* Commits all pending edits in an edit session
*/
$commitEdit(handle: number, ownerUri: string): Thenable<void> { throw ni(); }
/**
* Creates a new row in the edit session
*/
$createRow(handle: number, ownerUri: string): Thenable<data.EditCreateRowResult> { throw ni(); }
/**
* Marks the selected row for deletion in the edit session
*/
$deleteRow(handle: number, ownerUri: string, rowId: number): Thenable<void> { throw ni(); }
/**
* Initializes a new edit data session for the requested table/view
*/
$initializeEdit(handle: number, ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number): Thenable<void> { throw ni(); }
/**
* Reverts any pending changes for the requested cell and returns the original value
*/
$revertCell(handle: number, ownerUri: string, rowId: number, columnId: number): Thenable<data.EditRevertCellResult> { throw ni(); }
/**
* Reverts any pending changes for the requested row
*/
$revertRow(handle: number, ownerUri: string, rowId: number): Thenable<void> { throw ni(); }
/**
* Updates a cell value in the requested row. Returns if there are any corrections to the value
*/
$updateCell(handle: number, ownerUri: string, rowId: number, columId: number, newValue: string): Thenable<data.EditUpdateCellResult> { throw ni(); }
/**
* Gets a subset of rows in a result set, merging pending edit changes in order to display in the UI
*/
$getEditRows(handle: number, rowData: data.EditSubsetParams): Thenable<data.EditSubsetResult> { throw ni(); }
/**
* Diposes an initialized edit session and cleans up pending edits
*/
$disposeEdit(handle: number, ownerUri: string): Thenable<void> { throw ni(); }
/**
* Create a new database on the provided connection
*/
$createDatabase(handle: number, connectionUri: string, database: data.DatabaseInfo): Thenable<data.CreateDatabaseResponse> { throw ni(); }
/**
* Get the default database prototype
*/
$getDefaultDatabaseInfo(handle: number, connectionUri: string): Thenable<data.DatabaseInfo> { throw ni(); }
/**
* Get the database info
*/
$getDatabaseInfo(handle: number, connectionUri: string): Thenable<data.DatabaseInfo> { throw ni(); }
/**
* Create a new login on the provided connection
*/
$createLogin(handle: number, connectionUri: string, login: data.LoginInfo): Thenable<data.CreateLoginResponse> { throw ni(); }
/**
* Backup a database
*/
$backup(handle: number, connectionUri: string, backupInfo: { [key: string]: any }, taskExecutionMode: data.TaskExecutionMode): Thenable<data.BackupResponse> { throw ni(); }
/**
* Get the extended database prototype
*/
$getBackupConfigInfo(handle: number, connectionUri: string): Thenable<data.BackupConfigInfo> { throw ni(); }
/**
* Restores a database
*/
$restore(handle: number, connectionUri: string, restoreInfo: data.RestoreInfo): Thenable<data.RestoreResponse> { throw ni(); }
/**
* Gets a plan for restoring a database
*/
$getRestorePlan(handle: number, connectionUri: string, restoreInfo: data.RestoreInfo): Thenable<data.RestorePlanResponse> { throw ni(); }
/**
* Cancels a plan
*/
$cancelRestorePlan(handle: number, connectionUri: string, restoreInfo: data.RestoreInfo): Thenable<boolean> { throw ni(); }
/**
* Gets restore config Info
*/
$getRestoreConfigInfo(handle: number, connectionUri: string): Thenable<data.RestoreConfigInfo> { throw ni(); }
/**
* Open a file browser
*/
$openFileBrowser(handle: number, ownerUri: string, expandPath: string, fileFilters: string[], changeFilter: boolean): Thenable<boolean> { throw ni(); }
/**
* Expand a folder node
*/
$expandFolderNode(handle: number, ownerUri: string, expandPath: string): Thenable<boolean> { throw ni(); }
/**
* Validate selected file paths
*/
$validateFilePaths(handle: number, ownerUri: string, serviceType: string, selectedFiles: string[]): Thenable<boolean> { throw ni(); }
/**
* Close file browser
*/
$closeFileBrowser(handle: number, ownerUri: string): Thenable<data.FileBrowserCloseResponse> { throw ni(); }
}
/**
* ResourceProvider extension host class.
*/
export abstract class ExtHostResourceProviderShape {
/**
* Create a firewall rule
*/
$createFirewallRule(handle: number, account: data.Account, firewallRuleInfo: data.FirewallRuleInfo): Thenable<data.CreateFirewallRuleResponse> { throw ni(); }
/**
* Handle firewall rule
*/
$handleFirewallRule(handle: number, errorCode: number, errorMessage: string, connectionTypeId: string): Thenable<data.HandleFirewallRuleResponse> { throw ni(); }
}
/**
* Credential Management extension host class.
*/
export abstract class ExtHostCredentialManagementShape {
$saveCredential(credentialId: string, password: string): Thenable<boolean> { throw ni(); }
$readCredential(credentialId: string): Thenable<data.Credential> { throw ni(); }
$deleteCredential(credentialId: string): Thenable<boolean> { throw ni(); }
}
/**
* Serialization provider extension host class.
*/
export abstract class ExtHostSerializationProviderShape {
$saveAs(saveFormat: string, savePath: string, results: string, appendToFile: boolean): Thenable<data.SaveResultRequestResult> { throw ni(); }
}
export abstract class MainThreadAccountManagementShape {
$registerAccountProvider(providerMetadata: data.AccountProviderMetadata, handle: number): Thenable<any> { throw ni(); }
$unregisterAccountProvider(handle: number): Thenable<any> { throw ni(); }
$performOAuthAuthorization(url: string, silent: boolean): Thenable<string> { throw ni(); }
}
export abstract class MainThreadResourceProviderShape {
$registerResourceProvider(providerMetadata: data.ResourceProviderMetadata, handle: number): Thenable<any> { throw ni(); }
$unregisterResourceProvider(handle: number): Thenable<any> { throw ni(); }
}
export abstract class MainThreadDataProtocolShape {
$registerProvider(providerId: string, handle: number): TPromise<any> { throw ni(); }
$unregisterProvider(handle: number): TPromise<any> { throw ni(); }
$onConnectionComplete(handle: number, connectionInfoSummary: data.ConnectionInfoSummary): void { throw ni(); }
$onIntelliSenseCacheComplete(handle: number, connectionUri: string): void { throw ni(); }
$onConnectionChangeNotification(handle: number, changedConnInfo: data.ChangedConnectionInfo): void { throw ni(); }
$onQueryComplete(handle: number, result: data.QueryExecuteCompleteNotificationResult): void { throw ni(); }
$onBatchStart(handle: number, batchInfo: data.QueryExecuteBatchNotificationParams): void { throw ni(); }
$onBatchComplete(handle: number, batchInfo: data.QueryExecuteBatchNotificationParams): void { throw ni(); }
$onResultSetComplete(handle: number, resultSetInfo: data.QueryExecuteResultSetCompleteNotificationParams): void { throw ni(); }
$onQueryMessage(handle: number, message: data.QueryExecuteMessageParams): void { throw ni(); }
$onObjectExplorerSessionCreated(handle: number, message: data.ObjectExplorerSession): void { throw ni(); }
$onObjectExplorerNodeExpanded(handle: number, message: data.ObjectExplorerExpandInfo): void { throw ni(); }
$onTaskCreated(handle: number, sessionResponse: data.TaskInfo): void { throw ni(); }
$onTaskStatusChanged(handle: number, sessionResponse: data.TaskProgressInfo): void { throw ni(); }
$onFileBrowserOpened(handle: number, response: data.FileBrowserOpenedParams): void { throw ni(); }
$onFolderNodeExpanded(handle: number, response: data.FileBrowserExpandedParams): void { throw ni(); }
$onFilePathsValidated(handle: number, response: data.FileBrowserValidatedParams): void { throw ni(); }
$onScriptingComplete(handle: number, message: data.ScriptingCompleteResult): void { throw ni(); }
/**
* Callback when a session has completed initialization
*/
$onEditSessionReady(handle: number, ownerUri: string, success: boolean, message: string) { throw ni(); }
}
export abstract class MainThreadCredentialManagementShape {
$registerCredentialProvider(handle: number): TPromise<any> { throw ni(); }
$unregisterCredentialProvider(handle: number): TPromise<any> { throw ni(); }
}
export abstract class MainThreadSerializationProviderShape {
$registerSerializationProvider(handle: number): TPromise<any> { throw ni(); }
$unregisterSerializationProvider(handle: number): TPromise<any> { throw ni(); }
}
// export class SqlInstanceCollection {
// private _items: { [id: string]: any; };
// constructor() {
// this._items = Object.create(null);
// }
// public define<T>(id: ProxyIdentifier<T>): InstanceSetter<T> {
// let that = this;
// return new class {
// set<R extends T>(value: T): R {
// that._set(id, value);
// return <R>value;
// }
// };
// }
// _set<T>(id: ProxyIdentifier<T>, value: T): void {
// this._items[id.id] = value;
// }
// public finish(isMain: boolean, threadService: IThreadService): void {
// let expected = (isMain ? SqlMainContext : SqlExtHostContext);
// Object.keys(expected).forEach((key) => {
// let id = expected[key];
// let value = this._items[id.id];
// if (!value) {
// throw new Error(`Missing actor ${key} (isMain: ${id.isMain}, id: ${id.id})`);
// }
// threadService.set<any>(id, value);
// });
// }
// }
function ni() { return new Error('Not implemented'); }
// --- proxy identifiers
export const SqlMainContext = {
// SQL entries
MainThreadAccountManagement: createMainId<MainThreadAccountManagementShape>('MainThreadAccountManagement'),
MainThreadCredentialManagement: createMainId<MainThreadCredentialManagementShape>('MainThreadCredentialManagement'),
MainThreadDataProtocol: createMainId<MainThreadDataProtocolShape>('MainThreadDataProtocol'),
MainThreadSerializationProvider: createMainId<MainThreadSerializationProviderShape>('MainThreadSerializationProvider'),
MainThreadResourceProvider: createMainId<MainThreadResourceProviderShape>('MainThreadResourceProvider')
};
export const SqlExtHostContext = {
ExtHostAccountManagement: createExtId<ExtHostAccountManagementShape>('ExtHostAccountManagement'),
ExtHostCredentialManagement: createExtId<ExtHostCredentialManagementShape>('ExtHostCredentialManagement'),
ExtHostDataProtocol: createExtId<ExtHostDataProtocolShape>('ExtHostDataProtocol'),
ExtHostSerializationProvider: createExtId<ExtHostSerializationProviderShape>('ExtHostSerializationProvider'),
ExtHostResourceProvider: createExtId<ExtHostResourceProviderShape>('ExtHostResourceProvider')
};

View File

@@ -0,0 +1,64 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
// SQL added extension host types
export enum ServiceOptionType {
string = 0,
multistring = 1,
password = 2,
number = 3,
category = 4,
boolean = 5,
object = 6
}
export enum ConnectionOptionSpecialType {
serverName = 0,
databaseName = 1,
authType = 2,
userName = 3,
password = 4,
appName = 5
}
export enum MetadataType {
Table = 0,
View = 1,
SProc = 2,
Function = 3
}
export enum EditRowState {
clean = 0,
dirtyInsert = 1,
dirtyDelete = 2,
dirtyUpdate = 3
}
export enum TaskStatus {
notStarted = 0,
inProgress = 1,
succeeded = 2,
succeededWithWarning = 3,
failed = 4,
canceled = 5
}
export enum TaskExecutionMode {
execute = 0,
script = 1,
executeAndScript = 2,
}
export enum ScriptOperation {
Select = 0,
Create = 1,
Insert = 2,
Update = 3,
Delete = 4
}

View File

@@ -0,0 +1,51 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { registerTask } from 'sql/platform/tasks/taskRegistry';
import * as Actions from './actions';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
import * as nls from 'vs/nls';
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
import { Registry } from 'vs/platform/registry/common/platform';
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actionRegistry';
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions';
import { ShowCurrentReleaseNotesAction, ProductContribution } from 'sql/workbench/update/releaseNotes';
const backupSchema: IJSONSchema = {
description: nls.localize('carbon.actions.back', 'Open up backup dialog'),
type: 'null',
default: null
};
const restoreSchema: IJSONSchema = {
description: nls.localize('carbon.actions.restore', 'Open up restore dialog'),
type: 'null',
default: null
};
const newQuerySchema: IJSONSchema = {
description: nls.localize('carbon.actions.newQuery', 'Open a new query window'),
type: 'null',
default: null
};
const configureDashboardSchema: IJSONSchema = {
description: nls.localize('carbon.actions.configureDashboard', 'Configure the Management Dashboard'),
type: 'null',
default: null
};
registerTask('backup', '', backupSchema, Actions.BackupAction);
registerTask('restore', '', restoreSchema, Actions.RestoreAction);
registerTask('new-query', '', newQuerySchema, Actions.NewQueryAction);
registerTask('configure-dashboard', '', configureDashboardSchema, Actions.ConfigureDashboardAction);
// add product update and release notes contributions
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench)
.registerWorkbenchContribution(ProductContribution);
Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions)
.registerWorkbenchAction(new SyncActionDescriptor(ShowCurrentReleaseNotesAction, ShowCurrentReleaseNotesAction.ID, ShowCurrentReleaseNotesAction.LABEL), 'Show Getting Started');

View File

@@ -0,0 +1,369 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IConnectionManagementService, IErrorMessageService } from 'sql/parts/connection/common/connectionManagement';
import * as TaskUtilities from './taskUtilities';
import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo';
import { IInsightsConfig } from 'sql/parts/dashboard/widgets/insights/interfaces';
import { IScriptingService } from 'sql/services/scripting/scriptingService';
import { IDisasterRecoveryUiService, IRestoreDialogController } from 'sql/parts/disasterRecovery/common/interfaces';
import { IAngularEventingService, AngularEventType } from 'sql/services/angularEventing/angularEventingService';
import { IInsightsDialogService } from 'sql/parts/insights/common/interfaces';
import { IAdminService } from 'sql/parts/admin/common/adminService';
import * as Constants from 'sql/common/constants';
import { ObjectMetadata } from 'data';
import { ScriptOperation } from 'sql/workbench/common/taskUtilities';
import { TPromise } from 'vs/base/common/winjs.base';
import { Action } from 'vs/base/common/actions';
import { IWindowsService } from 'vs/platform/windows/common/windows';
import * as nls from 'vs/nls';
export class TaskAction extends Action {
constructor(id: string, label: string, private _icon: string) {
super(id, label);
}
get icon(): string {
return this._icon;
}
}
export interface BaseActionContext extends ITaskActionContext {
uri?: string;
object?: ObjectMetadata;
connInfo?: ConnectionManagementInfo;
}
export interface ITaskActionContext {
profile: IConnectionProfile;
}
export interface InsightActionContext extends BaseActionContext {
insight: IInsightsConfig;
}
// --- actions
export class NewQueryAction extends TaskAction {
public static ID = 'newQuery';
public static LABEL = nls.localize('newQuery', 'New Query');
public static ICON = 'new-query';
constructor(
id: string, label: string, icon: string,
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService
) {
super(id, label, icon);
}
public run(actionContext: ITaskActionContext): TPromise<boolean> {
return new TPromise<boolean>((resolve, reject) => {
TaskUtilities.newQuery(
actionContext.profile,
this._connectionManagementService,
this._queryEditorService
).then(
result => {
resolve(true);
},
error => {
resolve(false);
}
);
});
}
}
export class ScriptSelectAction extends Action {
public static ID = 'selectTop';
public static LABEL = nls.localize('scriptSelect', 'Select Top 1000');
constructor(
id: string, label: string,
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
@IScriptingService protected _scriptingService: IScriptingService
) {
super(id, label);
}
public run(actionContext: BaseActionContext): TPromise<boolean> {
return new TPromise<boolean>((resolve, reject) => {
TaskUtilities.scriptSelect(
actionContext.profile,
actionContext.object,
actionContext.uri,
this._connectionManagementService,
this._queryEditorService,
this._scriptingService
).then(
result => {
resolve(true);
},
error => {
resolve(false);
});
});
}
}
export class EditDataAction extends Action {
public static ID = 'editData';
public static LABEL = nls.localize('editData', 'Edit Data');
constructor(
id: string, label: string,
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService
) {
super(id, label);
}
public run(actionContext: BaseActionContext): TPromise<boolean> {
return new TPromise<boolean>((resolve, reject) => {
TaskUtilities.editData(
actionContext.profile,
actionContext.object.name,
actionContext.object.schema,
this._connectionManagementService,
this._queryEditorService
).then(
result => {
resolve(true);
},
error => {
resolve(false);
}
);
});
}
}
export class ScriptCreateAction extends Action {
public static ID = 'scriptCreate';
public static LABEL = nls.localize('scriptCreate', "Script as Create");
constructor(
id: string, label: string,
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
@IScriptingService protected _scriptingService: IScriptingService,
@IErrorMessageService protected _errorMessageService: IErrorMessageService
) {
super(id, label);
}
public run(actionContext: BaseActionContext): TPromise<boolean> {
return new TPromise<boolean>((resolve, reject) => {
TaskUtilities.script(
actionContext.profile,
actionContext.object,
actionContext.uri,
this._connectionManagementService,
this._queryEditorService,
this._scriptingService,
ScriptOperation.Create,
this._errorMessageService
).then(
result => {
resolve(true);
},
error => {
resolve(false);
}
);
});
}
}
export class ScriptDeleteAction extends Action {
public static ID = 'scriptDelete';
public static LABEL = nls.localize('scriptDelete', 'Script as Delete');
constructor(
id: string, label: string,
@IQueryEditorService protected _queryEditorService: IQueryEditorService,
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
@IScriptingService protected _scriptingService: IScriptingService,
@IErrorMessageService protected _errorMessageService: IErrorMessageService
) {
super(id, label);
}
public run(actionContext: BaseActionContext): TPromise<boolean> {
return new TPromise<boolean>((resolve, reject) => {
TaskUtilities.script(
actionContext.profile,
actionContext.object,
actionContext.uri,
this._connectionManagementService,
this._queryEditorService,
this._scriptingService,
ScriptOperation.Delete,
this._errorMessageService
).then(
result => {
resolve(true);
},
error => {
resolve(false);
}
);
});
}
}
export class BackupAction extends TaskAction {
public static ID = Constants.BackupFeatureName;
public static LABEL = nls.localize('backup', 'Backup');
public static ICON = Constants.BackupFeatureName;
constructor(
id: string, label: string, icon: string,
@IDisasterRecoveryUiService protected _disasterRecoveryService: IDisasterRecoveryUiService
) {
super(id, label, icon);
}
run(actionContext: ITaskActionContext): TPromise<boolean> {
return new TPromise<boolean>((resolve, reject) => {
TaskUtilities.showBackup(
actionContext.profile,
this._disasterRecoveryService,
).then(
result => {
resolve(true);
},
error => {
resolve(false);
}
);
});
}
}
export class RestoreAction extends TaskAction {
public static ID = Constants.RestoreFeatureName;
public static LABEL = nls.localize('restore', 'Restore');
public static ICON = Constants.RestoreFeatureName;
constructor(
id: string, label: string, icon: string,
@IRestoreDialogController protected _restoreService: IRestoreDialogController
) {
super(id, label, icon);
}
run(actionContext: ITaskActionContext): TPromise<boolean> {
return new TPromise<boolean>((resolve, reject) => {
TaskUtilities.showRestore(
actionContext.profile,
this._restoreService
).then(
result => {
resolve(true);
},
error => {
resolve(false);
}
);
});
}
}
export class ManageAction extends Action {
public static ID = 'manage';
public static LABEL = nls.localize('manage', 'Manage');
constructor(
id: string, label: string,
@IConnectionManagementService protected _connectionManagementService: IConnectionManagementService,
@IAngularEventingService protected _angularEventingService: IAngularEventingService
) {
super(id, label);
}
run(actionContext: BaseActionContext): TPromise<boolean> {
let self = this;
return new TPromise<boolean>((resolve, reject) => {
self._connectionManagementService.connect(actionContext.profile, actionContext.uri, { showDashboard: true, saveTheConnection: false, params: undefined, showConnectionDialogOnError: false, showFirewallRuleOnError: true }).then(
() => {
self._angularEventingService.sendAngularEvent(actionContext.uri, AngularEventType.NAV_DATABASE);
resolve(true);
},
error => {
resolve(error);
}
);
});
}
}
export class InsightAction extends Action {
public static ID = 'showInsight';
public static LABEL = nls.localize('showDetails', 'Show Details');
constructor(
id: string, label: string,
@IInsightsDialogService protected _insightsDialogService: IInsightsDialogService
) {
super(id, label);
}
run(actionContext: InsightActionContext): TPromise<boolean> {
let self = this;
return new TPromise<boolean>((resolve, reject) => {
self._insightsDialogService.show(actionContext.insight, actionContext.profile);
resolve(true);
});
}
}
export class NewDatabaseAction extends TaskAction {
public static ID = 'newDatabase';
public static LABEL = nls.localize('newDatabase', 'New Database');
public static ICON = 'new-database';
constructor(
id: string, label: string, icon: string,
@IAdminService private _adminService: IAdminService,
@IErrorMessageService private _errorMessageService: IErrorMessageService,
) {
super(id, label, icon);
}
run(actionContext: ITaskActionContext): TPromise<boolean> {
return new TPromise<boolean>((resolve, reject) => {
TaskUtilities.showCreateDatabase(actionContext.profile, this._adminService, this._errorMessageService);
});
}
}
export class ConfigureDashboardAction extends TaskAction {
public static ID = 'configureDashboard';
public static LABEL = nls.localize('configureDashboard', 'Configure');
public static ICON = 'configure-dashboard';
private static readonly configHelpUri = 'https://aka.ms/sqldashboardconfig';
constructor(
id: string, label: string, icon: string,
@IWindowsService private _windowsService
) {
super(id, label, icon);
}
run(actionContext: ITaskActionContext): TPromise<boolean> {
return new TPromise<boolean>((resolve, reject) => {
this._windowsService.openExternal(ConfigureDashboardAction.configHelpUri).then((result) => {
resolve(result);
}, err => {
resolve(err);
});
});
}
}

View File

@@ -0,0 +1,67 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import ConnectionConstants = require('sql/parts/connection/common/constants');
import { QueryInput } from 'sql/parts/query/common/queryInput';
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
import { IEditorInput } from 'vs/platform/editor/common/editor';
import URI from 'vs/base/common/uri';
/**
* Gets the 'sql' configuration section for use in looking up settings. Note that configs under
* 'mssql' or other sections are not available from this.
*
* @export
* @param {IWorkspaceConfigurationService} workspaceConfigService
* @param {string} sectionName
* @returns {*}
*/
export function getSqlConfigSection(workspaceConfigService: IWorkspaceConfigurationService, sectionName: string): any {
let config = workspaceConfigService.getConfiguration(ConnectionConstants.sqlConfigSectionName);
return config ? config[sectionName] : {};
}
export function getSqlConfigValue<T>(workspaceConfigService: IWorkspaceConfigurationService, configName: string): T {
let config = workspaceConfigService.getConfiguration(ConnectionConstants.sqlConfigSectionName);
return config[configName];
}
/**
* Executes a copy operation for an arbitrary string, by creating a temp div, copying
* the text to it, and calling copy on the document. This will clear any existing selection
* so if being called where selection state needs to be preserved, it's recommended to
* cache the existing selection first and re-set it after this method is called
*
* @export
* @param {string} text
*/
export function executeCopy(text: string): void {
let input = document.createElement('textarea');
document.body.appendChild(input);
input.value = text;
input.style.position = 'absolute';
input.style.bottom = '100%';
input.focus();
input.select();
document.execCommand('copy');
input.remove();
}
export function getEditorUri(input: IEditorInput): string{
let uri: URI;
if (input instanceof QueryInput) {
let queryCast: QueryInput = <QueryInput> input;
if (queryCast) {
uri = queryCast.getResource();
}
}
if (uri) {
return uri.toString();
}
return undefined;
}

View File

@@ -0,0 +1,374 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
import {
IConnectableInput, IConnectionManagementService,
IConnectionCompletionOptions, ConnectionType, IErrorMessageService,
RunQueryOnConnectionMode, IConnectionResult
} from 'sql/parts/connection/common/connectionManagement';
import { IQueryEditorService } from 'sql/parts/query/common/queryEditorService';
import { IScriptingService } from 'sql/services/scripting/scriptingService';
import { EditDataInput } from 'sql/parts/editData/common/editDataInput';
import { IAdminService } from 'sql/parts/admin/common/adminService';
import { IDisasterRecoveryUiService, IRestoreDialogController } from 'sql/parts/disasterRecovery/common/interfaces';
import { IInsightsConfig } from 'sql/parts/dashboard/widgets/insights/interfaces';
import { IInsightsDialogService } from 'sql/parts/insights/common/interfaces';
import { ConnectionManagementInfo } from 'sql/parts/connection/common/connectionManagementInfo';
import Severity from 'vs/base/common/severity';
import data = require('data');
import nls = require('vs/nls');
import os = require('os');
import path = require('path');
// map for the version of SQL Server (default is 140)
let scriptCompatibilityOptionMap = new Map<number, string>();
scriptCompatibilityOptionMap.set(90, "Script90Compat");
scriptCompatibilityOptionMap.set(100, "Script100Compat");
scriptCompatibilityOptionMap.set(105, "Script105Compat");
scriptCompatibilityOptionMap.set(110, "Script110Compat");
scriptCompatibilityOptionMap.set(120, "Script120Compat");
scriptCompatibilityOptionMap.set(130, "Script130Compat");
scriptCompatibilityOptionMap.set(140, "Script140Compat");
// map for the target database engine edition (default is Enterprise)
let targetDatabaseEngineEditionMap = new Map<number, string>();
targetDatabaseEngineEditionMap.set(0, "SqlServerEnterpriseEdition");
targetDatabaseEngineEditionMap.set(1, "SqlServerPersonalEdition");
targetDatabaseEngineEditionMap.set(2, "SqlServerStandardEdition");
targetDatabaseEngineEditionMap.set(3, "SqlServerEnterpriseEdition");
targetDatabaseEngineEditionMap.set(4, "SqlServerExpressEdition");
targetDatabaseEngineEditionMap.set(5, "SqlAzureDatabaseEdition");
targetDatabaseEngineEditionMap.set(6, "SqlDatawarehouseEdition");
targetDatabaseEngineEditionMap.set(7, "SqlServerStretchEdition");
// map for object types for scripting
let objectScriptMap = new Map<string, string>();
objectScriptMap.set("Table", "Table");
objectScriptMap.set("View", "View");
objectScriptMap.set("StoredProcedure", "Procedure");
objectScriptMap.set("UserDefinedFunction", "Function");
objectScriptMap.set("UserDefinedDataType", "Type");
objectScriptMap.set("User", "User");
objectScriptMap.set("Default", "Default");
objectScriptMap.set("Rule", "Rule");
objectScriptMap.set("DatabaseRole", "Role");
objectScriptMap.set("ApplicationRole", "Application Role");
objectScriptMap.set("SqlAssembly", "Assembly");
objectScriptMap.set("DdlTrigger", "Trigger");
objectScriptMap.set("Synonym", "Synonym");
objectScriptMap.set("XmlSchemaCollection", "Xml Schema Collection");
objectScriptMap.set("Schema", "Schema");
objectScriptMap.set("PlanGuide", "sp_create_plan_guide");
objectScriptMap.set("UserDefinedType", "Type");
objectScriptMap.set("UserDefinedAggregate", "Aggregate");
objectScriptMap.set("FullTextCatalog", "Fulltext Catalog");
objectScriptMap.set("UserDefinedTableType", "Type");
objectScriptMap.set("MaterializedView", "Materialized View");
export enum ScriptOperation {
Select = 0,
Create = 1,
Insert = 2,
Update = 3,
Delete = 4
}
export function GetScriptOperationName(operation: ScriptOperation) {
let defaultName: string = ScriptOperation[operation];
switch(operation) {
case ScriptOperation.Select:
return nls.localize('selectOperationName', 'Select');
case ScriptOperation.Create:
return nls.localize('createOperationName', 'Create');
case ScriptOperation.Insert:
return nls.localize('insertOperationName', 'Insert');
case ScriptOperation.Update:
return nls.localize('updateOperationName', 'Update');
case ScriptOperation.Delete:
return nls.localize('deleteOperationName', 'Delete');
default:
// return the raw, non-localized string name
return defaultName;
}
}
export function connectIfNotAlreadyConnected(connectionProfile: IConnectionProfile, connectionService: IConnectionManagementService): Promise<void> {
return new Promise<void>((resolve, reject) => {
let connectionID = connectionService.getConnectionId(connectionProfile);
let uri: string = connectionService.getFormattedUri(connectionID, connectionProfile);
if (!connectionService.isConnected(uri)) {
let options: IConnectionCompletionOptions = {
params: { connectionType: ConnectionType.editor, runQueryOnCompletion: RunQueryOnConnectionMode.executeQuery, input: undefined },
saveTheConnection: false,
showDashboard: false,
showConnectionDialogOnError: false,
showFirewallRuleOnError: true
};
connectionService.connect(connectionProfile, uri, options).then(() => {
setTimeout(function () {
resolve();
}, 2000);
}).catch(connectionError => {
reject(connectionError);
});
} else {
resolve();
}
});
}
/**
* Select the top rows from an object
*/
export function scriptSelect(connectionProfile: IConnectionProfile, metadata: data.ObjectMetadata, ownerUri: string, connectionService: IConnectionManagementService, queryEditorService: IQueryEditorService, scriptingService: IScriptingService): Promise<void> {
return new Promise<void>((resolve, reject) => {
connectIfNotAlreadyConnected(connectionProfile, connectionService).then(connectionResult => {
let paramDetails: data.ScriptingParamDetails = getScriptingParamDetails(connectionService, ownerUri, metadata);
scriptingService.script(ownerUri, metadata, ScriptOperation.Select, paramDetails).then(result => {
if (result.script) {
queryEditorService.newSqlEditor(result.script).then((owner: IConnectableInput) => {
// Connect our editor to the input connection
let options: IConnectionCompletionOptions = {
params: { connectionType: ConnectionType.editor, runQueryOnCompletion: RunQueryOnConnectionMode.executeQuery, input: owner },
saveTheConnection: false,
showDashboard: false,
showConnectionDialogOnError: true,
showFirewallRuleOnError: true
};
connectionService.connect(connectionProfile, owner.uri, options).then(() => {
resolve();
});
}).catch(editorError => {
reject(editorError);
});
} else {
let errMsg: string = nls.localize('scriptSelectNotFound', 'No script was returned when calling select script on object ');
reject(errMsg.concat(metadata.metadataTypeName));
}
}, scriptError => {
reject(scriptError);
})
});
});
}
/**
* Opens a new Edit Data session
*/
export function editData(connectionProfile: IConnectionProfile, tableName: string, schemaName: string, connectionService: IConnectionManagementService, queryEditorService: IQueryEditorService): Promise<void> {
return new Promise<void>((resolve) => {
queryEditorService.newEditDataEditor(schemaName, tableName).then((owner: EditDataInput) => {
// Connect our editor
let options: IConnectionCompletionOptions = {
params: { connectionType: ConnectionType.editor, runQueryOnCompletion: RunQueryOnConnectionMode.none, input: owner },
saveTheConnection: false,
showDashboard: false,
showConnectionDialogOnError: true,
showFirewallRuleOnError: true
};
connectionService.connect(connectionProfile, owner.uri, options).then(() => {
resolve();
});
});
});
}
/**
* Script the object as a statement based on the provided action (except Select)
*/
export function script(connectionProfile: IConnectionProfile, metadata: data.ObjectMetadata, ownerUri: string,
connectionService: IConnectionManagementService,
queryEditorService: IQueryEditorService,
scriptingService: IScriptingService,
operation: ScriptOperation,
errorMessageService: IErrorMessageService): Promise<void> {
return new Promise<void>((resolve, reject) => {
connectIfNotAlreadyConnected(connectionProfile, connectionService).then(connectionResult => {
let paramDetails = getScriptingParamDetails(connectionService, ownerUri, metadata);
scriptingService.script(ownerUri, metadata, operation, paramDetails).then(result => {
if (result) {
let script: string = result.script;
let startPos: number = 0;
if (connectionProfile.providerName === "MSSQL") {
startPos = getStartPos(script, operation, metadata.metadataTypeName);
}
if (startPos >= 0) {
script = script.substring(startPos);
queryEditorService.newSqlEditor(script, connectionProfile.providerName).then(() => {
resolve();
}).catch(editorError => {
reject(editorError);
});
}
else {
let scriptNotFoundMsg = nls.localize('scriptNotFoundForObject', 'No script was returned when scripting as {0} on object {1}',
GetScriptOperationName(operation), metadata.metadataTypeName);
let operationResult = scriptingService.getOperationFailedResult(result.operationId);
if (operationResult && operationResult.hasError && operationResult.errorMessage) {
scriptNotFoundMsg = operationResult.errorMessage;
}
if (errorMessageService) {
let title = nls.localize('scriptingFailed', 'Scripting Failed');
errorMessageService.showDialog(Severity.Error, title, scriptNotFoundMsg);
}
reject(scriptNotFoundMsg);
}
} else {
reject(nls.localize('scriptNotFound', 'No script was returned when scripting as {0}', GetScriptOperationName(operation)));
}
}, scriptingError => {
reject(scriptingError);
});
}).catch(connectionError => {
reject(connectionError);
});
});
}
export function newQuery(
connectionProfile: IConnectionProfile,
connectionService: IConnectionManagementService,
queryEditorService: IQueryEditorService,
sqlContent?: string,
executeOnOpen: RunQueryOnConnectionMode = RunQueryOnConnectionMode.none
): Promise<void> {
return new Promise<void>((resolve) => {
queryEditorService.newSqlEditor(sqlContent).then((owner: IConnectableInput) => {
// Connect our editor to the input connection
let options: IConnectionCompletionOptions = {
params: { connectionType: ConnectionType.editor, runQueryOnCompletion: executeOnOpen, input: owner },
saveTheConnection: false,
showDashboard: false,
showConnectionDialogOnError: true,
showFirewallRuleOnError: true
};
connectionService.connect(connectionProfile, owner.uri, options).then(() => {
resolve();
});
});
});
}
export function replaceConnection(oldUri: string, newUri: string, connectionService: IConnectionManagementService): Promise<IConnectionResult> {
return new Promise<IConnectionResult>((resolve, reject) => {
let defaultResult: IConnectionResult = {
connected: false,
errorMessage: undefined,
errorCode: undefined
};
if (connectionService) {
let connectionProfile = connectionService.getConnectionProfile(oldUri);
if (connectionProfile) {
let options: IConnectionCompletionOptions = {
params: { connectionType: ConnectionType.editor, runQueryOnCompletion: RunQueryOnConnectionMode.none },
saveTheConnection: false,
showDashboard: false,
showConnectionDialogOnError: true,
showFirewallRuleOnError: true
};
connectionService.disconnect(oldUri).then(() => {
connectionService.connect(connectionProfile, newUri, options).then(result => {
resolve(result);
}, connectError => {
reject(connectError);
});
}, disconnectError => {
reject(disconnectError);
});
} else {
resolve(defaultResult);
}
} else {
resolve(defaultResult);
}
});
}
export function showCreateDatabase(
connection: IConnectionProfile,
adminService: IAdminService,
errorMessageService: IErrorMessageService): Promise<void> {
return new Promise<void>((resolve) => {
// show not implemented
errorMessageService.showDialog(Severity.Info,
'Coming Soon',
'This feature is not yet implemented. It will be available in an upcoming release.');
// adminService.showCreateDatabaseWizard(uri, connection);
});
}
export function showCreateLogin(uri: string, connection: IConnectionProfile, adminService: IAdminService): Promise<void> {
return new Promise<void>((resolve) => {
adminService.showCreateLoginWizard(uri, connection);
});
}
export function showBackup(connection: IConnectionProfile, disasterRecoveryUiService: IDisasterRecoveryUiService): Promise<void> {
return new Promise<void>((resolve) => {
disasterRecoveryUiService.showBackup(connection);
});
}
export function showRestore(connection: IConnectionProfile, restoreDialogService: IRestoreDialogController): Promise<void> {
return new Promise<void>((resolve) => {
restoreDialogService.showDialog(connection);
});
}
export function openInsight(query: IInsightsConfig, profile: IConnectionProfile, insightDialogService: IInsightsDialogService) {
insightDialogService.show(query, profile);
}
/* Helper Methods */
function getStartPos(script: string, operation: ScriptOperation, typeName: string): number {
let objectTypeName = objectScriptMap.get(typeName);
if (objectTypeName && script) {
let scriptTypeName = objectTypeName.toLowerCase();
switch (operation) {
case (ScriptOperation.Create):
return script.toLowerCase().indexOf(`create ${scriptTypeName}`);
case (ScriptOperation.Delete):
return script.toLowerCase().indexOf(`drop ${scriptTypeName}`);
default:
/* script wasn't found for that object */
return -1;
}
} else {
return -1;
}
}
function getScriptingParamDetails(connectionService: IConnectionManagementService, ownerUri: string, metadata: data.ObjectMetadata): data.ScriptingParamDetails {
let serverInfo: data.ServerInfo = getServerInfo(connectionService, ownerUri);
let paramDetails: data.ScriptingParamDetails = {
filePath: getFilePath(metadata),
scriptCompatibilityOption: scriptCompatibilityOptionMap[serverInfo.serverMajorVersion],
targetDatabaseEngineEdition: targetDatabaseEngineEditionMap[serverInfo.engineEditionId],
targetDatabaseEngineType: serverInfo.isCloud ? 'SqlAzure' : 'SingleInstance'
}
return paramDetails;
}
function getFilePath(metadata: data.ObjectMetadata): string {
let schemaName: string = metadata.schema;
let objectName: string = metadata.name;
let timestamp = Date.now().toString();
if (schemaName !== null) {
return path.join(os.tmpdir(), `${schemaName}.${objectName}_${timestamp}.txt`);
} else {
return path.join(os.tmpdir(), `${objectName}_${timestamp}.txt`);
}
}
function getServerInfo(connectionService: IConnectionManagementService, ownerUri: string): data.ServerInfo {
let connection: ConnectionManagementInfo = connectionService.getConnectionInfo(ownerUri);
return connection.serverInfo;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 KiB

View File

@@ -0,0 +1,15 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
body, html {
margin: 0px;
height: 100%;
width: 100%;
}
.splash-modal {
background-image: url("splash.png");
background-repeat: no-repeat;
background-size: 100% 100%;
}

View File

@@ -0,0 +1,10 @@
<!-- Copyright (C) Microsoft Corporation. All rights reserved. -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="splashscreen.css">
</head>
<body class="splash-modal">
</body>
</html>

View File

@@ -0,0 +1,113 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import 'vs/css!sql/media/icons/common-icons';
import 'vs/css!./media/errorMessageDialog';
import { Modal } from 'sql/base/browser/ui/modal/modal';
import * as TelemetryKeys from 'sql/common/telemetryKeys';
import { attachModalDialogStyler } from 'sql/common/theme/styler';
import { Builder } from 'vs/base/browser/builder';
import Severity from 'vs/base/common/severity';
import { IThemeService } from 'vs/platform/theme/common/themeService';
import { attachButtonStyler } from 'vs/platform/theme/common/styler';
import { SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme';
import { IPartService } from 'vs/workbench/services/part/common/partService';
import Event, { Emitter } from 'vs/base/common/event';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
export class ErrorMessageDialog extends Modal {
private _body: HTMLElement;
private _severity: Severity;
private _message: string;
private _onOk = new Emitter<void>();
public onOk: Event<void> = this._onOk.event;
constructor(
@IThemeService private _themeService: IThemeService,
@IClipboardService private _clipboardService: IClipboardService,
@IPartService partService: IPartService,
@ITelemetryService telemetryService: ITelemetryService,
@IContextKeyService contextKeyService: IContextKeyService
) {
super('', TelemetryKeys.ErrorMessage, partService, telemetryService, contextKeyService, { isFlyout: false, hasTitleIcon: true });
}
protected renderBody(container: HTMLElement) {
new Builder(container).div({ 'class': 'error-dialog' }, (bodyBuilder) => {
this._body = bodyBuilder.getHTMLElement();;
});
}
public render() {
super.render();
attachModalDialogStyler(this, this._themeService);
let copyButton = this.addFooterButton('Copy to Clipboard', () => this._clipboardService.writeText(this._message), 'left');
copyButton.icon = 'icon scriptToClipboard';
attachButtonStyler(copyButton, this._themeService, { buttonBackground: SIDE_BAR_BACKGROUND, buttonHoverBackground: SIDE_BAR_BACKGROUND });
let okButton = this.addFooterButton('OK', () => this.ok());
attachButtonStyler(okButton, this._themeService);
}
protected layout(height?: number): void {
// Nothing to re-layout
}
private updateDialogBody(): void {
let builder = new Builder(this._body).empty();
builder.div({ class: 'error-message' }, (errorContainer) => {
errorContainer.innerHtml(this._message);
});
}
private updateIconTitle(): void {
switch (this._severity) {
case Severity.Error:
this.titleIconClassName = 'icon error';
break;
case Severity.Warning:
this.titleIconClassName = 'icon warning';
break;
case Severity.Info:
this.titleIconClassName = 'icon info';
break;
}
}
/* espace key */
protected onClose() {
this.ok();
}
/* enter key */
protected onAccept() {
this.ok();
}
public ok(): void {
this._onOk.fire();
this.close();
}
public close() {
this.hide();
}
public open(severity: Severity, headerTitle: string, message: string) {
this._severity = severity;
this._message = message;
this.title = headerTitle;
this.updateIconTitle();
this.updateDialogBody();
this.show();
}
public dispose(): void {
}
}

View File

@@ -0,0 +1,57 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { localize } from 'vs/nls';
import Severity from 'vs/base/common/severity';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IErrorMessageService } from 'sql/parts/connection/common/connectionManagement';
import { ErrorMessageDialog } from 'sql/workbench/errorMessageDialog/errorMessageDialog';
export class ErrorMessageService implements IErrorMessageService {
_serviceBrand: any;
private _errorDialog: ErrorMessageDialog;
private handleOnOk(): void {
}
constructor(
@IInstantiationService private _instantiationService: IInstantiationService
) { }
public showDialog(severity: Severity, headerTitle: string, message: string): void {
this.doShowDialog(severity, headerTitle, message);
}
private doShowDialog(severity: Severity, headerTitle: string, message: string): void {
if (!this._errorDialog) {
this._errorDialog = this._instantiationService.createInstance(ErrorMessageDialog);
this._errorDialog.onOk(() => this.handleOnOk());
this._errorDialog.render();
}
let title = headerTitle ? headerTitle : this.getDefaultTitle(severity);
return this._errorDialog.open(severity, title, message);
}
private getDefaultTitle(severity: Severity) {
let defaultTitle: string;
switch (severity) {
case Severity.Error:
defaultTitle = localize('error', 'Error');
break;
case Severity.Warning:
defaultTitle = localize('warning', 'Warning');
break;
case Severity.Info:
defaultTitle = localize('info', 'Info');
}
return defaultTitle;
}
}

View File

@@ -0,0 +1,16 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.error-dialog {
padding: 15px;
overflow: auto;
height: 200px;
}
.error-dialog .icon.error, .error-dialog .icon.warning , .error-dialog .icon.info {
width: 20px;
height: 20px;
float: left;
margin-right: 10px;
}

View File

@@ -0,0 +1,82 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import nls = require('vs/nls');
import { TPromise } from 'vs/base/common/winjs.base';
import { Action } from 'vs/base/common/actions';
import { IMessageService, CloseAction, Severity } from 'vs/platform/message/common/message';
import pkg from 'vs/platform/node/package';
import product from 'vs/platform/node/product';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ReleaseNotesInput } from 'vs/workbench/parts/update/electron-browser/releaseNotesInput';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import URI from 'vs/base/common/uri';
import { IOpenerService } from 'vs/platform/opener/common/opener';
import { AbstractShowReleaseNotesAction, loadReleaseNotes } from 'vs/workbench/parts/update/electron-browser/update';
export class OpenGettingStartedInBrowserAction extends Action {
constructor(
@IOpenerService private openerService: IOpenerService
) {
super('update.openGettingStartedGuide', nls.localize('gettingStarted', "Get Started"), null, true);
}
run(): TPromise<any> {
const uri = URI.parse(product.releaseNotesUrl);
return this.openerService.open(uri);
}
}
export class ShowCurrentReleaseNotesAction extends AbstractShowReleaseNotesAction {
static ID = 'update.showCurrentCarbonReleaseNotes';
static LABEL = nls.localize('showReleaseNotes', "Show Getting Started");
constructor(
id = ShowCurrentReleaseNotesAction.ID,
label = ShowCurrentReleaseNotesAction.LABEL,
@IWorkbenchEditorService editorService: IWorkbenchEditorService,
@IInstantiationService instantiationService: IInstantiationService
) {
super(id, label, true, pkg.version, editorService, instantiationService);
}
}
export class ProductContribution implements IWorkbenchContribution {
private static KEY = 'releaseNotes/carbonLastVersion';
getId() { return 'carbon.product'; }
constructor(
@IStorageService storageService: IStorageService,
@IInstantiationService instantiationService: IInstantiationService,
@IMessageService messageService: IMessageService,
@IWorkbenchEditorService editorService: IWorkbenchEditorService
) {
const lastVersion = storageService.get(ProductContribution.KEY, StorageScope.GLOBAL, '');
// was there an update? if so, open release notes
if (product.releaseNotesUrl && pkg.version !== lastVersion) {
instantiationService.invokeFunction(loadReleaseNotes, pkg.version).then(
text => editorService.openEditor(instantiationService.createInstance(ReleaseNotesInput, pkg.version, text), { pinned: true }),
() => {
messageService.show(Severity.Info, {
message: nls.localize('read the release notes', "Welcome to {0} Public Preview 1! Would you like to view the Getting Started Guide?", product.nameLong, pkg.version),
actions: [
instantiationService.createInstance(OpenGettingStartedInBrowserAction),
CloseAction
]
});
});
}
storageService.store(ProductContribution.KEY, pkg.version, StorageScope.GLOBAL);
}
}