Notebooks: re-factor grid streaming (#12937)

* refactor grid streaming (convert to data first)

* change convertRowsToHtml method to return value

* remove griddataconversioncomplete checks

* send row data from STS to gridoutput component

* clean up code

* send data updates to cell model

* serialize cell output at the end of cell execution

* remove unused parameters

* update output contents instead of output reference

* remove unnecessary promise

* move azdata changes to proposed

* update comment
This commit is contained in:
Lucy Zhang
2020-10-28 09:08:15 -07:00
committed by GitHub
parent 42e16b1752
commit 86357b45b0
18 changed files with 266 additions and 412 deletions

View File

@@ -13,7 +13,7 @@ import * as uuid from 'uuid';
import * as sinon from 'sinon';
import { DataResourceDataProvider } from '../../browser/outputs/gridOutput.component';
import { IDataResource } from 'sql/workbench/services/notebook/browser/sql/sqlSessionManager';
import { ResultSetSubset, ResultSetSummary } from 'sql/workbench/services/query/common/query';
import { ResultSetSummary } from 'sql/workbench/services/query/common/query';
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
import { TestFileDialogService, TestEditorService } from 'vs/workbench/test/browser/workbenchTestServices';
import { TestContextService } from 'vs/workbench/test/common/workbenchTestServices';
@@ -23,7 +23,6 @@ import { InstantiationService } from 'vs/platform/instantiation/common/instantia
import { URI } from 'vs/base/common/uri';
import { CellModel } from 'sql/workbench/services/notebook/browser/models/cell';
import { createandLoadNotebookModel } from 'sql/workbench/contrib/notebook/test/browser/cellToolbarActions.test';
import QueryRunner from 'sql/workbench/services/query/common/queryRunner';
export class TestSerializationProvider implements azdata.SerializationProvider {
providerId: string;
@@ -98,9 +97,6 @@ suite('Data Resource Data Provider', function () {
let tempFolderPath = path.join(os.tmpdir(), `TestDataResourceDataProvider_${uuid.v4()}`);
await fs.mkdir(tempFolderPath);
let dataResourceDataProvider = new DataResourceDataProvider(
0, // batchId
0, // id
undefined, // QueryRunner
source,
resultSet,
cellModel.object,
@@ -131,38 +127,4 @@ suite('Data Resource Data Provider', function () {
const withHeadersResult = await fs.readFile(withHeadersFile.fsPath);
assert.equal(withHeadersResult.toString(), 'col1 col2 \n1 2 \n3 4 \n', 'result data should include headers');
});
test('convertAllData correctly converts row data to mimetype and html', async function (): Promise<void> {
let resultSetSubset: ResultSetSubset = {
rowCount: 2,
rows: [[{ displayValue: '1' }, { displayValue: '2' }], [{ displayValue: '3' }, { displayValue: '4' }]]
};
let queryRunner: TypeMoq.Mock<QueryRunner> = TypeMoq.Mock.ofType(QueryRunner);
queryRunner.setup(x => x.getQueryRows(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve(resultSetSubset));
let dataResourceDataProvider = new DataResourceDataProvider(
0, // batchId
0, // id
queryRunner.object,
source,
resultSet,
cellModel.object,
notificationService,
undefined, // IClipboardService
undefined, // IConfigurationService
undefined, // ITextResourcePropertiesService
serializationService,
instantiationService.object
);
let spy = sinon.spy(cellModel.object, 'updateOutputData');
let expectedData = {
'application/vnd.dataresource+json': {
data: [{ 0: '1', 1: '2' }, { 0: '3', 1: '4' }],
schema: { fields: [{ name: 'col1' }, { name: 'col2' }] }
},
'text/html': ['<table>', '<tr><th>col1</th><th>col2</th></tr>', '<tr><td>1</td><td>2</td></tr>', '<tr><td>3</td><td>4</td></tr>', '</table>']
};
await dataResourceDataProvider.convertAllData(resultSet);
sinon.assert.calledOnce(spy);
sinon.assert.calledWithExactly(spy, 0, 0, expectedData);
});
});

View File

@@ -56,8 +56,6 @@ import { UntitledTextEditorInput } from 'vs/workbench/services/untitled/common/u
import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
import { workbenchInstantiationService } from 'vs/workbench/test/browser/workbenchTestServices';
import { IProductService } from 'vs/platform/product/common/productService';
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
import { INotificationService } from 'vs/platform/notification/common/notification';
class NotebookModelStub extends stubs.NotebookModelStub {
public contentChangedEmitter = new Emitter<NotebookContentChange>();
@@ -97,11 +95,10 @@ suite.skip('Test class NotebookEditor:', () => {
let queryTextEditor: QueryTextEditor;
let untitledNotebookInput: UntitledNotebookInput;
let notebookEditorStub: NotebookEditorStub;
let notificationService: TypeMoq.Mock<INotificationService>;
setup(async () => {
// setup services
({ instantiationService, workbenchThemeService, notebookService, testTitle, extensionService, cellTextEditorGuid, queryTextEditor, untitledNotebookInput, notebookEditorStub, notificationService } = setupServices({ instantiationService, workbenchThemeService }));
({ instantiationService, workbenchThemeService, notebookService, testTitle, extensionService, cellTextEditorGuid, queryTextEditor, untitledNotebookInput, notebookEditorStub } = setupServices({ instantiationService, workbenchThemeService }));
// Create notebookEditor
notebookEditor = createNotebookEditor(instantiationService, workbenchThemeService, notebookService);
});
@@ -122,7 +119,7 @@ suite.skip('Test class NotebookEditor:', () => {
const untitledTextInput = instantiationService.createInstance(UntitledTextEditorInput, untitledTextEditorService.create({ associatedResource: untitledUri }));
const untitledNotebookInput = new UntitledNotebookInput(
testTitle, untitledUri, untitledTextInput,
undefined, instantiationService, notebookService, extensionService, notificationService.object
undefined, instantiationService, notebookService, extensionService
);
const testNotebookEditor = new NotebookEditorStub({ cellGuid: cellTextEditorGuid, editor: queryTextEditor, model: notebookModel, notebookParams: <INotebookParams>{ notebookUri: untitledNotebookInput.notebookUri } });
notebookService.addNotebookEditor(testNotebookEditor);
@@ -670,7 +667,6 @@ function setupServices(arg: { workbenchThemeService?: WorkbenchThemeService, ins
const uninstallEvent = new Emitter<IExtensionIdentifier>();
const didUninstallEvent = new Emitter<DidUninstallExtensionEvent>();
const notificationService = TypeMoq.Mock.ofType(TestNotificationService, TypeMoq.MockBehavior.Loose);
const instantiationService = arg.instantiationService ?? <TestInstantiationService>workbenchInstantiationService();
const workbenchThemeService = arg.workbenchThemeService ?? instantiationService.createInstance(WorkbenchThemeService);
instantiationService.stub(IWorkbenchThemeService, workbenchThemeService);
@@ -707,7 +703,7 @@ function setupServices(arg: { workbenchThemeService?: WorkbenchThemeService, ins
const untitledTextInput = instantiationService.createInstance(UntitledTextEditorInput, untitledTextEditorService.create({ associatedResource: untitledUri }));
const untitledNotebookInput = new UntitledNotebookInput(
testTitle, untitledUri, untitledTextInput,
undefined, instantiationService, notebookService, extensionService, notificationService.object
undefined, instantiationService, notebookService, extensionService
);
const cellTextEditorGuid = generateUuid();
@@ -722,7 +718,7 @@ function setupServices(arg: { workbenchThemeService?: WorkbenchThemeService, ins
);
const notebookEditorStub = new NotebookEditorStub({ cellGuid: cellTextEditorGuid, editor: queryTextEditor, model: new NotebookModelStub(), notebookParams: <INotebookParams>{ notebookUri: untitledNotebookInput.notebookUri } });
notebookService.addNotebookEditor(notebookEditorStub);
return { instantiationService, workbenchThemeService, notebookService, testTitle, extensionService, cellTextEditorGuid, queryTextEditor, untitledNotebookInput, notebookEditorStub, notificationService };
return { instantiationService, workbenchThemeService, notebookService, testTitle, extensionService, cellTextEditorGuid, queryTextEditor, untitledNotebookInput, notebookEditorStub };
}
function createNotebookEditor(instantiationService: TestInstantiationService, workbenchThemeService: WorkbenchThemeService, notebookService: NotebookService) {

View File

@@ -20,7 +20,6 @@ import { IExtensionService, NullExtensionService } from 'vs/workbench/services/e
import { INotebookService, IProviderInfo } from 'sql/workbench/services/notebook/browser/notebookService';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { IUntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
suite('Notebook Input', function (): void {
const instantiationService = workbenchInstantiationService();
@@ -45,8 +44,6 @@ suite('Notebook Input', function (): void {
(instantiationService as TestInstantiationService).stub(INotebookService, mockNotebookService.object);
const mockNotificationService = TypeMoq.Mock.ofType(TestNotificationService);
let untitledTextInput: UntitledTextEditorInput;
let untitledNotebookInput: UntitledNotebookInput;
@@ -56,14 +53,14 @@ suite('Notebook Input', function (): void {
untitledTextInput = instantiationService.createInstance(UntitledTextEditorInput, service.create({ associatedResource: untitledUri }));
untitledNotebookInput = new UntitledNotebookInput(
testTitle, untitledUri, untitledTextInput,
undefined, instantiationService, mockNotebookService.object, mockExtensionService.object, mockNotificationService.object);
undefined, instantiationService, mockNotebookService.object, mockExtensionService.object);
});
test('File Notebook Input', async function (): Promise<void> {
let fileUri = URI.from({ scheme: Schemas.file, path: 'TestPath' });
let fileNotebookInput = new FileNotebookInput(
testTitle, fileUri, undefined,
undefined, instantiationService, mockNotebookService.object, mockExtensionService.object, mockNotificationService.object);
undefined, instantiationService, mockNotebookService.object, mockExtensionService.object);
let inputId = fileNotebookInput.getTypeId();
assert.strictEqual(inputId, FileNotebookInput.ID);

View File

@@ -43,9 +43,6 @@ export class NotebookModelStub implements INotebookModel {
get sessionLoadFinished(): Promise<void> {
throw new Error('method not implemented.');
}
get gridDataConversionComplete(): Promise<any[]> {
throw new Error('method not implemented.');
}
get notebookManagers(): INotebookManager[] {
throw new Error('method not implemented.');
}