Merge branch 'master' into release/1.3

This commit is contained in:
Karl Burtram
2018-12-10 17:39:23 -08:00
17 changed files with 137 additions and 95 deletions

View File

@@ -69,7 +69,7 @@ export class AlertData implements IAgentDialogData {
this.eventDescriptionKeyword = alertInfo.eventDescriptionKeyword; this.eventDescriptionKeyword = alertInfo.eventDescriptionKeyword;
this.eventSource = alertInfo.eventSource; this.eventSource = alertInfo.eventSource;
this.hasNotification = alertInfo.hasNotification; this.hasNotification = alertInfo.hasNotification;
this.includeEventDescription = alertInfo.includeEventDescription.toString(); this.includeEventDescription = alertInfo.includeEventDescription ? alertInfo.includeEventDescription.toString() : null;
this.isEnabled = alertInfo.isEnabled; this.isEnabled = alertInfo.isEnabled;
this.jobId = alertInfo.jobId; this.jobId = alertInfo.jobId;
this.lastOccurrenceDate = alertInfo.lastOccurrenceDate; this.lastOccurrenceDate = alertInfo.lastOccurrenceDate;
@@ -82,7 +82,7 @@ export class AlertData implements IAgentDialogData {
this.databaseName = alertInfo.databaseName; this.databaseName = alertInfo.databaseName;
this.countResetDate = alertInfo.countResetDate; this.countResetDate = alertInfo.countResetDate;
this.categoryName = alertInfo.categoryName; this.categoryName = alertInfo.categoryName;
this.alertType = alertInfo.alertType.toString(); this.alertType = alertInfo.alertType ? alertInfo.alertType.toString() : null;
this.wmiEventNamespace = alertInfo.wmiEventNamespace; this.wmiEventNamespace = alertInfo.wmiEventNamespace;
this.wmiEventQuery = alertInfo.wmiEventQuery; this.wmiEventQuery = alertInfo.wmiEventQuery;
} }

View File

@@ -202,7 +202,7 @@ export class DataTierApplicationWizard {
} }
private async deploy() { private async deploy() {
let service = await DataTierApplicationWizard.getService(); let service = await DataTierApplicationWizard.getService(this.model.server.providerName);
let ownerUri = await sqlops.connection.getUriForConnection(this.model.server.connectionId); let ownerUri = await sqlops.connection.getUriForConnection(this.model.server.connectionId);
let result = await service.deployDacpac(this.model.filePath, this.model.database, this.model.upgradeExisting, ownerUri, sqlops.TaskExecutionMode.execute); let result = await service.deployDacpac(this.model.filePath, this.model.database, this.model.upgradeExisting, ownerUri, sqlops.TaskExecutionMode.execute);
@@ -213,7 +213,7 @@ export class DataTierApplicationWizard {
} }
private async extract() { private async extract() {
let service = await DataTierApplicationWizard.getService(); let service = await DataTierApplicationWizard.getService(this.model.server.providerName);
let ownerUri = await sqlops.connection.getUriForConnection(this.model.server.connectionId); let ownerUri = await sqlops.connection.getUriForConnection(this.model.server.connectionId);
let result = await service.extractDacpac(this.model.database, this.model.filePath, this.model.database, this.model.version, ownerUri, sqlops.TaskExecutionMode.execute); let result = await service.extractDacpac(this.model.database, this.model.filePath, this.model.database, this.model.version, ownerUri, sqlops.TaskExecutionMode.execute);
@@ -224,7 +224,7 @@ export class DataTierApplicationWizard {
} }
private async export() { private async export() {
let service = await DataTierApplicationWizard.getService(); let service = await DataTierApplicationWizard.getService(this.model.server.providerName);
let ownerUri = await sqlops.connection.getUriForConnection(this.model.server.connectionId); let ownerUri = await sqlops.connection.getUriForConnection(this.model.server.connectionId);
let result = await service.exportBacpac(this.model.database, this.model.filePath, ownerUri, sqlops.TaskExecutionMode.execute); let result = await service.exportBacpac(this.model.database, this.model.filePath, ownerUri, sqlops.TaskExecutionMode.execute);
@@ -235,7 +235,7 @@ export class DataTierApplicationWizard {
} }
private async import() { private async import() {
let service = await DataTierApplicationWizard.getService(); let service = await DataTierApplicationWizard.getService(this.model.server.providerName);
let ownerUri = await sqlops.connection.getUriForConnection(this.model.server.connectionId); let ownerUri = await sqlops.connection.getUriForConnection(this.model.server.connectionId);
let result = await service.importBacpac(this.model.filePath, this.model.database, ownerUri, sqlops.TaskExecutionMode.execute); let result = await service.importBacpac(this.model.filePath, this.model.database, ownerUri, sqlops.TaskExecutionMode.execute);
@@ -245,9 +245,8 @@ export class DataTierApplicationWizard {
} }
} }
public static async getService(): Promise<sqlops.DacFxServicesProvider> { private static async getService(providerName: string): Promise<sqlops.DacFxServicesProvider> {
let currentConnection = await sqlops.connection.getCurrentConnection(); let service = sqlops.dataprotocol.getProvider<sqlops.DacFxServicesProvider>(providerName, sqlops.DataProviderType.DacFxServicesProvider);
let service = sqlops.dataprotocol.getProvider<sqlops.DacFxServicesProvider>(currentConnection.providerName, sqlops.DataProviderType.DacFxServicesProvider);
return service; return service;
} }
} }

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/ *--------------------------------------------------------------------------------------------*/
import { IDisposableDataProvider } from 'sql/base/browser/ui/table/interfaces'; import { IDisposableDataProvider } from 'sql/base/browser/ui/table/interfaces';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
export interface IObservableCollection<T> { export interface IObservableCollection<T> {
getLength(): number; getLength(): number;
@@ -14,16 +15,12 @@ export interface IObservableCollection<T> {
dispose(): void; dispose(): void;
} }
class LoadCancellationToken {
isCancelled: boolean;
}
class DataWindow<T> { class DataWindow<T> {
private _data: T[]; private _data: T[];
private _length: number = 0; private _length: number = 0;
private _offsetFromDataSource: number = -1; private _offsetFromDataSource: number = -1;
private lastLoadCancellationToken: LoadCancellationToken; private cancellationToken = new CancellationTokenSource();
constructor( constructor(
private loadFunction: (offset: number, count: number) => Thenable<T[]>, private loadFunction: (offset: number, count: number) => Thenable<T[]>,
@@ -36,9 +33,7 @@ class DataWindow<T> {
this.loadFunction = undefined; this.loadFunction = undefined;
this.placeholderItemGenerator = undefined; this.placeholderItemGenerator = undefined;
this.loadCompleteCallback = undefined; this.loadCompleteCallback = undefined;
if (this.lastLoadCancellationToken) { this.cancellationToken.cancel();
this.lastLoadCancellationToken.isCancelled = true;
}
} }
public getStartIndex(): number { public getStartIndex(): number {
@@ -65,17 +60,16 @@ class DataWindow<T> {
this._length = length; this._length = length;
this._data = undefined; this._data = undefined;
if (this.lastLoadCancellationToken) { this.cancellationToken.cancel();
this.lastLoadCancellationToken.isCancelled = true; this.cancellationToken = new CancellationTokenSource();
} const currentCancellation = this.cancellationToken;
if (length === 0) { if (length === 0) {
return; return;
} }
this.lastLoadCancellationToken = new LoadCancellationToken();
this.loadFunction(offset, length).then(data => { this.loadFunction(offset, length).then(data => {
if (!this.lastLoadCancellationToken.isCancelled) { if (!currentCancellation.token.isCancellationRequested) {
this._data = data; this._data = data;
this.loadCompleteCallback(this._offsetFromDataSource, this._offsetFromDataSource + this._length); this.loadCompleteCallback(this._offsetFromDataSource, this._offsetFromDataSource + this._length);
} }

View File

@@ -78,7 +78,7 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
this._onRowCountChange.fire(); this._onRowCountChange.fire();
} }
find(exp: string): Thenable<IFindPosition> { find(exp: string, maxMatches: number = 0): Thenable<IFindPosition> {
if (!this._findFn) { if (!this._findFn) {
return TPromise.wrapError(new Error('no find function provided')); return TPromise.wrapError(new Error('no find function provided'));
} }
@@ -87,7 +87,8 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
this._onFindCountChange.fire(this._findArray.length); this._onFindCountChange.fire(this._findArray.length);
if (exp) { if (exp) {
this._findObs = Observable.create((observer: Observer<IFindPosition>) => { this._findObs = Observable.create((observer: Observer<IFindPosition>) => {
this._data.forEach((item, i) => { for (let i = 0; i < this._data.length; i++) {
let item = this._data[i];
let result = this._findFn(item, exp); let result = this._findFn(item, exp);
if (result) { if (result) {
result.forEach(pos => { result.forEach(pos => {
@@ -96,8 +97,11 @@ export class TableDataView<T extends Slick.SlickData> implements IDisposableData
observer.next(index); observer.next(index);
this._onFindCountChange.fire(this._findArray.length); this._onFindCountChange.fire(this._findArray.length);
}); });
if (maxMatches > 0 && this._findArray.length > maxMatches) {
break;
}
} }
}); }
}); });
return this._findObs.take(1).toPromise().then(() => { return this._findObs.take(1).toPromise().then(() => {
return this._findArray[this._findIndex]; return this._findArray[this._findIndex];

View File

@@ -304,14 +304,6 @@ table.jobprevruns > tbody {
background-image: url('refresh_inverse.svg'); background-image: url('refresh_inverse.svg');
} }
.agent-actionbar-container .monaco-action-bar > ul.actions-container {
padding-top: 10px;
}
jobsview-component .agent-actionbar-container {
height: 40px;
}
.agent-actionbar-container .monaco-action-bar > ul.actions-container > li.action-item { .agent-actionbar-container .monaco-action-bar > ul.actions-container > li.action-item {
padding-left: 20px; padding-left: 20px;
} }
@@ -414,4 +406,11 @@ jobsview-component .jobview-grid .slick-cell.error-row {
#proxiesDiv .proxyview-proxynameindicatordisabled { #proxiesDiv .proxyview-proxynameindicatordisabled {
width: 5px; width: 5px;
background: red; background: red;
}
#jobsDiv jobsview-component .monaco-toolbar.carbon-taskbar,
#operatorsDiv joboperatorsview-component .monaco-toolbar.carbon-taskbar,
#alertsDiv jobalertsview-component .monaco-toolbar.carbon-taskbar,
#proxiesDiv jobproxiesview-component .monaco-toolbar.carbon-taskbar {
margin: 10px 0px 10px 0px;
} }

View File

@@ -156,8 +156,8 @@
</td> </td>
</tr> </tr>
</table> </table>
<div #jobsteps style="flex: 1 1 auto; position: relative"> <div #jobsteps *ngIf="showSteps === true" style="flex: 1 1 auto; position: relative">
<jobstepsview-component *ngIf="showSteps === true" style="position: absolute; height: 100%; width: 100%"></jobstepsview-component> <jobstepsview-component *ngIf="showSteps === true"></jobstepsview-component>
</div> </div>
<h3 *ngIf="showSteps === false">No Steps Available</h3> <h3 *ngIf="showSteps === false">No Steps Available</h3>
</div> </div>

View File

@@ -65,7 +65,6 @@ export class JobHistoryComponent extends JobManagementView implements OnInit {
private _agentJobInfo: sqlops.AgentJobInfo; private _agentJobInfo: sqlops.AgentJobInfo;
private _noJobsAvailable: boolean = false; private _noJobsAvailable: boolean = false;
private static readonly INITIAL_TREE_HEIGHT: number = 780;
private static readonly HEADING_HEIGHT: number = 24; private static readonly HEADING_HEIGHT: number = 24;
constructor( constructor(

View File

@@ -7,7 +7,6 @@
.all-jobs { .all-jobs {
display: inline; display: inline;
font-size: 15px; font-size: 15px;
padding-bottom: 15px;
} }
.overview-container .overview-tab .resultsViewCollapsible { .overview-container .overview-tab .resultsViewCollapsible {
@@ -266,14 +265,22 @@ jobhistory-component > .jobhistory-heading-container > .icon.in-progress {
padding-left: 20px; padding-left: 20px;
} }
jobhistory-component > .agent-actionbar-container .monaco-action-bar > ul.actions-container { jobhistory-component > .agent-actionbar-container {
border-top: 3px solid #f4f4f4; border-top: 3px solid #f4f4f4;
} }
.vs-dark jobhistory-component > .agent-actionbar-container .monaco-action-bar > ul.actions-container { .vs-dark jobhistory-component > .agent-actionbar-container {
border-top: 3px solid #444444; border-top: 3px solid #444444;
} }
.hc-black jobhistory-component > .agent-actionbar-container .monaco-action-bar > ul.actions-container { .hc-black jobhistory-component > .agent-actionbar-container {
border-top: 3px solid #2b56f2; border-top: 3px solid #2b56f2;
}
jobhistory-component .step-table.prev-run-list .monaco-tree-wrapper .monaco-tree-row {
width: 96%;
}
jobhistory-component .agent-actionbar-container > .monaco-toolbar.carbon-taskbar {
margin: 10px 0px 5px 0px;
} }

View File

@@ -80,4 +80,11 @@
jobstepsview-component { jobstepsview-component {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: absolute;
height: 100%;
width: 100%;
} }
jobstepsview-component .steps-tree .monaco-tree-wrapper .monaco-tree-row {
width: 99.2%;
}

View File

@@ -591,7 +591,7 @@ export class JobsViewComponent extends JobManagementView implements OnInit, OnDe
private async curateJobHistory(jobs: sqlops.AgentJobInfo[], ownerUri: string) { private async curateJobHistory(jobs: sqlops.AgentJobInfo[], ownerUri: string) {
const self = this; const self = this;
jobs.forEach(async (job) => { await Promise.all(jobs.map(async (job) => {
await this._jobManagementService.getJobHistory(ownerUri, job.jobId, job.name).then(async(result) => { await this._jobManagementService.getJobHistory(ownerUri, job.jobId, job.name).then(async(result) => {
if (result) { if (result) {
self.jobSteps[job.jobId] = result.steps ? result.steps : []; self.jobSteps[job.jobId] = result.steps ? result.steps : [];
@@ -622,32 +622,23 @@ export class JobsViewComponent extends JobManagementView implements OnInit, OnDe
} }
} }
}); });
}); }));
} }
private createJobChart(jobId: string, jobHistories: sqlops.AgentJobHistoryInfo[]): void { private createJobChart(jobId: string, jobHistories: sqlops.AgentJobHistoryInfo[]): void {
let chartHeights = this.getChartHeights(jobHistories); let chartHeights = this.getChartHeights(jobHistories);
let runCharts = []; let runCharts = [];
for (let i = 0; i < jobHistories.length; i++) { for (let i = 0; i < chartHeights.length; i++) {
let runGraph = $(`table#${jobId}.jobprevruns > tbody > tr > td > div.bar${i}`); let runGraph = $(`table#${jobId}.jobprevruns > tbody > tr > td > div.bar${i}`);
if (jobHistories && jobHistories.length > 0) { runGraph.css('height', chartHeights[i]);
runGraph.css('height', chartHeights[i]); let bgColor = jobHistories[i].runStatus === 0 ? 'red' : 'green';
let bgColor = jobHistories[i].runStatus === 0 ? 'red' : 'green'; runGraph.css('background', bgColor);
runGraph.css('background', bgColor); runGraph.hover((e) => {
runGraph.hover((e) => { let currentTarget = e.currentTarget;
let currentTarget = e.currentTarget; currentTarget.title = jobHistories[i].runDuration;
currentTarget.title = jobHistories[i].runDuration; });
}); if (runGraph.get(0)) {
if (runGraph.get(0)) { runCharts.push(runGraph.get(0).outerHTML);
runCharts.push(runGraph.get(0).outerHTML);
}
} else {
runGraph.css('height', '5px');
runGraph.css('background', 'red');
runGraph.hover((e) => {
let currentTarget = e.currentTarget;
currentTarget.title = 'Job not run.';
});
} }
} }
if (runCharts.length > 0) { if (runCharts.length > 0) {
@@ -658,7 +649,7 @@ export class JobsViewComponent extends JobManagementView implements OnInit, OnDe
// chart height normalization logic // chart height normalization logic
private getChartHeights(jobHistories: sqlops.AgentJobHistoryInfo[]): string[] { private getChartHeights(jobHistories: sqlops.AgentJobHistoryInfo[]): string[] {
if (!jobHistories || jobHistories.length === 0) { if (!jobHistories || jobHistories.length === 0) {
return ['5px', '5px', '5px', '5px', '5px']; return [];
} }
let maxDuration: number = 0; let maxDuration: number = 0;
jobHistories.forEach(history => { jobHistories.forEach(history => {

View File

@@ -11,7 +11,7 @@
</code-component> </code-component>
</div> </div>
<div style="overflow: hidden; width: 100%; height: 100%; display: flex; flex-flow: row"> <div style="overflow: hidden; width: 100%; height: 100%; display: flex; flex-flow: row">
<div #preview style="flex: 1 1 auto; user-select: initial;" (dblclick)="toggleEditMode()"> <div #preview class ="notebook-preview" style="flex: 1 1 auto; user-select: initial;" (dblclick)="toggleEditMode()">
</div> </div>
<div #moreactions class="moreActions" style="flex: 0 0 auto; display: flex; flex-flow:column;width: 20px; min-height: 20px; max-height: 20px; padding-top: 0px; orientation: portrait"> <div #moreactions class="moreActions" style="flex: 0 0 auto; display: flex; flex-flow:column;width: 20px; min-height: 20px; max-height: 20px; padding-top: 0px; orientation: portrait">
</div> </div>

View File

@@ -149,10 +149,10 @@ export class SparkMagicContexts {
} }
} }
let profile = connectionInfo as IConnectionProfile; let profile = connectionInfo as IConnectionProfile;
if (foundSavedKernelInSpecs && specs && connectionInfo && profile.providerName === notebookConstants.hadoopKnoxProviderName) { if (specs && connectionInfo && profile.providerName === notebookConstants.hadoopKnoxProviderName) {
// set default kernel to default spark kernel if profile exists // set default kernel to default spark kernel if profile exists
// otherwise, set default to kernel info loaded from existing file // otherwise, set default to kernel info loaded from existing file
defaultKernel = !savedKernelInfo ? specs.kernels.find((spec) => spec.name === notebookConstants.defaultSparkKernel) : savedKernelInfo; defaultKernel = !foundSavedKernelInSpecs ? specs.kernels.find((spec) => spec.name === notebookConstants.defaultSparkKernel) : foundSavedKernelInSpecs;
} else { } else {
// Handle kernels // Handle kernels
if (savedKernelInfo && savedKernelInfo.name.toLowerCase().indexOf('spark') > -1) { if (savedKernelInfo && savedKernelInfo.name.toLowerCase().indexOf('spark') > -1) {

View File

@@ -391,7 +391,10 @@ export class NotebookComponent extends AngularDisposable implements OnInit, OnDe
} }
promptForPath(defaultPath: string): TPromise<string> { promptForPath(defaultPath: string): TPromise<string> {
return this.windowService.showSaveDialog({ defaultPath }); return this.windowService.showSaveDialog({
defaultPath: defaultPath,
filters: [{ name: localize('notebookFile', 'Notebook'), extensions: ['ipynb']}]
});
} }
// Entry point to save notebook // Entry point to save notebook

View File

@@ -22,7 +22,7 @@ import { Widget } from 'vs/base/browser/ui/widget';
import { Sash, IHorizontalSashLayoutProvider, ISashEvent, Orientation } from 'vs/base/browser/ui/sash/sash'; import { Sash, IHorizontalSashLayoutProvider, ISashEvent, Orientation } from 'vs/base/browser/ui/sash/sash';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IOverlayWidget, IOverlayWidgetPosition, OverlayWidgetPositionPreference } from 'vs/editor/browser/editorBrowser'; import { IOverlayWidget, IOverlayWidgetPosition, OverlayWidgetPositionPreference } from 'vs/editor/browser/editorBrowser';
import { FIND_IDS, MATCHES_LIMIT, CONTEXT_FIND_INPUT_FOCUSED } from 'vs/editor/contrib/find/findModel'; import { FIND_IDS, CONTEXT_FIND_INPUT_FOCUSED } from 'vs/editor/contrib/find/findModel';
import { FindReplaceState, FindReplaceStateChangedEvent } from 'vs/editor/contrib/find/findState'; import { FindReplaceState, FindReplaceStateChangedEvent } from 'vs/editor/contrib/find/findState';
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey'; import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
import { ITheme, registerThemingParticipant, IThemeService } from 'vs/platform/theme/common/themeService'; import { ITheme, registerThemingParticipant, IThemeService } from 'vs/platform/theme/common/themeService';
@@ -36,7 +36,7 @@ const NLS_FIND_INPUT_PLACEHOLDER = nls.localize('placeholder.find', "Find");
const NLS_PREVIOUS_MATCH_BTN_LABEL = nls.localize('label.previousMatchButton', "Previous match"); const NLS_PREVIOUS_MATCH_BTN_LABEL = nls.localize('label.previousMatchButton', "Previous match");
const NLS_NEXT_MATCH_BTN_LABEL = nls.localize('label.nextMatchButton', "Next match"); const NLS_NEXT_MATCH_BTN_LABEL = nls.localize('label.nextMatchButton', "Next match");
const NLS_CLOSE_BTN_LABEL = nls.localize('label.closeButton', "Close"); const NLS_CLOSE_BTN_LABEL = nls.localize('label.closeButton', "Close");
const NLS_MATCHES_COUNT_LIMIT_TITLE = nls.localize('title.matchesCountLimit', "Only the first 999 results are highlighted, but all find operations work on the entire text."); const NLS_MATCHES_COUNT_LIMIT_TITLE = nls.localize('title.matchesCountLimit', "Your search returned a large number of results, only the first 999 matches will be highlighted.");
const NLS_MATCHES_LOCATION = nls.localize('label.matchesLocation', "{0} of {1}"); const NLS_MATCHES_LOCATION = nls.localize('label.matchesLocation', "{0} of {1}");
const NLS_NO_RESULTS = nls.localize('label.noResults', "No Results"); const NLS_NO_RESULTS = nls.localize('label.noResults', "No Results");
@@ -46,6 +46,8 @@ const FIND_INPUT_AREA_WIDTH = PART_WIDTH - 54;
let MAX_MATCHES_COUNT_WIDTH = 69; let MAX_MATCHES_COUNT_WIDTH = 69;
export const PROFILER_MAX_MATCHES = 999;
export const ACTION_IDS = { export const ACTION_IDS = {
FIND_NEXT: 'findNext', FIND_NEXT: 'findNext',
FIND_PREVIOUS: 'findPrev' FIND_PREVIOUS: 'findPrev'
@@ -86,6 +88,8 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
private _resizeSash: Sash; private _resizeSash: Sash;
private searchTimeoutHandle: number;
constructor( constructor(
tableController: ITableController, tableController: ITableController,
state: FindReplaceState, state: FindReplaceState,
@@ -213,7 +217,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
private _updateMatchesCount(): void { private _updateMatchesCount(): void {
this._matchesCount.style.minWidth = MAX_MATCHES_COUNT_WIDTH + 'px'; this._matchesCount.style.minWidth = MAX_MATCHES_COUNT_WIDTH + 'px';
if (this._state.matchesCount >= MATCHES_LIMIT) { if (this._state.matchesCount >= PROFILER_MAX_MATCHES) {
this._matchesCount.title = NLS_MATCHES_COUNT_LIMIT_TITLE; this._matchesCount.title = NLS_MATCHES_COUNT_LIMIT_TITLE;
} else { } else {
this._matchesCount.title = ''; this._matchesCount.title = '';
@@ -227,8 +231,8 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
let label: string; let label: string;
if (this._state.matchesCount > 0) { if (this._state.matchesCount > 0) {
let matchesCount: string = String(this._state.matchesCount); let matchesCount: string = String(this._state.matchesCount);
if (this._state.matchesCount >= MATCHES_LIMIT) { if (this._state.matchesCount >= PROFILER_MAX_MATCHES) {
matchesCount += '+'; matchesCount = PROFILER_MAX_MATCHES + '+';
} }
let matchesPosition: string = String(this._state.matchesPosition); let matchesPosition: string = String(this._state.matchesPosition);
if (matchesPosition === '0') { if (matchesPosition === '0') {
@@ -401,7 +405,14 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
this._findInput.setWholeWords(!!this._state.wholeWord); this._findInput.setWholeWords(!!this._state.wholeWord);
this._register(this._findInput.onKeyDown((e) => this._onFindInputKeyDown(e))); this._register(this._findInput.onKeyDown((e) => this._onFindInputKeyDown(e)));
this._register(this._findInput.onInput(() => { this._register(this._findInput.onInput(() => {
this._state.change({ searchString: this._findInput.getValue() }, true); let self = this;
if (self.searchTimeoutHandle) {
clearTimeout(self.searchTimeoutHandle);
}
this.searchTimeoutHandle = setTimeout(function () {
self._state.change({ searchString: self._findInput.getValue() }, true);
}, 300);
})); }));
this._register(this._findInput.onDidOptionChange(() => { this._register(this._findInput.onDidOptionChange(() => {
this._state.change({ this._state.change({

View File

@@ -27,6 +27,7 @@ import { Event, Emitter } from 'vs/base/common/event';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Dimension } from 'vs/base/browser/dom'; import { Dimension } from 'vs/base/browser/dom';
import { textFormatter } from 'sql/parts/grid/services/sharedServices'; import { textFormatter } from 'sql/parts/grid/services/sharedServices';
import { PROFILER_MAX_MATCHES } from 'sql/parts/profiler/editor/controller/profilerFindWidget';
export interface ProfilerTableViewState { export interface ProfilerTableViewState {
scrollTop: number; scrollTop: number;
@@ -214,7 +215,7 @@ export class ProfilerTableEditor extends BaseEditor implements IProfilerControll
if (e.searchString) { if (e.searchString) {
if (this._input && this._input.data) { if (this._input && this._input.data) {
if (this._findState.searchString) { if (this._findState.searchString) {
this._input.data.find(this._findState.searchString).then(p => { this._input.data.find(this._findState.searchString, PROFILER_MAX_MATCHES).then(p => {
if (p) { if (p) {
this._profilerTable.setActiveCell(p.row, p.col); this._profilerTable.setActiveCell(p.row, p.col);
this._updateFinderMatchState(); this._updateFinderMatchState();

View File

@@ -305,6 +305,11 @@ let registryProperties = {
'description': localize('sql.saveAsCsv.encoding', '[Optional] File encoding used when saving results as CSV'), 'description': localize('sql.saveAsCsv.encoding', '[Optional] File encoding used when saving results as CSV'),
'default': 'utf-8' 'default': 'utf-8'
}, },
'sql.results.streaming': {
'type': 'boolean',
'description': localize('sql.results.streaming', 'Enable results streaming; contains few minor visual issues'),
'default': true
},
'sql.copyIncludeHeaders': { 'sql.copyIncludeHeaders': {
'type': 'boolean', 'type': 'boolean',
'description': localize('sql.copyIncludeHeaders', '[Optional] Configuration options for copying results from the Results View'), 'description': localize('sql.copyIncludeHeaders', '[Optional] Configuration options for copying results from the Results View'),

View File

@@ -188,23 +188,24 @@ export class GridPanel extends ViewletPanel {
} }
private onResultSet(resultSet: sqlops.ResultSetSummary | sqlops.ResultSetSummary[]) { private onResultSet(resultSet: sqlops.ResultSetSummary | sqlops.ResultSetSummary[]) {
this.addResultSet(resultSet); if (this.configurationService.getValue<boolean>('sql.results.streaming')) {
this.addResultSet(resultSet);
this.tables.map(t => { this.tables.map(t => {
t.state.canBeMaximized = this.tables.length > 1; t.state.canBeMaximized = this.tables.length > 1;
}); });
this.maximumBodySize = this.tables.reduce((p, c) => { this.maximumBodySize = this.tables.reduce((p, c) => {
return p + c.maximumSize; return p + c.maximumSize;
}, 0); }, 0);
if (this.state && this.state.scrollPosition) { if (this.state && this.state.scrollPosition) {
this.splitView.setScrollPosition(this.state.scrollPosition); this.splitView.setScrollPosition(this.state.scrollPosition);
}
} }
} }
private updateResultSet(resultSet: sqlops.ResultSetSummary | sqlops.ResultSetSummary[]) { private updateResultSet(resultSet: sqlops.ResultSetSummary | sqlops.ResultSetSummary[]) {
let resultsToUpdate: sqlops.ResultSetSummary[]; let resultsToUpdate: sqlops.ResultSetSummary[];
if (!Array.isArray(resultSet)) { if (!Array.isArray(resultSet)) {
resultsToUpdate = [resultSet]; resultsToUpdate = [resultSet];
@@ -212,21 +213,42 @@ export class GridPanel extends ViewletPanel {
resultsToUpdate = resultSet; resultsToUpdate = resultSet;
} }
for (let set of resultsToUpdate) { if (this.configurationService.getValue<boolean>('sql.results.streaming')) {
let table = this.tables.find(t => t.resultSet.batchId === set.batchId && t.resultSet.id === set.id); for (let set of resultsToUpdate) {
if (table) { let table = this.tables.find(t => t.resultSet.batchId === set.batchId && t.resultSet.id === set.id);
table.updateResult(set); if (table) {
} else { table.updateResult(set);
warn('Got result set update request for non-existant table'); } else {
warn('Got result set update request for non-existant table');
}
} }
}
this.maximumBodySize = this.tables.reduce((p, c) => { this.maximumBodySize = this.tables.reduce((p, c) => {
return p + c.maximumSize; return p + c.maximumSize;
}, 0); }, 0);
if (this.state && this.state.scrollPosition) { if (this.state && this.state.scrollPosition) {
this.splitView.setScrollPosition(this.state.scrollPosition); this.splitView.setScrollPosition(this.state.scrollPosition);
}
} else {
let change = false;
for (let set of resultsToUpdate) {
if (set.complete) {
this.addResultSet(resultSet);
change = true;
}
}
if (change) {
this.maximumBodySize = this.tables.reduce((p, c) => {
return p + c.maximumSize;
}, 0);
if (this.state && this.state.scrollPosition) {
this.splitView.setScrollPosition(this.state.scrollPosition);
}
}
} }
} }