mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-16 17:23:38 -05:00
A regression was introduced in the scripting service refactoring where data is no longer scripted. This commit fixes the issue, and updates the tests to catch this in the future. The issue is in the getter for SqlScriptPublishModel.AdvancedOptions, there is some strange logic which will cause the SqlScriptPublishModel.AdvancedOptions to get reset and lose all values based the ordering of when SqlScriptPublishModel.ScriptAllObjects is set. In the scripting service refactoring, we started to hit this reset of the AdvanceOptions, which would lose the option to script data, along with other options. To workaround this, we initialize with SqlScriptPublishModel.ScriptAllObjects to true, and then set all SqlScriptPublishModel.AdvancedOptions values. Then, we set SqlScriptPublishModel.ScriptAllObjects, and avoid calling the SqlScriptPublishModel.AdvancedOptions getter. Also including some misc scripting service changes: 1) Adding a sequence number field to the scripting operation events 2) Adding a error message to scripting progress events 3) Expect a null scripting option parameter 4) Correctly set the exception message and details for json-rpc events 5) More logging
129 lines
4.8 KiB
C#
129 lines
4.8 KiB
C#
//
|
|
// Copyright (c) Microsoft. All rights reserved.
|
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
//
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.SqlServer.Management.Sdk.Sfc;
|
|
using Microsoft.SqlServer.Management.SqlScriptPublish;
|
|
using Microsoft.SqlTools.ServiceLayer.Scripting.Contracts;
|
|
using Microsoft.SqlTools.Utility;
|
|
|
|
namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|
{
|
|
/// <summary>
|
|
/// Extension methods used by the scripting service.
|
|
/// </summary>
|
|
internal static class ScriptingExtensionMethods
|
|
{
|
|
/// <summary>
|
|
/// Gets the status of a scripting operation for the passed scripting event.
|
|
/// </summary>
|
|
/// <param name="e">The scripting event.</param>
|
|
/// <returns>The status.</returns>
|
|
public static string GetStatus(this ScriptEventArgs e)
|
|
{
|
|
Validate.IsNotNull("e", e);
|
|
|
|
string status = null;
|
|
|
|
if (e.Error != null)
|
|
{
|
|
status = "Error";
|
|
}
|
|
else if (e.Completed)
|
|
{
|
|
status = "Completed";
|
|
}
|
|
else
|
|
{
|
|
status = "Progress";
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns a list of ScriptingObject instances for the passed SqlScriptPublishModel instance.
|
|
/// </summary>
|
|
/// <param name="publishModel">The sql script publish model instance.</param>
|
|
/// <returns>The list of scripting objects.</returns>
|
|
public static List<ScriptingObject> GetDatabaseObjects(this SqlScriptPublishModel publishModel)
|
|
{
|
|
Validate.IsNotNull("publishModel", publishModel);
|
|
|
|
List<ScriptingObject> databaseObjects = new List<ScriptingObject>();
|
|
|
|
IEnumerable<DatabaseObjectType> objectTypes = publishModel.GetDatabaseObjectTypes();
|
|
Logger.Write(
|
|
LogLevel.Verbose,
|
|
string.Format(
|
|
"Loaded SMO object type count {0}, types: {1}",
|
|
objectTypes.Count(),
|
|
string.Join(", ", objectTypes)));
|
|
|
|
foreach (DatabaseObjectType objectType in objectTypes)
|
|
{
|
|
IEnumerable<KeyValuePair<string, string>> databaseObjectsOfType = publishModel.EnumChildrenForDatabaseObjectType(objectType);
|
|
|
|
Logger.Write(
|
|
LogLevel.Verbose,
|
|
string.Format(
|
|
"Loaded SMO urn object count {0} for type {1}, urns: {2}",
|
|
objectType,
|
|
databaseObjectsOfType.Count(),
|
|
string.Join(", ", databaseObjectsOfType.Select(p => p.Value))));
|
|
|
|
databaseObjects.AddRange(databaseObjectsOfType.Select(d => new Urn(d.Value).ToScriptingObject()));
|
|
}
|
|
|
|
return databaseObjects;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a SMO Urn instance based on the passed ScriptingObject instance.
|
|
/// </summary>
|
|
/// <param name="scriptingObject">The scripting object instance.</param>
|
|
/// <param name="database">The name of the database referenced by the Urn.</param>
|
|
/// <returns>The Urn instance.</returns>
|
|
public static Urn ToUrn(this ScriptingObject scriptingObject, string database)
|
|
{
|
|
Validate.IsNotNull("scriptingObject", scriptingObject);
|
|
Validate.IsNotNullOrWhitespaceString("database", database);
|
|
|
|
Validate.IsNotNullOrWhitespaceString("scriptingObject.Name", scriptingObject.Name);
|
|
Validate.IsNotNullOrWhitespaceString("scriptingObject.Type", scriptingObject.Type);
|
|
|
|
// Leaving the server name blank will automatically match whatever the server SMO is running against.
|
|
string urn = string.Format(
|
|
"Server/Database[@Name='{0}']/{1}[@Name='{2}' {3}]",
|
|
database,
|
|
scriptingObject.Type,
|
|
scriptingObject.Name,
|
|
scriptingObject.Schema != null ? string.Format("and @Schema = '{0}'", scriptingObject.Schema) : string.Empty);
|
|
|
|
return new Urn(urn);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a ScriptingObject instance based on the passed SMO Urn instance.
|
|
/// </summary>
|
|
/// <param name="urn">The urn instance.</param>
|
|
/// <returns>The scripting object instance.</returns>
|
|
public static ScriptingObject ToScriptingObject(this Urn urn)
|
|
{
|
|
Validate.IsNotNull("urn", urn);
|
|
|
|
return new ScriptingObject
|
|
{
|
|
Type = urn.Type,
|
|
Schema = urn.GetAttribute("Schema"),
|
|
Name = urn.GetAttribute("Name"),
|
|
};
|
|
}
|
|
}
|
|
}
|