diff --git a/src/Microsoft.SqlTools.ServiceLayer/Metadata/Contracts/ObjectMetadata.cs b/src/Microsoft.SqlTools.ServiceLayer/Metadata/Contracts/ObjectMetadata.cs index c0f208c8..854011bf 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Metadata/Contracts/ObjectMetadata.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Metadata/Contracts/ObjectMetadata.cs @@ -13,7 +13,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Metadata.Contracts Table = 0, View = 1, SProc = 2, - Function = 3 + Function = 3, + Schema = 4, + Database = 5 } /// diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.cs index 8fe4033b..e012f3b5 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/SmoQueryModel.cs @@ -1,16 +1,16 @@ -// This file was generated by a T4 Template. Do not modify directly, instead update the SmoQueryModelDefinition.xml file -// and re-run the T4 template. This can be done in Visual Studio by right-click in and choosing "Run Custom Tool", -// or from the command-line on any platform by running "build.cmd -Target=CodeGen" or "build.sh -Target=CodeGen". - -using System; -using System.Collections.Generic; -using System.Composition; -using System.Linq; -using Microsoft.SqlServer.Management.Smo; -using Microsoft.SqlServer.Management.Smo.Broker; - -namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel -{ +// This file was generated by a T4 Template. Do not modify directly, instead update the SmoQueryModelDefinition.xml file +// and re-run the T4 template. This can be done in Visual Studio by right-click in and choosing "Run Custom Tool", +// or from the command-line on any platform by running "build.cmd -Target=CodeGen" or "build.sh -Target=CodeGen". + +using System; +using System.Collections.Generic; +using System.Composition; +using System.Linq; +using Microsoft.SqlServer.Management.Smo; +using Microsoft.SqlServer.Management.Smo.Broker; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel +{ [Export(typeof(SmoQuerier))] internal partial class SqlDatabaseQuerier: SmoQuerier @@ -1628,5 +1628,5 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel return Enumerable.Empty(); } } -} - +} + diff --git a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.cs b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.cs index 4a4944e2..c65105fa 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/ObjectExplorer/SmoModel/TreeNodeGenerator.cs @@ -1,13 +1,13 @@ -using System; -using System.Collections.Generic; -using System.Composition; -using Microsoft.SqlServer.Management.Smo; -using Microsoft.SqlTools.ServiceLayer; -using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes; - -namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel -{ - +using System; +using System.Collections.Generic; +using System.Composition; +using Microsoft.SqlServer.Management.Smo; +using Microsoft.SqlTools.ServiceLayer; +using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes; + +namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel +{ + internal sealed partial class DatabaseTreeNode : SmoTreeNode { public DatabaseTreeNode() : base() @@ -3965,5 +3965,5 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel } } -} - +} + diff --git a/src/Microsoft.SqlTools.ServiceLayer/Scripting/Scripter.cs b/src/Microsoft.SqlTools.ServiceLayer/Scripting/Scripter.cs index cbc6af55..7f6bfa23 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Scripting/Scripter.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Scripting/Scripter.cs @@ -1,29 +1,31 @@ -// -// Copyright (c) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. -// -// THIS FILE IS GENERATED BY A CODEGEN TOOL. DO NOT EDIT!!!! -// IF YOU NEED TO MAKE CHANGES, EDIT THE .TT FILE!!! - -// To regenerate either (1) save the .TT file from Visual Studio or (2) run the build script codegen task. - -using System; -using System.IO; -using System.Collections.Generic; -using System.Collections.Specialized; -using Microsoft.SqlServer.Management.Smo; -using Microsoft.SqlServer.Management.SqlParser.Intellisense; -using Microsoft.SqlTools.Utility; -namespace Microsoft.SqlTools.ServiceLayer.Scripting -{ - internal partial class Scripter - { - +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// +// THIS FILE IS GENERATED BY A CODEGEN TOOL. DO NOT EDIT!!!! +// IF YOU NEED TO MAKE CHANGES, EDIT THE .TT FILE!!! + +// To regenerate either (1) save the .TT file from Visual Studio or (2) run the build script codegen task. + +using System; +using System.IO; +using System.Collections.Generic; +using System.Collections.Specialized; +using Microsoft.SqlServer.Management.Smo; +using Microsoft.SqlServer.Management.SqlParser.Intellisense; +using Microsoft.SqlTools.Utility; +namespace Microsoft.SqlTools.ServiceLayer.Scripting +{ + internal partial class Scripter + { + private void Initialize() { AddSupportedType(DeclarationType.Table, GetTableScripts, "Table", "table"); AddSupportedType(DeclarationType.View, GetViewScripts, "View", "view"); AddSupportedType(DeclarationType.StoredProcedure, GetStoredProcedureScripts, "Procedure", "stored procedure"); + AddSupportedType(DeclarationType.Schema, GetSchemaScripts, "Schema", "schema"); + AddSupportedType(DeclarationType.Database, GetDatabaseScripts, "Database", "database"); AddSupportedType(DeclarationType.UserDefinedDataType, GetUserDefinedDataTypeScripts, "Type", "user-defined data type"); AddSupportedType(DeclarationType.UserDefinedTableType, GetUserDefinedTableTypeScripts, "Type", "user-defined table type"); AddSupportedType(DeclarationType.Synonym, GetSynonymScripts, "Synonym", ""); @@ -43,7 +45,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting { Table smoObject = string.IsNullOrEmpty(schemaName) ? new Table(this.Database, objectName) : new Table(this.Database, objectName, schemaName); smoObject.Refresh(); - return smoObject.Script(); + return (scriptingOptions == null) ? smoObject.Script() : smoObject.Script(scriptingOptions); } catch (Exception ex) { @@ -64,7 +66,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting { View smoObject = string.IsNullOrEmpty(schemaName) ? new View(this.Database, objectName) : new View(this.Database, objectName, schemaName); smoObject.Refresh(); - return smoObject.Script(); + return (scriptingOptions == null) ? smoObject.Script() : smoObject.Script(scriptingOptions); } catch (Exception ex) { @@ -85,7 +87,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting { StoredProcedure smoObject = string.IsNullOrEmpty(schemaName) ? new StoredProcedure(this.Database, objectName) : new StoredProcedure(this.Database, objectName, schemaName); smoObject.Refresh(); - return smoObject.Script(); + return (scriptingOptions == null) ? smoObject.Script() : smoObject.Script(scriptingOptions); } catch (Exception ex) { @@ -94,6 +96,48 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting } } + /// + /// Script a Schema using SMO + /// + /// Schema name + /// Schema name + /// String collection of scripts + internal StringCollection GetSchemaScripts(string objectName, string schemaName, ScriptingOptions scriptingOptions = null) + { + try + { + Schema smoObject = new Schema(this.Database, objectName); + smoObject.Refresh(); + return (scriptingOptions == null) ? smoObject.Script() : smoObject.Script(scriptingOptions); + } + catch (Exception ex) + { + Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetSchemaScripts : " + ex.Message); + return null; + } + } + + /// + /// Script a Database using SMO + /// + /// Database name + /// Schema name + /// String collection of scripts + internal StringCollection GetDatabaseScripts(string objectName, string schemaName, ScriptingOptions scriptingOptions = null) + { + try + { + Database smoObject = new Database(new Server(this.serverConnection), objectName); + smoObject.Refresh(); + return (scriptingOptions == null) ? smoObject.Script() : smoObject.Script(scriptingOptions); + } + catch (Exception ex) + { + Logger.Write(LogLevel.Error,"Exception at PeekDefinition GetDatabaseScripts : " + ex.Message); + return null; + } + } + /// /// Script a UserDefinedDataType using SMO /// @@ -106,7 +150,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting { UserDefinedDataType smoObject = string.IsNullOrEmpty(schemaName) ? new UserDefinedDataType(this.Database, objectName) : new UserDefinedDataType(this.Database, objectName, schemaName); smoObject.Refresh(); - return smoObject.Script(); + return (scriptingOptions == null) ? smoObject.Script() : smoObject.Script(scriptingOptions); } catch (Exception ex) { @@ -127,7 +171,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting { UserDefinedTableType smoObject = string.IsNullOrEmpty(schemaName) ? new UserDefinedTableType(this.Database, objectName) : new UserDefinedTableType(this.Database, objectName, schemaName); smoObject.Refresh(); - return smoObject.Script(); + return (scriptingOptions == null) ? smoObject.Script() : smoObject.Script(scriptingOptions); } catch (Exception ex) { @@ -148,7 +192,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting { Synonym smoObject = string.IsNullOrEmpty(schemaName) ? new Synonym(this.Database, objectName) : new Synonym(this.Database, objectName, schemaName); smoObject.Refresh(); - return smoObject.Script(); + return (scriptingOptions == null) ? smoObject.Script() : smoObject.Script(scriptingOptions); } catch (Exception ex) { @@ -169,7 +213,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting { UserDefinedFunction smoObject = string.IsNullOrEmpty(schemaName) ? new UserDefinedFunction(this.Database, objectName) : new UserDefinedFunction(this.Database, objectName, schemaName); smoObject.Refresh(); - return smoObject.Script(); + return (scriptingOptions == null) ? smoObject.Script() : smoObject.Script(scriptingOptions); } catch (Exception ex) { @@ -190,7 +234,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting { UserDefinedFunction smoObject = string.IsNullOrEmpty(schemaName) ? new UserDefinedFunction(this.Database, objectName) : new UserDefinedFunction(this.Database, objectName, schemaName); smoObject.Refresh(); - return smoObject.Script(); + return (scriptingOptions == null) ? smoObject.Script() : smoObject.Script(scriptingOptions); } catch (Exception ex) { @@ -199,6 +243,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting } } - } -} + } +} \ No newline at end of file diff --git a/src/Microsoft.SqlTools.ServiceLayer/Scripting/Scripter.tt b/src/Microsoft.SqlTools.ServiceLayer/Scripting/Scripter.tt index 76b09cee..da75e8d9 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Scripting/Scripter.tt +++ b/src/Microsoft.SqlTools.ServiceLayer/Scripting/Scripter.tt @@ -79,12 +79,20 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting } else { - statement = string.Format("{0} smoObject = new {0}(this.Database, objectName);", typeProperty["Name"]); + // If it's a database + if (typeProperty["AccessClass"] == "Database") + { + statement = string.Format("{0} smoObject = new {0}(new Server(this.serverConnection), objectName);", typeProperty["Name"]); + } + else + { + statement = string.Format("{0} smoObject = new {0}(this.Database, objectName);", typeProperty["Name"]); + } } PushIndent(indent); WriteLine(statement); WriteLine("smoObject.Refresh();"); - WriteLine("return smoObject.Script();"); + WriteLine("return (scriptingOptions == null) ? smoObject.Script() : smoObject.Script(scriptingOptions);"); PopIndent(); WriteLine("}"); diff --git a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScripterSupportedTypes.xml b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScripterSupportedTypes.xml index b5325208..b6aa7471 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScripterSupportedTypes.xml +++ b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScripterSupportedTypes.xml @@ -28,6 +28,20 @@ SupportsSchemaQuery - Boolean denoting if the object can be queried/accessed usi stored procedure true + + Schema + Schema + Schema + schema + false + + + Database + Database + Database + database + false + UserDefinedDataType Type diff --git a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingService.cs b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingService.cs index 17e64949..76e6b3be 100644 --- a/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingService.cs +++ b/src/Microsoft.SqlTools.ServiceLayer/Scripting/ScriptingService.cs @@ -18,6 +18,7 @@ using Microsoft.SqlTools.ServiceLayer.LanguageServices; using Microsoft.SqlTools.ServiceLayer.Metadata.Contracts; using Microsoft.SqlTools.ServiceLayer.Scripting.Contracts; using Microsoft.SqlTools.Utility; +using Microsoft.SqlServer.Management.Smo; namespace Microsoft.SqlTools.ServiceLayer.Scripting { @@ -231,19 +232,27 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting { Scripter scripter = new Scripter(bindingContext.ServerConnection, connInfo); StringCollection results = null; - if (metadata.MetadataType == MetadataType.Table) + switch(metadata.MetadataTypeName) { - results = scripter.GetTableScripts(metadata.Name, metadata.Schema); + case ("Table"): + results = scripter.GetTableScripts(metadata.Name, metadata.Schema); + break; + case ("View"): + results = scripter.GetViewScripts(metadata.Name, metadata.Schema); + break; + case("StoredProcedure"): + results = scripter.GetStoredProcedureScripts(metadata.Name, metadata.Schema); + break; + case("Schema"): + results = scripter.GetSchemaScripts(metadata.Name, metadata.Schema); + break; + case("Database"): + results = scripter.GetDatabaseScripts(metadata.Name, metadata.Schema); + break; + default: + results = null; + break; } - else if (metadata.MetadataType == MetadataType.SProc) - { - results = scripter.GetStoredProcedureScripts(metadata.Name, metadata.Schema); - } - else if (metadata.MetadataType == MetadataType.View) - { - results = scripter.GetViewScripts(metadata.Name, metadata.Schema); - } - StringBuilder builder = null; if (results != null) { @@ -287,7 +296,42 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting ConnectionInfo connInfo, ObjectMetadata metadata) { - return null; + Scripter scripter = new Scripter(bindingContext.ServerConnection, connInfo); + StringCollection results = null; + ScriptingOptions options = new ScriptingOptions(); + options.ScriptDrops = true; + switch(metadata.MetadataTypeName) + { + case ("Table"): + results = scripter.GetTableScripts(metadata.Name, metadata.Schema, options); + break; + case ("View"): + results = scripter.GetViewScripts(metadata.Name, metadata.Schema, options); + break; + case("StoredProcedure"): + results = scripter.GetStoredProcedureScripts(metadata.Name, metadata.Schema, options); + break; + case("Schema"): + results = scripter.GetSchemaScripts(metadata.Name, metadata.Schema, options); + break; + case("Database"): + results = scripter.GetDatabaseScripts(metadata.Name, metadata.Schema, options); + break; + default: + results = null; + break; + } + StringBuilder builder = null; + if (results != null) + { + builder = new StringBuilder(); + foreach (var result in results) + { + builder.AppendLine(result); + builder.AppendLine(); + } + } + return builder != null ? builder.ToString() : null; } /// diff --git a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Scripting/ScriptingServiceTests.cs b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Scripting/ScriptingServiceTests.cs index df6602db..6410a4da 100644 --- a/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Scripting/ScriptingServiceTests.cs +++ b/test/Microsoft.SqlTools.ServiceLayer.IntegrationTests/Scripting/ScriptingServiceTests.cs @@ -22,6 +22,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting { private const string SchemaName = "dbo"; private const string TableName = "spt_monitor"; + private const string ViewName = "test"; + private const string DatabaseName = "test-db"; + private const string StoredProcName = "test-sp"; + private string[] objects = new string[5] {"Table", "View", "Schema", "Database", "SProc"}; private LiveConnectionHelper.TestConnectionResult GetLiveAutoCompleteTestObjects() { @@ -40,8 +44,44 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting return result; } + private static ObjectMetadata GenerateMetadata(string objectType) + { + var metadata = new ObjectMetadata() + { + Schema = SchemaName, + Name = objectType + }; + switch(objectType) + { + case("Table"): + metadata.MetadataType = MetadataType.Table; + metadata.Name = TableName; + break; + case("View"): + metadata.MetadataType = MetadataType.View; + metadata.Name = ViewName; + break; + case("Database"): + metadata.MetadataType = MetadataType.Database; + metadata.Name = DatabaseName; + break; + case("Schema"): + metadata.MetadataType = MetadataType.Schema; + metadata.MetadataTypeName = SchemaName; + break; + case("SProc"): + metadata.MetadataType = MetadataType.SProc; + metadata.MetadataTypeName = StoredProcName; + break; + default: + metadata.MetadataType = MetadataType.Table; + metadata.Name = TableName; + break; + } + return metadata; + } - private async Task>> SendAndValidateScriptRequest(ScriptOperation operation) + private async Task>> SendAndValidateScriptRequest(ScriptOperation operation, string objectType) { var result = GetLiveAutoCompleteTestObjects(); var requestContext = new Mock>(); @@ -51,13 +91,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting { OwnerUri = result.ConnectionInfo.OwnerUri, Operation = operation, - Metadata = new ObjectMetadata() - { - MetadataType = MetadataType.Table, - MetadataTypeName = "Table", - Schema = SchemaName, - Name = TableName - } + Metadata = GenerateMetadata(objectType) }; await ScriptingService.HandleScriptingScriptAsRequest(scriptingParams, requestContext.Object); @@ -71,7 +105,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting [Fact] public async void ScriptingScriptAsSelect() { - await SendAndValidateScriptRequest(ScriptOperation.Select); + foreach (string obj in objects) + { + Assert.NotNull(await SendAndValidateScriptRequest(ScriptOperation.Select, obj)); + } } /// @@ -80,7 +117,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting [Fact] public async void ScriptingScriptAsCreate() { - await SendAndValidateScriptRequest(ScriptOperation.Create); + foreach (string obj in objects) + { + Assert.NotNull(await SendAndValidateScriptRequest(ScriptOperation.Create, obj)); + } } /// @@ -89,7 +129,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting [Fact] public async void ScriptingScriptAsInsert() { - await SendAndValidateScriptRequest(ScriptOperation.Insert); + foreach (string obj in objects) + { + Assert.NotNull(await SendAndValidateScriptRequest(ScriptOperation.Insert, obj)); + } } /// @@ -98,7 +141,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting [Fact] public async void ScriptingScriptAsUpdate() { - await SendAndValidateScriptRequest(ScriptOperation.Update); + foreach (string obj in objects) + { + Assert.NotNull(await SendAndValidateScriptRequest(ScriptOperation.Select, obj)); + } } /// @@ -107,7 +153,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting [Fact] public async void ScriptingScriptAsDelete() { - await SendAndValidateScriptRequest(ScriptOperation.Delete); + foreach (string obj in objects) + { + Assert.NotNull(await SendAndValidateScriptRequest(ScriptOperation.Select, obj)); + } } } }