diff --git a/extensions/mssql/src/config.json b/extensions/mssql/src/config.json index 03cfcae18e..eb4f1b5249 100644 --- a/extensions/mssql/src/config.json +++ b/extensions/mssql/src/config.json @@ -1,6 +1,6 @@ { "downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}", - "version": "1.5.0-alpha.85", + "version": "1.5.0-alpha.87", "downloadFileNames": { "Windows_86": "win-x86-netcoreapp2.2.zip", "Windows_64": "win-x64-netcoreapp2.2.zip", diff --git a/extensions/mssql/src/contracts.ts b/extensions/mssql/src/contracts.ts index 5c7c8104b1..a378cac45b 100644 --- a/extensions/mssql/src/contracts.ts +++ b/extensions/mssql/src/contracts.ts @@ -448,6 +448,13 @@ export interface SchemaCompareGenerateScriptParams { taskExecutionMode: TaskExecutionMode; } +export interface SchemaComparePublishChangesParams { + operationId: string; + targetServerName: string; + targetDatabaseName: string; + taskExecutionMode: TaskExecutionMode; +} + export namespace SchemaCompareRequest { export const type = new RequestType('schemaCompare/compare'); } @@ -455,4 +462,8 @@ export namespace SchemaCompareRequest { export namespace SchemaCompareGenerateScriptRequest { export const type = new RequestType('schemaCompare/generateScript'); } + +export namespace SchemaComparePublishChangesRequest { + export const type = new RequestType('schemaCompare/publish'); +} // ------------------------------- ----------------------------- diff --git a/extensions/mssql/src/features.ts b/extensions/mssql/src/features.ts index b051f26d48..f3fcb93265 100644 --- a/extensions/mssql/src/features.ts +++ b/extensions/mssql/src/features.ts @@ -178,7 +178,7 @@ export class SchemaCompareServicesFeature extends SqlOpsFeature { ); }; - let schemaCompareGenerateScript = (operationId: string, targetDatabaseName: string, scriptFilePath: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable => { + let schemaCompareGenerateScript = (operationId: string, targetDatabaseName: string, scriptFilePath: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable => { let params: contracts.SchemaCompareGenerateScriptParams = { operationId: operationId, targetDatabaseName: targetDatabaseName, scriptFilePath: scriptFilePath, taskExecutionMode: taskExecutionMode }; return client.sendRequest(contracts.SchemaCompareGenerateScriptRequest.type, params).then( r => { @@ -191,10 +191,24 @@ export class SchemaCompareServicesFeature extends SqlOpsFeature { ); }; + let schemaComparePublishChanges = (operationId: string, targetServerName: string, targetDatabaseName: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable => { + let params: contracts.SchemaComparePublishChangesParams = { operationId: operationId, targetServerName: targetServerName, targetDatabaseName: targetDatabaseName, taskExecutionMode: taskExecutionMode }; + return client.sendRequest(contracts.SchemaComparePublishChangesRequest.type, params).then( + r => { + return r; + }, + e => { + client.logFailedRequest(contracts.SchemaComparePublishChangesRequest.type, e); + return Promise.resolve(undefined); + } + ); + }; + return azdata.dataprotocol.registerSchemaCompareServicesProvider({ providerId: client.providerId, schemaCompare, - schemaCompareGenerateScript + schemaCompareGenerateScript, + schemaComparePublishChanges }); } } diff --git a/extensions/schema-compare/src/dialogs/schemaCompareDialog.ts b/extensions/schema-compare/src/dialogs/schemaCompareDialog.ts index e1b5e040ac..8dd507b3c1 100644 --- a/extensions/schema-compare/src/dialogs/schemaCompareDialog.ts +++ b/extensions/schema-compare/src/dialogs/schemaCompareDialog.ts @@ -82,6 +82,7 @@ export class SchemaCompareDialog { sourceName = this.sourceTextBox.value; sourceEndpointInfo = { endpointType: azdata.SchemaCompareEndpointType.dacpac, + serverName: '', databaseName: '', ownerUri: '', packageFilePath: this.sourceTextBox.value @@ -92,6 +93,7 @@ export class SchemaCompareDialog { sourceEndpointInfo = { endpointType: azdata.SchemaCompareEndpointType.database, + serverName: (this.sourceServerDropdown.value as ConnectionDropdownValue).name, databaseName: (this.sourceDatabaseDropdown.value).name, ownerUri: ownerUri, packageFilePath: '' @@ -103,6 +105,7 @@ export class SchemaCompareDialog { targetName = this.targetTextBox.value; targetEndpointInfo = { endpointType: azdata.SchemaCompareEndpointType.dacpac, + serverName: '', databaseName: '', ownerUri: '', packageFilePath: this.targetTextBox.value @@ -113,6 +116,7 @@ export class SchemaCompareDialog { targetEndpointInfo = { endpointType: azdata.SchemaCompareEndpointType.database, + serverName: (this.targetServerDropdown.value as ConnectionDropdownValue).name, databaseName: (this.targetDatabaseDropdown.value).name, ownerUri: ownerUri, packageFilePath: '' diff --git a/extensions/schema-compare/src/media/start-inverse.svg b/extensions/schema-compare/src/media/start-inverse.svg new file mode 100644 index 0000000000..f4940c620e --- /dev/null +++ b/extensions/schema-compare/src/media/start-inverse.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/schema-compare/src/media/start.svg b/extensions/schema-compare/src/media/start.svg new file mode 100644 index 0000000000..8e079c1325 --- /dev/null +++ b/extensions/schema-compare/src/media/start.svg @@ -0,0 +1,3 @@ + + + diff --git a/extensions/schema-compare/src/schemaCompareResult.ts b/extensions/schema-compare/src/schemaCompareResult.ts index d2f2af8eea..69499503df 100644 --- a/extensions/schema-compare/src/schemaCompareResult.ts +++ b/extensions/schema-compare/src/schemaCompareResult.ts @@ -22,6 +22,7 @@ export class SchemaCompareResult { private switchButton: azdata.ButtonComponent; private compareButton: azdata.ButtonComponent; private generateScriptButton: azdata.ButtonComponent; + private applyButton: azdata.ButtonComponent; private SchemaCompareActionMap: Map; private comparisonResult: azdata.SchemaCompareResult; private sourceNameComponent: azdata.TableComponent; @@ -65,16 +66,18 @@ export class SchemaCompareResult { this.createSwitchButton(view); this.createCompareButton(view); this.createGenerateScriptButton(view); + this.createApplyButton(view); this.resetButtons(); let toolBar = view.modelBuilder.toolbarContainer(); toolBar.addToolbarItems([{ component: this.compareButton }, { - component: this.generateScriptButton, + component: this.generateScriptButton + }, { + component: this.applyButton, toolbarSeparatorAfter: true - }, - { + }, { component: this.switchButton }]); @@ -192,8 +195,10 @@ export class SchemaCompareResult { // only enable generate script button if the target is a db if (this.targetEndpointInfo.endpointType === azdata.SchemaCompareEndpointType.database) { this.generateScriptButton.enabled = true; + this.applyButton.enabled = true; } else { this.generateScriptButton.title = localize('schemaCompare.generateScriptButtonDisabledTitle', 'Generate script is enabled when the target is a database'); + this.applyButton.title = localize('schemaCompare.applyButtonDisabledTitle', 'Apply is enabled when the target is a database'); } } else { this.flexModel.addItem(this.noDifferencesLabel, { CSSStyles: { 'margin': 'auto' } }); @@ -310,11 +315,33 @@ export class SchemaCompareResult { }); } + private createApplyButton(view: azdata.ModelView) { + + this.applyButton = view.modelBuilder.button().withProperties({ + label: localize('schemaCompare.updateButton', 'Apply'), + iconPath: { + light: path.join(__dirname, 'media', 'start.svg'), + dark: path.join(__dirname, 'media', 'start-inverse.svg') + }, + }).component(); + + this.applyButton.onDidClick(async (click) => { + let service = await SchemaCompareResult.getService('MSSQL'); + let result = await service.schemaComparePublishChanges(this.comparisonResult.operationId, this.targetEndpointInfo.serverName, this.targetEndpointInfo.databaseName, azdata.TaskExecutionMode.execute); + if (!result || !result.success) { + vscode.window.showErrorMessage( + localize('schemaCompare.updateErrorMessage', "Schema Compare Apply failed '{0}'", result.errorMessage ? result.errorMessage : 'Unknown')); + } + }); + } + private resetButtons(): void { this.compareButton.enabled = false; this.switchButton.enabled = false; this.generateScriptButton.enabled = false; + this.applyButton.enabled = false; this.generateScriptButton.title = localize('schemaCompare.generateScriptEnabledButton', 'Generate script to deploy changes to target'); + this.applyButton.title = localize('schemaCompare.applyButtonEnabledTitle', 'Apply changes to target'); } private createSwitchButton(view: azdata.ModelView): void { diff --git a/src/sql/azdata.proposed.d.ts b/src/sql/azdata.proposed.d.ts index 6b0e3f62b6..c387104770 100644 --- a/src/sql/azdata.proposed.d.ts +++ b/src/sql/azdata.proposed.d.ts @@ -1737,6 +1737,7 @@ declare module 'azdata' { export interface SchemaCompareEndpointInfo { endpointType: SchemaCompareEndpointType; packageFilePath: string; + serverName: string; databaseName: string; ownerUri: string; } @@ -1744,6 +1745,7 @@ declare module 'azdata' { export interface SchemaCompareServicesProvider extends DataProvider { schemaCompare(sourceEndpointInfo: SchemaCompareEndpointInfo, targetEndpointInfo: SchemaCompareEndpointInfo, taskExecutionMode: TaskExecutionMode): Thenable; schemaCompareGenerateScript(operationId: string, targetDatabaseName: string, scriptFilePath: string, taskExecutionMode: TaskExecutionMode): Thenable; + schemaComparePublishChanges(operationId: string, targetServerName: string, targetDatabaseName: string, taskExecutionMode: TaskExecutionMode): Thenable; } // Security service interfaces ------------------------------------------------------------------------ diff --git a/src/sql/platform/schemaCompare/common/schemaCompareService.ts b/src/sql/platform/schemaCompare/common/schemaCompareService.ts index b3d3033553..c3a078608c 100644 --- a/src/sql/platform/schemaCompare/common/schemaCompareService.ts +++ b/src/sql/platform/schemaCompare/common/schemaCompareService.ts @@ -19,6 +19,7 @@ export interface ISchemaCompareService { registerProvider(providerId: string, provider: azdata.SchemaCompareServicesProvider): void; schemaCompare(sourceEndpointInfo: azdata.SchemaCompareEndpointInfo, targetEndpointInfo: azdata.SchemaCompareEndpointInfo, taskExecutionMode: azdata.TaskExecutionMode): void; schemaCompareGenerateScript(operationId: string, targetDatabaseName: string, scriptFilePath: string, taskExecutionMode: azdata.TaskExecutionMode): void; + schemaComparePublishChanges(operationId: string, targetServerName: string, targetDatabaseName: string, taskExecutionMode: azdata.TaskExecutionMode): void; } export class SchemaCompareService implements ISchemaCompareService { @@ -43,6 +44,12 @@ export class SchemaCompareService implements ISchemaCompareService { }); } + schemaComparePublishChanges(operationId: string, targetServerName: string, targetDatabaseName: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable { + return this._runAction('', (runner) => { + return runner.schemaComparePublishChanges(operationId, targetServerName, targetDatabaseName, taskExecutionMode); + }); + } + private _runAction(uri: string, action: (handler: azdata.SchemaCompareServicesProvider) => Thenable): Thenable { let providerId: string = this._connectionService.getProviderIdFromUri(uri); diff --git a/src/sql/workbench/api/node/mainThreadDataProtocol.ts b/src/sql/workbench/api/node/mainThreadDataProtocol.ts index 7123e84592..0ba45183b2 100644 --- a/src/sql/workbench/api/node/mainThreadDataProtocol.ts +++ b/src/sql/workbench/api/node/mainThreadDataProtocol.ts @@ -462,6 +462,9 @@ export class MainThreadDataProtocol implements MainThreadDataProtocolShape { }, schemaCompareGenerateScript(operationId: string, targetDatabaseName: string, scriptFilePath: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable { return self._proxy.$schemaCompareGenerateScript(handle, operationId, targetDatabaseName, scriptFilePath, taskExecutionMode); + }, + schemaComparePublishChanges(operationId: string, targetServerName: string, targetDatabaseName: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable { + return self._proxy.$schemaComparePublishChanges(handle, operationId, targetServerName, targetDatabaseName, taskExecutionMode); } }); diff --git a/src/sql/workbench/api/node/sqlExtHost.protocol.ts b/src/sql/workbench/api/node/sqlExtHost.protocol.ts index 521d2ab1f6..69e1b6439f 100644 --- a/src/sql/workbench/api/node/sqlExtHost.protocol.ts +++ b/src/sql/workbench/api/node/sqlExtHost.protocol.ts @@ -463,6 +463,11 @@ export abstract class ExtHostDataProtocolShape { * Schema compare generate script */ $schemaCompareGenerateScript(handle: number, operationId: string, targetDatabaseName: string, scriptFilePath: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable { throw ni(); } + + /** + * Schema compare publish changes + */ + $schemaComparePublishChanges(handle: number, operationId: string, targetServerName: string, targetDatabaseName: string, taskExecutionMode: azdata.TaskExecutionMode): Thenable { throw ni(); } } /**