diff --git a/extensions/mssql/src/contracts.ts b/extensions/mssql/src/contracts.ts index 312f7a22d0..de6ad2705a 100644 --- a/extensions/mssql/src/contracts.ts +++ b/extensions/mssql/src/contracts.ts @@ -602,29 +602,275 @@ export namespace SavePublishProfileRequest { // ------------------------------- ------------------------------------ // ------------------------------- < Sql Projects > ------------------------------------ +//#region SqlProjects -export namespace NewSqlProjectRequest { - export const type = new RequestType('sqlProjects/newProject'); +//#region Functions + +//#region Project-level functions + +export namespace CreateSqlProjectRequest { + export const type = new RequestType('sqlProjects/newProject'); // TODO: switch to "createProject" with next Tools Service update } export namespace OpenSqlProjectRequest { export const type = new RequestType('sqlProjects/openProject'); } +export namespace CloseSqlProjectRequest { + export const type = new RequestType('sqlProjects/closeProject'); +} + export namespace GetCrossPlatformCompatiblityRequest { export const type = new RequestType('sqlProjects/getCrossPlatformCompatibility'); } +export namespace UpdateProjectForCrossPlatformRequest { + export const type = new RequestType('sqlProjects/updateProjectForCrossPlatform'); +} + +//#endregion + +//#region File/folder functions + +//#region SQL object script functions + +export namespace AddSqlObjectScriptRequest { + export const type = new RequestType('sqlProjects/addSqlObjectScript'); +} + +export namespace DeleteSqlObjectScriptRequest { + export const type = new RequestType('sqlProjects/deleteSqlObjectScript'); +} + +export namespace ExcludeSqlObjectScriptRequest { + export const type = new RequestType('sqlProjects/excludeSqlObjectScript'); +} + +export namespace MoveSqlObjectScriptRequest { + export const type = new RequestType('sqlProjects/moveSqlObjectScript'); +} + +//#endregion + +//#region Folder functions + +export namespace AddFolderRequest { + export const type = new RequestType('sqlProjects/addFolder'); +} + +export namespace DeleteFolderRequest { + export const type = new RequestType('sqlProjects/deleteFolder'); +} + +//#endregion + +//#region Pre/Post-deployment script functions + +export namespace AddPostDeploymentScriptRequest { + export const type = new RequestType('sqlProjects/addPostDeploymentScript'); +} + +export namespace AddPreDeploymentScriptRequest { + export const type = new RequestType('sqlProjects/addPreDeploymentScript'); +} + +export namespace DeletePostDeploymentScriptRequest { + export const type = new RequestType('sqlProjects/deletePostDeploymentScript'); +} + +export namespace DeletePreDeploymentScriptRequest { + export const type = new RequestType('sqlProjects/deletePreDeploymentScript'); +} + +export namespace ExcludePostDeploymentScriptRequest { + export const type = new RequestType('sqlProjects/excludePostDeploymentScript'); +} + +export namespace ExcludePreDeploymentScriptRequest { + export const type = new RequestType('sqlProjects/excludePreDeploymentScript'); +} + +export namespace MovePostDeploymentScriptRequest { + export const type = new RequestType('sqlProjects/movePostDeploymentScript'); +} + +export namespace MovePreDeploymentScriptRequest { + export const type = new RequestType('sqlProjects/movePreDeploymentScript'); +} + +//#endregion + +//#endregion + +//#region SQLCMD variable functions + +export namespace AddSqlCmdVariableRequest { + export const type = new RequestType('sqlProjects/addSqlCmdVariable'); +} + +export namespace DeleteSqlCmdVariableRequest { + export const type = new RequestType('sqlProjects/deleteSqlCmdVariable'); +} + +export namespace UpdateSqlCmdVariableRequest { + export const type = new RequestType('sqlProjects/updateSqlCmdVariable'); +} + +//#endregion + +//#region Database reference functions + +export namespace AddDacpacReferenceRequest { + /** + * + */ + export const type = new RequestType('sqlprojects/addDacpacReference'); +} + +export namespace AddSqlProjectReferenceRequest { + export const type = new RequestType('sqlprojects/addSqlProjectReference'); +} + +export namespace AddSystemDatabaseReferenceRequest { + export const type = new RequestType('sqlprojects/addSystemDatabaseReference'); +} + +export namespace DeleteDatabaseReferenceRequest { + export const type = new RequestType('sqlprojects/deleteDatabaseReference'); +} + +//#endregion + +//#endregion + +//#region Parameters + export interface SqlProjectParams { + /** + * Absolute path of the project, including .sqlproj + */ projectUri: string; } -export interface NewSqlProjectParams extends SqlProjectParams { - sqlProjectType: mssql.ProjectType, - databaseSchemaProvider: string, - buildSdkVersion?: string +export interface SqlProjectScriptParams extends SqlProjectParams { + /** + * Path of the script, including .sql, relative to the .sqlproj + */ + path: string; } +export interface AddDacpacReferenceParams extends AddUserDatabaseReferenceParams { + /** + * Path to the .dacpac file + */ + dacpacPath: string; +} + +export interface AddDatabaseReferenceParams extends SqlProjectParams { + /** + * Whether to suppress missing dependencies + */ + suppressMissingDependencies: boolean; + /** + * Literal name used to reference another database in the same server, if not using SQLCMD variables + */ + databaseLiteral?: string; +} + +export interface AddSqlProjectReferenceParams extends AddUserDatabaseReferenceParams { + /** + * Path to the referenced .sqlproj file + */ + projectPath: string; + /** + * GUID for the referenced SQL project + */ + projectGuid: string; +} + +export interface AddSystemDatabaseReferenceParams extends AddDatabaseReferenceParams { + /** + * Type of system database + */ + systemDatabase: mssql.SystemDatabase; +} + +export interface AddUserDatabaseReferenceParams extends AddDatabaseReferenceParams { + /** + * SQLCMD variable name for specifying the other database this reference is to, if different from that of the current project + */ + databaseVariable?: string; + /** + * SQLCMD variable name for specifying the other server this reference is to, if different from that of the current project. + * If this is set, DatabaseVariable must also be set. + */ + serverVariable?: string; +} + +export interface DeleteDatabaseReferenceParams extends SqlProjectParams { + /** + * Name of the reference to be deleted. Name of the System DB, path of the sqlproj, or path of the dacpac + */ + name: string; +} + +export interface FolderParams extends SqlProjectParams { + /** + * Path of the folder, typically relative to the .sqlproj file + */ + path: string; +} + +export interface CreateSqlProjectParams extends SqlProjectParams { + /** + * Type of SQL Project: SDK-style or Legacy + */ + sqlProjectType: mssql.ProjectType; + /** + * Database schema provider for the project, in the format + * "Microsoft.Data.Tools.Schema.Sql.SqlXYZDatabaseSchemaProvider". + * Case sensitive. + */ + databaseSchemaProvider?: string; + /** + * Version of the Microsoft.Build.Sql SDK for the project, if overriding the default + */ + buildSdkVersion?: string; +} + +export interface AddSqlCmdVariableParams extends SqlProjectParams { + /** + * Name of the SQLCMD variable + */ + name: string; + /** + * Default value of the SQLCMD variable + */ + defaultValue: string; + /** + * Value of the SQLCMD variable, with or without the $() + */ + value: string; +} + +export interface DeleteSqlCmdVariableParams extends SqlProjectParams { + /** + * Name of the SQLCMD variable to be deleted + */ + name?: string; +} + +export interface MoveItemParams extends SqlProjectScriptParams { + /** + * Destination path of the file or folder, relative to the .sqlproj + */ + destinationPath: string; +} + +//#endregion + +//#endregion + // ------------------------------- ----------------------------------- // ------------------------------- ---------------------------------------- diff --git a/extensions/mssql/src/mssql.d.ts b/extensions/mssql/src/mssql.d.ts index 2e64fc43f6..ea6b1e9386 100644 --- a/extensions/mssql/src/mssql.d.ts +++ b/extensions/mssql/src/mssql.d.ts @@ -314,21 +314,270 @@ declare module 'mssql' { //#region --- Sql Projects + /** + * Interface for working with .sqlproj files + */ export interface ISqlProjectsService { - newProject(projectUri: string, sqlProjectType: ProjectType, databaseSchemaProvider: string, buildSdkVersion?: string): Promise; + /** + * Add a dacpac reference to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param dacpacPath Path to the .dacpac file + * @param suppressMissingDependencies Whether to suppress missing dependencies + * @param databaseVariable SQLCMD variable name for specifying the other database this reference is to, if different from that of the current project + * @param serverVariable SQLCMD variable name for specifying the other server this reference is to, if different from that of the current project. + If this is set, DatabaseVariable must also be set. + * @param databaseLiteral Literal name used to reference another database in the same server, if not using SQLCMD variables + */ + addDacpacReference(projectUri: string, dacpacPath: string, suppressMissingDependencies: boolean, databaseVariable?: string, serverVariable?: string, databaseLiteral?: string): Promise; + + /** + * Add a SQL Project reference to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param projectPath Path to the referenced .sqlproj file + * @param projectGuid GUID for the referenced SQL project + * @param suppressMissingDependencies Whether to suppress missing dependencies + * @param databaseVariable SQLCMD variable name for specifying the other database this reference is to, if different from that of the current project + * @param serverVariable SQLCMD variable name for specifying the other server this reference is to, if different from that of the current project. + If this is set, DatabaseVariable must also be set. + * @param databaseLiteral Literal name used to reference another database in the same server, if not using SQLCMD variables + */ + addSqlProjectReference(projectUri: string, projectPath: string, projectGuid: string, suppressMissingDependencies: boolean, databaseVariable?: string, serverVariable?: string, databaseLiteral?: string): Promise; + + /** + * Add a system database reference to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param systemDatabase Type of system database + * @param suppressMissingDependencies Whether to suppress missing dependencies + * @param databaseLiteral Literal name used to reference another database in the same server, if not using SQLCMD variables + */ + addSystemDatabaseReference(projectUri: string, systemDatabase: SystemDatabase, suppressMissingDependencies: boolean, databaseLiteral?: string): Promise; + + /** + * Delete a database reference from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + deleteDatabaseReference(projectUri: string, path: string): Promise; + + /** + * Add a folder to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the folder, typically relative to the .sqlproj file + */ + addFolder(projectUri: string, path: string): Promise; + + /** + * Delete a folder from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the folder, typically relative to the .sqlproj file + */ + deleteFolder(projectUri: string, path: string): Promise; + + /** + * Add a post-deployment script to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + addPostDeploymentScript(projectUri: string, path: string): Promise; + + /** + * Add a pre-deployment script to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + addPreDeploymentScript(projectUri: string, path: string): Promise; + + /** + * Delete a post-deployment script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + deletePostDeploymentScript(projectUri: string, path: string): Promise; + + /** + * Delete a pre-deployment script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + deletePreDeploymentScript(projectUri: string, path: string): Promise; + + /** + * Exclude a post-deployment script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + excludePostDeploymentScript(projectUri: string, path: string): Promise; + + /** + * Exclude a pre-deployment script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + excludePreDeploymentScript(projectUri: string, path: string): Promise; + + /** + * Move a post-deployment script in a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param destinationPath Destination path of the file or folder, relative to the .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + movePostDeploymentScript(projectUri: string, destinationPath: string, path: string): Promise; + + /** + * Move a pre-deployment script in a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param destinationPath Destination path of the file or folder, relative to the .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + movePreDeploymentScript(projectUri: string, destinationPath: string, path: string): Promise; + + /** + * Close a SQL project + * @param projectUri Absolute path of the project, including .sqlproj + */ + closeProject(projectUri: string): Promise; + + /** + * Create a new SQL project + * @param projectUri Absolute path of the project, including .sqlproj + * @param sqlProjectType Type of SQL Project: SDK-style or Legacy + * @param databaseSchemaProvider Database schema provider for the project, in the format + "Microsoft.Data.Tools.Schema.Sql.SqlXYZDatabaseSchemaProvider". + Case sensitive. + * @param buildSdkVersion Version of the Microsoft.Build.Sql SDK for the project, if overriding the default + */ + createProject(projectUri: string, sqlProjectType: ProjectType, databaseSchemaProvider?: string, buildSdkVersion?: string): Promise; + + /** + * Get the cross-platform compatibility status for a project + * @param projectUri Absolute path of the project, including .sqlproj + */ + getCrossPlatformCompatibility(projectUri: string): Promise; + + /** + * Open an existing SQL project + * @param projectUri Absolute path of the project, including .sqlproj + */ openProject(projectUri: string): Promise; - getCrossPlatformCompatiblityRequest(projectUri: string): Promise; + + /** + * Update a SQL project to be cross-platform compatible + * @param projectUri Absolute path of the project, including .sqlproj + */ + updateProjectForCrossPlatform(projectUri: string): Promise; + + /** + * Add a SQLCMD variable to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param name Name of the SQLCMD variable + * @param defaultValue Default value of the SQLCMD variable + * @param value Value of the SQLCMD variable, with or without the $() + */ + addSqlCmdVariable(projectUri: string, name: string, defaultValue: string, value: string): Promise; + + /** + * Delete a SQLCMD variable from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param name Name of the SQLCMD variable to be deleted + */ + deleteSqlCmdVariable(projectUri: string, name?: string): Promise; + + /** + * Update an existing SQLCMD variable in a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param name Name of the SQLCMD variable + * @param defaultValue Default value of the SQLCMD variable + * @param value Value of the SQLCMD variable, with or without the $() + */ + updateSqlCmdVariable(projectUri: string, name: string, defaultValue: string, value: string): Promise; + + /** + * Add a SQL object script to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + addSqlObjectScript(projectUri: string, path: string): Promise; + + /** + * Delete a SQL object script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + deleteSqlObjectScript(projectUri: string, path: string): Promise; + + /** + * Exclude a SQL object script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + excludeSqlObjectScript(projectUri: string, path: string): Promise; + + /** + * Move a SQL object script in a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param destinationPath Destination path of the file or folder, relative to the .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + moveSqlObjectScript(projectUri: string, destinationPath: string, path: string): Promise; } + + //#region Results + + export interface GetCrossPlatformCompatiblityResult extends azdata.ResultStatus { + isCrossPlatformCompatible: boolean; + } + + //#endregion + + //#region Types + export const enum ProjectType { SdkStyle = 0, LegacyStyle = 1 } - export interface GetCrossPlatformCompatiblityResult extends azdata.ResultStatus { - isCrossPlatformCompatible: boolean; + export interface DatabaseReference { + suppressMissingDependencies: boolean; + databaseVariableLiteralName?: string; } + interface UserDatabaseReference extends DatabaseReference { + databaseVariable: SqlCmdVariable; + serverVariable?: SqlCmdVariable; + } + + export interface SystemDatabaseReference extends DatabaseReference { + systemDb: SystemDatabase; + } + + export interface SqlProjectReference extends UserDatabaseReference { + projectPath: string; + projectGuid?: string; + } + + export interface DacpacReference extends UserDatabaseReference { + dacpacPath: string; + } + + export const enum SystemDatabase { + master = 0, + msdb = 1 + } + + export const enum ProjectType { + sdkStyle = 0, + legacyStyle = 1 + } + + export interface SqlCmdVariable { + varName: string; + value: string; + defaultValue: string + } + + //#endregion + //#endregion //#region --- Language Extensibility diff --git a/extensions/mssql/src/sqlProjects/sqlProjectsService.ts b/extensions/mssql/src/sqlProjects/sqlProjectsService.ts index c2d5586a9c..8949df63db 100644 --- a/extensions/mssql/src/sqlProjects/sqlProjectsService.ts +++ b/extensions/mssql/src/sqlProjects/sqlProjectsService.ts @@ -11,6 +11,7 @@ import * as contracts from '../contracts'; import { AppContext } from '../appContext'; import { ISqlOpsFeature, SqlOpsDataClient } from 'dataprotocol-client'; import { ClientCapabilities } from 'vscode-languageclient'; +import { RequestType } from 'vscode-languageclient'; export class SqlProjectsService implements mssql.ISqlProjectsService { public static asFeature(context: AppContext): ISqlOpsFeature { @@ -32,35 +33,292 @@ export class SqlProjectsService implements mssql.ISqlProjectsService { context.registerService(constants.SqlProjectsService, this); } - public async newProject(projectUri: string, sqlProjectType: mssql.ProjectType, databaseSchemaProvider: string, buildSdkVersion?: string): Promise { - const params: contracts.NewSqlProjectParams = { projectUri, sqlProjectType, databaseSchemaProvider, buildSdkVersion }; - try { - const result = await this.client.sendRequest(contracts.NewSqlProjectRequest.type, params); - return result; - } catch (e) { - this.client.logFailedRequest(contracts.NewSqlProjectRequest.type, e); - throw e; - } + /** + * Add a dacpac reference to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param dacpacPath Path to the .dacpac file + * @param suppressMissingDependencies Whether to suppress missing dependencies + * @param databaseVariable SQLCMD variable name for specifying the other database this reference is to, if different from that of the current project + * @param serverVariable SQLCMD variable name for specifying the other server this reference is to, if different from that of the current project. + * If this is set, DatabaseVariable must also be set. + * @param databaseLiteral Literal name used to reference another database in the same server, if not using SQLCMD variables + */ + public async addDacpacReference(projectUri: string, dacpacPath: string, suppressMissingDependencies: boolean, databaseVariable?: string, serverVariable?: string, databaseLiteral?: string): Promise { + const params: contracts.AddDacpacReferenceParams = { projectUri: projectUri, dacpacPath: dacpacPath, suppressMissingDependencies: suppressMissingDependencies, databaseVariable: databaseVariable, serverVariable: serverVariable, databaseLiteral: databaseLiteral }; + return await this.runWithErrorHandling(contracts.AddDacpacReferenceRequest.type, params); } + /** + * Add a SQL Project reference to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param projectPath Path to the referenced .sqlproj file + * @param projectGuid GUID for the referenced SQL project + * @param suppressMissingDependencies Whether to suppress missing dependencies + * @param databaseVariable SQLCMD variable name for specifying the other database this reference is to, if different from that of the current project + * @param serverVariable SQLCMD variable name for specifying the other server this reference is to, if different from that of the current project. + * If this is set, DatabaseVariable must also be set. + * @param databaseLiteral Literal name used to reference another database in the same server, if not using SQLCMD variables + */ + public async addSqlProjectReference(projectUri: string, projectPath: string, projectGuid: string, suppressMissingDependencies: boolean, databaseVariable?: string, serverVariable?: string, databaseLiteral?: string): Promise { + const params: contracts.AddSqlProjectReferenceParams = { projectUri: projectUri, projectPath: projectPath, projectGuid: projectGuid, suppressMissingDependencies: suppressMissingDependencies, databaseVariable: databaseVariable, serverVariable: serverVariable, databaseLiteral: databaseLiteral }; + return await this.runWithErrorHandling(contracts.AddSqlProjectReferenceRequest.type, params); + } + + /** + * Add a system database reference to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param systemDatabase Type of system database + * @param suppressMissingDependencies Whether to suppress missing dependencies + * @param databaseLiteral Literal name used to reference another database in the same server, if not using SQLCMD variables + */ + public async addSystemDatabaseReference(projectUri: string, systemDatabase: mssql.SystemDatabase, suppressMissingDependencies: boolean, databaseLiteral?: string): Promise { + const params: contracts.AddSystemDatabaseReferenceParams = { projectUri: projectUri, systemDatabase: systemDatabase, suppressMissingDependencies: suppressMissingDependencies, databaseLiteral: databaseLiteral }; + return await this.runWithErrorHandling(contracts.AddSystemDatabaseReferenceRequest.type, params); + } + + /** + * Delete a database reference from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + public async deleteDatabaseReference(projectUri: string, path: string): Promise { + const params: contracts.SqlProjectScriptParams = { projectUri: projectUri, path: path }; + return await this.runWithErrorHandling(contracts.DeleteDatabaseReferenceRequest.type, params); + } + + /** + * Add a folder to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the folder, typically relative to the .sqlproj file + */ + public async addFolder(projectUri: string, path: string): Promise { + const params: contracts.FolderParams = { projectUri: projectUri, path: path }; + return await this.runWithErrorHandling(contracts.AddFolderRequest.type, params); + } + + /** + * Delete a folder from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the folder, typically relative to the .sqlproj file + */ + public async deleteFolder(projectUri: string, path: string): Promise { + const params: contracts.FolderParams = { projectUri: projectUri, path: path }; + return await this.runWithErrorHandling(contracts.DeleteFolderRequest.type, params); + } + + /** + * Add a post-deployment script to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + public async addPostDeploymentScript(projectUri: string, path: string): Promise { + const params: contracts.SqlProjectScriptParams = { projectUri: projectUri, path: path }; + return await this.runWithErrorHandling(contracts.AddPostDeploymentScriptRequest.type, params); + } + + /** + * Add a pre-deployment script to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + public async addPreDeploymentScript(projectUri: string, path: string): Promise { + const params: contracts.SqlProjectScriptParams = { projectUri: projectUri, path: path }; + return await this.runWithErrorHandling(contracts.AddPreDeploymentScriptRequest.type, params); + } + + /** + * Delete a post-deployment script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + public async deletePostDeploymentScript(projectUri: string, path: string): Promise { + const params: contracts.SqlProjectScriptParams = { projectUri: projectUri, path: path }; + return await this.runWithErrorHandling(contracts.DeletePostDeploymentScriptRequest.type, params); + } + + /** + * Delete a pre-deployment script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + public async deletePreDeploymentScript(projectUri: string, path: string): Promise { + const params: contracts.SqlProjectScriptParams = { projectUri: projectUri, path: path }; + return await this.runWithErrorHandling(contracts.DeletePreDeploymentScriptRequest.type, params); + } + + /** + * Exclude a post-deployment script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + public async excludePostDeploymentScript(projectUri: string, path: string): Promise { + const params: contracts.SqlProjectScriptParams = { projectUri: projectUri, path: path }; + return await this.runWithErrorHandling(contracts.ExcludePostDeploymentScriptRequest.type, params); + } + + /** + * Exclude a pre-deployment script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + public async excludePreDeploymentScript(projectUri: string, path: string): Promise { + const params: contracts.SqlProjectScriptParams = { projectUri: projectUri, path: path }; + return await this.runWithErrorHandling(contracts.ExcludePreDeploymentScriptRequest.type, params); + } + + /** + * Move a post-deployment script in a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param destinationPath Destination path of the file or folder, relative to the .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + public async movePostDeploymentScript(projectUri: string, destinationPath: string, path: string): Promise { + const params: contracts.MoveItemParams = { projectUri: projectUri, destinationPath: destinationPath, path: path }; + return await this.runWithErrorHandling(contracts.MovePostDeploymentScriptRequest.type, params); + } + + /** + * Move a pre-deployment script in a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param destinationPath Destination path of the file or folder, relative to the .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + public async movePreDeploymentScript(projectUri: string, destinationPath: string, path: string): Promise { + const params: contracts.MoveItemParams = { projectUri: projectUri, destinationPath: destinationPath, path: path }; + return await this.runWithErrorHandling(contracts.MovePreDeploymentScriptRequest.type, params); + } + + /** + * Close a SQL project + * @param projectUri Absolute path of the project, including .sqlproj + */ + public async closeProject(projectUri: string): Promise { + const params: contracts.SqlProjectParams = { projectUri: projectUri }; + return await this.runWithErrorHandling(contracts.CloseSqlProjectRequest.type, params); + } + + /** + * Create a new SQL project + * @param projectUri Absolute path of the project, including .sqlproj + * @param sqlProjectType Type of SQL Project: SDK-style or Legacy + * @param databaseSchemaProvider Database schema provider for the project, in the format + * "Microsoft.Data.Tools.Schema.Sql.SqlXYZDatabaseSchemaProvider". + * Case sensitive. + * @param buildSdkVersion Version of the Microsoft.Build.Sql SDK for the project, if overriding the default + */ + public async createProject(projectUri: string, sqlProjectType: mssql.ProjectType, databaseSchemaProvider?: string, buildSdkVersion?: string): Promise { + const params: contracts.CreateSqlProjectParams = { projectUri: projectUri, sqlProjectType: sqlProjectType, databaseSchemaProvider: databaseSchemaProvider, buildSdkVersion: buildSdkVersion }; + return await this.runWithErrorHandling(contracts.CreateSqlProjectRequest.type, params); + } + + /** + * Get the cross-platform compatibility status for a project + * @param projectUri Absolute path of the project, including .sqlproj + */ + public async getCrossPlatformCompatibility(projectUri: string): Promise { + const params: contracts.SqlProjectParams = { projectUri: projectUri }; + return await this.runWithErrorHandling(contracts.GetCrossPlatformCompatiblityRequest.type, params); + } + + /** + * Open an existing SQL project + * @param projectUri Absolute path of the project, including .sqlproj + */ public async openProject(projectUri: string): Promise { - const params: contracts.SqlProjectParams = { projectUri }; - try { - const result = await this.client.sendRequest(contracts.OpenSqlProjectRequest.type, params); - return result; - } catch (e) { - this.client.logFailedRequest(contracts.OpenSqlProjectRequest.type, e); - throw e; - } + const params: contracts.SqlProjectParams = { projectUri: projectUri }; + return await this.runWithErrorHandling(contracts.OpenSqlProjectRequest.type, params); } - public async getCrossPlatformCompatiblityRequest(projectUri: string): Promise { - const params: contracts.SqlProjectParams = { projectUri }; + /** + * Update a SQL project to be cross-platform compatible + * @param projectUri Absolute path of the project, including .sqlproj + */ + public async updateProjectForCrossPlatform(projectUri: string): Promise { + const params: contracts.SqlProjectParams = { projectUri: projectUri }; + return await this.runWithErrorHandling(contracts.UpdateProjectForCrossPlatformRequest.type, params); + } + + /** + * Add a SQLCMD variable to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param name Name of the SQLCMD variable + * @param defaultValue Default value of the SQLCMD variable + * @param value Value of the SQLCMD variable, with or without the $() + */ + public async addSqlCmdVariable(projectUri: string, name: string, defaultValue: string, value: string): Promise { + const params: contracts.AddSqlCmdVariableParams = { projectUri: projectUri, name: name, defaultValue: defaultValue, value: value }; + return await this.runWithErrorHandling(contracts.AddSqlCmdVariableRequest.type, params); + } + + /** + * Delete a SQLCMD variable from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param name Name of the SQLCMD variable to be deleted + */ + public async deleteSqlCmdVariable(projectUri: string, name?: string): Promise { + const params: contracts.DeleteSqlCmdVariableParams = { projectUri: projectUri, name: name }; + return await this.runWithErrorHandling(contracts.DeleteSqlCmdVariableRequest.type, params); + } + + /** + * Update an existing SQLCMD variable in a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param name Name of the SQLCMD variable + * @param defaultValue Default value of the SQLCMD variable + * @param value Value of the SQLCMD variable, with or without the $() + */ + public async updateSqlCmdVariable(projectUri: string, name: string, defaultValue: string, value: string): Promise { + const params: contracts.AddSqlCmdVariableParams = { projectUri: projectUri, name: name, defaultValue: defaultValue, value: value }; + return await this.runWithErrorHandling(contracts.UpdateSqlCmdVariableRequest.type, params); + } + + /** + * Add a SQL object script to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + public async addSqlObjectScript(projectUri: string, path: string): Promise { + const params: contracts.SqlProjectScriptParams = { projectUri: projectUri, path: path }; + return await this.runWithErrorHandling(contracts.AddSqlObjectScriptRequest.type, params); + } + + /** + * Delete a SQL object script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + public async deleteSqlObjectScript(projectUri: string, path: string): Promise { + const params: contracts.SqlProjectScriptParams = { projectUri: projectUri, path: path }; + return await this.runWithErrorHandling(contracts.DeleteSqlObjectScriptRequest.type, params); + } + + /** + * Exclude a SQL object script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + public async excludeSqlObjectScript(projectUri: string, path: string): Promise { + const params: contracts.SqlProjectScriptParams = { projectUri: projectUri, path: path }; + return await this.runWithErrorHandling(contracts.ExcludeSqlObjectScriptRequest.type, params); + } + + /** + * Move a SQL object script in a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param destinationPath Destination path of the file or folder, relative to the .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + public async moveSqlObjectScript(projectUri: string, destinationPath: string, path: string): Promise { + const params: contracts.MoveItemParams = { projectUri: projectUri, destinationPath: destinationPath, path: path }; + return await this.runWithErrorHandling(contracts.MoveSqlObjectScriptRequest.type, params); + } + + private async runWithErrorHandling(type: RequestType, params: P): Promise { try { - const result = await this.client.sendRequest(contracts.GetCrossPlatformCompatiblityRequest.type, params); + const result = await this.client.sendRequest(type, params); return result; } catch (e) { - this.client.logFailedRequest(contracts.GetCrossPlatformCompatiblityRequest.type, e); + this.client.logFailedRequest(type, e); throw e; } } diff --git a/extensions/sql-bindings/src/test/testUtils.ts b/extensions/sql-bindings/src/test/testUtils.ts index f64a27556e..bae20a4423 100644 --- a/extensions/sql-bindings/src/test/testUtils.ts +++ b/extensions/sql-bindings/src/test/testUtils.ts @@ -24,11 +24,13 @@ export class MockVscodeMssqlIExtension implements vscodeMssql.IExtension { sqlToolsServicePath: string = ''; dacFx: vscodeMssql.IDacFxService; schemaCompare: vscodeMssql.ISchemaCompareService; + sqlProjects: vscodeMssql.ISqlProjectsService; azureAccountService: vscodeMssql.IAzureAccountService; azureResourceService: vscodeMssql.IAzureResourceService; constructor() { this.dacFx = TypeMoq.Mock.ofType().object; + this.sqlProjects = TypeMoq.Mock.ofType().object; this.schemaCompare = TypeMoq.Mock.ofType().object; this.azureAccountService = TypeMoq.Mock.ofType().object; this.azureResourceService = TypeMoq.Mock.ofType().object; diff --git a/extensions/sql-database-projects/src/controllers/projectController.ts b/extensions/sql-database-projects/src/controllers/projectController.ts index 9389fea25e..d342f76701 100644 --- a/extensions/sql-database-projects/src/controllers/projectController.ts +++ b/extensions/sql-database-projects/src/controllers/projectController.ts @@ -199,7 +199,7 @@ export class ProjectsController { } const sqlProjectsService = await utils.getSqlProjectsService(); - await sqlProjectsService.newProject(newProjFilePath, sdkStyle, targetPlatform); + await sqlProjectsService.createProject(newProjFilePath, sdkStyle, targetPlatform); await this.addTemplateFiles(newProjFilePath, creationParams.projectTypeId); diff --git a/extensions/sql-database-projects/src/test/dialogs/testUtils.ts b/extensions/sql-database-projects/src/test/dialogs/testUtils.ts index 5b82100159..bed9e1aeef 100644 --- a/extensions/sql-database-projects/src/test/dialogs/testUtils.ts +++ b/extensions/sql-database-projects/src/test/dialogs/testUtils.ts @@ -14,12 +14,14 @@ export interface TestUtils { export class MockVscodeMssqlIExtension implements vscodeMssql.IExtension { sqlToolsServicePath: string = ''; dacFx: vscodeMssql.IDacFxService; + sqlProjects: vscodeMssql.ISqlProjectsService; schemaCompare: vscodeMssql.ISchemaCompareService; azureAccountService: vscodeMssql.IAzureAccountService; azureResourceService: vscodeMssql.IAzureResourceService; constructor() { this.dacFx = TypeMoq.Mock.ofType().object; + this.sqlProjects = TypeMoq.Mock.ofType().object; this.schemaCompare = TypeMoq.Mock.ofType().object; this.azureAccountService = TypeMoq.Mock.ofType().object; this.azureResourceService = TypeMoq.Mock.ofType().object; diff --git a/extensions/types/vscode-mssql.d.ts b/extensions/types/vscode-mssql.d.ts index da5de8dd3d..4ddf6c2604 100644 --- a/extensions/types/vscode-mssql.d.ts +++ b/extensions/types/vscode-mssql.d.ts @@ -40,6 +40,11 @@ declare module 'vscode-mssql' { */ readonly schemaCompare: ISchemaCompareService; + /** + * Service for accessing SQL Projects file functionality + */ + readonly sqlProjects: ISqlProjectsService; + /** * Service for accessing Azure Account functionality */ @@ -429,6 +434,222 @@ declare module 'vscode-mssql' { savePublishProfile(profilePath: string, databaseName: string, connectionString: string, sqlCommandVariableValues?: Record, deploymentOptions?: DeploymentOptions): Thenable; } + /** + * Interface for working with .sqlproj files + */ + export interface ISqlProjectsService { + /** + * Add a dacpac reference to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param dacpacPath Path to the .dacpac file + * @param suppressMissingDependencies Whether to suppress missing dependencies + * @param databaseVariable SQLCMD variable name for specifying the other database this reference is to, if different from that of the current project + * @param serverVariable SQLCMD variable name for specifying the other server this reference is to, if different from that of the current project. + If this is set, DatabaseVariable must also be set. + * @param databaseLiteral Literal name used to reference another database in the same server, if not using SQLCMD variables + */ + addDacpacReference(projectUri: string, dacpacPath: string, suppressMissingDependencies: boolean, databaseVariable?: string, serverVariable?: string, databaseLiteral?: string): Promise; + + /** + * Add a SQL Project reference to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param projectPath Path to the referenced .sqlproj file + * @param projectGuid GUID for the referenced SQL project + * @param suppressMissingDependencies Whether to suppress missing dependencies + * @param databaseVariable SQLCMD variable name for specifying the other database this reference is to, if different from that of the current project + * @param serverVariable SQLCMD variable name for specifying the other server this reference is to, if different from that of the current project. + If this is set, DatabaseVariable must also be set. + * @param databaseLiteral Literal name used to reference another database in the same server, if not using SQLCMD variables + */ + addSqlProjectReference(projectUri: string, projectPath: string, projectGuid: string, suppressMissingDependencies: boolean, databaseVariable?: string, serverVariable?: string, databaseLiteral?: string): Promise; + + /** + * Add a system database reference to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param systemDatabase Type of system database + * @param suppressMissingDependencies Whether to suppress missing dependencies + * @param databaseLiteral Literal name used to reference another database in the same server, if not using SQLCMD variables + */ + addSystemDatabaseReference(projectUri: string, systemDatabase: SystemDatabase, suppressMissingDependencies: boolean, databaseLiteral?: string): Promise; + + /** + * Delete a database reference from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + deleteDatabaseReference(projectUri: string, path: string): Promise; + + /** + * Add a folder to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the folder, typically relative to the .sqlproj file + */ + addFolder(projectUri: string, path: string): Promise; + + /** + * Delete a folder from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the folder, typically relative to the .sqlproj file + */ + deleteFolder(projectUri: string, path: string): Promise; + + /** + * Add a post-deployment script to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + addPostDeploymentScript(projectUri: string, path: string): Promise; + + /** + * Add a pre-deployment script to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + addPreDeploymentScript(projectUri: string, path: string): Promise; + + /** + * Delete a post-deployment script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + deletePostDeploymentScript(projectUri: string, path: string): Promise; + + /** + * Delete a pre-deployment script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + deletePreDeploymentScript(projectUri: string, path: string): Promise; + + /** + * Exclude a post-deployment script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + excludePostDeploymentScript(projectUri: string, path: string): Promise; + + /** + * Exclude a pre-deployment script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + excludePreDeploymentScript(projectUri: string, path: string): Promise; + + /** + * Move a post-deployment script in a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param destinationPath Destination path of the file or folder, relative to the .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + movePostDeploymentScript(projectUri: string, destinationPath: string, path: string): Promise; + + /** + * Move a pre-deployment script in a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param destinationPath Destination path of the file or folder, relative to the .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + movePreDeploymentScript(projectUri: string, destinationPath: string, path: string): Promise; + + /** + * Close a SQL project + * @param projectUri Absolute path of the project, including .sqlproj + */ + closeProject(projectUri: string): Promise; + + /** + * Create a new SQL project + * @param projectUri Absolute path of the project, including .sqlproj + * @param sqlProjectType Type of SQL Project: SDK-style or Legacy + * @param databaseSchemaProvider Database schema provider for the project, in the format + "Microsoft.Data.Tools.Schema.Sql.SqlXYZDatabaseSchemaProvider". + Case sensitive. + * @param buildSdkVersion Version of the Microsoft.Build.Sql SDK for the project, if overriding the default + */ + createProject(projectUri: string, sqlProjectType: ProjectType, databaseSchemaProvider?: string, buildSdkVersion?: string): Promise; + + /** + * Get the cross-platform compatibility status for a project + * @param projectUri Absolute path of the project, including .sqlproj + */ + getCrossPlatformCompatibility(projectUri: string): Promise; + + /** + * Open an existing SQL project + * @param projectUri Absolute path of the project, including .sqlproj + */ + openProject(projectUri: string): Promise; + + /** + * Update a SQL project to be cross-platform compatible + * @param projectUri Absolute path of the project, including .sqlproj + */ + updateProjectForCrossPlatform(projectUri: string): Promise; + + /** + * Add a SQLCMD variable to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param name Name of the SQLCMD variable + * @param defaultValue Default value of the SQLCMD variable + * @param value Value of the SQLCMD variable, with or without the $() + */ + addSqlCmdVariable(projectUri: string, name: string, defaultValue: string, value: string): Promise; + + /** + * Delete a SQLCMD variable from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param name Name of the SQLCMD variable to be deleted + */ + deleteSqlCmdVariable(projectUri: string, name?: string): Promise; + + /** + * Update an existing SQLCMD variable in a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param name Name of the SQLCMD variable + * @param defaultValue Default value of the SQLCMD variable + * @param value Value of the SQLCMD variable, with or without the $() + */ + updateSqlCmdVariable(projectUri: string, name: string, defaultValue: string, value: string): Promise; + + /** + * Add a SQL object script to a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + addSqlObjectScript(projectUri: string, path: string): Promise; + + /** + * Delete a SQL object script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + deleteSqlObjectScript(projectUri: string, path: string): Promise; + + /** + * Exclude a SQL object script from a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + excludeSqlObjectScript(projectUri: string, path: string): Promise; + + /** + * Move a SQL object script in a project + * @param projectUri Absolute path of the project, including .sqlproj + * @param destinationPath Destination path of the file or folder, relative to the .sqlproj + * @param path Path of the script, including .sql, relative to the .sqlproj + */ + moveSqlObjectScript(projectUri: string, destinationPath: string, path: string): Promise; + } + + export interface GetCrossPlatformCompatiblityResult extends ResultStatus { + isCrossPlatformCompatible: boolean; + } + + export const enum ProjectType { + SdkStyle = 0, + LegacyStyle = 1 + } + /** * Represents a tenant information for an account. */ @@ -730,6 +951,66 @@ declare module 'vscode-mssql' { deploymentOptions?: DeploymentOptions; } + //#region ISqlProjectsService + + //#region Parameters + + export interface SqlProjectParams { + projectUri: string; + } + + //#endregion + + //#region Results + + export interface GetDatabaseReferencesResult extends ResultStatus { + systemDatabaseReferences: SystemDatabaseReference[]; + sqlProjectReferences: SqlProjectReference[]; + dacpacReferences: DacpacReference[]; + } + + //#endregion + + //#region Types + + export interface DatabaseReference { + suppressMissingDependencies: boolean; + databaseVariableLiteralName?: string; + } + + interface UserDatabaseReference extends DatabaseReference { + databaseVariable: SqlCmdVariable; + serverVariable?: SqlCmdVariable; + } + + export interface SystemDatabaseReference extends DatabaseReference { + systemDb: SystemDatabase; + } + + export interface SqlProjectReference extends UserDatabaseReference { + projectPath: string; + projectGuid?: string; + } + + export interface DacpacReference extends UserDatabaseReference { + dacpacPath: string; + } + + export const enum SystemDatabase { + Master = 0, + MSDB = 1 + } + + export interface SqlCmdVariable { + varName: string; + value: string; + defaultValue: string + } + + //#endregion + + //#endregion + export interface ITreeNodeInfo extends vscode.TreeItem { readonly connectionInfo: IConnectionInfo; nodeType: string;