SQL Kernel Improvements/Removing Spark Code from Core/Attach to Changes (#3790)

* Scenarios work besides loading saved kernel

* Fix compilation issue

* Save and load functional

* Fix loading kernesl issue when sql kernel is not enabled

* Fix language mapping to not be hardcoded any longer

* Remove unnecessary comment

* PR Comments vol. 1

* Code cleanup, use ConnectionProfile instead of IConnectionProfile when accessing serverName

* PR changes vol. 2

* One final comment for PR

* Fix linting issue
This commit is contained in:
Chris LaFreniere
2019-01-25 18:54:04 -08:00
committed by GitHub
parent ea67859de7
commit 43be88a37c
29 changed files with 768 additions and 627 deletions

View File

@@ -9,6 +9,7 @@ import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { ExtensionsRegistry, IExtensionPointUser } from 'vs/workbench/services/extensions/common/extensionsRegistry';
import { localize } from 'vs/nls';
import * as platform from 'vs/platform/registry/common/platform';
import * as sqlops from 'sqlops';
import { Event, Emitter } from 'vs/base/common/event';
export const Extensions = {
@@ -18,7 +19,7 @@ export const Extensions = {
export interface NotebookProviderRegistration {
provider: string;
fileExtensions: string | string[];
standardKernels: string | string[];
standardKernels: sqlops.nb.IStandardKernel | sqlops.nb.IStandardKernel[];
}
let notebookProviderType: IJSONSchema = {
@@ -44,11 +45,38 @@ let notebookProviderType: IJSONSchema = {
standardKernels: {
description: localize('carbon.extension.contributes.notebook.standardKernels', 'What kernels should be standard with this notebook provider'),
oneOf: [
{ type: 'string' },
{
type: 'object',
properties: {
name: {
type: 'string',
},
connectionProviderIds: {
type: 'array',
items: {
type: 'string'
}
}
}
},
{
type: 'array',
items: {
type: 'string'
type: 'object',
items: {
type: 'object',
properties: {
name: {
type: 'string',
},
connectionProviderIds: {
type: 'array',
items: {
type: 'string'
}
}
}
}
}
}
]

View File

@@ -48,6 +48,8 @@ export interface INotebookService {
getProvidersForFileType(fileType: string): string[];
getStandardKernelsForProvider(provider: string): sqlops.nb.IStandardKernel[];
/**
* Initializes and returns a Notebook manager that can handle all important calls to open, display, and
* run cells in a notebook.

View File

@@ -80,6 +80,7 @@ export class NotebookService extends Disposable implements INotebookService {
private _onNotebookEditorRename = new Emitter<INotebookEditor>();
private _editors = new Map<string, INotebookEditor>();
private _fileToProviders = new Map<string, NotebookProviderRegistration[]>();
private _providerToStandardKernels = new Map<string, nb.IStandardKernel[]>();
private _registrationComplete = new Deferred<void>();
private _isRegistrationComplete = false;
@@ -121,6 +122,9 @@ export class NotebookService extends Disposable implements INotebookService {
this.addFileProvider(registration.fileExtensions, registration);
}
}
if (registration.standardKernels) {
this.addStandardKernels(registration);
}
}
registerProvider(providerId: string, instance: INotebookProvider): void {
@@ -154,6 +158,26 @@ export class NotebookService extends Disposable implements INotebookService {
this._fileToProviders.set(fileType.toUpperCase(), providers);
}
// Standard kernels are contributed where a list of kernels are defined that can be shown
// in the kernels dropdown list before a SessionManager has been started; this way,
// every NotebookProvider doesn't need to have an active SessionManager in order to contribute
// kernels to the dropdown
private addStandardKernels(provider: NotebookProviderRegistration) {
let providerUpperCase = provider.provider.toUpperCase();
let standardKernels = this._providerToStandardKernels.get(providerUpperCase);
if (!standardKernels) {
standardKernels = [];
}
if (Array.isArray(provider.standardKernels)) {
provider.standardKernels.forEach(kernel => {
standardKernels.push(kernel);
});
} else {
standardKernels.push(provider.standardKernels);
}
this._providerToStandardKernels.set(providerUpperCase, standardKernels);
}
getSupportedFileExtensions(): string[] {
return Array.from(this._fileToProviders.keys());
}
@@ -165,6 +189,10 @@ export class NotebookService extends Disposable implements INotebookService {
return providers ? providers.map(provider => provider.provider) : undefined;
}
getStandardKernelsForProvider(provider: string): nb.IStandardKernel[] {
return this._providerToStandardKernels.get(provider.toUpperCase());
}
public shutdown(): void {
this._managersMap.forEach(manager => {
manager.forEach(m => {
@@ -337,7 +365,7 @@ export class NotebookService extends Disposable implements INotebookService {
notebookRegistry.registerNotebookProvider({
provider: sqlProvider.providerId,
fileExtensions: DEFAULT_NOTEBOOK_FILETYPE,
standardKernels: ['SQL']
standardKernels: { name: 'SQL', connectionProviderIds: ['MSSQL'] }
});
}
}
@@ -444,5 +472,4 @@ export class SqlNotebookManager implements INotebookManager {
public get sessionManager(): nb.SessionManager {
return this._sessionManager;
}
}

View File

@@ -7,6 +7,7 @@
import { nb } from 'sqlops';
import { localize } from 'vs/nls';
import { FutureInternal } from 'sql/parts/notebook/models/modelInterfaces';
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
export const noKernel: string = localize('noKernel', 'No Kernel');
const runNotebookDisabled = localize('runNotebookDisabled', 'Cannot run cells as no kernel has been configured');
@@ -91,6 +92,15 @@ export class EmptySession implements nb.ISession {
changeKernel(kernelInfo: nb.IKernelSpec): Thenable<nb.IKernel> {
return Promise.resolve(this.kernel);
}
// No kernel config necessary for empty session
configureKernel(kernelInfo: nb.IKernelSpec): Thenable<void> {
return Promise.resolve();
}
configureConnection(connection: ConnectionProfile): Thenable<void> {
return Promise.resolve();
}
}
class EmptyKernel implements nb.IKernel {

View File

@@ -14,8 +14,9 @@ import Severity from 'vs/base/common/severity';
import * as Utils from 'sql/platform/connection/common/utils';
import { Deferred } from 'sql/base/common/promise';
import { Disposable } from 'vs/base/common/lifecycle';
import { mssqlProviderName } from 'sql/platform/connection/common/constants';
import { IErrorMessageService } from 'sql/platform/errorMessage/common/errorMessageService';
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
import { IConnectionProfile } from 'sql/platform/connection/common/interfaces';
export const sqlKernel: string = localize('sqlKernel', 'SQL');
export const sqlKernelError: string = localize("sqlKernelError", "SQL kernel error");
@@ -63,6 +64,7 @@ export class SqlSessionManager implements nb.SessionManager {
export class SqlSession implements nb.ISession {
private _kernel: SqlKernel;
private _defaultKernelLoaded = false;
private _currentConnection: IConnectionProfile;
public set defaultKernelLoaded(value) {
this._defaultKernelLoaded = value;
@@ -107,12 +109,25 @@ export class SqlSession implements nb.ISession {
changeKernel(kernelInfo: nb.IKernelSpec): Thenable<nb.IKernel> {
return Promise.resolve(this.kernel);
}
configureKernel(kernelInfo: nb.IKernelSpec): Thenable<void> {
return Promise.resolve();
}
configureConnection(connection: ConnectionProfile): Thenable<void> {
if (this._kernel) {
this._kernel.connection = connection;
}
return Promise.resolve();
}
}
class SqlKernel extends Disposable implements nb.IKernel {
private _queryRunner: QueryRunner;
private _columns: IDbColumn[];
private _rows: DbCellValue[][];
private _currentConnection: IConnectionProfile;
static kernelId: number = 0;
constructor( @IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
@IInstantiationService private _instantiationService: IInstantiationService,
@@ -121,7 +136,7 @@ class SqlKernel extends Disposable implements nb.IKernel {
}
public get id(): string {
return '-1';
return (SqlKernel.kernelId++).toString();
}
public get name(): string {
@@ -159,6 +174,12 @@ class SqlKernel extends Disposable implements nb.IKernel {
return info;
}
public set connection(conn: IConnectionProfile) {
this._currentConnection = conn;
this._queryRunner = undefined;
}
getSpec(): Thenable<nb.IKernelSpec> {
return Promise.resolve(sqlKernelSpec);
}
@@ -167,11 +188,10 @@ class SqlKernel extends Disposable implements nb.IKernel {
if (this._queryRunner) {
this._queryRunner.runQuery(content.code);
} else {
let connections = this._connectionManagementService.getActiveConnections();
let connectionProfile = connections.find(connection => connection.providerName === mssqlProviderName);
let connectionUri = Utils.generateUri(connectionProfile, 'notebook');
let connectionUri = Utils.generateUri(this._currentConnection, 'notebook');
this._queryRunner = this._instantiationService.createInstance(QueryRunner, connectionUri, undefined);
this._connectionManagementService.connect(connectionProfile, connectionUri).then((result) => {
this._connectionManagementService.connect(this._currentConnection, connectionUri).then((result) =>
{
this.addQueryEventListeners(this._queryRunner);
this._queryRunner.runQuery(content.code);
});
@@ -186,7 +206,9 @@ class SqlKernel extends Disposable implements nb.IKernel {
}
interrupt(): Thenable<void> {
return Promise.resolve(undefined);
// TODO: figure out what to do with the QueryCancelResult
return this._queryRunner.cancelQuery().then((cancelResult) => {
});
}
private addQueryEventListeners(queryRunner: QueryRunner): void {
@@ -234,7 +256,11 @@ export class SQLFuture extends Disposable implements FutureInternal {
get inProgress(): boolean {
return !this._queryRunner.hasCompleted;
}
set inProgress(val: boolean) {
if (this._queryRunner && !val) {
this._queryRunner.cancelQuery();
}
}
get msg(): nb.IMessage {
return this._msg;
}