Skip to content

Commit e357f6d

Browse files
Add Schema Compare Controller Logic (#18619)
* Set up schema compare page * Localized strings * Add schema compare contracts and endpoints * Add schema compare icons * Use schema compare icon in webview. * Add init logic for SC webview controller * Defines and registers reducers * Remove unwanted change * Define and implement schame compare state provider * Fix controller init logic * Add SQL Projects schema compare entry point * Get full SQL projects path * Setup controller for tests * Add basic test * Add schema compare controller unit tests * Add more tests for SchemaCompare controller tests * Add additional tests to verify results * Code review changes * Add deployment options reducer * Rename reducers to be less redundant * Add doc strings * Code review changes * Fix schema compare docstring * Minor clean up * Clean up pipelines * Skip all tests for now * Add vscodeWrapper to controller * Bring back tests * Bring back all other tests * Set operationId in controller * Code review changes * Consolidate unit tests
1 parent e0e1716 commit e357f6d

17 files changed

+1499
-2
lines changed

gulpfile.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const gulp = require('gulp');
1+
const gulp = require('gulp');
22
const rename = require('gulp-rename');
33
const ts = require('gulp-typescript');
44
const tsProject = ts.createProject('tsconfig.json');
@@ -190,6 +190,7 @@ async function generateReactWebviewsBundle() {
190190
'queryResult': 'src/reactviews/pages/QueryResult/index.tsx',
191191
'userSurvey': 'src/reactviews/pages/UserSurvey/index.tsx',
192192
'schemaDesigner': 'src/reactviews/pages/SchemaDesigner/index.tsx',
193+
'schemaCompare': 'src/reactviews/pages/SchemaCompare/index.tsx',
193194
},
194195
bundle: true,
195196
outdir: 'out/src/reactviews/assets',

localization/l10n/bundle.l10n.json

+1
Original file line numberDiff line numberDiff line change
@@ -808,6 +808,7 @@
808808
]
809809
},
810810
"General": "General",
811+
"Schema Compare": "Schema Compare",
811812
"Azure sign in failed.": "Azure sign in failed.",
812813
"Select subscriptions": "Select subscriptions",
813814
"Error loading Azure subscriptions.": "Error loading Azure subscriptions.",

localization/xliff/vscode-mssql.xlf

+6
Original file line numberDiff line numberDiff line change
@@ -1103,6 +1103,9 @@
11031103
<trans-unit id="++CODE++07b091a3fdc4e4c03cd047b5264e61241f20fe8dbc36a4c796d46cd8dc3e7d03">
11041104
<source xml:lang="en">Schema</source>
11051105
</trans-unit>
1106+
<trans-unit id="++CODE++154e484fc5e1a7cb4991c071caef673c453eaa7dcfef4321db537c576a5c56cf">
1107+
<source xml:lang="en">Schema Compare</source>
1108+
</trans-unit>
11061109
<trans-unit id="++CODE++cce7c24ebb0a14bc98b7d6a3f18ddfe9c893e65adb1a599321b3e0eca3515490">
11071110
<source xml:lang="en">Script As Create</source>
11081111
</trans-unit>
@@ -1803,6 +1806,9 @@
18031806
<trans-unit id="mssql.runQueryHistory">
18041807
<source xml:lang="en">Run Query</source>
18051808
</trans-unit>
1809+
<trans-unit id="mssql.schemaCompare">
1810+
<source xml:lang="en">Schema Compare (Preview)</source>
1811+
</trans-unit>
18061812
<trans-unit id="mssql.scriptAlter">
18071813
<source xml:lang="en">Script as Alter</source>
18081814
</trans-unit>

media/schemaCompare_dark.svg

+1
Loading

media/schemaCompare_light.svg

+1
Loading

package.json

+17
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,14 @@
422422
"when": "view == objectExplorer && config.mssql.enableRichExperiences && viewItem =~ /\\bfilterable=true\\b.*\\bhasFilters=true\\b/",
423423
"group": "inline@2"
424424
},
425+
{
426+
"command": "mssql.schemaCompare",
427+
"when": "view == objectExplorer && config.mssql.enableRichExperiences && viewItem =~ /\\btype=(disconnectedServer|Server|Database)\\b/"
428+
},
429+
{
430+
"command": "mssql.schemaCompare",
431+
"when": "view == dataworkspace.views.main && config.mssql.enableRichExperiences && viewItem =~ /^(databaseProject.itemType.project|databaseProject.itemType.legacyProject)$/"
432+
},
425433
{
426434
"command": "mssql.filterNode",
427435
"when": "view == objectExplorer && config.mssql.enableRichExperiences && viewItem =~ /\\bfilterable=true\\b.*\\bhasFilters=false\\b/"
@@ -524,6 +532,10 @@
524532
"command": "mssql.objectExplorerNewQuery",
525533
"when": "view == objectExplorer && viewItem =~ /\\btype=(disconnectedServer|Server|Database)\\b/"
526534
},
535+
{
536+
"command": "mssql.schemaCompare",
537+
"when": "view == objectExplorer && config.mssql.enableRichExperiences && viewItem =~ /\\btype=(disconnectedServer|Server|Database)\\b/"
538+
},
527539
{
528540
"command": "mssql.removeObjectExplorerNode",
529541
"when": "view == objectExplorer && viewItem =~ /\\btype=(disconnectedServer|Server)\\b/"
@@ -705,6 +717,11 @@
705717
"title": "%mssql.newQuery%",
706718
"category": "MS SQL"
707719
},
720+
{
721+
"command": "mssql.schemaCompare",
722+
"title": "%mssql.schemaCompare%",
723+
"category": "MS SQL"
724+
},
708725
{
709726
"command": "mssql.rebuildIntelliSenseCache",
710727
"title": "%mssql.rebuildIntelliSenseCache%",

package.nls.json

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"mssql.showGettingStarted":"Getting Started Guide",
3535
"mssql.newQuery":"New Query",
3636
"mssql.objectExplorerNewQuery":"New Query",
37+
"mssql.schemaCompare": "Schema Compare (Preview)",
3738
"mssql.toggleSqlCmd":"Toggle SQLCMD Mode",
3839
"mssql.copyObjectName":"Copy Object Name",
3940
"mssql.addAadAccount":"Add Microsoft Entra Account",

src/constants/constants.ts

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export const cmdStartQueryHistory = "mssql.startQueryHistoryCapture";
4141
export const cmdPauseQueryHistory = "mssql.pauseQueryHistoryCapture";
4242
export const cmdCommandPaletteQueryHistory = "mssql.commandPaletteQueryHistory";
4343
export const cmdNewQuery = "mssql.newQuery";
44+
export const cmdSchemaCompare = "mssql.schemaCompare";
4445
export const cmdManageConnectionProfiles = "mssql.manageProfiles";
4546
export const cmdClearPooledConnections = "mssql.clearPooledConnections";
4647
export const cmdRebuildIntelliSenseCache = "mssql.rebuildIntelliSenseCache";

src/constants/locConstants.ts

+4
Original file line numberDiff line numberDiff line change
@@ -799,3 +799,7 @@ export class TableDesigner {
799799
public static Columns = l10n.t("Columns");
800800
public static AdvancedOptions = l10n.t("Advanced Options");
801801
}
802+
803+
export class SchemaCompare {
804+
public static Title = l10n.t("Schema Compare");
805+
}

src/controllers/mainController.ts

+27-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*---------------------------------------------------------------------------------------------
1+
/*---------------------------------------------------------------------------------------------
22
* Copyright (c) Microsoft Corporation. All rights reserved.
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
@@ -63,6 +63,8 @@ import { ObjectExplorerDragAndDropController } from "../objectExplorer/objectExp
6363
import { SchemaDesignerService } from "../services/schemaDesignerService";
6464
import { SchemaDesignerWebviewController } from "../schemaDesigner/schemaDesignerWebviewController";
6565
import store from "../queryResult/singletonStore";
66+
import { SchemaCompareWebViewController } from "../schemaCompare/schemaCompareWebViewController";
67+
import { SchemaCompare } from "../constants/locConstants";
6668

6769
/**
6870
* The main controller class that initializes the extension
@@ -896,6 +898,13 @@ export default class MainController implements vscode.Disposable {
896898
);
897899

898900
if (this.isRichExperiencesEnabled) {
901+
this._context.subscriptions.push(
902+
vscode.commands.registerCommand(
903+
Constants.cmdSchemaCompare,
904+
async (node: any) => this.onSchemaCompare(node),
905+
),
906+
);
907+
899908
this._context.subscriptions.push(
900909
vscode.commands.registerCommand(
901910
Constants.cmdEditConnection,
@@ -1983,6 +1992,23 @@ export default class MainController implements vscode.Disposable {
19831992
return false;
19841993
}
19851994

1995+
public async onSchemaCompare(node: any): Promise<void> {
1996+
if (node) {
1997+
const result = await this.schemaCompareService.getDefaultOptions();
1998+
const schemaCompareWebView = new SchemaCompareWebViewController(
1999+
this._context,
2000+
this._vscodeWrapper,
2001+
node,
2002+
this.schemaCompareService,
2003+
this._connectionMgr,
2004+
result,
2005+
SchemaCompare.Title,
2006+
);
2007+
2008+
schemaCompareWebView.revealToForeground();
2009+
}
2010+
}
2011+
19862012
/**
19872013
* Check if the extension launched file exists.
19882014
* This is to detect when we are running in a clean install scenario.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
export const SchemaComparePage = () => {
7+
return (
8+
<div>
9+
{/* WIP/Initial Checkin: Page is a work in progress */}
10+
<h1>Schema Compare Page</h1>
11+
</div>
12+
);
13+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import * as sc from "../../../sharedInterfaces/schemaCompare";
7+
import * as mssql from "vscode-mssql";
8+
9+
import { createContext } from "react";
10+
import { useVscodeWebview } from "../../common/vscodeWebviewProvider";
11+
12+
const schemaCompareContext = createContext<sc.SchemaCompareContextProps>(
13+
{} as sc.SchemaCompareContextProps,
14+
);
15+
16+
interface SchemaCompareStateProviderProps {
17+
children: React.ReactNode;
18+
}
19+
20+
const SchemaCompareStateProvider: React.FC<SchemaCompareStateProviderProps> = ({
21+
children,
22+
}) => {
23+
const webViewState = useVscodeWebview<
24+
sc.SchemaCompareWebViewState,
25+
sc.SchemaCompareReducers
26+
>();
27+
const schemaCompareState = webViewState?.state;
28+
29+
return (
30+
<schemaCompareContext.Provider
31+
value={{
32+
state: schemaCompareState,
33+
themeKind: webViewState?.themeKind,
34+
compare: function (
35+
sourceEndpointInfo: mssql.SchemaCompareEndpointInfo,
36+
targetEndpointInfo: mssql.SchemaCompareEndpointInfo,
37+
taskExecutionMode: mssql.TaskExecutionMode,
38+
deploymentOptions: mssql.DeploymentOptions,
39+
): void {
40+
webViewState?.extensionRpc.action("compare", {
41+
sourceEndpointInfo: sourceEndpointInfo,
42+
targetEndpointInfo: targetEndpointInfo,
43+
taskExecutionMode: taskExecutionMode,
44+
deploymentOptions: deploymentOptions,
45+
});
46+
},
47+
generateScript: function (
48+
targetServerName: string,
49+
targetDatabaseName: string,
50+
taskExecutionMode: mssql.TaskExecutionMode,
51+
): void {
52+
webViewState?.extensionRpc.action("generateScript", {
53+
targetServerName: targetServerName,
54+
targetDatabaseName: targetDatabaseName,
55+
taskExecutionMode: taskExecutionMode,
56+
});
57+
},
58+
publishDatabaseChanges: function (
59+
targetServerName: string,
60+
targetDatabaseName: string,
61+
taskExecutionMode: mssql.TaskExecutionMode,
62+
): void {
63+
webViewState?.extensionRpc.action(
64+
"publishDatabaseChanges",
65+
{
66+
targetServerName: targetServerName,
67+
targetDatabaseName: targetDatabaseName,
68+
taskExecutionMode: taskExecutionMode,
69+
},
70+
);
71+
},
72+
publishProjectChanges: function (
73+
targetProjectPath: string,
74+
targetFolderStructure: mssql.ExtractTarget,
75+
taskExecutionMode: mssql.TaskExecutionMode,
76+
): void {
77+
webViewState?.extensionRpc.action("publishProjectChanges", {
78+
targetProjectPath: targetProjectPath,
79+
targetFolderStructure: targetFolderStructure,
80+
taskExecutionMode: taskExecutionMode,
81+
});
82+
},
83+
getDefaultOptions: function (): void {
84+
webViewState?.extensionRpc.action("getDefaultOptions", {});
85+
},
86+
includeExcludeNode: function (
87+
diffEntry: mssql.DiffEntry,
88+
includeRequest: boolean,
89+
taskExecutionMode: mssql.TaskExecutionMode,
90+
): void {
91+
webViewState?.extensionRpc.action("includeExcludeNode", {
92+
diffEntry: diffEntry,
93+
includeRequest: includeRequest,
94+
taskExecutionMode: taskExecutionMode,
95+
});
96+
},
97+
openScmp: function (filePath: string): void {
98+
webViewState?.extensionRpc.action("openScmp", {
99+
filePath: filePath,
100+
});
101+
},
102+
saveScmp: function (
103+
sourceEndpointInfo: mssql.SchemaCompareEndpointInfo,
104+
targetEndpointInfo: mssql.SchemaCompareEndpointInfo,
105+
taskExecutionMode: mssql.TaskExecutionMode,
106+
deploymentOptions: mssql.DeploymentOptions,
107+
scmpFilePath: string,
108+
excludedSourceObjects: mssql.SchemaCompareObjectId[],
109+
excludedTargetObjects: mssql.SchemaCompareObjectId[],
110+
): void {
111+
webViewState?.extensionRpc.action("saveScmp", {
112+
sourceEndpointInfo: sourceEndpointInfo,
113+
targetEndpointInfo: targetEndpointInfo,
114+
taskExecutionMode: taskExecutionMode,
115+
deploymentOptions: deploymentOptions,
116+
scmpFilePath: scmpFilePath,
117+
excludedSourceObjects: excludedSourceObjects,
118+
excludedTargetObjects: excludedTargetObjects,
119+
});
120+
},
121+
cancel: function (): void {
122+
webViewState?.extensionRpc.action("cancel", {});
123+
},
124+
}}
125+
>
126+
{children}
127+
</schemaCompareContext.Provider>
128+
);
129+
};
130+
131+
export { SchemaCompareStateProvider };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import ReactDOM from "react-dom/client";
7+
import "../../index.css";
8+
import { VscodeWebviewProvider } from "../../common/vscodeWebviewProvider";
9+
import { SchemaComparePage } from "./SchemaCompare";
10+
import { SchemaCompareStateProvider } from "./SchemaCompareStateProvider";
11+
12+
ReactDOM.createRoot(document.getElementById("root")!).render(
13+
<VscodeWebviewProvider>
14+
<SchemaCompareStateProvider>
15+
<SchemaComparePage />
16+
</SchemaCompareStateProvider>
17+
</VscodeWebviewProvider>,
18+
);

0 commit comments

Comments
 (0)