diff --git a/extensions/schema-compare/src/schemaCompareMainWindow.ts b/extensions/schema-compare/src/schemaCompareMainWindow.ts index acd9737ccf..ffb8d976bb 100644 --- a/extensions/schema-compare/src/schemaCompareMainWindow.ts +++ b/extensions/schema-compare/src/schemaCompareMainWindow.ts @@ -23,6 +23,8 @@ const generateScriptNoChangesMessage = localize('schemaCompare.generateScriptNoC const applyEnabledMessage = localize('schemaCompare.applyButtonEnabledTitle', "Apply changes to target"); const applyNoChangesMessage = localize('schemaCompare.applyNoChanges', "No changes to apply"); const includeExcludeInfoMessage = localize('schemaCompare.includeExcludeInfoMessage', "Please note that include/exclude operations can take a moment to calculate affected dependencies"); +const sourceTitle = localize('schemaCompareDialog.SourceTitle', "Source"); +const targetTitle = localize('schemaCompareDialog.TargetTitle', "Target"); // Do not localize this, this is used to decide the icon for the editor. // TODO : In future icon should be decided based on language id (scmp) and not resource name @@ -256,8 +258,12 @@ export class SchemaCompareMainWindow { }, ]); - // reset buttons to before comparison state - this.resetButtons(ResetButtonState.beforeCompareStart); + if (!this.sourceName || !this.targetName || this.sourceName === ' ' || this.targetName === ' ') { + this.resetButtons(ResetButtonState.noSourceTarget); + } else { + // reset buttons to before comparison state + this.resetButtons(ResetButtonState.beforeCompareStart); + } } // only for test @@ -819,7 +825,6 @@ export class SchemaCompareMainWindow { // reset state afer loading an scmp private resetForNewCompare(): void { - this.resetButtons(ResetButtonState.beforeCompareStart); this.flexModel.removeItem(this.splitView); this.flexModel.removeItem(this.noDifferencesLabel); this.flexModel.addItem(this.startText, { CSSStyles: { 'margin': 'auto' } }); @@ -941,44 +946,8 @@ export class SchemaCompareMainWindow { return; } - if (result.sourceEndpointInfo && result.sourceEndpointInfo.endpointType === mssql.SchemaCompareEndpointType.Database) { - // only set endpoint info if able to connect to the database - const ownerUri = await verifyConnectionAndGetOwnerUri(result.sourceEndpointInfo); - if (ownerUri) { - this.sourceEndpointInfo = result.sourceEndpointInfo; - this.sourceEndpointInfo.ownerUri = ownerUri; - } - } else { - // need to do this instead of just setting it to the result.sourceEndpointInfo because some fields are null which will cause an error when sending the compare request - this.sourceEndpointInfo = { - endpointType: mssql.SchemaCompareEndpointType.Dacpac, - serverDisplayName: '', - serverName: '', - databaseName: '', - ownerUri: '', - packageFilePath: result.sourceEndpointInfo.packageFilePath, - connectionDetails: undefined - }; - } - - if (result.targetEndpointInfo && result.targetEndpointInfo.endpointType === mssql.SchemaCompareEndpointType.Database) { - const ownerUri = await verifyConnectionAndGetOwnerUri(result.targetEndpointInfo); - if (ownerUri) { - this.targetEndpointInfo = result.targetEndpointInfo; - this.targetEndpointInfo.ownerUri = ownerUri; - } - } else { - // need to do this instead of just setting it to the result.targetEndpointInfo because some fields are null which will cause an error when sending the compare request - this.targetEndpointInfo = { - endpointType: mssql.SchemaCompareEndpointType.Dacpac, - serverDisplayName: '', - serverName: '', - databaseName: '', - ownerUri: '', - packageFilePath: result.targetEndpointInfo.packageFilePath, - connectionDetails: undefined - }; - } + this.sourceEndpointInfo = await this.constructEndpointInfo(result.sourceEndpointInfo, sourceTitle); + this.targetEndpointInfo = await this.constructEndpointInfo(result.targetEndpointInfo, targetTitle); this.updateSourceAndTarget(); this.setDeploymentOptions(result.deploymentOptions); @@ -995,6 +964,31 @@ export class SchemaCompareMainWindow { }); } + private async constructEndpointInfo(endpoint: mssql.SchemaCompareEndpointInfo, caller: string): Promise { + let ownerUri; + let endpointInfo; + if (endpoint && endpoint.endpointType === mssql.SchemaCompareEndpointType.Database) { + // only set endpoint info if able to connect to the database + ownerUri = await verifyConnectionAndGetOwnerUri(endpoint, caller); + } + if (ownerUri) { + endpointInfo = endpoint; + endpointInfo.ownerUri = ownerUri; + } else { + // need to do this instead of just setting it to the endpoint because some fields are null which will cause an error when sending the compare request + endpointInfo = { + endpointType: endpoint.endpointType === mssql.SchemaCompareEndpointType.Database ? mssql.SchemaCompareEndpointType.Database : mssql.SchemaCompareEndpointType.Dacpac, + serverDisplayName: '', + serverName: '', + databaseName: '', + ownerUri: '', + packageFilePath: endpoint.packageFilePath, + connectionDetails: undefined + }; + } + return endpointInfo; + } + private createSaveScmpButton(view: azdata.ModelView): void { this.saveScmpButton = view.modelBuilder.button().withProperties({ label: localize('schemaCompare.saveScmpButton', "Save .scmp file"), diff --git a/extensions/schema-compare/src/utils.ts b/extensions/schema-compare/src/utils.ts index 9a33459356..89a53f82ea 100644 --- a/extensions/schema-compare/src/utils.ts +++ b/extensions/schema-compare/src/utils.ts @@ -3,10 +3,12 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ 'use strict'; +import * as nls from 'vscode-nls'; import * as azdata from 'azdata'; import * as vscode from 'vscode'; import * as mssql from '../../mssql'; import * as os from 'os'; +const localize = nls.loadMessageBundle(); export interface IPackageInfo { name: string; @@ -50,7 +52,15 @@ export function getEndpointName(endpoint: mssql.SchemaCompareEndpointInfo): stri if (!endpoint.serverName && endpoint.connectionDetails) { endpoint.serverName = endpoint.connectionDetails['serverName']; } - return `${endpoint.serverName}.${endpoint.databaseName}`; + if (!endpoint.databaseName && endpoint.connectionDetails) { + endpoint.databaseName = endpoint.connectionDetails['databaseName']; + } + if (endpoint.serverName && endpoint.databaseName) { + return `${endpoint.serverName}.${endpoint.databaseName}`; + } else { + return ' '; + } + } else { return endpoint.packageFilePath; } @@ -74,17 +84,44 @@ function connectionInfoToConnectionProfile(details: azdata.ConnectionInfo): azda }; } -export async function verifyConnectionAndGetOwnerUri(endpoint: mssql.SchemaCompareEndpointInfo): Promise { +export async function verifyConnectionAndGetOwnerUri(endpoint: mssql.SchemaCompareEndpointInfo, caller: string): Promise { + let ownerUri = undefined; if (endpoint.endpointType === mssql.SchemaCompareEndpointType.Database && endpoint.connectionDetails) { - let connection = await azdata.connection.connect(connectionInfoToConnectionProfile(endpoint.connectionDetails), false, false); + let connectionProfile = await connectionInfoToConnectionProfile(endpoint.connectionDetails); + let connection = await azdata.connection.connect(connectionProfile, false, false); + if (connection) { + ownerUri = await azdata.connection.getUriForConnection(connection.connectionId); + if (!ownerUri) { + let connectionList = await azdata.connection.getConnections(true); + let userConnection; + userConnection = connectionList.find(connection => + (endpoint.connectionDetails['authenticationType'] === 'SqlLogin' + && endpoint.connectionDetails['serverName'] === connection.options.server + && endpoint.connectionDetails['userName'] === connection.options.user + && (endpoint.connectionDetails['databaseName'].toLowerCase() === connection.options.database.toLowerCase() + || connection.options.database.toLowerCase() === 'master'))); - // show error message if the can't connect to the database - if (connection.errorMessage) { - vscode.window.showErrorMessage(connection.errorMessage); + if (userConnection === undefined) { + const getConnectionString = localize('schemaCompare.GetConnectionString', "Do you want to connect to {0}?", caller); + // need only yes button - since the modal dialog has a default cancel + const yesString = localize('schemaCompare.ApplyYes', "Yes"); + + let result = await vscode.window.showWarningMessage(getConnectionString, { modal: true }, yesString); + if (result === yesString) { + userConnection = await azdata.connection.openConnectionDialog(undefined, connectionProfile); + } + } + + if (userConnection !== undefined) { + ownerUri = await azdata.connection.getUriForConnection(userConnection.connectionId); + } + } + if (!ownerUri && connection.errorMessage) { + vscode.window.showErrorMessage(connection.errorMessage); + } } - return await azdata.connection.getUriForConnection(connection.connectionId); } - return undefined; + return ownerUri; } /**