diff --git a/extensions/mssql/config.json b/extensions/mssql/config.json index 0bebd00044..2bdc628751 100644 --- a/extensions/mssql/config.json +++ b/extensions/mssql/config.json @@ -1,6 +1,6 @@ { "downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/{#version#}/microsoft.sqltools.servicelayer-{#fileName#}", - "version": "4.7.0.28", + "version": "4.7.0.29", "downloadFileNames": { "Windows_86": "win-x86-net7.0.zip", "Windows_64": "win-x64-net7.0.zip", diff --git a/extensions/mssql/package.json b/extensions/mssql/package.json index 9ab12f1c4b..3381441aad 100644 --- a/extensions/mssql/package.json +++ b/extensions/mssql/package.json @@ -770,7 +770,6 @@ "connectionProvider": { "providerId": "MSSQL", "displayName": "%mssql.provider.displayName%", - "useFullOptions": true, "isExecutionPlanProvider": true, "azureResource": "Sql", "supportedExecutionPlanFileExtensions": [ diff --git a/extensions/mssql/src/tableDesigner/tableDesigner.ts b/extensions/mssql/src/tableDesigner/tableDesigner.ts index fa24f8a91d..25934bcd24 100644 --- a/extensions/mssql/src/tableDesigner/tableDesigner.ts +++ b/extensions/mssql/src/tableDesigner/tableDesigner.ts @@ -26,18 +26,11 @@ export function registerTableDesignerCommands(appContext: AppContext) { if (!connectionString) { throw new Error(FailedToGetConnectionStringError); } - let titleString = `${context.connectionProfile!.serverName} - ${context.connectionProfile!.databaseName} - ${NewTableText}`; - // append non default options to end to let users know exact connection. - let nonDefaultOptions = await azdata.connection.getEditorConnectionProfileTitle(context.connectionProfile, true); - nonDefaultOptions = nonDefaultOptions.replace('(', '[').replace(')', ']'); - if (nonDefaultOptions !== '') { - titleString += `${nonDefaultOptions}`; - } const tableIcon = context.nodeInfo!.nodeSubType as azdata.designers.TableIcon; const telemetryInfo = await getTelemetryInfo(context, tableIcon); await azdata.designers.openTableDesigner(sqlProviderName, { title: NewTableText, - tooltip: titleString, + tooltip: `${context.connectionProfile!.serverName} - ${context.connectionProfile!.databaseName} - ${NewTableText}`, server: context.connectionProfile!.serverName, database: context.connectionProfile!.databaseName, isNewTable: true, @@ -63,18 +56,11 @@ export function registerTableDesignerCommands(appContext: AppContext) { if (!connectionString) { throw new Error(FailedToGetConnectionStringError); } - let titleString = `${server} - ${database} - ${schema}.${name}`; - // append non default options to end to let users know exact connection. - let nonDefaultOptions = await azdata.connection.getEditorConnectionProfileTitle(context.connectionProfile, true); - nonDefaultOptions = nonDefaultOptions.replace('(', '[').replace(')', ']'); - if (nonDefaultOptions !== '') { - titleString += `${nonDefaultOptions}`; - } const tableIcon = context.nodeInfo!.nodeSubType as azdata.designers.TableIcon; const telemetryInfo = await getTelemetryInfo(context, tableIcon); await azdata.designers.openTableDesigner(sqlProviderName, { title: `${schema}.${name}`, - tooltip: titleString, + tooltip: `${server} - ${database} - ${schema}.${name}`, server: server, database: database, isNewTable: false, diff --git a/src/sql/azdata.proposed.d.ts b/src/sql/azdata.proposed.d.ts index 3be7b98b4c..9095714868 100644 --- a/src/sql/azdata.proposed.d.ts +++ b/src/sql/azdata.proposed.d.ts @@ -508,14 +508,6 @@ declare module 'azdata' { * @returns The new password that is returned from the operation or undefined if unsuccessful. */ export function openChangePasswordDialog(profile: IConnectionProfile): Thenable; - - /** - * Gets the formatted title of the connection profile for display - * @param profile The connection profile we want to get the full display info for (without non default options). - * @param getNonDefaultsOnly Provide if you only want to get the non default options string (for some titles). - * @returns The title formatted with connection name in front, server info in the middle, with non default options at the end. - */ - export function getEditorConnectionProfileTitle(profile: IConnectionProfile, getNonDefaultsOnly?: boolean): Thenable; } /* diff --git a/src/sql/platform/capabilities/common/capabilitiesService.ts b/src/sql/platform/capabilities/common/capabilitiesService.ts index 6bf41ae696..42ef4f4dd8 100644 --- a/src/sql/platform/capabilities/common/capabilitiesService.ts +++ b/src/sql/platform/capabilities/common/capabilitiesService.ts @@ -67,12 +67,6 @@ export interface ConnectionProviderProperties { */ displayName: string; - /** - * Enable to use all connection properties for URI generation (ServiceLayer requires the same options as well.) - * If not specified, only IsIdentity options will be used instead (URI with basic info). - */ - useFullOptions?: boolean; - /** * Alias to be used for the kernel in notebooks */ diff --git a/src/sql/platform/capabilities/test/common/testCapabilitiesService.ts b/src/sql/platform/capabilities/test/common/testCapabilitiesService.ts index 1e5f21eb9b..e4195a4115 100644 --- a/src/sql/platform/capabilities/test/common/testCapabilitiesService.ts +++ b/src/sql/platform/capabilities/test/common/testCapabilitiesService.ts @@ -101,7 +101,6 @@ export class TestCapabilitiesService implements ICapabilitiesService { providerId: mssqlProviderName, displayName: 'MSSQL', connectionOptions: connectionProvider, - useFullOptions: true, }; let pgSQLCapabilities = { providerId: this.pgsqlProviderName, diff --git a/src/sql/platform/connection/common/connectionConfig.ts b/src/sql/platform/connection/common/connectionConfig.ts index 45b1488b08..d1e370b1c9 100644 --- a/src/sql/platform/connection/common/connectionConfig.ts +++ b/src/sql/platform/connection/common/connectionConfig.ts @@ -70,51 +70,6 @@ export class ConnectionConfig { }); } - /** - * Checks to make sure that the profile that is being edited is not identical to another profile. - */ - public isDuplicateEdit(profile: IConnectionProfile, matcher: ProfileMatcher = ConnectionProfile.matchesProfile): Promise { - let profiles = deepClone(this.configurationService.inspect(CONNECTIONS_CONFIG_KEY).userValue as IConnectionProfileStore[]); - if (!profiles) { - profiles = []; - } - - return this.addGroupFromProfile(profile).then(groupId => { - let connectionProfile = this.getConnectionProfileInstance(profile, groupId); - // Profile to be stored during an edit, used to check for duplicate profile edits. - let firstMatchProfile = undefined; - - profiles.find(value => { - const providerConnectionProfile = ConnectionProfile.createFromStoredProfile(value, this._capabilitiesService); - const match = matcher(providerConnectionProfile, connectionProfile); - // If we have a profile match, and the matcher is an edit, we must store this match. - if (match && (matcher.toString() !== ConnectionProfile.matchesProfile.toString())) { - firstMatchProfile = value; - } - return match; - }); - - // If a profile edit, we must now check to see it does not match the other profiles available. - if (firstMatchProfile) { - // Copy over profile list so that we can remove the actual profile we want to edit. - const index = profiles.indexOf(firstMatchProfile); - if (index > -1) { - profiles.splice(index, 1); - } - - // Use the regular profile matching here to find if edit is duplicate. - let matchesExistingProfile = profiles.find(value => { - const providerConnectionProfile = ConnectionProfile.createFromStoredProfile(value, this._capabilitiesService); - const match = ConnectionProfile.matchesProfile(providerConnectionProfile, connectionProfile); - return match; - }); - - return Promise.resolve(matchesExistingProfile !== undefined); - } - return Promise.resolve(false); - }); - } - /** * Add a new connection to the connection config. */ @@ -362,18 +317,10 @@ export class ConnectionConfig { p.options.database === profile.options.database && p.options.server === profile.options.server && p.options.user === profile.options.user && - p.options.connectionName === profile.options.connectionName && - p.groupId === newGroupID && - this.checkIfNonDefaultOptionsMatch(p, profile)); + p.groupId === newGroupID); return existingProfile === undefined; } - private checkIfNonDefaultOptionsMatch(profileStore: IConnectionProfileStore, profile: ConnectionProfile): boolean { - let tempProfile = ConnectionProfile.createFromStoredProfile(profileStore, this._capabilitiesService); - let result = profile.getNonDefaultOptionsString() === tempProfile.getNonDefaultOptionsString(); - return result; - } - /** * Moves the connection under the target group with the new ID. */ diff --git a/src/sql/platform/connection/common/connectionManagement.ts b/src/sql/platform/connection/common/connectionManagement.ts index 967b829aa7..77ec582292 100644 --- a/src/sql/platform/connection/common/connectionManagement.ts +++ b/src/sql/platform/connection/common/connectionManagement.ts @@ -378,14 +378,6 @@ export interface IConnectionManagementService { * @returns the new valid password that is entered, or undefined if cancelled or errored. */ openChangePasswordDialog(profile: IConnectionProfile): Promise; - - /** - * Gets the formatted title of the connection profile for display. - * @param profile The connection profile to change the password. - * @param getNonDefaultsOnly Provide if you only want to get the non default options string (for some titles). - * @returns the new valid password that is entered, or undefined if cancelled or errored. - */ - getEditorConnectionProfileTitle(profile: IConnectionProfile, getNonDefaultsOnly?: boolean): string; } export enum RunQueryOnConnectionMode { diff --git a/src/sql/platform/connection/common/connectionProfile.ts b/src/sql/platform/connection/common/connectionProfile.ts index e26492b343..000cecbd77 100644 --- a/src/sql/platform/connection/common/connectionProfile.ts +++ b/src/sql/platform/connection/common/connectionProfile.ts @@ -39,9 +39,6 @@ export class ConnectionProfile extends ProviderConnectionInfo implements interfa public isDisconnecting: boolean = false; - // title from ProviderConnectionInfo cannot be changed, in order to show different dynamic options appended, we must override the title with our own. - private _title?: string; - public constructor( capabilitiesService: ICapabilitiesService, model: string | azdata.IConnectionProfile | azdata.connection.ConnectionProfile | undefined) { @@ -202,33 +199,6 @@ export class ConnectionProfile extends ProviderConnectionInfo implements interfa return (this._groupName === ConnectionProfile.RootGroupName); } - public override get title(): string { - if (this._title) { - return this._title; - } - return this.getOriginalTitle(); - } - - public getOriginalTitle(): string { - return super.title; - } - - public getEditorFullTitleWithOptions(): string { - let textResult = ''; - if (this.connectionName) { - textResult += `${this.connectionName}: `; - } - textResult += this.serverInfo; - if (textResult.length === 0) { - return undefined; - } - return textResult; - } - - public override set title(value: string) { - this._title = value; - } - public override clone(): ConnectionProfile { let instance = new ConnectionProfile(this.capabilitiesService, this); return instance; @@ -257,33 +227,24 @@ export class ConnectionProfile extends ProviderConnectionInfo implements interfa /** * Returns a key derived the connections options (providerName, authenticationType, serverName, databaseName, userName, groupid) - * and all the other properties if useFullOptions is enabled for the provider. * This key uniquely identifies a connection in a group * Example: "providerName:MSSQL|authenticationType:|databaseName:database|serverName:server3|userName:user|group:testid" - * @param getOriginalOptions will return the original URI format regardless if useFullOptions was set or not. (used for retrieving passwords) */ - public override getOptionsKey(getOriginalOptions?: boolean): string { - let id = super.getOptionsKey(getOriginalOptions); + public override getOptionsKey(): string { + let id = super.getOptionsKey(); let databaseDisplayName: string = this.options['databaseDisplayName']; if (databaseDisplayName) { id += ProviderConnectionInfo.idSeparator + 'databaseDisplayName' + ProviderConnectionInfo.nameValueSeparator + databaseDisplayName; } - return id + ProviderConnectionInfo.idSeparator + 'groupId' + ProviderConnectionInfo.nameValueSeparator + this.groupId; + return id + ProviderConnectionInfo.idSeparator + 'group' + ProviderConnectionInfo.nameValueSeparator + this.groupId; } /** - * Returns the unique id for the connection that doesn't include the group name. - * Used primarily for retrieving shared passwords among different connections in default state. - * @param getOriginalOptions will return the original URI format regardless if useFullOptions was set or not. (used for retrieving passwords) + * Returns the unique id for the connection that doesn't include the group name */ - public getConnectionInfoId(getOriginalOptions = true): string { - let id = super.getOptionsKey(getOriginalOptions); - let databaseDisplayName: string = this.options['databaseDisplayName']; - if (databaseDisplayName && !getOriginalOptions && this.serverCapabilities?.useFullOptions) { - id += ProviderConnectionInfo.idSeparator + 'databaseDisplayName' + ProviderConnectionInfo.nameValueSeparator + databaseDisplayName; - } - return id; + public getConnectionInfoId(): string { + return super.getOptionsKey(); } public toIConnectionProfile(): interfaces.IConnectionProfile { @@ -292,7 +253,6 @@ export class ConnectionProfile extends ProviderConnectionInfo implements interfa serverName: this.serverName, databaseName: this.databaseName, authenticationType: this.authenticationType, - serverCapabilities: this.serverCapabilities, getOptionsKey: this.getOptionsKey, matches: this.matches, groupId: this.groupId, diff --git a/src/sql/platform/connection/common/connectionStore.ts b/src/sql/platform/connection/common/connectionStore.ts index 28ff48ed85..686fd9420e 100644 --- a/src/sql/platform/connection/common/connectionStore.ts +++ b/src/sql/platform/connection/common/connectionStore.ts @@ -67,7 +67,6 @@ export class ConnectionStore { } cred.push(CRED_ITEMTYPE_PREFIX.concat(itemType)); - // Use basic info for credentials so that passwords can be shared among similar profiles for now. cred.push(CRED_ID_PREFIX.concat(connectionProfileInstance.getConnectionInfoId())); return cred.join(CRED_SEPARATOR); } @@ -150,17 +149,6 @@ export class ConnectionStore { } } - /** - * Checks to see if a connection profile edit is not identical to an existing saved profile. - * - * @param profile the profile group that is being edited. - * @param matcher the profile matching function for the actual connection we want to edit. - * @returns a boolean value indicating if there's an identical profile to the edit. - */ - public isDuplicateEdit(profile: IConnectionProfile, matcher?: ProfileMatcher): Promise { - return this.connectionConfig.isDuplicateEdit(profile, matcher); - } - /** * Gets the list of recently used connections. These will not include the password - a separate call to * {addSavedPassword} is needed to fill that before connecting @@ -229,7 +217,7 @@ export class ConnectionStore { // Remove the connection from the list if it already exists list = list.filter(value => { - let equal = value && value.getConnectionInfoId(false) === savedProfile.getConnectionInfoId(false); + let equal = value && value.getConnectionInfoId() === savedProfile.getConnectionInfoId(); if (equal && savedProfile.saveProfile) { equal = value.groupId === savedProfile.groupId || ConnectionProfileGroup.sameGroupName(value.groupFullName, savedProfile.groupFullName); @@ -247,7 +235,7 @@ export class ConnectionStore { // Remove the connection from the list if it already exists list = list.filter(value => { - let equal = value && value.getConnectionInfoId(false) === savedProfile.getConnectionInfoId(false); + let equal = value && value.getConnectionInfoId() === savedProfile.getConnectionInfoId(); if (equal && savedProfile.saveProfile) { equal = value.groupId === savedProfile.groupId || ConnectionProfileGroup.sameGroupName(value.groupFullName, savedProfile.groupFullName); @@ -282,8 +270,6 @@ export class ConnectionStore { private doSavePassword(conn: IConnectionProfile): Promise { if (conn.password) { - // Credentials are currently shared between profiles with the same basic details. - // Credentials are currently not cleared upon deletion of a profile. const credentialId = this.formatCredentialId(conn); return this.credentialService.saveCredential(credentialId, conn.password); } else { diff --git a/src/sql/platform/connection/common/interfaces.ts b/src/sql/platform/connection/common/interfaces.ts index 119f9ec6e8..9b1786963e 100644 --- a/src/sql/platform/connection/common/interfaces.ts +++ b/src/sql/platform/connection/common/interfaces.ts @@ -4,14 +4,12 @@ *--------------------------------------------------------------------------------------------*/ import * as azdata from 'azdata'; -import { ConnectionProviderProperties } from 'sql/platform/capabilities/common/capabilitiesService'; // Used to allow various methods of matching profiles export type ProfileMatcher = (a: IConnectionProfile, b: IConnectionProfile) => boolean; export interface IConnectionProfile extends azdata.IConnectionProfile { - serverCapabilities: ConnectionProviderProperties | undefined; - getOptionsKey(getOriginalOptions?: boolean): string; + getOptionsKey(): string; matches(profile: azdata.IConnectionProfile): boolean; } diff --git a/src/sql/platform/connection/common/providerConnectionInfo.ts b/src/sql/platform/connection/common/providerConnectionInfo.ts index 4b8694a81b..c12aa85a83 100644 --- a/src/sql/platform/connection/common/providerConnectionInfo.ts +++ b/src/sql/platform/connection/common/providerConnectionInfo.ts @@ -8,7 +8,7 @@ import { isString } from 'vs/base/common/types'; import * as azdata from 'azdata'; import * as Constants from 'sql/platform/connection/common/constants'; import { ICapabilitiesService, ConnectionProviderProperties } from 'sql/platform/capabilities/common/capabilitiesService'; -import { ConnectionOptionSpecialType } from 'sql/platform/connection/common/interfaces'; +import { ConnectionOptionSpecialType, ServiceOptionType } from 'sql/platform/connection/common/interfaces'; import { localize } from 'vs/nls'; type SettableProperty = 'serverName' | 'authenticationType' | 'databaseName' | 'password' | 'connectionName' | 'userName'; @@ -161,7 +161,7 @@ export class ProviderConnectionInfo implements azdata.ConnectionInfo { } } // The provider capabilities are registered at the same time at load time, we can assume all providers are registered as long as the collection is not empty. - else if (this.hasLoaded()) { + else if (Object.keys(this.capabilitiesService.providers).length > 0) { return localize('connection.unsupported', "Unsupported connection"); } else { return localize('loading', "Loading..."); @@ -169,16 +169,8 @@ export class ProviderConnectionInfo implements azdata.ConnectionInfo { return label; } - public hasLoaded(): boolean { - return Object.keys(this.capabilitiesService.providers).length > 0; - } - public get serverInfo(): string { - let value = this.getServerInfo(); - if (this.serverCapabilities?.useFullOptions) { - value += this.getNonDefaultOptionsString(); - } - return value; + return this.getServerInfo(); } public isPasswordRequired(): boolean { @@ -206,23 +198,16 @@ export class ProviderConnectionInfo implements azdata.ConnectionInfo { /** * Returns a key derived the connections options (providerName, authenticationType, serverName, databaseName, userName, groupid) - * and all the other properties if useFullOptions is enabled for the provider. * This key uniquely identifies a connection in a group * Example: "providerName:MSSQL|authenticationType:|databaseName:database|serverName:server3|userName:user|group:testid" - * @param getOriginalOptions will return the original URI format regardless if useFullOptions was set or not. (used for retrieving passwords) */ - public getOptionsKey(getOriginalOptions?: boolean): string { - let useFullOptions = false; + public getOptionsKey(): string { let idNames = []; if (this.serverCapabilities) { - useFullOptions = this.serverCapabilities.useFullOptions; idNames = this.serverCapabilities.connectionOptions.map(o => { - // All options enabled, use every property besides password. - let newProperty = useFullOptions && o.specialValueType !== ConnectionOptionSpecialType.password && !getOriginalOptions; - // Fallback to original base IsIdentity properties otherwise. - let originalProperty = (o.specialValueType || o.isIdentity) && o.specialValueType !== ConnectionOptionSpecialType.password - && o.specialValueType !== ConnectionOptionSpecialType.connectionName; - if (newProperty || originalProperty) { + if ((o.specialValueType || o.isIdentity) + && o.specialValueType !== ConnectionOptionSpecialType.password + && o.specialValueType !== ConnectionOptionSpecialType.connectionName) { return o.name; } else { return undefined; @@ -241,45 +226,14 @@ export class ProviderConnectionInfo implements azdata.ConnectionInfo { let idValues: string[] = []; for (let index = 0; index < idNames.length; index++) { let value = this.options[idNames[index]!]; - // If we're using the new URI format, we do not include any values that are empty or are default. - let isFullOptions = useFullOptions && !getOriginalOptions; - if (isFullOptions) { - let finalValue = undefined; - let options = this.serverCapabilities.connectionOptions.filter(value => value.name === idNames[index]!); - if (options.length > 0 && value) { - finalValue = value !== options[0].defaultValue ? value : undefined; - } - value = finalValue; - } - else { - value = value ? value : ''; - } - if ((isFullOptions && value !== undefined) || !isFullOptions) { - idValues.push(`${idNames[index]}${ProviderConnectionInfo.nameValueSeparator}${value}`); - } + value = value ? value : ''; + idValues.push(`${idNames[index]}${ProviderConnectionInfo.nameValueSeparator}${value}`); } return ProviderConnectionInfo.ProviderPropertyName + ProviderConnectionInfo.nameValueSeparator + this.providerName + ProviderConnectionInfo.idSeparator + idValues.join(ProviderConnectionInfo.idSeparator); } - /** - * Returns a more readable version of the options key intended for display areas, replaces the regular separators with display separators - * @param optionsKey options key in the original format. - */ - public static getDisplayOptionsKey(optionsKey: string) { - let ids: string[] = optionsKey.split(ProviderConnectionInfo.idSeparator); - ids = ids.map(id => { - let idParts = id.split(ProviderConnectionInfo.nameValueSeparator); - let result = idParts[0] + ProviderConnectionInfo.displayNameValueSeparator; - if (idParts.length >= 2) { - result += idParts.slice(1).join(ProviderConnectionInfo.nameValueSeparator); - } - return result; - }); - return ids.join(ProviderConnectionInfo.displayIdSeparator); - } - public static getProviderFromOptionsKey(optionsKey: string) { let providerId: string = ''; if (optionsKey) { @@ -337,68 +291,28 @@ export class ProviderConnectionInfo implements azdata.ConnectionInfo { return ':'; } - public static get displayIdSeparator(): string { - return '; '; - } - - public static get displayNameValueSeparator(): string { - return '='; - } - - - /** - * Get all non specialValueType (or if distinct connections share same connection name, everything but connectionName and password). - * Also allows for getting the non default options for this profile. (this function is used for changing the title). - * @param needSpecial include all the special options key besides connection name or password in case we have multiple - * distinct connections sharing the same connection name. - * @param getNonDefault get only the non default options (for individual connections) to be used for identfying different properties - * among connections sharing the same title. - */ - public getConnectionOptionsList(needSpecial: boolean, getNonDefault: boolean): azdata.ConnectionOption[] { - let connectionOptions: azdata.ConnectionOption[] = []; + public get titleParts(): string[] { + let parts: string[] = []; + // Always put these three on top. TODO: maybe only for MSSQL? + parts.push(this.serverName); + parts.push(this.databaseName); + parts.push(this.authenticationTypeDisplayName); if (this.serverCapabilities) { this.serverCapabilities.connectionOptions.forEach(element => { - if (((!needSpecial && element.specialValueType !== ConnectionOptionSpecialType.serverName && + if (element.specialValueType !== ConnectionOptionSpecialType.serverName && element.specialValueType !== ConnectionOptionSpecialType.databaseName && element.specialValueType !== ConnectionOptionSpecialType.authType && - element.specialValueType !== ConnectionOptionSpecialType.userName) || needSpecial) && + element.specialValueType !== ConnectionOptionSpecialType.password && element.specialValueType !== ConnectionOptionSpecialType.connectionName && - element.specialValueType !== ConnectionOptionSpecialType.password) { - if (getNonDefault) { - let value = this.getOptionValue(element.name); - if (value && value !== element.defaultValue) { - connectionOptions.push(element); - } - } - else { - connectionOptions.push(element); + element.isIdentity && element.valueType === ServiceOptionType.string) { + let value = this.getOptionValue(element.name); + if (value) { + parts.push(value); } } }); } - //Need to sort for consistency. - connectionOptions.sort(); - return connectionOptions; - } - - /** - * Append all non default options to tooltip string if useFullOptions is enabled. - */ - public getNonDefaultOptionsString(): string { - let parts: string = ""; - let nonDefaultOptions = this.getConnectionOptionsList(false, true); - nonDefaultOptions.forEach(element => { - let value = this.getOptionValue(element.name); - if (parts.length === 0) { - parts = " ("; - } - let addValue = element.name + ProviderConnectionInfo.displayNameValueSeparator + `${value}`; - parts += parts === " (" ? addValue : (ProviderConnectionInfo.displayIdSeparator + addValue); - }); - if (parts.length > 0) { - parts += ")"; - } return parts; } diff --git a/src/sql/platform/connection/test/common/connectionConfig.test.ts b/src/sql/platform/connection/test/common/connectionConfig.test.ts index 33c69ae22e..03ff595c19 100644 --- a/src/sql/platform/connection/test/common/connectionConfig.test.ts +++ b/src/sql/platform/connection/test/common/connectionConfig.test.ts @@ -181,30 +181,6 @@ suite('ConnectionConfig', () => { isRequired: true, specialValueType: ConnectionOptionSpecialType.password, valueType: ServiceOptionType.string - }, - { - name: 'testProperty1', - displayName: undefined!, - description: undefined!, - groupName: undefined!, - categoryValues: undefined!, - defaultValue: "default", - isIdentity: true, - isRequired: true, - specialValueType: undefined!, - valueType: ServiceOptionType.string - }, - { - name: 'testProperty2', - displayName: undefined!, - description: undefined!, - groupName: undefined!, - categoryValues: undefined!, - defaultValue: "10", - isIdentity: true, - isRequired: true, - specialValueType: undefined!, - valueType: ServiceOptionType.number } ] }; @@ -301,7 +277,6 @@ suite('ConnectionConfig', () => { groupFullName: undefined, groupId: undefined, getOptionsKey: undefined!, - serverCapabilities: undefined, matches: undefined!, providerName: 'MSSQL', options: {}, @@ -334,7 +309,6 @@ suite('ConnectionConfig', () => { savePassword: true, groupFullName: undefined, getOptionsKey: undefined!, - serverCapabilities: undefined, matches: undefined!, providerName: 'MSSQL', options: {}, @@ -367,7 +341,6 @@ suite('ConnectionConfig', () => { groupFullName: 'g2/g2-2', groupId: undefined, getOptionsKey: undefined!, - serverCapabilities: undefined, matches: undefined!, providerName: 'MSSQL', options: {}, @@ -511,7 +484,6 @@ suite('ConnectionConfig', () => { groupFullName: 'g3', groupId: 'g3', getOptionsKey: undefined!, - serverCapabilities: undefined, matches: undefined!, providerName: 'MSSQL', options: {}, @@ -542,7 +514,6 @@ suite('ConnectionConfig', () => { groupFullName: 'g3', groupId: 'g3', getOptionsKey: undefined!, - serverCapabilities: undefined, matches: undefined!, providerName: 'MSSQL', options: {}, @@ -580,7 +551,6 @@ suite('ConnectionConfig', () => { groupFullName: 'g3', groupId: 'newid', getOptionsKey: undefined!, - serverCapabilities: undefined, matches: undefined!, providerName: 'MSSQL', options: {}, @@ -661,7 +631,6 @@ suite('ConnectionConfig', () => { groupFullName: 'g3', groupId: 'g3', getOptionsKey: () => { return 'connectionId'; }, - serverCapabilities: undefined, matches: undefined!, providerName: 'MSSQL', options: {}, @@ -679,7 +648,6 @@ suite('ConnectionConfig', () => { groupFullName: 'test', groupId: 'test', getOptionsKey: () => { return 'connectionId'; }, - serverCapabilities: undefined, matches: undefined!, providerName: 'MSSQL', options: {}, @@ -709,189 +677,6 @@ suite('ConnectionConfig', () => { } }); - test('change group for connection should accept similar connection with different options', async () => { - let changingProfile: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: () => { return 'connectionId'; }, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { - 'testProperty1': 'nonDefault', - 'testProperty2': '10', - }, - saveProfile: true, - id: 'server3-2', - connectionName: undefined! - }; - let existingProfile = ConnectionProfile.convertToProfileStore(capabilitiesService.object, { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'test', - groupId: 'test', - getOptionsKey: () => { return 'connectionId'; }, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { 'testProperty2': '15' }, - saveProfile: true, - id: 'server3', - connectionName: undefined! - }); - - let _testConnections = [...deepClone(testConnections), existingProfile, changingProfile]; - - let configurationService = new TestConfigurationService(); - configurationService.updateValue('datasource.connections', _testConnections, ConfigurationTarget.USER); - - let connectionProfile = new ConnectionProfile(capabilitiesService.object, changingProfile); - - let config = new ConnectionConfig(configurationService, capabilitiesService.object); - - await config.changeGroupIdForConnection(connectionProfile, 'test'); - - let editedConnections = configurationService.inspect('datasource.connections').userValue!; - - assert.strictEqual(editedConnections.length, _testConnections.length); - let editedConnection = editedConnections.find(con => con.id === 'server3-2'); - assert.ok(editedConnection); - assert.strictEqual(editedConnection!.groupId, 'test'); - }); - - test('change group for connection should not accept similar connection with default options same as another', async () => { - let changingProfile: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: () => { return 'connectionId'; }, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { - 'testProperty1': 'nonDefault', - 'testProperty2': '10', - }, - saveProfile: true, - id: 'server3-2', - connectionName: undefined! - }; - let existingProfile = ConnectionProfile.convertToProfileStore(capabilitiesService.object, { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'test', - groupId: 'test', - getOptionsKey: () => { return 'connectionId'; }, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { 'testProperty1': 'nonDefault' }, - saveProfile: true, - id: 'server3', - connectionName: undefined! - }); - - let _testConnections = [...deepClone(testConnections), existingProfile, changingProfile]; - - let configurationService = new TestConfigurationService(); - configurationService.updateValue('datasource.connections', _testConnections, ConfigurationTarget.USER); - - let connectionProfile = new ConnectionProfile(capabilitiesService.object, changingProfile); - - let config = new ConnectionConfig(configurationService, capabilitiesService.object); - - try { - await config.changeGroupIdForConnection(connectionProfile, 'test'); - assert.fail(); - } catch (e) { - let editedConnections = configurationService.inspect('datasource.connections').userValue!; - // two - assert.strictEqual(editedConnections.length, _testConnections.length); - let editedConnection = editedConnections.find(con => con.id === 'server3-2'); - assert.ok(!!editedConnection); - assert.strictEqual(editedConnection!.groupId, 'g3'); - } - }); - - test('change group for connection should accept similar connection with a distinguishing option', async () => { - let changingProfile: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: () => { return 'connectionId'; }, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { - 'testProperty1': 'nonDefault', - 'testProperty2': '15', - }, - saveProfile: true, - id: 'server3-2', - connectionName: undefined! - }; - let existingProfile = ConnectionProfile.convertToProfileStore(capabilitiesService.object, { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'test', - groupId: 'test', - getOptionsKey: () => { return 'connectionId'; }, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { 'testProperty2': '15' }, - saveProfile: true, - id: 'server3', - connectionName: undefined! - }); - - let _testConnections = [...deepClone(testConnections), existingProfile, changingProfile]; - - let configurationService = new TestConfigurationService(); - configurationService.updateValue('datasource.connections', _testConnections, ConfigurationTarget.USER); - - let connectionProfile = new ConnectionProfile(capabilitiesService.object, changingProfile); - - let config = new ConnectionConfig(configurationService, capabilitiesService.object); - - await config.changeGroupIdForConnection(connectionProfile, 'test'); - - let editedConnections = configurationService.inspect('datasource.connections').userValue!; - - assert.strictEqual(editedConnections.length, _testConnections.length); - let editedConnection = editedConnections.find(con => con.id === 'server3-2'); - assert.ok(editedConnection); - assert.strictEqual(editedConnection!.groupId, 'test'); - }); - test('change group(parent) for connection', async () => { let newProfile: IConnectionProfile = { serverName: 'server3', @@ -903,7 +688,6 @@ suite('ConnectionConfig', () => { groupFullName: 'g3', groupId: 'g3', getOptionsKey: () => { return 'connectionId'; }, - serverCapabilities: undefined, matches: undefined!, providerName: 'MSSQL', options: {}, @@ -994,146 +778,4 @@ suite('ConnectionConfig', () => { assert.strictEqual(editGroups.length, testGroups.length); } }); - - test('isDuplicateEdit should return true if an edit profile matches an existing profile', async () => { - let originalProfile: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: () => { return 'connectionId'; }, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: {}, - saveProfile: true, - id: 'server3-2', - connectionName: undefined! - }; - let changedProfile: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'test', - groupId: 'test', - getOptionsKey: () => { return 'connectionId'; }, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: {}, - saveProfile: true, - id: 'server3-2', - connectionName: undefined! - }; - let existingProfile = ConnectionProfile.convertToProfileStore(capabilitiesService.object, { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'test', - groupId: 'test', - getOptionsKey: () => { return 'connectionId'; }, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: {}, - saveProfile: true, - id: 'server3', - connectionName: undefined! - }); - - let _testConnections = [...deepClone(testConnections), existingProfile, originalProfile]; - - let configurationService = new TestConfigurationService(); - configurationService.updateValue('datasource.connections', _testConnections, ConfigurationTarget.USER); - - let connectionProfile = new ConnectionProfile(capabilitiesService.object, changedProfile); - - let config = new ConnectionConfig(configurationService, capabilitiesService.object); - - let matcher = (a: IConnectionProfile, b: IConnectionProfile) => a.id === originalProfile.id; - let result = await config.isDuplicateEdit(connectionProfile, matcher); - - assert(result, 'Matcher did not find a match for identical edit'); - }); - - test('isDuplicateEdit should return false if an edit profile has different properties', async () => { - let originalProfile: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'test', - groupId: 'test', - getOptionsKey: () => { return 'connectionId'; }, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: {}, - saveProfile: true, - id: 'server3-2', - connectionName: undefined! - }; - let changedProfile: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: 'Integrated', - savePassword: true, - groupFullName: 'test', - groupId: 'test', - getOptionsKey: () => { return 'connectionId'; }, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: {}, - saveProfile: true, - id: 'server3-2', - connectionName: undefined! - }; - let existingProfile = ConnectionProfile.convertToProfileStore(capabilitiesService.object, { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'test', - groupId: 'test', - getOptionsKey: () => { return 'connectionId'; }, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: {}, - saveProfile: true, - id: 'server3', - connectionName: undefined! - }); - - let _testConnections = [...deepClone(testConnections), existingProfile, originalProfile]; - - let configurationService = new TestConfigurationService(); - configurationService.updateValue('datasource.connections', _testConnections, ConfigurationTarget.USER); - - let connectionProfile = new ConnectionProfile(capabilitiesService.object, changedProfile); - - let config = new ConnectionConfig(configurationService, capabilitiesService.object); - - let matcher = (a: IConnectionProfile, b: IConnectionProfile) => a.id === originalProfile.id; - let result = await config.isDuplicateEdit(connectionProfile, matcher); - - assert(!result, 'Matcher matched the profile even when it had a different property'); - }); }); diff --git a/src/sql/platform/connection/test/common/connectionProfile.test.ts b/src/sql/platform/connection/test/common/connectionProfile.test.ts index 090e845686..4797835ed2 100644 --- a/src/sql/platform/connection/test/common/connectionProfile.test.ts +++ b/src/sql/platform/connection/test/common/connectionProfile.test.ts @@ -26,7 +26,6 @@ suite('SQL ConnectionProfileInfo tests', () => { groupFullName: 'g2/g2-2', groupId: 'group id', getOptionsKey: undefined!, - serverCapabilities: undefined, matches: undefined!, providerName: mssqlProviderName, options: {}, @@ -172,8 +171,7 @@ suite('SQL ConnectionProfileInfo tests', () => { msSQLCapabilities = { providerId: mssqlProviderName, displayName: 'MSSQL', - connectionOptions: connectionProvider, - useFullOptions: true + connectionOptions: connectionProvider }; capabilitiesService = new TestCapabilitiesService(); capabilitiesService.capabilities[mssqlProviderName] = { connection: msSQLCapabilities }; @@ -236,7 +234,7 @@ suite('SQL ConnectionProfileInfo tests', () => { test('getOptionsKey should create a valid unique id', () => { let conn = new ConnectionProfile(capabilitiesService, iConnectionProfile); - let expectedId = 'providerName:MSSQL|connectionName:new name|databaseName:database|serverName:new server|userName:user|databaseDisplayName:database|groupId:group id'; + let expectedId = 'providerName:MSSQL|authenticationType:|databaseName:database|serverName:new server|userName:user|databaseDisplayName:database|group:group id'; let id = conn.getOptionsKey(); assert.strictEqual(id, expectedId); }); @@ -283,10 +281,4 @@ suite('SQL ConnectionProfileInfo tests', () => { test('an empty connection profile does not cause issues', () => { assert.doesNotThrow(() => new ConnectionProfile(capabilitiesService, {} as IConnectionProfile)); }); - - test('getOptionsKey should produce the same optionsKey after converting to IConnectionProfile', () => { - let conn = new ConnectionProfile(capabilitiesService, iConnectionProfile); - const myIConnectionProfile = conn.toIConnectionProfile(); - assert.equal(conn.getOptionsKey(), myIConnectionProfile.getOptionsKey()); - }); }); diff --git a/src/sql/platform/connection/test/common/connectionStore.test.ts b/src/sql/platform/connection/test/common/connectionStore.test.ts index 0b78249efa..cd23b4cdc2 100644 --- a/src/sql/platform/connection/test/common/connectionStore.test.ts +++ b/src/sql/platform/connection/test/common/connectionStore.test.ts @@ -32,7 +32,6 @@ suite('ConnectionStore', () => { groupId: '', groupFullName: '', getOptionsKey: undefined!, - serverCapabilities: undefined, matches: () => false, providerName: mssqlProviderName, options: {}, diff --git a/src/sql/platform/connection/test/common/providerConnectionInfo.test.ts b/src/sql/platform/connection/test/common/providerConnectionInfo.test.ts index e0c6e83857..74a2308eee 100644 --- a/src/sql/platform/connection/test/common/providerConnectionInfo.test.ts +++ b/src/sql/platform/connection/test/common/providerConnectionInfo.test.ts @@ -25,7 +25,6 @@ suite('SQL ProviderConnectionInfo tests', () => { groupFullName: 'g2/g2-2', groupId: undefined, getOptionsKey: undefined!, - serverCapabilities: undefined, matches: undefined!, providerName: mssqlProviderName, options: undefined!, @@ -34,6 +33,7 @@ suite('SQL ProviderConnectionInfo tests', () => { }; setup(() => { + let capabilities: azdata.DataProtocolServerCapabilities[] = []; let connectionProvider: azdata.ConnectionOption[] = [ { name: 'connectionName', @@ -125,8 +125,8 @@ suite('SQL ProviderConnectionInfo tests', () => { providerId: mssqlProviderName, displayName: 'MSSQL', connectionOptions: connectionProvider, - useFullOptions: true }; + capabilities.push(msSQLCapabilities); capabilitiesService = new TestCapabilitiesService(); capabilitiesService.capabilities[mssqlProviderName] = { connection: msSQLCapabilities }; }); @@ -230,37 +230,15 @@ suite('SQL ProviderConnectionInfo tests', () => { }); test('getOptionsKey should create a valid unique id', () => { - // Test the new option key format let conn = new ProviderConnectionInfo(capabilitiesService, connectionProfile); - let expectedId = 'providerName:MSSQL|connectionName:name|databaseName:database|serverName:new server|userName:user'; - let id = conn.getOptionsKey(); - assert.strictEqual(id, expectedId); - - // Test for original options key (used for retrieving passwords and as a fallback for unsupported providers) - // **IMPORTANT** The original format option key should NEVER change without thorough review and consideration of side effects. This version of the key controls + // **IMPORTANT** This should NEVER change without thorough review and consideration of side effects. This key controls // things like how passwords are saved, which means if its changed then serious side effects will occur. - expectedId = 'providerName:MSSQL|authenticationType:|databaseName:database|serverName:new server|userName:user'; - id = conn.getOptionsKey(true); - assert.strictEqual(id, expectedId); - }); - - test('getOptionsKey should return original formatted ID if useFullOptions is not supported', () => { - // Test the new option key format - let originalCapabilitiesConnection = capabilitiesService.capabilities[mssqlProviderName].connection; - originalCapabilitiesConnection.useFullOptions = false; - let newCapabilitiesService = new TestCapabilitiesService(); - newCapabilitiesService.capabilities[mssqlProviderName] = { connection: originalCapabilitiesConnection } - let conn = new ProviderConnectionInfo(newCapabilitiesService, connectionProfile); let expectedId = 'providerName:MSSQL|authenticationType:|databaseName:database|serverName:new server|userName:user'; let id = conn.getOptionsKey(); assert.strictEqual(id, expectedId); - - // Should be the same when getOriginalOptions is true. - id = conn.getOptionsKey(true); - assert.strictEqual(id, expectedId); }); - test('getOptionsKey should create different keys based on optional options', () => { + test('getOptionsKey should create the same ID regardless of optional options', () => { const conn1 = new ProviderConnectionInfo(capabilitiesService, connectionProfile); let id1 = conn1.getOptionsKey(); @@ -270,19 +248,6 @@ suite('SQL ProviderConnectionInfo tests', () => { const conn2 = new ProviderConnectionInfo(capabilitiesService, connectionProfile); const id2 = conn2.getOptionsKey(); - assert.notEqual(id1, id2); - }); - - test('getOptionsKey should have the same key if original options is used', () => { - const conn1 = new ProviderConnectionInfo(capabilitiesService, connectionProfile); - let id1 = conn1.getOptionsKey(true); - - connectionProfile.options = { - 'encrypt': true - }; - const conn2 = new ProviderConnectionInfo(capabilitiesService, connectionProfile); - const id2 = conn2.getOptionsKey(true); - assert.strictEqual(id1, id2); }); @@ -293,6 +258,16 @@ suite('SQL ProviderConnectionInfo tests', () => { assert.notStrictEqual(conn.getOptionsKey(), conn2.getOptionsKey()); }); + test('titleParts should return server, database and auth type as first items', () => { + let conn = new ProviderConnectionInfo(capabilitiesService, connectionProfile); + let titleParts = conn.titleParts; + assert.strictEqual(titleParts.length, 4); + assert.strictEqual(titleParts[0], connectionProfile.serverName); + assert.strictEqual(titleParts[1], connectionProfile.databaseName); + assert.strictEqual(titleParts[2], connectionProfile.authenticationType); + assert.strictEqual(titleParts[3], connectionProfile.userName); + }); + test('getProviderFromOptionsKey should return the provider name from the options key successfully', () => { let optionsKey = `providerName:${mssqlProviderName}|authenticationType:|databaseName:database|serverName:new server|userName:user`; let actual = ProviderConnectionInfo.getProviderFromOptionsKey(optionsKey); diff --git a/src/sql/platform/connection/test/common/testConnectionManagementService.ts b/src/sql/platform/connection/test/common/testConnectionManagementService.ts index f5445bbb99..6a6f46057e 100644 --- a/src/sql/platform/connection/test/common/testConnectionManagementService.ts +++ b/src/sql/platform/connection/test/common/testConnectionManagementService.ts @@ -354,10 +354,6 @@ export class TestConnectionManagementService implements IConnectionManagementSer return undefined; } - getEditorConnectionProfileTitle(profile: IConnectionProfile, getNonDefaultsOnly?: boolean): string { - return undefined!; - } - openCustomErrorDialog(options: azdata.window.IErrorDialogOptions): Promise { return undefined; } diff --git a/src/sql/platform/connection/test/node/connectionStatusManager.test.ts b/src/sql/platform/connection/test/node/connectionStatusManager.test.ts index e75d991ee2..b49f676b27 100644 --- a/src/sql/platform/connection/test/node/connectionStatusManager.test.ts +++ b/src/sql/platform/connection/test/node/connectionStatusManager.test.ts @@ -27,7 +27,6 @@ let connectionProfile: IConnectionProfile = { groupFullName: 'g2/g2-2', groupId: 'group id', getOptionsKey: () => 'connection1', - serverCapabilities: undefined, matches: undefined!, providerName: mssqlProviderName, options: {}, @@ -45,7 +44,6 @@ let editorConnectionProfile: IConnectionProfile = { groupFullName: 'g2/g2-2', groupId: 'group id', getOptionsKey: () => 'connection2', - serverCapabilities: undefined, matches: undefined!, providerName: mssqlProviderName, options: {}, @@ -63,7 +61,6 @@ let connectionProfileWithoutDbName: IConnectionProfile = { groupFullName: 'g2/g2-2', groupId: 'group id', getOptionsKey: () => 'connection1', - serverCapabilities: undefined, matches: undefined!, providerName: mssqlProviderName, options: {}, diff --git a/src/sql/workbench/api/browser/mainThreadConnectionManagement.ts b/src/sql/workbench/api/browser/mainThreadConnectionManagement.ts index 6902686066..2e0e371439 100644 --- a/src/sql/workbench/api/browser/mainThreadConnectionManagement.ts +++ b/src/sql/workbench/api/browser/mainThreadConnectionManagement.ts @@ -185,11 +185,6 @@ export class MainThreadConnectionManagement extends Disposable implements MainTh return this._connectionManagementService.openChangePasswordDialog(convertedProfile); } - public $getEditorConnectionProfileTitle(profile: IConnectionProfile, getNonDefaultsOnly?: boolean): Thenable { - // Need to have access to getOptionsKey, so recreate profile from details. - return Promise.resolve(this._connectionManagementService.getEditorConnectionProfileTitle(profile, getNonDefaultsOnly)); - } - public async $listDatabases(connectionId: string): Promise { let connectionUri = await this.$getUriForConnection(connectionId); let result = await this._connectionManagementService.listDatabases(connectionUri); diff --git a/src/sql/workbench/api/common/extHostConnectionManagement.ts b/src/sql/workbench/api/common/extHostConnectionManagement.ts index a171d71ee5..56f27dbc8f 100644 --- a/src/sql/workbench/api/common/extHostConnectionManagement.ts +++ b/src/sql/workbench/api/common/extHostConnectionManagement.ts @@ -78,10 +78,6 @@ export class ExtHostConnectionManagement extends ExtHostConnectionManagementShap return this._proxy.$openChangePasswordDialog(profile); } - public $getEditorConnectionProfileTitle(profile: azdata.IConnectionProfile, getNonDefaultsOnly?: boolean): Thenable { - return this._proxy.$getEditorConnectionProfileTitle(profile, getNonDefaultsOnly); - } - public $listDatabases(connectionId: string): Thenable { return this._proxy.$listDatabases(connectionId); } diff --git a/src/sql/workbench/api/common/sqlExtHost.api.impl.ts b/src/sql/workbench/api/common/sqlExtHost.api.impl.ts index 4d6dc20b1f..a1a9b8fa26 100644 --- a/src/sql/workbench/api/common/sqlExtHost.api.impl.ts +++ b/src/sql/workbench/api/common/sqlExtHost.api.impl.ts @@ -141,9 +141,6 @@ export function createAdsApiFactory(accessor: ServicesAccessor): IAdsExtensionAp openChangePasswordDialog(profile: azdata.IConnectionProfile): Thenable { return extHostConnectionManagement.$openChangePasswordDialog(profile); }, - getEditorConnectionProfileTitle(profile: azdata.IConnectionProfile, getNonDefaultsOnly?: boolean): Thenable { - return extHostConnectionManagement.$getEditorConnectionProfileTitle(profile, getNonDefaultsOnly); - }, listDatabases(connectionId: string): Thenable { return extHostConnectionManagement.$listDatabases(connectionId); }, diff --git a/src/sql/workbench/api/common/sqlExtHost.protocol.ts b/src/sql/workbench/api/common/sqlExtHost.protocol.ts index c501aaab89..227bfc4636 100644 --- a/src/sql/workbench/api/common/sqlExtHost.protocol.ts +++ b/src/sql/workbench/api/common/sqlExtHost.protocol.ts @@ -724,7 +724,6 @@ export interface MainThreadConnectionManagementShape extends IDisposable { $getServerInfo(connectedId: string): Thenable; $openConnectionDialog(providers: string[], initialConnectionProfile?: azdata.IConnectionProfile, connectionCompletionOptions?: azdata.IConnectionCompletionOptions): Thenable; $openChangePasswordDialog(profile: azdata.IConnectionProfile): Thenable; - $getEditorConnectionProfileTitle(profile: azdata.IConnectionProfile, getNonDefaultsOnly?: boolean): Thenable; $listDatabases(connectionId: string): Thenable; $getConnectionString(connectionId: string, includePassword: boolean): Thenable; $getUriForConnection(connectionId: string): Thenable; diff --git a/src/sql/workbench/common/editor/query/queryEditorInput.ts b/src/sql/workbench/common/editor/query/queryEditorInput.ts index e5943e8fa9..721fbcc055 100644 --- a/src/sql/workbench/common/editor/query/queryEditorInput.ts +++ b/src/sql/workbench/common/editor/query/queryEditorInput.ts @@ -243,18 +243,11 @@ export abstract class QueryEditorInput extends EditorInput implements IConnectab title = this._description + ' '; } if (profile) { - let fullTitleText = this.connectionManagementService.getEditorConnectionProfileTitle(profile); - if (fullTitleText.length !== 0) { - title += fullTitleText; - } - else { - title += `${profile.serverName}`; - if (profile.databaseName) { - title += `.${profile.databaseName}`; - } - title += ` (${profile.userName || profile.authenticationType})`; - title += profile.getOptionsKey(); + title += `${profile.serverName}`; + if (profile.databaseName) { + title += `.${profile.databaseName}`; } + title += ` (${profile.userName || profile.authenticationType})`; } else { title += localize('disconnected', "disconnected"); } diff --git a/src/sql/workbench/contrib/connection/browser/connectionStatus.ts b/src/sql/workbench/contrib/connection/browser/connectionStatus.ts index 8588bf3cc6..6881ceb1f7 100644 --- a/src/sql/workbench/contrib/connection/browser/connectionStatus.ts +++ b/src/sql/workbench/contrib/connection/browser/connectionStatus.ts @@ -68,38 +68,23 @@ export class ConnectionStatusbarItem extends Disposable implements IWorkbenchCon // Set connection info to connection status bar private _setConnectionText(connectionProfile: IConnectionProfile): void { - let text: string = undefined; - let fullEditorText: string = this.connectionManagementService.getEditorConnectionProfileTitle(connectionProfile); - if (fullEditorText.length === 0) { - text = connectionProfile.serverName; - if (text) { - if (connectionProfile.databaseName && connectionProfile.databaseName !== '') { - text = text + ' : ' + connectionProfile.databaseName; - } else { - text = text + ' : ' + ''; - } + let text: string = connectionProfile.serverName; + if (text) { + if (connectionProfile.databaseName && connectionProfile.databaseName !== '') { + text = text + ' : ' + connectionProfile.databaseName; + } else { + text = text + ' : ' + ''; } } - else { - text = fullEditorText; + + let tooltip: string = + 'Server: ' + connectionProfile.serverName + '\r\n' + + 'Database: ' + (connectionProfile.databaseName ? connectionProfile.databaseName : '') + '\r\n'; + + if (connectionProfile.userName && connectionProfile.userName !== '') { + tooltip = tooltip + 'Login: ' + connectionProfile.userName + '\r\n'; } - let tooltip: string = undefined; - - if (!fullEditorText) { - tooltip = 'Server: ' + connectionProfile.serverName + '\r\n' + - 'Database: ' + (connectionProfile.databaseName ? connectionProfile.databaseName : '') + '\r\n'; - - if (connectionProfile.userName && connectionProfile.userName !== '') { - tooltip = tooltip + 'Login: ' + connectionProfile.userName + '\r\n'; - } - } - else { - // It is difficult to have every possible option that is different displayed as above with consistent naming, therefore the tooltip will show the full string. - tooltip = fullEditorText; - } - - this.statusItem.update({ name: this.name, text: text, diff --git a/src/sql/workbench/contrib/notebook/browser/notebookActions.ts b/src/sql/workbench/contrib/notebook/browser/notebookActions.ts index 0bf036e58a..fbce065e33 100644 --- a/src/sql/workbench/contrib/notebook/browser/notebookActions.ts +++ b/src/sql/workbench/contrib/notebook/browser/notebookActions.ts @@ -731,10 +731,7 @@ export class AttachToDropdown extends SelectBox { } else { let connections: string[] = []; if (model.context && model.context.title && (connProviderIds.includes(this.model.context.providerName))) { - let textResult = model.context.title; - let fullTitleText = this._connectionManagementService.getEditorConnectionProfileTitle(model.context); - textResult = fullTitleText.length !== 0 ? fullTitleText : textResult; - connections.push(textResult); + connections.push(model.context.title); } else if (this._configurationService.getValue(saveConnectionNameConfigName) && model.savedConnectionName) { connections.push(model.savedConnectionName); } else { diff --git a/src/sql/workbench/contrib/objectExplorer/browser/serverTreeView.ts b/src/sql/workbench/contrib/objectExplorer/browser/serverTreeView.ts index a56e586fdd..e746a1ab57 100644 --- a/src/sql/workbench/contrib/objectExplorer/browser/serverTreeView.ts +++ b/src/sql/workbench/contrib/objectExplorer/browser/serverTreeView.ts @@ -121,7 +121,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView { // get the full ConnectionProfiles with the server info updated properly const treeInput = TreeUpdateUtils.getTreeInput(this._connectionManagementService)!; await this._tree.setInput(treeInput); - await this.refreshConnectionTreeTitles(); this._treeSelectionHandler.onTreeActionStateChange(false); } else { if (this._connectionManagementService.hasRegisteredServers()) { @@ -269,7 +268,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView { if (connectionParentGroup) { connectionParentGroup.addOrReplaceConnection(newConnection); await this._tree.updateChildren(connectionParentGroup); - await this.refreshConnectionTreeTitles(); await this._tree.revealSelectFocusElement(newConnection); await this._tree.expand(newConnection); } @@ -284,7 +282,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView { await this._tree.rerender(connectionInTree); await this._tree.revealSelectFocusElement(connectionInTree); await this._tree.updateChildren(connectionInTree); - await this.refreshConnectionTreeTitles(); await this._tree.expand(connectionInTree); } } @@ -297,7 +294,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView { if (parentGroup) { parentGroup.removeConnections([e]); await this._tree.updateChildren(parentGroup); - await this.refreshConnectionTreeTitles(); await this._tree.revealSelectFocusElement(parentGroup); } } @@ -315,14 +311,12 @@ export class ServerTreeView extends Disposable implements IServerTreeView { const newProfileParent = this._tree.getElementById(e.profile.groupId); newProfileParent.addOrReplaceConnection(e.profile); await this._tree.updateChildren(newProfileParent); - await this.refreshConnectionTreeTitles(); await this._tree.revealSelectFocusElement(e.profile); await this._tree.expand(e.profile); } else { // If the profile was not moved to a different group then just update the profile in the group. oldProfileParent.replaceConnection(e.profile, e.oldProfileId); await this._tree.updateChildren(oldProfileParent) - await this.refreshConnectionTreeTitles(); await this._tree.revealSelectFocusElement(e.profile); await this._tree.expand(e.profile); } @@ -344,7 +338,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView { newParent.addOrReplaceConnection(movedConnection); await this._tree.updateChildren(newParent); } - await this.refreshConnectionTreeTitles(); const newConnection = this._tree.getElementById(movedConnection.id); if (newConnection) { await this._tree.revealSelectFocusElement(newConnection); @@ -359,7 +352,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView { const parent = this._tree.getElementById(e.parentId); parent.children = parent.children.filter(c => c.id !== e.id); await this._tree.updateChildren(parent); - await this.refreshConnectionTreeTitles(); await this._tree.revealSelectFocusElement(parent); } })); @@ -382,7 +374,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView { e.parent = parent; e.parentId = parent.id; await this._tree.updateChildren(parent); - await this.refreshConnectionTreeTitles(); await this._tree.revealSelectFocusElement(e); } })); @@ -393,7 +384,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView { if (newParent) { newParent.children[newParent.children.findIndex(c => c.id === e.id)] = e; await this._tree.updateChildren(newParent); - await this.refreshConnectionTreeTitles(); await this._tree.revealSelectFocusElement(e); } } @@ -412,7 +402,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView { (movedGroup).parent = newParent; (movedGroup).parentId = newParent.id; await this._tree.updateChildren(newParent); - await this.refreshConnectionTreeTitles(); await this._tree.revealSelectFocusElement(movedGroup); // Expanding the previously expanded children of the moved group after the move. this._tree.expandElements(profileExpandedState); @@ -652,7 +641,6 @@ export class ServerTreeView extends Disposable implements IServerTreeView { if (this._tree instanceof AsyncServerTree) { await this._tree.setInput(treeInput!); await this._tree.updateChildren(treeInput!); - await this.refreshConnectionTreeTitles(); return; } await this._tree.setInput(treeInput!); @@ -913,11 +901,4 @@ export class ServerTreeView extends Disposable implements IServerTreeView { } return actionContext; } - - private async refreshConnectionTreeTitles(): Promise { - let treeInput = TreeUpdateUtils.getTreeInput(this._connectionManagementService); - let treeArray = TreeUpdateUtils.alterTreeChildrenTitles([treeInput]); - treeInput = treeArray[0]; - await this._tree!.setInput(treeInput); - } } diff --git a/src/sql/workbench/services/connection/browser/connectionManagementService.ts b/src/sql/workbench/services/connection/browser/connectionManagementService.ts index 9e36ad6af7..11eec6dfb6 100644 --- a/src/sql/workbench/services/connection/browser/connectionManagementService.ts +++ b/src/sql/workbench/services/connection/browser/connectionManagementService.ts @@ -539,22 +539,6 @@ export class ConnectionManagementService extends Disposable implements IConnecti let isEdit = options?.params?.isEditConnection ?? false; - let matcher: interfaces.ProfileMatcher; - if (isEdit) { - matcher = (a: interfaces.IConnectionProfile, b: interfaces.IConnectionProfile) => a.id === options.params.oldProfileId; - - //Check to make sure the edits are not identical to another connection. - await this._connectionStore.isDuplicateEdit(connection, matcher).then(result => { - if (result) { - // Must get connection group name here as it may not always be initialized and causes problems when deleting when included with options. - this._logService.error(`Profile edit for '${connection.id}' exactly matches an existing profile with data: '${ConnectionProfile.getDisplayOptionsKey(connection.getOptionsKey())}'`); - throw new Error(`Cannot save profile, the selected connection options are identical to an existing profile with details: \n - ${ConnectionProfile.getDisplayOptionsKey(connection.getOptionsKey())}${(connection.groupFullName !== undefined && connection.groupFullName !== '' && connection.groupFullName !== '/') ? - ConnectionProfile.displayIdSeparator + 'groupName' + ConnectionProfile.displayNameValueSeparator + connection.groupFullName : ''}`); - } - }); - } - if (!uri) { uri = Utils.generateUri(connection); } @@ -602,6 +586,11 @@ export class ConnectionManagementService extends Disposable implements IConnecti callbacks.onConnectSuccess(options.params, connectionResult.connectionProfile); } if (options.saveTheConnection || isEdit) { + let matcher: interfaces.ProfileMatcher; + if (isEdit) { + matcher = (a: interfaces.IConnectionProfile, b: interfaces.IConnectionProfile) => a.id === options.params.oldProfileId; + } + await this.saveToSettings(uri, connection, matcher).then(value => { this._onAddConnectionProfile.fire(connection); if (isEdit) { @@ -709,20 +698,6 @@ export class ConnectionManagementService extends Disposable implements IConnecti return result; } - public getEditorConnectionProfileTitle(profile: interfaces.IConnectionProfile, getNonDefaultsOnly?: boolean): string { - let result = ''; - if (profile) { - let tempProfile = new ConnectionProfile(this._capabilitiesService, profile); - if (!getNonDefaultsOnly) { - result = tempProfile.getEditorFullTitleWithOptions(); - } - else { - result = tempProfile.getNonDefaultOptionsString(); - } - } - return result; - } - private doActionsAfterConnectionComplete(uri: string, options: IConnectionCompletionOptions): void { let connectionManagementInfo = this._connectionStatusManager.findConnection(uri); if (!connectionManagementInfo) { @@ -1295,7 +1270,7 @@ export class ConnectionManagementService extends Disposable implements IConnecti this._connectionGlobalStatus.setStatusToConnected(info.connectionSummary); } - const connectionUniqueId = connection.connectionProfile.getOptionsKey(); + const connectionUniqueId = connection.connectionProfile.getConnectionInfoId(); if (info.isSupportedVersion === false && this._connectionsGotUnsupportedVersionWarning.indexOf(connectionUniqueId) === -1 && this._configurationService.getValue('connection.showUnsupportedServerVersionWarning')) { diff --git a/src/sql/workbench/services/connection/test/browser/connectionManagementService.test.ts b/src/sql/workbench/services/connection/test/browser/connectionManagementService.test.ts index d3b97c466c..3da07f667f 100644 --- a/src/sql/workbench/services/connection/test/browser/connectionManagementService.test.ts +++ b/src/sql/workbench/services/connection/test/browser/connectionManagementService.test.ts @@ -16,7 +16,7 @@ import * as Constants from 'sql/platform/connection/common/constants'; import * as Utils from 'sql/platform/connection/common/utils'; import { IHandleFirewallRuleResult } from 'sql/workbench/services/resourceProvider/common/resourceProviderService'; -import { IConnectionProfile, ServiceOptionType } from 'sql/platform/connection/common/interfaces'; +import { IConnectionProfile } from 'sql/platform/connection/common/interfaces'; import { TestCapabilitiesService } from 'sql/platform/capabilities/test/common/testCapabilitiesService'; import { TestConnectionProvider } from 'sql/platform/connection/test/common/testConnectionProvider'; import { TestResourceProvider } from 'sql/workbench/services/resourceProvider/test/common/testResourceProviderService'; @@ -68,7 +68,6 @@ suite('SQL ConnectionManagementService tests', () => { groupFullName: 'g2/g2-2', groupId: 'group id', getOptionsKey: () => { return 'connectionId'; }, - serverCapabilities: undefined, matches: undefined, providerName: 'MSSQL', options: {}, @@ -515,7 +514,7 @@ suite('SQL ConnectionManagementService tests', () => { assert.ok(called, 'expected changeGroupIdForConnectionGroup to be called on ConnectionStore'); }); - test('findExistingConnection should find connection for connectionProfile with same basic info', async () => { + test('findExistingConnection should find connection for connectionProfile with same info', async () => { let profile = Object.assign({}, connectionProfile); let uri1 = 'connection:connectionId'; let options: IConnectionCompletionOptions = { @@ -1014,15 +1013,7 @@ suite('SQL ConnectionManagementService tests', () => { showFirewallRuleOnError: true }; - let originalProfileKey = ''; - connectionStore.setup(x => x.isDuplicateEdit(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((inputProfile, matcher) => { - let newProfile = ConnectionProfile.fromIConnectionProfile(new TestCapabilitiesService(), inputProfile); - let result = newProfile.getOptionsKey() === originalProfileKey; - return Promise.resolve(result); - }); await connect(uri1, options, true, profile); - let originalProfile = ConnectionProfile.fromIConnectionProfile(new TestCapabilitiesService(), connectionProfile); - originalProfileKey = originalProfile.getOptionsKey(); let newProfile = Object.assign({}, connectionProfile); newProfile.connectionName = newname; options.params.isEditConnection = true; @@ -1056,8 +1047,6 @@ suite('SQL ConnectionManagementService tests', () => { showFirewallRuleOnError: true }; - // In an actual edit situation, the profile options would be different for different URIs, as a placeholder, we check the test uris instead here. - connectionStore.setup(x => x.isDuplicateEdit(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve(uri1 === uri2)); await connect(uri1, options, true, profile); options.params.isEditConnection = true; await connect(uri2, options, true, profile); @@ -1066,51 +1055,6 @@ suite('SQL ConnectionManagementService tests', () => { assert.strictEqual(uri1info.connectionProfile.id, uri2info.connectionProfile.id); }); - test('Edit Connection - Connecting with an already connected profile via edit should throw an error', async () => { - let uri1 = 'test_uri1'; - let profile = Object.assign({}, connectionProfile); - profile.id = '0451'; - let options: IConnectionCompletionOptions = { - params: { - connectionType: ConnectionType.editor, - input: { - onConnectSuccess: undefined, - onConnectReject: undefined, - onConnectStart: undefined, - onDisconnect: undefined, - onConnectCanceled: undefined, - uri: uri1 - }, - queryRange: undefined, - runQueryOnCompletion: RunQueryOnConnectionMode.none, - isEditConnection: true - }, - saveTheConnection: true, - showDashboard: false, - showConnectionDialogOnError: true, - showFirewallRuleOnError: true - }; - - let originalProfileKey = ''; - connectionStore.setup(x => x.isDuplicateEdit(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns((inputProfile, matcher) => { - let newProfile = ConnectionProfile.fromIConnectionProfile(new TestCapabilitiesService(), inputProfile); - let result = newProfile.getOptionsKey() === originalProfileKey; - return Promise.resolve(result) - }); - - await connect(uri1, options, true, profile); - let originalProfile = ConnectionProfile.fromIConnectionProfile(new TestCapabilitiesService(), connectionProfile); - originalProfileKey = originalProfile.getOptionsKey(); - let newProfile = Object.assign({}, connectionProfile); - options.params.isEditConnection = true; - try { - await connect(uri1, options, true, newProfile); - assert.fail; - } - catch { - } - }); - test('failed firewall rule should open the firewall rule dialog', async () => { handleFirewallRuleResult.canHandleFirewallRule = true; @@ -2048,118 +1992,6 @@ test('clearRecentConnection and ConnectionsList should call connectionStore func assert(called); }); -test('getEditorConnectionProfileTitle should return a correctly formatted title for a connection profile', () => { - let profile: IConnectionProfile = { - connectionName: 'new name', - serverName: 'new server', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: Constants.AuthenticationType.Integrated, - savePassword: true, - groupFullName: 'g2/g2-2', - groupId: 'group id', - getOptionsKey: () => { return ''; }, - serverCapabilities: undefined, - matches: undefined, - providerName: 'MSSQL', - options: {}, - saveProfile: true, - id: undefined - }; - - let capabilitiesService = new TestCapabilitiesService(); - const testOption1 = { - name: 'testOption1', - displayName: 'testOption1', - description: 'test description', - groupName: 'test group name', - valueType: ServiceOptionType.string, - specialValueType: undefined, - defaultValue: '', - categoryValues: undefined, - isIdentity: false, - isRequired: false - }; - - const testOption2 = { - name: 'testOption2', - displayName: 'testOption2', - description: 'test description', - groupName: 'test group name', - valueType: ServiceOptionType.number, - specialValueType: undefined, - defaultValue: '10', - categoryValues: undefined, - isIdentity: false, - isRequired: false - }; - - const testOption3 = { - name: 'testOption3', - displayName: 'testOption3', - description: 'test description', - groupName: 'test group name', - valueType: ServiceOptionType.string, - specialValueType: undefined, - defaultValue: 'default', - categoryValues: undefined, - isIdentity: false, - isRequired: false - }; - - profile.options['testOption1'] = 'test value'; - profile.options['testOption2'] = '50'; - profile.options['testOption3'] = 'default'; - - let mainProvider = capabilitiesService.capabilities['MSSQL']; - let mainProperties = mainProvider.connection; - let mainOptions = mainProperties.connectionOptions; - - mainOptions.push(testOption1); - mainOptions.push(testOption2); - mainOptions.push(testOption3); - - mainProperties.connectionOptions = mainOptions; - mainProvider.connection = mainProperties; - - capabilitiesService.capabilities['MSSQL'] = mainProvider; - - const connectionStoreMock = TypeMoq.Mock.ofType(ConnectionStore, TypeMoq.MockBehavior.Loose, new TestStorageService()); - const testInstantiationService = new TestInstantiationService(); - testInstantiationService.stub(IStorageService, new TestStorageService()); - sinon.stub(testInstantiationService, 'createInstance').withArgs(ConnectionStore).returns(connectionStoreMock.object); - const connectionManagementService = new ConnectionManagementService(undefined, testInstantiationService, undefined, undefined, undefined, capabilitiesService, undefined, undefined, undefined, new TestErrorDiagnosticsService(), undefined, undefined, undefined, undefined, getBasicExtensionService(), undefined, undefined, undefined); - - // We should expect that non default options are returned when we try to get the nonDefaultOptions string. - let result = connectionManagementService.getEditorConnectionProfileTitle(profile, true); - let expectedNonDefaultOption = ' (testOption1=test value; testOption2=50)'; - assert.strictEqual(result, expectedNonDefaultOption, `Profile non default options contained incorrect options`); - - // We should expect that the string contains the connection name and the server info (with all non default options appended). - let generatedProfile = ConnectionProfile.fromIConnectionProfile(capabilitiesService, profile); - let profileServerInfo = generatedProfile.serverInfo; - result = connectionManagementService.getEditorConnectionProfileTitle(profile); - - assert.strictEqual(result, `${profile.connectionName}: ${profileServerInfo}`, `getEditorConnectionProfileTitle does not return the correct string for ${profile.connectionName}`); - - // We should expect that the string contains only the server info (with non default options) if there is no connection name. - profile.connectionName = undefined; - - result = connectionManagementService.getEditorConnectionProfileTitle(profile); - - assert.strictEqual(result, `${profileServerInfo}`, `getEditorConnectionProfileTitle included a connection name when it shouldn't`); - - // We should expect that the string only contains the server info without any non default options if no such options exist. - profile.options['testOption1'] = undefined; - profile.options['testOption2'] = undefined; - profile.options['testOption3'] = undefined; - - result = connectionManagementService.getEditorConnectionProfileTitle(profile); - - assert.notEqual(result, `${profileServerInfo}`, `getEditorConnectionProfileTitle included non default connection options when it shouldn't`); -}); - export function createConnectionProfile(id: string, password?: string): ConnectionProfile { const capabilitiesService = new TestCapabilitiesService(); return new ConnectionProfile(capabilitiesService, { diff --git a/src/sql/workbench/services/insights/test/browser/insightsDialogController.test.ts b/src/sql/workbench/services/insights/test/browser/insightsDialogController.test.ts index 61902fb317..f8294c9df0 100644 --- a/src/sql/workbench/services/insights/test/browser/insightsDialogController.test.ts +++ b/src/sql/workbench/services/insights/test/browser/insightsDialogController.test.ts @@ -75,7 +75,6 @@ suite('Insights Dialog Controller Tests', () => { groupFullName: '', groupId: '', getOptionsKey: () => '', - serverCapabilities: undefined, matches: undefined, providerName: '', saveProfile: true, diff --git a/src/sql/workbench/services/objectExplorer/browser/treeUpdateUtils.ts b/src/sql/workbench/services/objectExplorer/browser/treeUpdateUtils.ts index 9468fc5779..23d1c167f1 100644 --- a/src/sql/workbench/services/objectExplorer/browser/treeUpdateUtils.ts +++ b/src/sql/workbench/services/objectExplorer/browser/treeUpdateUtils.ts @@ -76,8 +76,6 @@ export class TreeUpdateUtils { } const previousTreeInput = tree.getInput(); if (treeInput) { - let treeArray = TreeUpdateUtils.alterTreeChildrenTitles([treeInput]); - treeInput = treeArray[0]; await tree.setInput(treeInput); } if (previousTreeInput instanceof Disposable) { @@ -95,29 +93,13 @@ export class TreeUpdateUtils { } } - /** - * Calls alterConnectionTitles on all levels of the Object Explorer Tree - * so that profiles in connection groups can have distinguishing titles too. - */ - public static alterTreeChildrenTitles(inputGroups: ConnectionProfileGroup[]): ConnectionProfileGroup[] { - inputGroups.forEach(group => { - group.children = this.alterTreeChildrenTitles(group.children); - let connections = group.connections; - TreeUpdateUtils.alterConnectionTitles(connections); - group.connections = connections; - }); - return inputGroups; - } - /** * Set input for the registered servers tree. */ public static async registeredServerUpdate(tree: ITree | AsyncServerTree, connectionManagementService: IConnectionManagementService, elementToSelect?: any): Promise { if (tree instanceof AsyncServerTree) { - let treeInput = TreeUpdateUtils.getTreeInput(connectionManagementService); + const treeInput = TreeUpdateUtils.getTreeInput(connectionManagementService); if (treeInput) { - let treeArray = TreeUpdateUtils.alterTreeChildrenTitles([treeInput]); - treeInput = treeArray[0]; await tree.setInput(treeInput); } tree.rerender(); @@ -146,8 +128,6 @@ export class TreeUpdateUtils { let treeInput = TreeUpdateUtils.getTreeInput(connectionManagementService); if (treeInput) { - let treeArray = TreeUpdateUtils.alterTreeChildrenTitles([treeInput]); - treeInput = treeArray[0]; const originalInput = tree.getInput(); if (treeInput !== originalInput) { return tree.setInput(treeInput).then(async () => { @@ -390,85 +370,4 @@ export class TreeUpdateUtils { } return connectionProfile; } - - /** - * Change the connection title to display only the unique properties among profiles. - */ - private static alterConnectionTitles(inputList: ConnectionProfile[]): void { - let profileListMap = new Map(); - - // Map the indices of profiles that share the same connection name. - for (let i = 0; i < inputList.length; i++) { - // do not add if the profile is still loading as that will result in erroneous entries. - if (inputList[i].serverCapabilities && inputList[i].hasLoaded()) { - let titleKey = inputList[i].getOriginalTitle(); - if (profileListMap.has(titleKey)) { - let profilesForKey = profileListMap.get(titleKey); - profilesForKey.push(i); - profileListMap.set(titleKey, profilesForKey); - } - else { - profileListMap.set(titleKey, [i]); - } - } - } - - profileListMap.forEach(function (indexes, titleString) { - if (profileListMap.get(titleString)?.length > 1) { - let combinedOptions = []; - let needSpecial = false; - if (titleString === inputList[indexes[0]].connectionName) { - // check for potential connections with the same name but technically different connections. - let listOfDuplicates = indexes.filter(item => inputList[item].getOptionsKey() !== inputList[indexes[0]].getOptionsKey()); - if (listOfDuplicates.length > 0) { - // if we do find duplicates, we will need to include the special properties. - needSpecial = true; - } - } - indexes.forEach((indexValue) => { - // Add all possible options across all profiles with the same title to an option list. - let valueOptions = inputList[indexValue].getConnectionOptionsList(needSpecial, false); - combinedOptions = combinedOptions.concat(valueOptions.filter(item => combinedOptions.indexOf(item) < 0)); - }); - - // Generate list of non default option keys for each profile that shares the same basic connection name. - let optionKeyMap = new Map(); - let optionValueOccuranceMap = new Map(); - for (let p = 0; p < indexes.length; p++) { - optionKeyMap.set(inputList[indexes[p]], []); - for (let i = 0; i < combinedOptions.length; i++) { - // See if the option is not default for the inputList profile or is. - if (inputList[indexes[p]].getConnectionOptionsList(needSpecial, true).indexOf(combinedOptions[i]) > -1) { - let optionValue = inputList[indexes[p]].getOptionValue(combinedOptions[i].name); - let currentArray = optionKeyMap.get(inputList[indexes[p]]); - let valueString = combinedOptions[i].name + ConnectionProfile.displayNameValueSeparator + optionValue; - if (!optionValueOccuranceMap.get(valueString)) { - optionValueOccuranceMap.set(valueString, 0); - } - optionValueOccuranceMap.set(valueString, optionValueOccuranceMap.get(valueString) + 1); - currentArray.push(valueString); - optionKeyMap.set(inputList[indexes[p]], currentArray); - } - } - } - - // Filter out options that are found in ALL the entries with the same basic name. - optionValueOccuranceMap.forEach(function (count, optionValue) { - optionKeyMap.forEach(function (connOptionValues, profile) { - if (count === optionKeyMap.size) { - optionKeyMap.set(profile, connOptionValues.filter(value => value !== optionValue)); - } - }); - }); - - // Generate the final unique connection string for each profile in the list. - optionKeyMap.forEach(function (connOptionValues, profile) { - let uniqueOptionString = connOptionValues.join(ConnectionProfile.displayIdSeparator); - if (uniqueOptionString.length > 0) { - profile.title += ' (' + uniqueOptionString + ')'; - } - }); - } - }); - } } diff --git a/src/sql/workbench/services/objectExplorer/test/browser/asyncServerTreeDragAndDrop.test.ts b/src/sql/workbench/services/objectExplorer/test/browser/asyncServerTreeDragAndDrop.test.ts index 965e76a24d..dd36db9005 100644 --- a/src/sql/workbench/services/objectExplorer/test/browser/asyncServerTreeDragAndDrop.test.ts +++ b/src/sql/workbench/services/objectExplorer/test/browser/asyncServerTreeDragAndDrop.test.ts @@ -36,7 +36,6 @@ suite('AsyncServerTreeDragAndDrop', () => { groupFullName: 'g2/g2-2', groupId: 'group id', getOptionsKey: undefined!, - serverCapabilities: undefined, matches: undefined!, providerName: mssqlProviderName, options: {}, diff --git a/src/sql/workbench/services/objectExplorer/test/browser/dragAndDropController.test.ts b/src/sql/workbench/services/objectExplorer/test/browser/dragAndDropController.test.ts index e5feaffc6a..17bd29a7b3 100644 --- a/src/sql/workbench/services/objectExplorer/test/browser/dragAndDropController.test.ts +++ b/src/sql/workbench/services/objectExplorer/test/browser/dragAndDropController.test.ts @@ -41,7 +41,6 @@ suite('SQL Drag And Drop Controller tests', () => { groupFullName: 'g2/g2-2', groupId: 'group id', getOptionsKey: undefined!, - serverCapabilities: undefined, matches: undefined!, providerName: mssqlProviderName, options: {}, @@ -60,7 +59,6 @@ suite('SQL Drag And Drop Controller tests', () => { groupFullName: 'g2/g2-2', groupId: 'group id', getOptionsKey: undefined!, - serverCapabilities: undefined, matches: undefined!, providerName: pgsqlProviderName, options: {}, diff --git a/src/sql/workbench/services/objectExplorer/test/browser/treeUpdateUtils.test.ts b/src/sql/workbench/services/objectExplorer/test/browser/treeUpdateUtils.test.ts deleted file mode 100644 index eb6b895bb7..0000000000 --- a/src/sql/workbench/services/objectExplorer/test/browser/treeUpdateUtils.test.ts +++ /dev/null @@ -1,625 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the Source EULA. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile'; -import { ConnectionProfileGroup } from 'sql/platform/connection/common/connectionProfileGroup'; -import { IConnectionProfile } from 'sql/platform/connection/common/interfaces'; -import { TestCapabilitiesService } from 'sql/platform/capabilities/test/common/testCapabilitiesService'; -import { mssqlProviderName } from 'sql/platform/connection/common/constants'; -import { TreeUpdateUtils } from 'sql/workbench/services/objectExplorer/browser/treeUpdateUtils'; -import * as assert from 'assert'; - -import * as azdata from 'azdata'; - -suite('treeUpdateUtils alterConnection', () => { - - let capabilitiesService: TestCapabilitiesService; - - const testOption1 = { - name: 'testOption1', - displayName: 'testOption1', - description: 'test description', - groupName: 'test group name', - valueType: 'string', - specialValueType: undefined, - defaultValue: '', - categoryValues: undefined, - isIdentity: false, - isRequired: false - }; - - const testOption2 = { - name: 'testOption2', - displayName: 'testOption2', - description: 'test description', - groupName: 'test group name', - valueType: 'number', - specialValueType: undefined, - defaultValue: '10', - categoryValues: undefined, - isIdentity: false, - isRequired: false - }; - - const testOption3 = { - name: 'testOption3', - displayName: 'testOption3', - description: 'test description', - groupName: 'test group name', - valueType: 'string', - specialValueType: undefined, - defaultValue: 'default', - categoryValues: undefined, - isIdentity: false, - isRequired: false - }; - - setup(() => { - capabilitiesService = new TestCapabilitiesService(); - let mainProvider = capabilitiesService.capabilities[mssqlProviderName]; - let mainProperties = mainProvider.connection; - let mainOptions = mainProperties.connectionOptions; - - mainOptions.push((testOption1 as azdata.ConnectionOption)); - mainOptions.push((testOption2 as azdata.ConnectionOption)); - mainOptions.push((testOption3 as azdata.ConnectionOption)); - - mainProperties.connectionOptions = mainOptions; - mainProvider.connection = mainProperties; - - capabilitiesService.capabilities['MSSQL'] = mainProvider; - }); - - test('Default properties should not be added to the altered title', async () => { - let profile1: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { testOption3: 'default', testOption2: '10' }, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let profile2: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { testOption3: 'nonDefault' }, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let connectionProfile1 = new ConnectionProfile(capabilitiesService, profile1); - let connectionProfile2 = new ConnectionProfile(capabilitiesService, profile2); - - - let connectionProfileGroup = new ConnectionProfileGroup('g3', undefined, 'g3', undefined, undefined); - connectionProfileGroup.addConnections([connectionProfile1, connectionProfile2]); - - let updatedProfileGroup = TreeUpdateUtils.alterTreeChildrenTitles([connectionProfileGroup]); - - let updatedTitleMap = updatedProfileGroup[0].connections.map(profile => profile.title); - - assert.equal(connectionProfile1.title, updatedTitleMap[0]); - assert.equal(connectionProfile1.title + ' (testOption3=nonDefault)', updatedTitleMap[1]); - }); - - test('Similar connections should have different titles based on all differing properties', async () => { - let profile1: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { testOption2: '15', testOption1: 'test string 1', testOption3: 'nonDefault' }, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let profile2: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { testOption2: '50', testOption1: 'test string 1', testOption3: 'nonDefault' }, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let profile3: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { testOption2: '15', testOption1: 'test string 2', testOption3: 'nonDefault' }, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let profile4: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { testOption2: '50', testOption1: 'test string 2', testOption3: 'nonDefault' }, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let defaultProfile: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { testOption3: 'nonDefault' }, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let defaultConnectionProfile = new ConnectionProfile(capabilitiesService, defaultProfile); - let connectionProfile1 = new ConnectionProfile(capabilitiesService, profile1); - let connectionProfile2 = new ConnectionProfile(capabilitiesService, profile2); - let connectionProfile3 = new ConnectionProfile(capabilitiesService, profile3); - let connectionProfile4 = new ConnectionProfile(capabilitiesService, profile4); - - - let connectionProfileGroup = new ConnectionProfileGroup('g3', undefined, 'g3', undefined, undefined); - let originalTitle = defaultConnectionProfile.title; - connectionProfileGroup.addConnections([defaultConnectionProfile, connectionProfile1, connectionProfile2, connectionProfile3, connectionProfile4]); - - let updatedProfileGroup = TreeUpdateUtils.alterTreeChildrenTitles([connectionProfileGroup]); - - let updatedTitleMap = updatedProfileGroup[0].connections.map(profile => profile.title); - - assert.equal(originalTitle, updatedTitleMap[0]); - assert.equal(originalTitle + ' (testOption1=test string 1; testOption2=15)', updatedTitleMap[1]); - assert.equal(originalTitle + ' (testOption1=test string 1; testOption2=50)', updatedTitleMap[2]); - assert.equal(originalTitle + ' (testOption1=test string 2; testOption2=15)', updatedTitleMap[3]); - assert.equal(originalTitle + ' (testOption1=test string 2; testOption2=50)', updatedTitleMap[4]); - }); - - test('identical connections should have same title if on different levels', async () => { - let profile1: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: {}, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let profile2: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3-1', - groupId: 'g3-1', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: {}, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let profile3: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3-2', - groupId: 'g3-2', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: {}, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let connectionProfile1 = new ConnectionProfile(capabilitiesService, profile1); - let connectionProfile2 = new ConnectionProfile(capabilitiesService, profile2); - let connectionProfile3 = new ConnectionProfile(capabilitiesService, profile3); - - let connectionProfileGroup = new ConnectionProfileGroup('g3', undefined, 'g3', undefined, undefined); - let childConnectionProfileGroup = new ConnectionProfileGroup('g3-1', undefined, 'g3-1', undefined, undefined); - let grandChildConnectionProfileGroup = new ConnectionProfileGroup('g3-2', undefined, 'g3-2', undefined, undefined); - childConnectionProfileGroup.addConnections([connectionProfile2]); - connectionProfileGroup.addConnections([connectionProfile1]); - grandChildConnectionProfileGroup.addConnections([connectionProfile3]); - childConnectionProfileGroup.addGroups([grandChildConnectionProfileGroup]); - connectionProfileGroup.addGroups([childConnectionProfileGroup]); - - let updatedProfileGroup = TreeUpdateUtils.alterTreeChildrenTitles([connectionProfileGroup]); - - let updatedTitleMap = updatedProfileGroup[0].connections.map(profile => profile.title); - let updatedChildTitleMap = updatedProfileGroup[0].children[0].connections.map(profile => profile.title); - let updatedGrandChildTitleMap = updatedProfileGroup[0].children[0].children[0].connections.map(profile => profile.title); - - // Titles should be the same if they're in different levels. - assert.equal(updatedTitleMap[0], updatedChildTitleMap[0]); - assert.equal(updatedTitleMap[0], updatedGrandChildTitleMap[0]); - assert.equal(updatedChildTitleMap[0], updatedGrandChildTitleMap[0]); - }); - - test('connections should not affect connections on a different level', async () => { - let profile1: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { testOption1: 'value1' }, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let profile1a: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { testOption1: 'value2' }, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let profile2: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3-1', - groupId: 'g3-1', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: {}, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let connectionProfile1 = new ConnectionProfile(capabilitiesService, profile1); - let connectionProfile1a = new ConnectionProfile(capabilitiesService, profile1a); - let connectionProfile2 = new ConnectionProfile(capabilitiesService, profile2); - - let connectionProfileGroup = new ConnectionProfileGroup('g3', undefined, 'g3', undefined, undefined); - let childConnectionProfileGroup = new ConnectionProfileGroup('g3-1', undefined, 'g3-1', undefined, undefined); - - childConnectionProfileGroup.addConnections([connectionProfile2]); - connectionProfileGroup.addConnections([connectionProfile1, connectionProfile1a]); - connectionProfileGroup.addGroups([childConnectionProfileGroup]); - - let updatedProfileGroup = TreeUpdateUtils.alterTreeChildrenTitles([connectionProfileGroup]); - - let updatedTitleMap = updatedProfileGroup[0].connections.map(profile => profile.title); - let updatedChildTitleMap = updatedProfileGroup[0].children[0].connections.map(profile => profile.title); - - // Titles should be altered for the first group only. - assert.equal(updatedChildTitleMap[0] + ' (testOption1=value1)', updatedTitleMap[0]); - assert.equal(updatedChildTitleMap[0] + ' (testOption1=value2)', updatedTitleMap[1]); - }); - - test('non default options should only be appended to the connection with non default options', async () => { - let profile1: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: {}, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let profile2: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { testOption1: 'value1', testOption2: '15' }, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let connectionProfile1 = new ConnectionProfile(capabilitiesService, profile1); - let connectionProfile2 = new ConnectionProfile(capabilitiesService, profile2); - - let connectionProfileGroup = new ConnectionProfileGroup('g3', undefined, 'g3', undefined, undefined); - - connectionProfileGroup.addConnections([connectionProfile1, connectionProfile2]); - - let updatedProfileGroup = TreeUpdateUtils.alterTreeChildrenTitles([connectionProfileGroup]); - - let updatedTitleMap = updatedProfileGroup[0].connections.map(profile => profile.title); - - //Title for second profile should be the same as the first but with non default options appended. - assert.equal(updatedTitleMap[0] + ' (testOption1=value1; testOption2=15)', updatedTitleMap[1]); - }); - - test('identical profiles added into one group and separate groups should have the same options appended', async () => { - let profile1: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { testOption1: 'value1', testOption2: '15' }, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let profile2: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3', - groupId: 'g3', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { testOption1: 'value2', testOption2: '30' }, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let connectionProfile1Base = new ConnectionProfile(capabilitiesService, profile1); - let connectionProfile2Base = new ConnectionProfile(capabilitiesService, profile2); - - let connectionProfileGroup = new ConnectionProfileGroup('g3', undefined, 'g3', undefined, undefined); - - connectionProfileGroup.addConnections([connectionProfile1Base, connectionProfile2Base]); - - profile1.groupFullName = 'g3-1'; - profile1.groupId = 'g3-1'; - profile2.groupFullName = 'g3-1'; - profile2.groupId = 'g3-1'; - - let connectionProfile1Child = new ConnectionProfile(capabilitiesService, profile1); - let connectionProfile2Child = new ConnectionProfile(capabilitiesService, profile2); - - let childConnectionProfileGroup = new ConnectionProfileGroup('g3-1', undefined, 'g3-1', undefined, undefined); - - childConnectionProfileGroup.addConnections([connectionProfile1Child, connectionProfile2Child]); - - profile1.groupFullName = 'g3-2'; - profile1.groupId = 'g3-2'; - profile2.groupFullName = 'g3-2'; - profile2.groupId = 'g3-2'; - - let connectionProfile1Grandchild = new ConnectionProfile(capabilitiesService, profile1); - let connectionProfile2Grandchild = new ConnectionProfile(capabilitiesService, profile2); - - let grandchildConnectionProfileGroup = new ConnectionProfileGroup('g3-2', undefined, 'g3-2', undefined, undefined); - - grandchildConnectionProfileGroup.addConnections([connectionProfile1Grandchild, connectionProfile2Grandchild]); - - childConnectionProfileGroup.addGroups([grandchildConnectionProfileGroup]); - - connectionProfileGroup.addGroups([childConnectionProfileGroup]); - - let updatedProfileGroup = TreeUpdateUtils.alterTreeChildrenTitles([connectionProfileGroup]); - - let updatedTitleMap = updatedProfileGroup[0].connections.map(profile => profile.title); - let updatedChildTitleMap = updatedProfileGroup[0].children[0].connections.map(profile => profile.title); - let updatedGrandchildTitleMap = updatedProfileGroup[0].children[0].children[0].connections.map(profile => profile.title); - - //Titles for the same profile in different groups should be identical - assert.equal(updatedTitleMap[0], updatedChildTitleMap[0]); - assert.equal(updatedTitleMap[0], updatedGrandchildTitleMap[0]); - assert.equal(updatedTitleMap[1], updatedChildTitleMap[1]); - assert.equal(updatedTitleMap[1], updatedGrandchildTitleMap[1]); - }); - - test('profiles in adjacent groups on the same layer should not affect titles on nearby groups', async () => { - let profile1: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3a', - groupId: 'g3a', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: {}, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let profile2: IConnectionProfile = { - serverName: 'server3', - databaseName: 'database', - userName: 'user', - password: 'password', - authenticationType: '', - savePassword: true, - groupFullName: 'g3a', - groupId: 'g3a', - getOptionsKey: undefined!, - serverCapabilities: undefined, - matches: undefined!, - providerName: 'MSSQL', - options: { testOption1: 'value2', testOption2: '30' }, - saveProfile: true, - id: undefined!, - connectionName: undefined! - }; - - let connectionProfile1a = new ConnectionProfile(capabilitiesService, profile1); - let connectionProfile2a = new ConnectionProfile(capabilitiesService, profile2); - - let connectionProfileGroup = new ConnectionProfileGroup('g3', undefined, 'g3', undefined, undefined); - - let childConnectionProfileGroup1 = new ConnectionProfileGroup('g3a', undefined, 'g3a', undefined, undefined); - childConnectionProfileGroup1.addConnections([connectionProfile1a, connectionProfile2a]); - - profile1.groupFullName = 'g3b'; - profile1.groupId = 'g3b'; - profile2.groupFullName = 'g3b'; - profile2.groupId = 'g3b'; - - let connectionProfile1b = new ConnectionProfile(capabilitiesService, profile1); - let connectionProfile2b = new ConnectionProfile(capabilitiesService, profile2); - - let childConnectionProfileGroup2 = new ConnectionProfileGroup('g3b', undefined, 'g3b', undefined, undefined); - - childConnectionProfileGroup2.addConnections([connectionProfile1b, connectionProfile2b]); - - connectionProfileGroup.addGroups([childConnectionProfileGroup1]); - - connectionProfileGroup.addGroups([childConnectionProfileGroup2]); - - let updatedProfileGroup = TreeUpdateUtils.alterTreeChildrenTitles([connectionProfileGroup]); - - let updatedChildATitleMap = updatedProfileGroup[0].children[0].connections.map(profile => profile.title); - let updatedChildBTitleMap = updatedProfileGroup[0].children[1].connections.map(profile => profile.title); - - //Check that titles are generated properly for the first group. - assert.equal(updatedChildATitleMap[0] + ' (testOption1=value2; testOption2=30)', updatedChildATitleMap[1]); - - //Titles for the same profile in adjacent groups should be identical - assert.equal(updatedChildATitleMap[0], updatedChildBTitleMap[0]); - assert.equal(updatedChildATitleMap[1], updatedChildBTitleMap[1]); - }); -}); diff --git a/src/sql/workbench/services/resourceProvider/test/browser/firewallRuleDialogController.test.ts b/src/sql/workbench/services/resourceProvider/test/browser/firewallRuleDialogController.test.ts index 52ebf70af0..64e1e0d8a3 100644 --- a/src/sql/workbench/services/resourceProvider/test/browser/firewallRuleDialogController.test.ts +++ b/src/sql/workbench/services/resourceProvider/test/browser/firewallRuleDialogController.test.ts @@ -89,7 +89,6 @@ suite('Firewall rule dialog controller tests', () => { groupFullName: 'g2/g2-2', groupId: 'group id', getOptionsKey: () => '', - serverCapabilities: undefined, matches: () => false, providerName: mssqlProviderName, options: {},