mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-02 17:23:40 -05:00
SQL Project: Opening connection viewlet after deploying database (#19544)
This commit is contained in:
@@ -0,0 +1,185 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as constants from '../../common/constants';
|
||||
import * as utils from '../../common/utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { ConnectionResult } from 'azdata';
|
||||
import { IFireWallRuleError } from 'vscode-mssql';
|
||||
|
||||
export interface ISqlConnectionProperties {
|
||||
tenantId?: string,
|
||||
accountId?: string
|
||||
serverName: string,
|
||||
userName: string,
|
||||
password: string,
|
||||
port: number,
|
||||
dbName: string,
|
||||
profileName?: string,
|
||||
connectionRetryTimeout?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes methods to open connections and interact with connection views
|
||||
*/
|
||||
export class ConnectionService {
|
||||
|
||||
constructor(private _outputChannel: vscode.OutputChannel) {
|
||||
}
|
||||
|
||||
private defaultSqlRetryTimeoutInSec: number = 10;
|
||||
private defaultSqlNumberOfRetries: number = 3;
|
||||
|
||||
/**
|
||||
* Connects to a database
|
||||
* @param profile connection profile
|
||||
* @param saveConnectionAndPassword if true, connection will be saved in the connection view
|
||||
* @param database database name
|
||||
* @returns
|
||||
*/
|
||||
private async connectToDatabase(profile: ISqlConnectionProperties, saveConnectionAndPassword: boolean, database: string): Promise<ConnectionResult | string | undefined> {
|
||||
const azdataApi = utils.getAzdataApi();
|
||||
const vscodeMssqlApi = azdataApi ? undefined : await utils.getVscodeMssqlApi();
|
||||
if (azdataApi) {
|
||||
const connectionProfile = {
|
||||
password: profile.password,
|
||||
serverName: `${profile.serverName},${profile.port}`,
|
||||
database: database,
|
||||
savePassword: saveConnectionAndPassword,
|
||||
userName: profile.userName,
|
||||
providerName: 'MSSQL',
|
||||
saveProfile: false,
|
||||
id: '',
|
||||
connectionName: profile.profileName,
|
||||
options: [],
|
||||
authenticationType: 'SqlLogin'
|
||||
};
|
||||
return await azdataApi.connection.connect(connectionProfile, saveConnectionAndPassword, false);
|
||||
} else if (vscodeMssqlApi) {
|
||||
const connectionProfile = {
|
||||
password: profile.password,
|
||||
server: `${profile.serverName}`,
|
||||
port: profile.port,
|
||||
database: database,
|
||||
savePassword: saveConnectionAndPassword,
|
||||
user: profile.userName,
|
||||
authenticationType: 'SqlLogin',
|
||||
encrypt: false,
|
||||
connectTimeout: 30,
|
||||
applicationName: 'SQL Database Project',
|
||||
accountId: profile.accountId,
|
||||
azureAccountToken: undefined,
|
||||
applicationIntent: undefined,
|
||||
attachDbFilename: undefined,
|
||||
connectRetryCount: undefined,
|
||||
connectRetryInterval: undefined,
|
||||
connectionString: undefined,
|
||||
currentLanguage: undefined,
|
||||
email: undefined,
|
||||
failoverPartner: undefined,
|
||||
loadBalanceTimeout: undefined,
|
||||
maxPoolSize: undefined,
|
||||
minPoolSize: undefined,
|
||||
multiSubnetFailover: undefined,
|
||||
multipleActiveResultSets: undefined,
|
||||
packetSize: undefined,
|
||||
persistSecurityInfo: undefined,
|
||||
pooling: undefined,
|
||||
replication: undefined,
|
||||
trustServerCertificate: undefined,
|
||||
typeSystemVersion: undefined,
|
||||
workstationId: undefined,
|
||||
profileName: profile.profileName,
|
||||
expiresOn: undefined,
|
||||
tenantId: profile.tenantId
|
||||
};
|
||||
let connectionUrl = '';
|
||||
try {
|
||||
connectionUrl = await vscodeMssqlApi.connect(connectionProfile, saveConnectionAndPassword);
|
||||
} catch (err) {
|
||||
const firewallRuleError = <IFireWallRuleError>err;
|
||||
if (firewallRuleError?.connectionUri) {
|
||||
await vscodeMssqlApi.promptForFirewallRule(err.connectionUri, connectionProfile);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
// If connected successfully and saved the connection in the view, open the connection view
|
||||
if (saveConnectionAndPassword && connectionUrl) {
|
||||
await vscode.commands.executeCommand('objectExplorer.focus');
|
||||
}
|
||||
return connectionUrl;
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the connection result. If using azdata API, verifies connection was successful and connection id is returns
|
||||
* If using vscode API, verifies the connection url is returns
|
||||
* @param connection connection result or connection Id
|
||||
* @returns validation result
|
||||
*/
|
||||
private async validateConnection(connection: ConnectionResult | string | undefined): Promise<utils.ValidationResult> {
|
||||
const azdataApi = utils.getAzdataApi();
|
||||
if (!connection) {
|
||||
return { validated: false, errorMessage: constants.connectionFailedError('No result returned') };
|
||||
} else if (azdataApi) {
|
||||
const connectionResult = <ConnectionResult>connection;
|
||||
if (connectionResult) {
|
||||
const connected = connectionResult !== undefined && connectionResult.connected && connectionResult.connectionId !== undefined;
|
||||
return { validated: connected, errorMessage: connected ? '' : constants.connectionFailedError(connectionResult?.errorMessage!) };
|
||||
} else {
|
||||
return { validated: false, errorMessage: constants.connectionFailedError('') };
|
||||
}
|
||||
} else {
|
||||
return { validated: connection !== undefined, errorMessage: constants.connectionFailedError('') };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats connection result to string to be able to add to log
|
||||
* @param connection connection result or connection Id
|
||||
* @returns formatted connection result
|
||||
*/
|
||||
private async formatConnectionResult(connection: ConnectionResult | string | undefined): Promise<string> {
|
||||
const azdataApi = utils.getAzdataApi();
|
||||
const connectionResult = connection !== undefined && azdataApi ? <ConnectionResult>connection : undefined;
|
||||
return connectionResult?.connected ? connectionResult.connectionId! : <string>connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a connections and returns the connection id
|
||||
* @param profile connection profile
|
||||
* @param saveConnectionAndPassword is set to true the connection will be saved in the connection view
|
||||
* @param database database name
|
||||
* @returns connection id
|
||||
*/
|
||||
public async getConnection(profile: ISqlConnectionProperties, saveConnectionAndPassword: boolean, database: string): Promise<string | undefined> {
|
||||
const azdataApi = utils.getAzdataApi();
|
||||
let connection = await utils.retry(
|
||||
constants.connectingToSqlServerMessage,
|
||||
async () => {
|
||||
return await this.connectToDatabase(profile, saveConnectionAndPassword, database);
|
||||
},
|
||||
this.validateConnection,
|
||||
this.formatConnectionResult,
|
||||
this._outputChannel,
|
||||
this.defaultSqlNumberOfRetries, profile.connectionRetryTimeout || this.defaultSqlRetryTimeoutInSec);
|
||||
|
||||
if (connection) {
|
||||
const connectionResult = <ConnectionResult>connection;
|
||||
if (azdataApi) {
|
||||
utils.throwIfNotConnected(connectionResult);
|
||||
return azdataApi.connection.getUriForConnection(connectionResult.connectionId!);
|
||||
} else {
|
||||
return <string>connection;
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user