Compare commits

...

17 Commits
1.4.2 ... 1.3.9

Author SHA1 Message Date
kisantia
cacf0777c7 Moving onValidityChanged listener to showPage() so that it gets added to pages that are added to the wizard after the initial start up (#3691) 2019-01-14 15:01:54 -08:00
Karl Burtram
cb433fbeac Bump Azure Data Studio to 1.3.9 2019-01-14 14:24:28 -08:00
Kevin Cunnane
8f6736df5e Fix #3736 Notebook: cannot connect to SQL big data cluster due to empty config.json file (#3738)
- Writing the config file in the core for now, will look to move to the extension in Feb release
2019-01-14 14:19:45 -08:00
Anthony Dresser
ef76d730e3 fix html formatting in grid (#3722) 2019-01-14 14:15:25 -08:00
Karl Burtram
aabbeeffa9 Add connection dialog icon dark theme and HC styles (#3721) 2019-01-14 14:13:43 -08:00
Anthony Dresser
7a513de543 Duplicate Result sets (fix merge conflicts) 2019-01-14 14:12:29 -08:00
Karl Burtram
abbd5ec037 Add Idera extension to recommendation list (#3709) 2019-01-14 14:09:08 -08:00
Karl Burtram
84009f65ec Save grid selection/vertical scroll when switching tabs 2019-01-08 15:37:20 -08:00
kisantia
191648df0a Fix database not getting set correctly in DacFx wizard deploy scenario (#3641)
* fix db not getting set correctly for deploy scenario if coming from import page

* removed space so that comments go directly after //
2019-01-07 12:06:20 -08:00
Matt Irvine
1265a56ff4 Update edit data for result set streaming changes (#3634) 2019-01-07 12:06:11 -08:00
Aditya Bist
2171d44922 removed potentially PII (#3619) 2018-12-12 14:13:50 -08:00
Anthony Dresser
812f315e69 Account for different situations for stream setting (#3615)
* add cases for different situation

* default streaming setting false
2018-12-12 12:12:18 -08:00
Karl Burtram
d48258a0fb Turn off "something went wrong" message (#3606) 2018-12-11 16:19:23 -08:00
Karl Burtram
8ec78f67af Merge branch 'master' into release/1.3 2018-12-11 15:10:32 -08:00
Karl Burtram
348b03327e Merge branch 'master' into release/1.3 2018-12-11 11:29:01 -08:00
Karl Burtram
6497bbcc38 Merge branch 'master' into release/1.3 2018-12-10 17:39:23 -08:00
Karl Burtram
a1abca26df Remove a style that is breaking the "Clear MRU" list (#3587) 2018-12-10 17:36:55 -08:00
16 changed files with 215 additions and 160 deletions

View File

@@ -32,7 +32,7 @@ export class DeployConfigPage extends DacFxConfigPage {
}
async start(): Promise<boolean> {
let serverComponent = await this.createServerDropdown(true);
let serverComponent = await this.createServerDropdown(true);
let fileBrowserComponent = await this.createFileBrowser();
this.databaseComponent = await this.createDatabaseTextBox();
this.databaseComponent.title = localize('dacFx.databaseNameTextBox', 'Database Name');
@@ -131,7 +131,7 @@ export class DeployConfigPage extends DacFxConfigPage {
this.model.database = this.databaseTextBox.value;
});
// Initialize with upgrade existing true
//Initialize with upgrade existing true
upgradeRadioButton.checked = true;
this.model.upgradeExisting = true;
@@ -149,10 +149,10 @@ export class DeployConfigPage extends DacFxConfigPage {
}
protected async createDeployDatabaseDropdown(): Promise<sqlops.FormComponent> {
this.databaseDropdown = this.view.modelBuilder.dropDown().withProperties({
this.databaseDropdown = this.view.modelBuilder.dropDown().withProperties({
required: true
}).component();
// Handle database changes
//Handle database changes
this.databaseDropdown.onValueChanged(async () => {
this.model.database = (<sqlops.CategoryValue>this.databaseDropdown.value).name;
});
@@ -172,7 +172,8 @@ export class DeployConfigPage extends DacFxConfigPage {
}
let values = await this.getDatabaseValues();
if (this.model.database === undefined) {
//set the database to the first dropdown value if upgrading, otherwise it should get set to the textbox value
if (this.model.upgradeExisting) {
this.model.database = values[0].name;
}

View File

@@ -1,6 +1,6 @@
{
"name": "azuredatastudio",
"version": "1.3.8",
"version": "1.3.9",
"distro": "8c3e97e3425cc9814496472ab73e076de2ba99ee",
"author": {
"name": "Microsoft Corporation"

View File

@@ -42,7 +42,8 @@
"Microsoft.server-report",
"Microsoft.sql-vnext",
"Microsoft.whoisactive",
"Redgate.sql-search"
"Redgate.sql-search",
"IDERA.sqldm-performance-insights"
],
"extensionsGallery": {
"serviceUrl": "https://sqlopsextensions.blob.core.windows.net/marketplace/v1/extensionsGallery.json"

View File

@@ -90,6 +90,8 @@
margin: 0px 13px;
}
.vs-dark .connection-dialog .connection-history-actions .action-label.icon,
.hc-black .connection-dialog .connection-history-actions .action-label.icon,
.connection-dialog .connection-history-actions .action-label.icon {
display: block;
height: 20px;
@@ -105,10 +107,12 @@
background: url('clear-search-results.svg');
}
/*
.vs-dark .search-action.clear-search-results,
.hc-black .search-action.clear-search-results {
background: url('clear-search-results-dark.svg');
}
*/
.connection-details-title {
font-size: 14px;

View File

@@ -168,8 +168,7 @@ export const DashboardModule = (params, selector: string, instantiationService:
if (e instanceof NavigationEnd) {
this.navigations++;
TelemetryUtils.addTelemetry(this.telemetryService, TelemetryKeys.DashboardNavigated, {
numberOfNavigations: this.navigations,
routeUrl: e.url
numberOfNavigations: this.navigations
});
}
});

View File

@@ -48,13 +48,13 @@ export function textFormatter(row: number, cell: any, value: any, columnDef: any
if (!value.isNull) {
valueToDisplay = value.displayValue.replace(/(\r\n|\n|\r)/g, ' ');
valueToDisplay = escape(valueToDisplay.length > 250 ? valueToDisplay.slice(0, 250) + '...' : valueToDisplay);
titleValue = value.displayValue;
titleValue = valueToDisplay;
} else {
cellClasses += ' missing-value';
}
} else if (typeof value === 'string') {
valueToDisplay = escape(value.length > 250 ? value.slice(0, 250) + '...' : value);
titleValue = value;
titleValue = valueToDisplay;
}
return `<span title="${titleValue}" class="${cellClasses}">${valueToDisplay}</span>`;

View File

@@ -343,6 +343,9 @@ export class EditDataComponent extends GridParentComponent implements OnInit, On
handleResultSet(self: EditDataComponent, event: any): void {
// Clone the data before altering it to avoid impacting other subscribers
let resultSet = Object.assign({}, event.data);
if (!resultSet.complete) {
return;
}
// Add an extra 'new row'
resultSet.rowCount++;

View File

@@ -350,7 +350,7 @@ export class NotebookModel extends Disposable implements INotebookModel {
if (!newConnection && this._activeContexts.defaultConnection.options['host'] === host) {
newConnection = this._activeContexts.defaultConnection;
}
SparkMagicContexts.configureContext(this.notebookOptions);
SparkMagicContexts.configureContext();
this._hadoopConnection = new NotebookConnection(newConnection);
this.refreshConnections(newConnection);
this._clientSession.updateConnection(this._hadoopConnection);

View File

@@ -8,7 +8,6 @@
import * as path from 'path';
import { nb } from 'sqlops';
import * as json from 'vs/base/common/json';
import * as pfs from 'vs/base/node/pfs';
import { localize } from 'vs/nls';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
@@ -17,11 +16,48 @@ import * as notebookUtils from '../notebookUtils';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
const configBase = {
'kernel_python_credentials': {
'url': ''
},
'kernel_scala_credentials': {
'url': ''
},
'kernel_r_credentials': {
'url': ''
},
'ignore_ssl_errors': true,
'logging_config': {
'version': 1,
'formatters': {
'magicsFormatter': {
'format': '%(asctime)s\t%(levelname)s\t%(message)s',
'datefmt': ''
}
},
'handlers': {
'magicsHandler': {
'class': 'hdijupyterutils.filehandler.MagicsFileHandler',
'formatter': 'magicsFormatter',
'home_path': ''
}
},
'loggers': {
'magicsLogger': {
'handlers': ['magicsHandler'],
'level': 'DEBUG',
'propagate': 0
}
}
}
};
export class SparkMagicContexts {
public static get DefaultContext(): IDefaultConnection {
// TODO NOTEBOOK REFACTOR fix default connection handling
let defaultConnection: IConnectionProfile = <any> {
let defaultConnection: IConnectionProfile = <any>{
providerName: notebookConstants.hadoopKnoxProviderName,
id: '-1',
options:
@@ -47,7 +83,7 @@ export class SparkMagicContexts {
let connections: IDefaultConnection = this.DefaultContext;
if (!profile) {
if (!kernelChangedArgs || !kernelChangedArgs.newValue ||
(kernelChangedArgs.oldValue && kernelChangedArgs.newValue.id === kernelChangedArgs.oldValue.id)) {
(kernelChangedArgs.oldValue && kernelChangedArgs.newValue.id === kernelChangedArgs.oldValue.id)) {
// nothing to do, kernels are the same or new kernel is undefined
return connections;
}
@@ -55,7 +91,7 @@ export class SparkMagicContexts {
if (kernelChangedArgs && kernelChangedArgs.newValue && kernelChangedArgs.newValue.name) {
switch (kernelChangedArgs.newValue.name) {
case (notebookConstants.python3):
// python3 case, use this.DefaultContext for the only connection
// python3 case, use this.DefaultContext for the only connection
break;
//TO DO: Handle server connections based on kernel type. Right now, we call the same method for all kernel types.
default:
@@ -76,13 +112,13 @@ export class SparkMagicContexts {
let defaultConnection: IConnectionProfile = SparkMagicContexts.DefaultContext.defaultConnection;
let activeConnections: IConnectionProfile[] = await connectionService.getActiveConnections();
// If no connections exist, only show 'n/a'
if (activeConnections && activeConnections.length > 0) {
// Remove all non-Spark connections
activeConnections = activeConnections.filter(conn => conn.providerName === notebookConstants.hadoopKnoxProviderName);
}
if (activeConnections.length === 0) {
return SparkMagicContexts.DefaultContext;
}
if (activeConnections && activeConnections.length > 0) {
// Remove all non-Spark connections
activeConnections = activeConnections.filter(conn => conn.providerName === notebookConstants.hadoopKnoxProviderName);
}
if (activeConnections.length === 0) {
return SparkMagicContexts.DefaultContext;
}
// If launched from the right click or server dashboard, connection profile data exists, so use that as default
if (profile && profile.options) {
@@ -95,7 +131,7 @@ export class SparkMagicContexts {
defaultConnection = activeConnections[0];
} else {
// TODO NOTEBOOK REFACTOR change this so it's no longer incompatible with IConnectionProfile
defaultConnection = <IConnectionProfile> <any>{
defaultConnection = <IConnectionProfile><any>{
providerName: notebookConstants.hadoopKnoxProviderName,
id: '-1',
options:
@@ -107,31 +143,28 @@ export class SparkMagicContexts {
}
}
return {
otherConnections: activeConnections,
defaultConnection: defaultConnection
otherConnections: activeConnections,
defaultConnection: defaultConnection
};
}
public static async configureContext(options: INotebookModelOptions): Promise<object> {
public static async configureContext(): Promise<object> {
let sparkmagicConfDir = path.join(notebookUtils.getUserHome(), '.sparkmagic');
// TODO NOTEBOOK REFACTOR re-enable this or move to extension. Requires config files to be available in order to work
// await notebookUtils.mkDir(sparkmagicConfDir);
await notebookUtils.mkDir(sparkmagicConfDir);
// // Default to localhost in config file.
// let creds: ICredentials = {
// 'url': 'http://localhost:8088'
// };
// Default to localhost in config file.
let creds: ICredentials = {
'url': 'http://localhost:8088'
};
// let configPath = notebookUtils.getTemplatePath(options.extensionContext.extensionPath, path.join('jupyter_config', 'sparkmagic_config.json'));
// let fileBuffer: Buffer = await pfs.readFile(configPath);
// let fileContents: string = fileBuffer.toString();
// let config: ISparkMagicConfig = json.parse(fileContents);
// SparkMagicContexts.updateConfig(config, creds, sparkmagicConfDir);
let config: ISparkMagicConfig = Object.assign({}, configBase);
SparkMagicContexts.updateConfig(config, creds, sparkmagicConfDir);
// let configFilePath = path.join(sparkmagicConfDir, 'config.json');
// await pfs.writeFile(configFilePath, JSON.stringify(config));
let configFilePath = path.join(sparkmagicConfDir, 'config.json');
await pfs.writeFile(configFilePath, JSON.stringify(config));
return {'SPARKMAGIC_CONF_DIR': sparkmagicConfDir};
return { 'SPARKMAGIC_CONF_DIR': sparkmagicConfDir };
}
/**
*
@@ -186,10 +219,13 @@ interface ISparkMagicConfig {
kernel_python_credentials: ICredentials;
kernel_scala_credentials: ICredentials;
kernel_r_credentials: ICredentials;
ignore_ssl_errors?: boolean;
logging_config: {
handlers: {
magicsHandler: {
home_path: string;
class?: string;
formatter?: string
}
}
};

View File

@@ -308,7 +308,7 @@ let registryProperties = {
'sql.results.streaming': {
'type': 'boolean',
'description': localize('sql.results.streaming', 'Enable results streaming; contains few minor visual issues'),
'default': true
'default': false
},
'sql.copyIncludeHeaders': {
'type': 'boolean',

View File

@@ -88,7 +88,8 @@ export class GridTableState extends Disposable {
private _canBeMaximized: boolean;
/* The top row of the current scroll */
public scrollPosition = 0;
public scrollPositionY = 0;
public scrollPositionX = 0;
public selection: Slick.Range[];
public activeCell: Slick.Cell;
@@ -145,7 +146,7 @@ export class GridPanel extends ViewletPanel {
super(options, keybindingService, contextMenuService, configurationService);
this.splitView = new ScrollableSplitView(this.container, { enableResizing: false, verticalScrollbarVisibility: ScrollbarVisibility.Visible });
this.splitView.onScroll(e => {
if (this.state) {
if (this.state && this.splitView.length !== 0) {
this.state.scrollPosition = e;
}
});
@@ -185,12 +186,31 @@ export class GridPanel extends ViewletPanel {
}
this.reset();
}));
this.addResultSet(this.runner.batchSets.reduce<sqlops.ResultSetSummary[]>((p, e) => {
if (this.configurationService.getValue<boolean>('sql.results.streaming')) {
p = p.concat(e.resultSetSummaries);
} else {
p = p.concat(e.resultSetSummaries.filter(c => c.complete));
}
return p;
}, []));
this.maximumBodySize = this.tables.reduce((p, c) => {
return p + c.maximumSize;
}, 0);
if (this.state && this.state.scrollPosition) {
this.splitView.setScrollPosition(this.state.scrollPosition);
}
}
private onResultSet(resultSet: sqlops.ResultSetSummary | sqlops.ResultSetSummary[]) {
if (this.configurationService.getValue<boolean>('sql.results.streaming')) {
this.addResultSet(resultSet);
let resultsToAdd: sqlops.ResultSetSummary[];
if (!Array.isArray(resultSet)) {
resultsToAdd = [resultSet];
} else {
resultsToAdd = resultSet.splice(0);
}
const sizeChanges = () => {
this.tables.map(t => {
t.state.canBeMaximized = this.tables.length > 1;
});
@@ -202,6 +222,17 @@ export class GridPanel extends ViewletPanel {
if (this.state && this.state.scrollPosition) {
this.splitView.setScrollPosition(this.state.scrollPosition);
}
};
if (this.configurationService.getValue<boolean>('sql.results.streaming')) {
this.addResultSet(resultsToAdd);
sizeChanges();
} else {
resultsToAdd = resultsToAdd.filter(e => e.complete);
if (resultsToAdd.length > 0) {
this.addResultSet(resultsToAdd);
}
sizeChanges();
}
}
@@ -210,9 +241,19 @@ export class GridPanel extends ViewletPanel {
if (!Array.isArray(resultSet)) {
resultsToUpdate = [resultSet];
} else {
resultsToUpdate = resultSet;
resultsToUpdate = resultSet.splice(0);
}
const sizeChanges = () => {
this.maximumBodySize = this.tables.reduce((p, c) => {
return p + c.maximumSize;
}, 0);
if (this.state && this.state.scrollPosition) {
this.splitView.setScrollPosition(this.state.scrollPosition);
}
};
if (this.configurationService.getValue<boolean>('sql.results.streaming')) {
for (let set of resultsToUpdate) {
let table = this.tables.find(t => t.resultSet.batchId === set.batchId && t.resultSet.id === set.id);
@@ -222,47 +263,20 @@ export class GridPanel extends ViewletPanel {
warn('Got result set update request for non-existant table');
}
}
this.maximumBodySize = this.tables.reduce((p, c) => {
return p + c.maximumSize;
}, 0);
if (this.state && this.state.scrollPosition) {
this.splitView.setScrollPosition(this.state.scrollPosition);
}
sizeChanges();
} else {
let change = false;
for (let set of resultsToUpdate) {
if (set.complete) {
this.addResultSet(set);
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);
}
resultsToUpdate = resultsToUpdate.filter(e => e.complete);
if (resultsToUpdate.length > 0) {
this.addResultSet(resultsToUpdate);
}
sizeChanges();
}
}
private addResultSet(resultSet: sqlops.ResultSetSummary | sqlops.ResultSetSummary[]) {
let resultsToAdd: sqlops.ResultSetSummary[];
if (!Array.isArray(resultSet)) {
resultsToAdd = [resultSet];
} else {
resultsToAdd = resultSet;
}
private addResultSet(resultSet: sqlops.ResultSetSummary[]) {
let tables: GridTable<any>[] = [];
for (let set of resultsToAdd) {
for (let set of resultSet) {
let tableState: GridTableState;
if (this._state) {
tableState = this.state.tableStates.find(e => e.batchId === set.batchId && e.resultId === set.id);
@@ -442,6 +456,7 @@ class GridTable<T> extends Disposable implements IView {
});
this.dataProvider.dataRows = collection;
this.table.updateRowCount();
this.setupState();
}
public onRemove() {
@@ -535,12 +550,18 @@ class GridTable<T> extends Disposable implements IView {
});
this.table.grid.onScroll.subscribe((e, data) => {
if (!this.scrolled && this.state.scrollPosition && isInDOM(this.container)) {
if (!this.visible) {
// If the grid is not set up yet it can get scroll events resetting the top to 0px,
// so ignore those events
return;
}
if (!this.scrolled && (this.state.scrollPositionY || this.state.scrollPositionX) && isInDOM(this.container)) {
this.scrolled = true;
this.table.grid.scrollTo(this.state.scrollPosition);
this.restoreScrollState();
}
if (this.state && isInDOM(this.container)) {
this.state.scrollPosition = data.scrollTop;
this.state.scrollPositionY = data.scrollTop;
this.state.scrollPositionX = data.scrollLeft;
}
});
@@ -549,8 +570,13 @@ class GridTable<T> extends Disposable implements IView {
this.state.activeCell = this.table.grid.getActiveCell();
}
});
}
this.setupState();
private restoreScrollState() {
if (this.state.scrollPositionX || this.state.scrollPositionY) {
this.table.grid.scrollTo(this.state.scrollPositionY);
this.table.grid.getContainerNode().children[3].scrollLeft = this.state.scrollPositionX;
}
}
private setupState() {
@@ -559,20 +585,18 @@ class GridTable<T> extends Disposable implements IView {
this._register(this.state.onCanBeMaximizedChange(this.rebuildActionBar, this));
if (this.state.scrollPosition) {
// most of the time this won't do anything
this.table.grid.scrollTo(this.state.scrollPosition);
// the problem here is that the scrolling state slickgrid uses
// doesn't work with it offDOM.
}
this.restoreScrollState();
if (this.state.selection) {
this.selectionModel.setSelectedRanges(this.state.selection);
}
// Setting the active cell resets the selection so save it here
let savedSelection = this.state.selection;
if (this.state.activeCell) {
this.table.setActiveCell(this.state.activeCell.row, this.state.activeCell.cell);
}
if (savedSelection) {
this.selectionModel.setSelectedRanges(savedSelection);
}
}
public get state(): GridTableState {

View File

@@ -144,6 +144,7 @@ export class MessagePanel extends ViewletPanel {
this.reset();
this.queryRunnerDisposables.push(runner.onQueryStart(() => this.reset()));
this.queryRunnerDisposables.push(runner.onMessage(e => this.onMessage(e)));
this.onMessage(runner.messages);
}
private onMessage(message: IResultMessage | IResultMessage[]) {

View File

@@ -387,8 +387,12 @@ export class QueryModelService implements IQueryModelService {
// We do not have a query runner for this editor, so create a new one
// and map it to the results uri
queryRunner = this._instantiationService.createInstance(QueryRunner, ownerUri);
const resultSetEventType = 'resultSet';
queryRunner.addListener(QREvents.RESULT_SET, resultSet => {
this._fireQueryEvent(ownerUri, 'resultSet', resultSet);
this._fireQueryEvent(ownerUri, resultSetEventType, resultSet);
});
queryRunner.onResultSetUpdate(resultSetSummary => {
this._fireQueryEvent(ownerUri, resultSetEventType, resultSetSummary);
});
queryRunner.addListener(QREvents.BATCH_START, batch => {
let link = undefined;

View File

@@ -13,6 +13,7 @@ import { IQueryManagementService } from 'sql/parts/query/common/queryManagement'
import * as Utils from 'sql/parts/connection/common/utils';
import { SaveFormat } from 'sql/parts/grid/common/interfaces';
import { echo, debounceEvent } from 'sql/base/common/event';
import { Deferred } from 'sql/base/common/promise';
import Severity from 'vs/base/common/severity';
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
@@ -26,7 +27,6 @@ import { Emitter, Event } from 'vs/base/common/event';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ResultSerializer } from 'sql/parts/query/common/resultSerializer';
import { TPromise } from 'vs/base/common/winjs.base';
import { Deferred } from 'sql/base/common/promise';
export interface IEditSessionReadyEvent {
ownerUri: string;
@@ -69,6 +69,7 @@ export default class QueryRunner extends Disposable {
private _isExecuting: boolean = false;
private _hasCompleted: boolean = false;
private _batchSets: sqlops.BatchSummary[] = [];
private _messages: sqlops.IResultMessage[] = [];
private _eventEmitter = new EventEmitter();
private _isQueryPlan: boolean;
@@ -77,40 +78,13 @@ export default class QueryRunner extends Disposable {
public get planXml(): Thenable<string> { return this._planXml.promise; }
private _onMessage = this._register(new Emitter<sqlops.IResultMessage>());
private _debouncedMessage = debounceEvent<sqlops.IResultMessage, sqlops.IResultMessage[]>(this._onMessage.event, (l, e) => {
// on first run
if (types.isUndefinedOrNull(l)) {
return [e];
} else {
return l.concat(e);
}
});
private _echoedMessages = echo(this._debouncedMessage.event);
public readonly onMessage = this._echoedMessages.event;
public readonly onMessage = this._onMessage.event;
private _onResultSet = this._register(new Emitter<sqlops.ResultSetSummary>());
private _debouncedResultSet = debounceEvent<sqlops.ResultSetSummary, sqlops.ResultSetSummary[]>(this._onResultSet.event, (l, e) => {
// on first run
if (types.isUndefinedOrNull(l)) {
return [e];
} else {
return l.concat(e);
}
});
private _echoedResultSet = echo(this._debouncedResultSet.event);
public readonly onResultSet = this._echoedResultSet.event;
public readonly onResultSet = this._onResultSet.event;
private _onResultSetUpdate = this._register(new Emitter<sqlops.ResultSetSummary>());
private _debouncedResultSetUpdate = debounceEvent<sqlops.ResultSetSummary, sqlops.ResultSetSummary[]>(this._onResultSetUpdate.event, (l, e) => {
// on first run
if (types.isUndefinedOrNull(l)) {
return [e];
} else {
return l.concat(e);
}
});
private _echoedResultSetUpdate = echo(this._debouncedResultSetUpdate.event);
public readonly onResultSetUpdate = this._echoedResultSetUpdate.event;
public readonly onResultSetUpdate = this._onResultSetUpdate.event;
private _onQueryStart = this._register(new Emitter<void>());
public readonly onQueryStart: Event<void> = this._onQueryStart.event;
@@ -153,8 +127,18 @@ export default class QueryRunner extends Disposable {
return this._hasCompleted;
}
get batchSets(): sqlops.BatchSummary[] {
return this._batchSets;
/**
* For public use only, for private use, directly access the member
*/
public get batchSets(): sqlops.BatchSummary[] {
return this._batchSets.slice(0);
}
/**
* For public use only, for private use, directly access the member
*/
public get messages(): sqlops.IResultMessage[] {
return this._messages.slice(0);
}
// PUBLIC METHODS ======================================================
@@ -202,10 +186,6 @@ export default class QueryRunner extends Disposable {
if (this.isExecuting) {
return TPromise.as(undefined);
}
this._echoedMessages.clear();
this._echoedResultSet.clear();
this._debouncedMessage.clear();
this._debouncedResultSet.clear();
this._planXml = new Deferred<string>();
this._batchSets = [];
this._hasCompleted = false;
@@ -274,7 +254,7 @@ export default class QueryRunner extends Disposable {
this._hasCompleted = true;
this._batchSets = result.batchSummaries ? result.batchSummaries : [];
this.batchSets.map(batch => {
this._batchSets.map(batch => {
if (batch.selection) {
batch.selection.startLine = batch.selection.startLine + this._resultLineOffset;
batch.selection.endLine = batch.selection.endLine + this._resultLineOffset;
@@ -291,6 +271,7 @@ export default class QueryRunner extends Disposable {
isError: false,
time: undefined
};
this._messages.push(message);
this._onQueryEnd.fire(timeStamp);
this._onMessage.fire(message);
@@ -312,7 +293,7 @@ export default class QueryRunner extends Disposable {
batch.resultSetSummaries = [];
// Store the batch
this.batchSets[batch.id] = batch;
this._batchSets[batch.id] = batch;
let message = {
// account for index by 1
@@ -321,6 +302,7 @@ export default class QueryRunner extends Disposable {
selection: batch.selection,
isError: false
};
this._messages.push(message);
this._eventEmitter.emit(EventType.BATCH_START, batch);
this._onMessage.fire(message);
this._onBatchStart.fire(batch);
@@ -333,7 +315,7 @@ export default class QueryRunner extends Disposable {
let batch: sqlops.BatchSummary = result.batchSummary;
// Store the batch again to get the rest of the data
this.batchSets[batch.id] = batch;
this._batchSets[batch.id] = batch;
let executionTime = <number>(Utils.parseTimeString(batch.executionElapsed) || 0);
this._totalElapsedMilliseconds += executionTime;
if (executionTime > 0) {
@@ -355,8 +337,8 @@ export default class QueryRunner extends Disposable {
if (!resultSet.batchId) {
// Missing the batchId. In this case, default to always using the first batch in the list
// or create one in the case the DMP extension didn't obey the contract perfectly
if (this.batchSets.length > 0) {
batchSet = this.batchSets[0];
if (this._batchSets.length > 0) {
batchSet = this._batchSets[0];
} else {
batchSet = <sqlops.BatchSummary>{
id: 0,
@@ -364,10 +346,10 @@ export default class QueryRunner extends Disposable {
hasError: false,
resultSetSummaries: []
};
this.batchSets[0] = batchSet;
this._batchSets[0] = batchSet;
}
} else {
batchSet = this.batchSets[resultSet.batchId];
batchSet = this._batchSets[resultSet.batchId];
}
// handle getting queryPlanxml if we need too
if (this.isQueryPlan) {
@@ -392,7 +374,7 @@ export default class QueryRunner extends Disposable {
if (result && result.resultSetSummary) {
let resultSet = result.resultSetSummary;
let batchSet: sqlops.BatchSummary;
batchSet = this.batchSets[resultSet.batchId];
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
@@ -415,6 +397,7 @@ export default class QueryRunner extends Disposable {
public handleMessage(obj: sqlops.QueryExecuteMessageParams): void {
let message = obj.message;
message.time = new Date(message.time).toLocaleTimeString();
this._messages.push(message);
// Send the message to the results pane
this._eventEmitter.emit(EventType.MESSAGE, message);
@@ -434,10 +417,10 @@ export default class QueryRunner extends Disposable {
};
return this._queryManagementService.getQueryRows(rowData).then(r => r, error => {
this._notificationService.notify({
severity: Severity.Error,
message: nls.localize('query.gettingRowsFailedError', 'Something went wrong getting more rows: {0}', error)
});
// this._notificationService.notify({
// severity: Severity.Error,
// message: nls.localize('query.gettingRowsFailedError', 'Something went wrong getting more rows: {0}', error)
// });
return error;
});
}
@@ -492,11 +475,11 @@ export default class QueryRunner extends Disposable {
}
resolve(result);
}, error => {
let errorMessage = nls.localize('query.moreRowsFailedError', 'Something went wrong getting more rows:');
self._notificationService.notify({
severity: Severity.Error,
message: `${errorMessage} ${error}`
});
// let errorMessage = nls.localize('query.moreRowsFailedError', 'Something went wrong getting more rows:');
// self._notificationService.notify({
// severity: Severity.Error,
// message: `${errorMessage} ${error}`
// });
reject(error);
});
});
@@ -636,7 +619,7 @@ export default class QueryRunner extends Disposable {
private getColumnHeaders(batchId: number, resultId: number, range: Slick.Range): string[] {
let headers: string[] = undefined;
let batchSummary: sqlops.BatchSummary = this.batchSets[batchId];
let batchSummary: sqlops.BatchSummary = this._batchSets[batchId];
if (batchSummary !== undefined) {
let resultSetSummary = batchSummary.resultSetSummaries[resultId];
headers = resultSetSummary.columnInfo.slice(range.fromCell, range.toCell + 1).map((info, i) => {
@@ -669,6 +652,7 @@ export default class QueryRunner extends Disposable {
time: undefined,
isError: false
};
this._messages.push(message);
// Send the message to the results pane
this._onMessage.fire(message);
}

View File

@@ -97,15 +97,6 @@ export class WizardModal extends Modal {
messageChangeHandler(this._wizard.message);
this._wizard.onMessageChange(message => messageChangeHandler(message));
this._wizard.pages.forEach((page, index) => {
page.onValidityChanged(valid => {
if (index === this._wizard.currentPage) {
this._nextButton.enabled = this._wizard.nextButton.enabled && page.valid;
this._doneButton.enabled = this._wizard.doneButton.enabled && page.valid;
}
});
});
}
private addDialogButton(button: DialogButton, onSelect: () => void = () => undefined, registerClickEvent: boolean = true, requirePageValid: boolean = false): Button {
@@ -198,6 +189,13 @@ export class WizardModal extends Modal {
let currentPageValid = this._wizard.pages[this._wizard.currentPage].valid;
this._nextButton.enabled = this._wizard.nextButton.enabled && currentPageValid;
this._doneButton.enabled = this._wizard.doneButton.enabled && currentPageValid;
pageToShow.onValidityChanged(valid => {
if (index === this._wizard.currentPage) {
this._nextButton.enabled = this._wizard.nextButton.enabled && pageToShow.valid;
this._doneButton.enabled = this._wizard.doneButton.enabled && pageToShow.valid;
}
});
}
private setButtonsForPage(index: number) {

View File

@@ -24,7 +24,7 @@ export function resolveCommonProperties(commit: string, version: string, machine
result['sessionID'] = '';
// __GDPR__COMMON__ "commitHash" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
result['commitHash'] = commit;
result['commitHash'] = '';
// __GDPR__COMMON__ "version" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
result['version'] = version;
// __GDPR__COMMON__ "common.platformVersion" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }