Strict null on some query and connection (#7300)

* wip

* make connection work with strict-nulls

* change comments

* fix tests; remove unneeded type forcing

* address feedback

* adjust the logic of query editor

* clean up typing
This commit is contained in:
Anthony Dresser
2019-10-21 15:50:12 -07:00
committed by GitHub
parent 6a375fdd8c
commit 06e86e57e7
22 changed files with 367 additions and 369 deletions

View File

@@ -36,7 +36,7 @@ export class QueryInfo {
public queryEventQueue: QueryEvent[];
public selection: Array<azdata.ISelectionData>;
public queryInput: QueryInput;
public selectionSnippet: string;
public selectionSnippet?: string;
// Notes if the angular components have obtained the DataService. If not, all messages sent
// via the data service will be lost.
@@ -85,7 +85,10 @@ export class QueryModelService implements IQueryModelService {
// IQUERYMODEL /////////////////////////////////////////////////////////
public getDataService(uri: string): DataService {
let dataService = this._getQueryInfo(uri).dataService;
let dataService: DataService | undefined;
if (this._queryInfoMap.has(uri)) {
dataService = this._getQueryInfo(uri)!.dataService;
}
if (!dataService) {
throw new Error('Could not find data service for uri: ' + uri);
}
@@ -119,40 +122,44 @@ export class QueryModelService implements IQueryModelService {
* angular is listening for them.
*/
public onAngularLoaded(uri: string) {
let info = this._getQueryInfo(uri);
info.dataServiceReady = true;
this._sendQueuedEvents(uri);
if (this._queryInfoMap.has(uri)) {
let info = this._getQueryInfo(uri)!;
info.dataServiceReady = true;
this._sendQueuedEvents(uri);
}
}
/**
* Get more data rows from the current resultSets from the service layer
*/
public getQueryRows(uri: string, rowStart: number, numberOfRows: number, batchId: number, resultId: number): Thenable<azdata.ResultSetSubset> {
return this._getQueryInfo(uri).queryRunner.getQueryRows(rowStart, numberOfRows, batchId, resultId).then(results => {
return results.resultSubset;
});
public getQueryRows(uri: string, rowStart: number, numberOfRows: number, batchId: number, resultId: number): Promise<azdata.ResultSetSubset | undefined> {
if (this._queryInfoMap.has(uri)) {
return this._getQueryInfo(uri)!.queryRunner.getQueryRows(rowStart, numberOfRows, batchId, resultId).then(results => {
return results.resultSubset;
});
} else {
return Promise.resolve(undefined);
}
}
public getEditRows(uri: string, rowStart: number, numberOfRows: number): Thenable<azdata.EditSubsetResult> {
return this._queryInfoMap.get(uri).queryRunner.getEditRows(rowStart, numberOfRows).then(results => {
return results;
});
}
public getConfig(): Promise<{ [key: string]: any }> {
return undefined;
}
public getShortcuts(): Promise<any> {
return undefined;
public getEditRows(uri: string, rowStart: number, numberOfRows: number): Promise<azdata.EditSubsetResult | undefined> {
if (this._queryInfoMap.has(uri)) {
return this._queryInfoMap.get(uri)!.queryRunner.getEditRows(rowStart, numberOfRows).then(results => {
return results;
});
} else {
return Promise.resolve(undefined);
}
}
public copyResults(uri: string, selection: Slick.Range[], batchId: number, resultId: number, includeHeaders?: boolean): void {
this._queryInfoMap.get(uri).queryRunner.copyResults(selection, batchId, resultId, includeHeaders);
if (this._queryInfoMap.has(uri)) {
this._queryInfoMap.get(uri)!.queryRunner.copyResults(selection, batchId, resultId, includeHeaders);
}
}
public setEditorSelection(uri: string, index: number): void {
let info: QueryInfo = this._queryInfoMap.get(uri);
let info = this._queryInfoMap.get(uri);
if (info && info.queryInput) {
info.queryInput.updateSelection(info.selection[index]);
}
@@ -174,7 +181,7 @@ export class QueryModelService implements IQueryModelService {
public isRunningQuery(uri: string): boolean {
return !this._queryInfoMap.has(uri)
? false
: this._getQueryInfo(uri).queryRunner.isExecuting;
: this._getQueryInfo(uri)!.queryRunner.isExecuting;
}
/**
@@ -204,11 +211,11 @@ export class QueryModelService implements IQueryModelService {
private doRunQuery(uri: string, selection: azdata.ISelectionData | string, queryInput: QueryInput,
runCurrentStatement: boolean, runOptions?: azdata.ExecutionPlanOptions): void {
// Reuse existing query runner if it exists
let queryRunner: QueryRunner;
let queryRunner: QueryRunner | undefined;
let info: QueryInfo;
if (this._queryInfoMap.has(uri)) {
info = this._getQueryInfo(uri);
info = this._getQueryInfo(uri)!;
let existingRunner: QueryRunner = info.queryRunner;
// If the query is already in progress, don't attempt to send it
@@ -365,11 +372,11 @@ export class QueryModelService implements IQueryModelService {
}
public cancelQuery(input: QueryRunner | string): void {
let queryRunner: QueryRunner;
let queryRunner: QueryRunner | undefined;
if (typeof input === 'string') {
if (this._queryInfoMap.has(input)) {
queryRunner = this._getQueryInfo(input).queryRunner;
queryRunner = this._getQueryInfo(input)!.queryRunner;
}
} else {
queryRunner = input;
@@ -391,7 +398,7 @@ export class QueryModelService implements IQueryModelService {
severity: Severity.Error,
message: strings.format(LocalizedConstants.msgCancelQueryFailed, error)
});
this._fireQueryEvent(queryRunner.uri, 'complete', 0);
this._fireQueryEvent(queryRunner!.uri, 'complete', 0);
});
}
@@ -415,7 +422,7 @@ export class QueryModelService implements IQueryModelService {
let info: QueryInfo;
if (this._queryInfoMap.has(ownerUri)) {
info = this._getQueryInfo(ownerUri);
info = this._getQueryInfo(ownerUri)!;
let existingRunner: QueryRunner = info.queryRunner;
// If the initialization is already in progress
@@ -522,16 +529,16 @@ export class QueryModelService implements IQueryModelService {
// TODO: Implement query cancellation service
}
public disposeEdit(ownerUri: string): Thenable<void> {
public disposeEdit(ownerUri: string): Promise<void> {
// Get existing query runner
let queryRunner = this.internalGetQueryRunner(ownerUri);
if (queryRunner) {
return queryRunner.disposeEdit(ownerUri);
}
return Promise.resolve(null);
return Promise.resolve();
}
public updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Thenable<azdata.EditUpdateCellResult> {
public updateCell(ownerUri: string, rowId: number, columnId: number, newValue: string): Promise<azdata.EditUpdateCellResult | undefined> {
// Get existing query runner
let queryRunner = this.internalGetQueryRunner(ownerUri);
if (queryRunner) {
@@ -543,10 +550,10 @@ export class QueryModelService implements IQueryModelService {
return Promise.reject(error);
});
}
return Promise.resolve(null);
return Promise.resolve(undefined);
}
public commitEdit(ownerUri): Thenable<void> {
public commitEdit(ownerUri: string): Promise<void> {
// Get existing query runner
let queryRunner = this.internalGetQueryRunner(ownerUri);
if (queryRunner) {
@@ -558,49 +565,49 @@ export class QueryModelService implements IQueryModelService {
return Promise.reject(error);
});
}
return Promise.resolve(null);
return Promise.resolve();
}
public createRow(ownerUri: string): Thenable<azdata.EditCreateRowResult> {
public createRow(ownerUri: string): Promise<azdata.EditCreateRowResult | undefined> {
// Get existing query runner
let queryRunner = this.internalGetQueryRunner(ownerUri);
if (queryRunner) {
return queryRunner.createRow(ownerUri);
}
return Promise.resolve(null);
return Promise.resolve(undefined);
}
public deleteRow(ownerUri: string, rowId: number): Thenable<void> {
public deleteRow(ownerUri: string, rowId: number): Promise<void> {
// Get existing query runner
let queryRunner = this.internalGetQueryRunner(ownerUri);
if (queryRunner) {
return queryRunner.deleteRow(ownerUri, rowId);
}
return Promise.resolve(null);
return Promise.resolve();
}
public revertCell(ownerUri: string, rowId: number, columnId: number): Thenable<azdata.EditRevertCellResult> {
public revertCell(ownerUri: string, rowId: number, columnId: number): Promise<azdata.EditRevertCellResult | undefined> {
// Get existing query runner
let queryRunner = this.internalGetQueryRunner(ownerUri);
if (queryRunner) {
return queryRunner.revertCell(ownerUri, rowId, columnId);
}
return Promise.resolve(null);
return Promise.resolve(undefined);
}
public revertRow(ownerUri: string, rowId: number): Thenable<void> {
public revertRow(ownerUri: string, rowId: number): Promise<void> {
// Get existing query runner
let queryRunner = this.internalGetQueryRunner(ownerUri);
if (queryRunner) {
return queryRunner.revertRow(ownerUri, rowId);
}
return Promise.resolve(null);
return Promise.resolve();
}
public getQueryRunner(ownerUri): QueryRunner {
let queryRunner: QueryRunner = undefined;
public getQueryRunner(ownerUri: string): QueryRunner | undefined {
let queryRunner: QueryRunner | undefined = undefined;
if (this._queryInfoMap.has(ownerUri)) {
queryRunner = this._getQueryInfo(ownerUri).queryRunner;
queryRunner = this._getQueryInfo(ownerUri)!.queryRunner;
}
// return undefined if not found or is already executing
return queryRunner;
@@ -608,13 +615,13 @@ export class QueryModelService implements IQueryModelService {
// PRIVATE METHODS //////////////////////////////////////////////////////
private internalGetQueryRunner(ownerUri): QueryRunner {
let queryRunner: QueryRunner = undefined;
private internalGetQueryRunner(ownerUri: string): QueryRunner | undefined {
let queryRunner: QueryRunner | undefined;
if (this._queryInfoMap.has(ownerUri)) {
let existingRunner = this._getQueryInfo(ownerUri).queryRunner;
let existingRunner = this._getQueryInfo(ownerUri)!.queryRunner;
// If the query is not already executing then set it up
if (!existingRunner.isExecuting) {
queryRunner = this._getQueryInfo(ownerUri).queryRunner;
queryRunner = this._getQueryInfo(ownerUri)!.queryRunner;
}
}
// return undefined if not found or is already executing
@@ -622,7 +629,7 @@ export class QueryModelService implements IQueryModelService {
}
private _fireGridContentEvent(uri: string, type: string): void {
let info: QueryInfo = this._getQueryInfo(uri);
let info = this._getQueryInfo(uri);
if (info && info.dataServiceReady) {
let service: DataService = this.getDataService(uri);
@@ -635,29 +642,29 @@ export class QueryModelService implements IQueryModelService {
}
private _fireQueryEvent(uri: string, type: string, data?: any) {
let info: QueryInfo = this._getQueryInfo(uri);
let info = this._getQueryInfo(uri);
if (info.dataServiceReady) {
if (info && info.dataServiceReady) {
let service: DataService = this.getDataService(uri);
service.queryEventObserver.next({
type: type,
data: data
});
} else {
} else if (info) {
let queueItem: QueryEvent = { type: type, data: data };
info.queryEventQueue.push(queueItem);
}
}
private _sendQueuedEvents(uri: string): void {
let info: QueryInfo = this._getQueryInfo(uri);
while (info.queryEventQueue.length > 0) {
let event: QueryEvent = info.queryEventQueue.shift();
let info = this._getQueryInfo(uri);
while (info && info.queryEventQueue.length > 0) {
let event = info.queryEventQueue.shift()!;
this._fireQueryEvent(uri, event.type, event.data);
}
}
public _getQueryInfo(uri: string): QueryInfo {
public _getQueryInfo(uri: string): QueryInfo | undefined {
return this._queryInfoMap.get(uri);
}