Schema Compare save scmp file (#6150)

* initial changes

* send source and target excludes

* disable save scmp button until there is source and target

* addressing comments
This commit is contained in:
Kim Santiago
2019-06-25 15:07:58 -07:00
committed by GitHub
parent ac76302d6c
commit f01c318c30
10 changed files with 136 additions and 3 deletions

View File

@@ -467,6 +467,16 @@ export interface SchemaCompareNodeParams {
taskExecutionMode: TaskExecutionMode; taskExecutionMode: TaskExecutionMode;
} }
export interface SchemaCompareSaveScmpParams {
sourceEndpointInfo: azdata.SchemaCompareEndpointInfo;
targetEndpointInfo: azdata.SchemaCompareEndpointInfo;
taskExecutionMode: TaskExecutionMode;
deploymentOptions: azdata.DeploymentOptions;
scmpFilePath: string;
excludedSourceObjects: azdata.SchemaCompareObjectId[];
excludedTargetObjects: azdata.SchemaCompareObjectId[];
}
export interface SchemaCompareCancelParams { export interface SchemaCompareCancelParams {
operationId: string; operationId: string;
} }
@@ -491,6 +501,10 @@ export namespace SchemaCompareIncludeExcludeNodeRequest {
export const type = new RequestType<SchemaCompareNodeParams, azdata.ResultStatus, void, void>('schemaCompare/includeExcludeNode'); export const type = new RequestType<SchemaCompareNodeParams, azdata.ResultStatus, void, void>('schemaCompare/includeExcludeNode');
} }
export namespace SchemaCompareSaveScmpRequest {
export const type = new RequestType<SchemaCompareSaveScmpParams, azdata.ResultStatus, void, void>('schemaCompare/saveScmp');
}
export namespace SchemaCompareCancellationRequest { export namespace SchemaCompareCancellationRequest {
export const type = new RequestType<SchemaCompareCancelParams, azdata.ResultStatus, void, void>('schemaCompare/cancel'); export const type = new RequestType<SchemaCompareCancelParams, azdata.ResultStatus, void, void>('schemaCompare/cancel');
} }

View File

@@ -147,7 +147,8 @@ export class SchemaCompareServicesFeature extends SqlOpsFeature<undefined> {
contracts.SchemaCompareRequest.type, contracts.SchemaCompareRequest.type,
contracts.SchemaCompareGenerateScriptRequest.type, contracts.SchemaCompareGenerateScriptRequest.type,
contracts.SchemaCompareGetDefaultOptionsRequest.type, contracts.SchemaCompareGetDefaultOptionsRequest.type,
contracts.SchemaCompareIncludeExcludeNodeRequest.type contracts.SchemaCompareIncludeExcludeNodeRequest.type,
contracts.SchemaCompareSaveScmpRequest.type
]; ];
constructor(client: SqlOpsDataClient) { constructor(client: SqlOpsDataClient) {
@@ -219,7 +220,7 @@ export class SchemaCompareServicesFeature extends SqlOpsFeature<undefined> {
); );
}; };
let schemaCompareIncludeExcludeNode = (operationId: string, diffEntry: azdata.DiffEntry, includeRequest: boolean, taskExecutionMode: azdata.TaskExecutionMode): Thenable<azdata.DacFxResult> => { let schemaCompareIncludeExcludeNode = (operationId: string, diffEntry: azdata.DiffEntry, includeRequest: boolean, taskExecutionMode: azdata.TaskExecutionMode): Thenable<azdata.ResultStatus> => {
let params: contracts.SchemaCompareNodeParams = { operationId: operationId, diffEntry, includeRequest, taskExecutionMode: taskExecutionMode }; let params: contracts.SchemaCompareNodeParams = { operationId: operationId, diffEntry, includeRequest, taskExecutionMode: taskExecutionMode };
return client.sendRequest(contracts.SchemaCompareIncludeExcludeNodeRequest.type, params).then( return client.sendRequest(contracts.SchemaCompareIncludeExcludeNodeRequest.type, params).then(
r => { r => {
@@ -232,6 +233,19 @@ export class SchemaCompareServicesFeature extends SqlOpsFeature<undefined> {
); );
}; };
let schemaCompareSaveScmp = (sourceEndpointInfo: azdata.SchemaCompareEndpointInfo, targetEndpointInfo: azdata.SchemaCompareEndpointInfo, taskExecutionMode: azdata.TaskExecutionMode, deploymentOptions: azdata.DeploymentOptions, scmpFilePath: string, excludedSourceObjects: azdata.SchemaCompareObjectId[], excludedTargetObjects: azdata.SchemaCompareObjectId[]): Thenable<azdata.ResultStatus> => {
let params: contracts.SchemaCompareSaveScmpParams = { sourceEndpointInfo: sourceEndpointInfo, targetEndpointInfo: targetEndpointInfo, taskExecutionMode: taskExecutionMode, deploymentOptions: deploymentOptions, scmpFilePath: scmpFilePath, excludedSourceObjects: excludedSourceObjects, excludedTargetObjects: excludedTargetObjects };
return client.sendRequest(contracts.SchemaCompareSaveScmpRequest.type, params).then(
r => {
return r;
},
e => {
client.logFailedRequest(contracts.SchemaCompareSaveScmpRequest.type, e);
return Promise.resolve(undefined);
}
);
};
let schemaCompareCancel = (operationId: string): Thenable<azdata.ResultStatus> => { let schemaCompareCancel = (operationId: string): Thenable<azdata.ResultStatus> => {
let params: contracts.SchemaCompareCancelParams = { operationId: operationId }; let params: contracts.SchemaCompareCancelParams = { operationId: operationId };
return client.sendRequest(contracts.SchemaCompareCancellationRequest.type, params).then( return client.sendRequest(contracts.SchemaCompareCancellationRequest.type, params).then(
@@ -252,6 +266,7 @@ export class SchemaCompareServicesFeature extends SqlOpsFeature<undefined> {
schemaComparePublishChanges, schemaComparePublishChanges,
schemaCompareGetDefaultOptions, schemaCompareGetDefaultOptions,
schemaCompareIncludeExcludeNode, schemaCompareIncludeExcludeNode,
schemaCompareSaveScmp,
schemaCompareCancel schemaCompareCancel
}); });
} }

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 1C14.1406 1 14.2708 1.02604 14.3906 1.07812C14.5104 1.13021 14.6146 1.20312 14.7031 1.29688C14.7969 1.38542 14.8698 1.48958 14.9219 1.60938C14.974 1.72917 15 1.85938 15 2V15H2.78906L1 13.2031V2C1 1.85938 1.02604 1.72917 1.07812 1.60938C1.13021 1.48958 1.20052 1.38542 1.28906 1.29688C1.38281 1.20312 1.48958 1.13021 1.60938 1.07812C1.72917 1.02604 1.85938 1 2 1H14ZM4 7H12V2H4V7ZM10 11H5V14H6V12H7V14H10V11ZM14 2H13V8H3V2H2V12.7891L3.20312 14H4V10H11V14H14V2Z" fill="#4894FE"/>
</svg>

After

Width:  |  Height:  |  Size: 594 B

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14 1C14.1406 1 14.2708 1.02604 14.3906 1.07812C14.5104 1.13021 14.6146 1.20312 14.7031 1.29688C14.7969 1.38542 14.8698 1.48958 14.9219 1.60938C14.974 1.72917 15 1.85938 15 2V15H2.78906L1 13.2031V2C1 1.85938 1.02604 1.72917 1.07812 1.60938C1.13021 1.48958 1.20052 1.38542 1.28906 1.29688C1.38281 1.20312 1.48958 1.13021 1.60938 1.07812C1.72917 1.02604 1.85938 1 2 1H14ZM4 7H12V2H4V7ZM10 11H5V14H6V12H7V14H10V11ZM14 2H13V8H3V2H2V12.7891L3.20312 14H4V10H11V14H14V2Z" fill="#015CDA"/>
</svg>

After

Width:  |  Height:  |  Size: 594 B

View File

@@ -46,6 +46,7 @@ export class SchemaCompareResult {
private applyButton: azdata.ButtonComponent; private applyButton: azdata.ButtonComponent;
private selectSourceButton: azdata.ButtonComponent; private selectSourceButton: azdata.ButtonComponent;
private selectTargetButton: azdata.ButtonComponent; private selectTargetButton: azdata.ButtonComponent;
private saveScmpButton: azdata.ButtonComponent;
private SchemaCompareActionMap: Map<Number, string>; private SchemaCompareActionMap: Map<Number, string>;
private operationId: string; private operationId: string;
private comparisonResult: azdata.SchemaCompareResult; private comparisonResult: azdata.SchemaCompareResult;
@@ -121,6 +122,7 @@ export class SchemaCompareResult {
this.createApplyButton(view); this.createApplyButton(view);
this.createOptionsButton(view); this.createOptionsButton(view);
this.createSourceAndTargetButtons(view); this.createSourceAndTargetButtons(view);
this.createSaveScmpButton(view);
this.resetButtons(false); // disable buttons because source and target aren't both selected yet this.resetButtons(false); // disable buttons because source and target aren't both selected yet
let toolBar = view.modelBuilder.toolbarContainer(); let toolBar = view.modelBuilder.toolbarContainer();
@@ -136,7 +138,10 @@ export class SchemaCompareResult {
component: this.optionsButton, component: this.optionsButton,
toolbarSeparatorAfter: true toolbarSeparatorAfter: true
}, { }, {
component: this.switchButton component: this.switchButton,
toolbarSeparatorAfter: true
}, {
component: this.saveScmpButton
}]); }]);
let sourceLabel = view.modelBuilder.text().withProperties({ let sourceLabel = view.modelBuilder.text().withProperties({
@@ -674,6 +679,7 @@ export class SchemaCompareResult {
this.optionsButton.enabled = true; this.optionsButton.enabled = true;
this.switchButton.enabled = true; this.switchButton.enabled = true;
this.cancelCompareButton.enabled = false; this.cancelCompareButton.enabled = false;
this.saveScmpButton.enabled = true;
} }
else { else {
this.compareButton.enabled = false; this.compareButton.enabled = false;
@@ -761,6 +767,72 @@ export class SchemaCompareResult {
}); });
} }
private createSaveScmpButton(view: azdata.ModelView): void {
this.saveScmpButton = view.modelBuilder.button().withProperties({
label: localize('schemaCompare.saveScmpButton', 'Save .scmp file'),
iconPath: {
light: path.join(__dirname, 'media', 'save-scmp.svg'),
dark: path.join(__dirname, 'media', 'save-scmp-inverse.svg')
},
title: localize('schemaCompare.saveScmpButtonTitle', 'Save source and target, options, and excluded elements'),
enabled: false
}).component();
this.saveScmpButton.onDidClick(async (click) => {
const rootPath = vscode.workspace.rootPath ? vscode.workspace.rootPath : os.homedir();
const filePath = await vscode.window.showSaveDialog(
{
defaultUri: vscode.Uri.file(rootPath),
saveLabel: localize('schemaCompare.saveFile', 'Save'),
filters: {
'scmp Files': ['scmp'],
}
}
);
if (!filePath) {
return;
}
// convert include/exclude maps to arrays of object ids
let sourceExcludes: azdata.SchemaCompareObjectId[] = this.convertExcludesToObjectIds(this.originalSourceExcludes);
let targetExcludes: azdata.SchemaCompareObjectId[] = this.convertExcludesToObjectIds(this.originalTargetExcludes);
let startTime = Date.now();
Telemetry.sendTelemetryEvent('SchemaCompareSaveScmp');
const service = await SchemaCompareResult.getService(msSqlProvider);
const result = await service.schemaCompareSaveScmp(this.sourceEndpointInfo, this.targetEndpointInfo, azdata.TaskExecutionMode.execute, this.deploymentOptions, filePath.fsPath, sourceExcludes, targetExcludes);
if (!result || !result.success) {
Telemetry.sendTelemetryEvent('SchemaCompareSaveScmpFailed', {
'errorType': getTelemetryErrorType(result.errorMessage),
'operationId': this.comparisonResult.operationId
});
vscode.window.showErrorMessage(
localize('schemaCompare.saveScmpErrorMessage', "Save scmp failed: '{0}'", (result && result.errorMessage) ? result.errorMessage : 'Unknown'));
}
Telemetry.sendTelemetryEvent('SchemaCompareSaveScmpEnded', {
'totalSaveTime:': (Date.now() - startTime).toString(),
'operationId': this.comparisonResult.operationId
});
});
}
/**
* Converts excluded diff entries into object ids which are needed to save them in an scmp
*/
private convertExcludesToObjectIds(excludedDiffEntries: Map<string, azdata.DiffEntry>): azdata.SchemaCompareObjectId[] {
let result = [];
excludedDiffEntries.forEach((value: azdata.DiffEntry) => {
result.push({
nameParts: value.sourceValue ? value.sourceValue : value.targetValue,
sqlObjectType: `Microsoft.Data.Tools.Schema.Sql.SchemaModel.${value.name}`
});
});
return result;
}
private setButtonStatesForNoChanges(enableButtons: boolean): void { private setButtonStatesForNoChanges(enableButtons: boolean): void {
// generate script and apply can only be enabled if the target is a database // generate script and apply can only be enabled if the target is a database
if (this.targetEndpointInfo.endpointType === azdata.SchemaCompareEndpointType.Database) { if (this.targetEndpointInfo.endpointType === azdata.SchemaCompareEndpointType.Database) {

View File

@@ -27,6 +27,11 @@ export class SchemaCompareTestService implements azdata.SchemaCompareServicesPro
throw new Error('Method not implemented.'); throw new Error('Method not implemented.');
} }
schemaCompareSaveScmp(sourceEndpointInfo: azdata.SchemaCompareEndpointInfo, targetEndpointInfo: azdata.SchemaCompareEndpointInfo, taskExecutionMode: azdata.TaskExecutionMode, deploymentOptions: azdata.DeploymentOptions, scmpFilePath: string, excludedSourceObjects: azdata.SchemaCompareObjectId[], excludedTargetObjects: azdata.SchemaCompareObjectId[]): Thenable<azdata.ResultStatus> {
throw new Error('Method not implemented.');
}
schemaCompare(operationId: string, sourceEndpointInfo: azdata.SchemaCompareEndpointInfo, targetEndpointInfo: azdata.SchemaCompareEndpointInfo, taskExecutionMode: azdata.TaskExecutionMode): Thenable<azdata.SchemaCompareResult> { schemaCompare(operationId: string, sourceEndpointInfo: azdata.SchemaCompareEndpointInfo, targetEndpointInfo: azdata.SchemaCompareEndpointInfo, taskExecutionMode: azdata.TaskExecutionMode): Thenable<azdata.SchemaCompareResult> {
let result: azdata.SchemaCompareResult = { let result: azdata.SchemaCompareResult = {
operationId: this.testOperationId, operationId: this.testOperationId,

View File

@@ -1781,6 +1781,11 @@ declare module 'azdata' {
ownerUri: string; ownerUri: string;
} }
export interface SchemaCompareObjectId {
nameParts: string[];
sqlObjectType: string;
}
export interface SchemaCompareOptionsResult extends ResultStatus { export interface SchemaCompareOptionsResult extends ResultStatus {
defaultDeploymentOptions: DeploymentOptions; defaultDeploymentOptions: DeploymentOptions;
} }
@@ -1941,6 +1946,7 @@ declare module 'azdata' {
schemaComparePublishChanges(operationId: string, targetServerName: string, targetDatabaseName: string, taskExecutionMode: TaskExecutionMode): Thenable<ResultStatus>; schemaComparePublishChanges(operationId: string, targetServerName: string, targetDatabaseName: string, taskExecutionMode: TaskExecutionMode): Thenable<ResultStatus>;
schemaCompareGetDefaultOptions(): Thenable<SchemaCompareOptionsResult>; schemaCompareGetDefaultOptions(): Thenable<SchemaCompareOptionsResult>;
schemaCompareIncludeExcludeNode(operationId: string, diffEntry: DiffEntry, IncludeRequest: boolean, taskExecutionMode: TaskExecutionMode): Thenable<ResultStatus>; schemaCompareIncludeExcludeNode(operationId: string, diffEntry: DiffEntry, IncludeRequest: boolean, taskExecutionMode: TaskExecutionMode): Thenable<ResultStatus>;
schemaCompareSaveScmp(sourceEndpointInfo: SchemaCompareEndpointInfo, targetEndpointInfo: SchemaCompareEndpointInfo, taskExecutionMode: TaskExecutionMode, deploymentOptions: DeploymentOptions, scmpFilePath: string, excludedSourceObjects: SchemaCompareObjectId[], excludedTargetObjects: SchemaCompareObjectId[]): Thenable<ResultStatus>;
schemaCompareCancel(operationId: string): Thenable<ResultStatus>; schemaCompareCancel(operationId: string): Thenable<ResultStatus>;
} }

View File

@@ -20,6 +20,7 @@ export interface ISchemaCompareService {
schemaComparePublishChanges(operationId: string, targetServerName: string, targetDatabaseName: string, taskExecutionMode: azdata.TaskExecutionMode): void; schemaComparePublishChanges(operationId: string, targetServerName: string, targetDatabaseName: string, taskExecutionMode: azdata.TaskExecutionMode): void;
schemaCompareGetDefaultOptions(): void; schemaCompareGetDefaultOptions(): void;
schemaCompareIncludeExcludeNode(operationId: string, diffEntry: azdata.DiffEntry, includeRequest: boolean, taskExecutionMode: azdata.TaskExecutionMode): void; schemaCompareIncludeExcludeNode(operationId: string, diffEntry: azdata.DiffEntry, includeRequest: boolean, taskExecutionMode: azdata.TaskExecutionMode): void;
schemaCompareSaveScmp(sourceEndpointInfo: azdata.SchemaCompareEndpointInfo, targetEndpointInfo: azdata.SchemaCompareEndpointInfo, taskExecutionMode: azdata.TaskExecutionMode, deploymentOptions: azdata.DeploymentOptions, scmpFilePath: string, excludedSourceObjects: azdata.SchemaCompareObjectId[], excludedTargetObjects: azdata.SchemaCompareObjectId[]);
schemaCompareCancel(operationId: string): void; schemaCompareCancel(operationId: string): void;
} }
@@ -63,6 +64,12 @@ export class SchemaCompareService implements ISchemaCompareService {
}); });
} }
schemaCompareSaveScmp(sourceEndpointInfo: azdata.SchemaCompareEndpointInfo, targetEndpointInfo: azdata.SchemaCompareEndpointInfo, taskExecutionMode: azdata.TaskExecutionMode, deploymentOptions: azdata.DeploymentOptions, scmpFilePath: string, excludedSourceObjects: azdata.SchemaCompareObjectId[], excludedTargetObjects: azdata.SchemaCompareObjectId[]) {
return this._runAction('', (runner) => {
return runner.schemaCompareSaveScmp(sourceEndpointInfo, targetEndpointInfo, taskExecutionMode, deploymentOptions, scmpFilePath, excludedSourceObjects, excludedTargetObjects);
});
}
schemaCompareCancel(operationId: string): Thenable<azdata.ResultStatus> { schemaCompareCancel(operationId: string): Thenable<azdata.ResultStatus> {
return this._runAction('', (runner) => { return this._runAction('', (runner) => {
return runner.schemaCompareCancel(operationId); return runner.schemaCompareCancel(operationId);

View File

@@ -485,6 +485,9 @@ export class MainThreadDataProtocol implements MainThreadDataProtocolShape {
schemaCompareIncludeExcludeNode(operationId: string, diffEntry: azdata.DiffEntry, includeRequest: boolean, taskExecutionMode: azdata.TaskExecutionMode): Thenable<azdata.ResultStatus> { schemaCompareIncludeExcludeNode(operationId: string, diffEntry: azdata.DiffEntry, includeRequest: boolean, taskExecutionMode: azdata.TaskExecutionMode): Thenable<azdata.ResultStatus> {
return self._proxy.$schemaCompareIncludeExcludeNode(handle, operationId, diffEntry, includeRequest, taskExecutionMode); return self._proxy.$schemaCompareIncludeExcludeNode(handle, operationId, diffEntry, includeRequest, taskExecutionMode);
}, },
schemaCompareSaveScmp(sourceEndpointInfo: azdata.SchemaCompareEndpointInfo, targetEndpointInfo: azdata.SchemaCompareEndpointInfo, taskExecutionMode: azdata.TaskExecutionMode, deploymentOptions: azdata.DeploymentOptions, scmpFilePath: string, excludedSourceObjects: azdata.SchemaCompareObjectId[], excludedTargetObjects: azdata.SchemaCompareObjectId[]): Thenable<azdata.ResultStatus> {
return self._proxy.$schemaCompareSaveScmp(handle, sourceEndpointInfo, targetEndpointInfo, taskExecutionMode, deploymentOptions, scmpFilePath, excludedSourceObjects, excludedTargetObjects);
},
schemaCompareCancel(operationId: string): Thenable<azdata.ResultStatus> { schemaCompareCancel(operationId: string): Thenable<azdata.ResultStatus> {
return self._proxy.$schemaCompareCancel(handle, operationId); return self._proxy.$schemaCompareCancel(handle, operationId);
} }

View File

@@ -488,6 +488,11 @@ export abstract class ExtHostDataProtocolShape {
*/ */
$schemaCompareIncludeExcludeNode(handle: number, operationId: string, diffEntry: azdata.DiffEntry, includeRequest: boolean, taskExecutionMode: azdata.TaskExecutionMode): Thenable<azdata.ResultStatus> { throw ni(); } $schemaCompareIncludeExcludeNode(handle: number, operationId: string, diffEntry: azdata.DiffEntry, includeRequest: boolean, taskExecutionMode: azdata.TaskExecutionMode): Thenable<azdata.ResultStatus> { throw ni(); }
/**
* Schema compare save scmp
*/
$schemaCompareSaveScmp(handle: number, sourceEndpointInfo: azdata.SchemaCompareEndpointInfo, targetEndpointInfo: azdata.SchemaCompareEndpointInfo, taskExecutionMode: azdata.TaskExecutionMode, deploymentOptions: azdata.DeploymentOptions, scmpFilePath: string, excludedSourceObjects: azdata.SchemaCompareObjectId[], excludedTargetObjects: azdata.SchemaCompareObjectId[]): Thenable<azdata.ResultStatus> { throw ni(); }
/** /**
* Schema compare cancel * Schema compare cancel
*/ */