Add support for setting query options in settings and through API (#5484)

Initial query execution options PR.  This is the second in a set of query editor extensibility improvements I'm making.  The PRs include (1) bug fix for webview in query tab (2) dynamic toolbars and (3) fix query event sequencing and event metadata info.
This commit is contained in:
Karl Burtram
2019-05-16 16:31:30 -07:00
committed by GitHub
parent 3158e9f63a
commit fe17955fa1
17 changed files with 222 additions and 60 deletions

View File

@@ -36,6 +36,7 @@ export interface IQueryManagementService {
getQueryRows(rowData: azdata.QueryExecuteSubsetParams): Thenable<azdata.QueryExecuteSubsetResult>;
disposeQuery(ownerUri: string): Thenable<void>;
saveResults(requestParams: azdata.SaveResultsRequestParams): Thenable<azdata.SaveResultRequestResult>;
setQueryExecutionOptions(uri: string, options: azdata.QueryExecutionOptions): Thenable<void>;
// Callbacks
onQueryComplete(result: azdata.QueryExecuteCompleteNotificationResult): void;
@@ -73,6 +74,7 @@ export interface IQueryRequestHandler {
getQueryRows(rowData: azdata.QueryExecuteSubsetParams): Thenable<azdata.QueryExecuteSubsetResult>;
disposeQuery(ownerUri: string): Thenable<void>;
saveResults(requestParams: azdata.SaveResultsRequestParams): Thenable<azdata.SaveResultRequestResult>;
setQueryExecutionOptions(ownerUri: string, options: azdata.QueryExecutionOptions): Thenable<void>;
// Edit Data actions
initializeEdit(ownerUri: string, schemaName: string, objectName: string, objectType: string, rowLimit: number, queryString: string): Thenable<void>;
@@ -177,9 +179,13 @@ export class QueryManagementService implements IQueryManagementService {
TelemetryUtils.addTelemetry(this._telemetryService, this.logService, eventName, data);
}
private _runAction<T>(uri: string, action: (handler: IQueryRequestHandler) => Thenable<T>): Thenable<T> {
private _runAction<T>(uri: string, action: (handler: IQueryRequestHandler) => Thenable<T>, fallBackToDefaultProvider: boolean = false): Thenable<T> {
let providerId: string = this._connectionService.getProviderIdFromUri(uri);
if (!providerId && fallBackToDefaultProvider) {
providerId = this._connectionService.getDefaultProviderId();
}
if (!providerId) {
return Promise.reject(new Error('Connection is required in order to interact with queries'));
}
@@ -236,6 +242,11 @@ export class QueryManagementService implements IQueryManagementService {
return runner.disposeQuery(ownerUri);
});
}
public setQueryExecutionOptions(ownerUri: string, options: azdata.QueryExecutionOptions): Thenable<void> {
return this._runAction(ownerUri, (runner) => {
return runner.setQueryExecutionOptions(ownerUri, options);
}, true);
}
public saveResults(requestParams: azdata.SaveResultsRequestParams): Thenable<azdata.SaveResultRequestResult> {
return this._runAction(requestParams.ownerUri, (runner) => {

View File

@@ -50,7 +50,7 @@ export default class QueryRunner extends Disposable {
private _messages: IQueryMessage[] = [];
private registered = false;
private _isQueryPlan: boolean;
private _isQueryPlan: boolean = false;
public get isQueryPlan(): boolean { return this._isQueryPlan; }
private _planXml = new Deferred<string>();
public get planXml(): Thenable<string> { return this._planXml.promise; }
@@ -180,12 +180,6 @@ export default class QueryRunner extends Disposable {
this._totalElapsedMilliseconds = 0;
// TODO issue #228 add statusview callbacks here
if (runOptions && (runOptions.displayActualQueryPlan || runOptions.displayEstimatedQueryPlan)) {
this._isQueryPlan = true;
} else {
this._isQueryPlan = false;
}
this._onQueryStart.fire();
// Send the request to execute the query
@@ -335,16 +329,15 @@ export default class QueryRunner extends Disposable {
batchSet = this._batchSets[resultSet.batchId];
}
// handle getting queryPlanxml if we need too
if (this.isQueryPlan) {
// check if this result has show plan, this needs work, it won't work for any other provider
let hasShowPlan = !!result.resultSetSummary.columnInfo.find(e => e.columnName === 'Microsoft SQL Server 2005 XML Showplan');
if (hasShowPlan) {
this.getQueryRows(0, 1, result.resultSetSummary.batchId, result.resultSetSummary.id).then(e => {
if (e.resultSubset.rows) {
this._planXml.resolve(e.resultSubset.rows[0][0].displayValue);
}
});
}
// check if this result has show plan, this needs work, it won't work for any other provider
let hasShowPlan = !!result.resultSetSummary.columnInfo.find(e => e.columnName === 'Microsoft SQL Server 2005 XML Showplan');
if (hasShowPlan) {
this._isQueryPlan = true;
this.getQueryRows(0, 1, result.resultSetSummary.batchId, result.resultSetSummary.id).then(e => {
if (e.resultSubset.rows) {
this._planXml.resolve(e.resultSubset.rows[0][0].displayValue);
}
});
}
// we will just ignore the set if we already have it
// ideally this should never happen
@@ -362,25 +355,24 @@ export default class QueryRunner extends Disposable {
let batchSet: azdata.BatchSummary;
batchSet = this._batchSets[resultSet.batchId];
// handle getting queryPlanxml if we need too
if (this.isQueryPlan) {
// check if this result has show plan, this needs work, it won't work for any other provider
let hasShowPlan = !!result.resultSetSummary.columnInfo.find(e => e.columnName === 'Microsoft SQL Server 2005 XML Showplan');
if (hasShowPlan) {
this.getQueryRows(0, 1, result.resultSetSummary.batchId, result.resultSetSummary.id).then(e => {
if (e.resultSubset.rows) {
let planXmlString = e.resultSubset.rows[0][0].displayValue;
this._planXml.resolve(e.resultSubset.rows[0][0].displayValue);
// fire query plan available event if execution is completed
if (result.resultSetSummary.complete) {
this._onQueryPlanAvailable.fire({
providerId: 'MSSQL',
fileUri: result.ownerUri,
planXml: planXmlString
});
}
// check if this result has show plan, this needs work, it won't work for any other provider
let hasShowPlan = !!result.resultSetSummary.columnInfo.find(e => e.columnName === 'Microsoft SQL Server 2005 XML Showplan');
if (hasShowPlan) {
this._isQueryPlan = true;
this.getQueryRows(0, 1, result.resultSetSummary.batchId, result.resultSetSummary.id).then(e => {
if (e.resultSubset.rows) {
let planXmlString = e.resultSubset.rows[0][0].displayValue;
this._planXml.resolve(e.resultSubset.rows[0][0].displayValue);
// fire query plan available event if execution is completed
if (result.resultSetSummary.complete) {
this._onQueryPlanAvailable.fire({
providerId: 'MSSQL',
fileUri: result.ownerUri,
planXml: planXmlString
});
}
});
}
}
});
}
if (batchSet) {
// Store the result set in the batch and emit that a result set has completed