mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-23 17:23:02 -05:00
187 lines
7.4 KiB
TypeScript
187 lines
7.4 KiB
TypeScript
/*---------------------------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
|
*--------------------------------------------------------------------------------------------*/
|
|
|
|
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
|
|
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
|
|
import { IInsightsConfigDetails } from 'sql/workbench/parts/dashboard/widgets/insights/interfaces';
|
|
import QueryRunner from 'sql/platform/query/common/queryRunner';
|
|
import * as Utils from 'sql/platform/connection/common/utils';
|
|
import { IInsightsDialogModel } from 'sql/workbench/services/insights/common/insightsDialogService';
|
|
import { IErrorMessageService } from 'sql/platform/errorMessage/common/errorMessageService';
|
|
import { resolveQueryFilePath } from '../common/insightsUtils';
|
|
|
|
import { DbCellValue, IDbColumn, QueryExecuteSubsetResult } from 'azdata';
|
|
|
|
import Severity from 'vs/base/common/severity';
|
|
import * as types from 'vs/base/common/types';
|
|
import * as pfs from 'vs/base/node/pfs';
|
|
import * as nls from 'vs/nls';
|
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
|
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
|
import { INotificationService } from 'vs/platform/notification/common/notification';
|
|
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
|
|
import { ILogService } from 'vs/platform/log/common/log';
|
|
|
|
export class InsightsDialogController {
|
|
private _queryRunner: QueryRunner;
|
|
private _connectionProfile: IConnectionProfile;
|
|
private _connectionUri: string;
|
|
private _columns: IDbColumn[];
|
|
private _rows: DbCellValue[][];
|
|
|
|
constructor(
|
|
private _model: IInsightsDialogModel,
|
|
@INotificationService private _notificationService: INotificationService,
|
|
@IErrorMessageService private _errorMessageService: IErrorMessageService,
|
|
@IInstantiationService private _instantiationService: IInstantiationService,
|
|
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
|
@IWorkspaceContextService private _workspaceContextService: IWorkspaceContextService,
|
|
@IConfigurationResolverService private _configurationResolverService: IConfigurationResolverService,
|
|
@ILogService private logService: ILogService
|
|
) { }
|
|
|
|
public async update(input: IInsightsConfigDetails, connectionProfile: IConnectionProfile): Promise<void> {
|
|
// execute string
|
|
if (typeof input === 'object') {
|
|
if (connectionProfile === undefined) {
|
|
this._notificationService.notify({
|
|
severity: Severity.Error,
|
|
message: nls.localize("insightsInputError", "No Connection Profile was passed to insights flyout")
|
|
});
|
|
return Promise.resolve();
|
|
}
|
|
if (types.isStringArray(input.query)) {
|
|
return this.createQuery(input.query.join(' '), connectionProfile).catch(e => {
|
|
this._errorMessageService.showDialog(Severity.Error, nls.localize("insightsError", "Insights error"), e);
|
|
}).then(() => undefined);
|
|
} else if (types.isString(input.query)) {
|
|
return this.createQuery(input.query, connectionProfile).catch(e => {
|
|
this._errorMessageService.showDialog(Severity.Error, nls.localize("insightsError", "Insights error"), e);
|
|
}).then(() => undefined);
|
|
} else if (types.isString(input.queryFile)) {
|
|
let filePath: string;
|
|
try {
|
|
filePath = await resolveQueryFilePath(input.queryFile,
|
|
this._workspaceContextService,
|
|
this._configurationResolverService);
|
|
}
|
|
catch (e) {
|
|
this._notificationService.notify({
|
|
severity: Severity.Error,
|
|
message: e
|
|
});
|
|
return Promise.resolve();
|
|
}
|
|
|
|
try {
|
|
let buffer: Buffer = await pfs.readFile(filePath);
|
|
this.createQuery(buffer.toString(), connectionProfile).catch(e => {
|
|
this._errorMessageService.showDialog(Severity.Error, nls.localize("insightsError", "Insights error"), e);
|
|
});
|
|
}
|
|
catch (e) {
|
|
this._notificationService.notify({
|
|
severity: Severity.Error,
|
|
message: nls.localize("insightsFileError", "There was an error reading the query file: ") + e
|
|
});
|
|
}
|
|
} else {
|
|
this.logService.error('Error reading details Query: ', input);
|
|
this._notificationService.notify({
|
|
severity: Severity.Error,
|
|
message: nls.localize("insightsConfigError", "There was an error parsing the insight config; could not find query array/string or queryfile")
|
|
});
|
|
return Promise.resolve();
|
|
}
|
|
}
|
|
|
|
return Promise.resolve();
|
|
}
|
|
|
|
private async createQuery(queryString: string, connectionProfile: IConnectionProfile): Promise<void> {
|
|
if (this._queryRunner) {
|
|
if (!this._queryRunner.hasCompleted) {
|
|
await this._queryRunner.cancelQuery();
|
|
}
|
|
try {
|
|
await this.createNewConnection(connectionProfile);
|
|
} catch (e) {
|
|
return Promise.reject(e);
|
|
}
|
|
this._queryRunner.uri = this._connectionUri;
|
|
} else {
|
|
try {
|
|
await this.createNewConnection(connectionProfile);
|
|
} catch (e) {
|
|
return Promise.reject(e);
|
|
}
|
|
this._queryRunner = this._instantiationService.createInstance(QueryRunner, this._connectionUri);
|
|
this.addQueryEventListeners(this._queryRunner);
|
|
}
|
|
|
|
return this._queryRunner.runQuery(queryString);
|
|
}
|
|
|
|
private async createNewConnection(connectionProfile: IConnectionProfile): Promise<void> {
|
|
// determine if we need to create a new connection
|
|
if (!this._connectionProfile || connectionProfile.getOptionsKey() !== this._connectionProfile.getOptionsKey()) {
|
|
if (this._connectionProfile) {
|
|
try {
|
|
await this._connectionManagementService.disconnect(this._connectionUri);
|
|
} catch (e) {
|
|
return Promise.reject(e);
|
|
}
|
|
}
|
|
this._connectionProfile = connectionProfile;
|
|
this._connectionUri = Utils.generateUri(this._connectionProfile, 'insights');
|
|
return this._connectionManagementService.connect(this._connectionProfile, this._connectionUri).then(result => undefined);
|
|
}
|
|
}
|
|
|
|
private addQueryEventListeners(queryRunner: QueryRunner): void {
|
|
queryRunner.onQueryEnd(() => {
|
|
this.queryComplete().catch(error => {
|
|
this._errorMessageService.showDialog(Severity.Error, nls.localize("insightsError", "Insights error"), error);
|
|
});
|
|
});
|
|
queryRunner.onMessage(message => {
|
|
if (message.isError) {
|
|
this._errorMessageService.showDialog(Severity.Error, nls.localize("insightsError", "Insights error"), message.message);
|
|
}
|
|
});
|
|
}
|
|
|
|
private async queryComplete(): Promise<void> {
|
|
let batches = this._queryRunner.batchSets;
|
|
// currently only support 1 batch set 1 resultset
|
|
if (batches.length > 0) {
|
|
let batch = batches[0];
|
|
if (batch.resultSetSummaries.length > 0
|
|
&& batch.resultSetSummaries[0].rowCount > 0
|
|
) {
|
|
let resultset = batch.resultSetSummaries[0];
|
|
this._columns = resultset.columnInfo;
|
|
let rows: QueryExecuteSubsetResult;
|
|
try {
|
|
rows = await this._queryRunner.getQueryRows(0, resultset.rowCount, batch.id, resultset.id);
|
|
} catch (e) {
|
|
return Promise.reject(e);
|
|
}
|
|
this._rows = rows.resultSubset.rows;
|
|
this.updateModel();
|
|
}
|
|
}
|
|
// TODO issue #2746 should ideally show a warning inside the dialog if have no data
|
|
}
|
|
|
|
private updateModel(): void {
|
|
let data = this._rows.map(r => r.map(c => c.displayValue));
|
|
let columns = this._columns.map(c => c.columnName);
|
|
|
|
this._model.rows = data;
|
|
this._model.columns = columns;
|
|
}
|
|
}
|