mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-16 10:58:30 -05:00
Feature/script execute (#563)
* added script as execute for stored procedures
This commit is contained in:
@@ -2397,6 +2397,30 @@ namespace Microsoft.SqlTools.ServiceLayer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string StoredProcedureScriptParameterComment
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Keys.GetString(Keys.StoredProcedureScriptParameterComment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ScriptingGeneralError
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Keys.GetString(Keys.ScriptingGeneralError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ScriptingExecuteNotSupportedError
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Keys.GetString(Keys.ScriptingExecuteNotSupportedError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static string unavailable
|
public static string unavailable
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -4597,6 +4621,15 @@ namespace Microsoft.SqlTools.ServiceLayer
|
|||||||
public const string ScriptingListObjectsCompleteParams_ConnectionString_Property_Invalid = "ScriptingListObjectsCompleteParams_ConnectionString_Property_Invalid";
|
public const string ScriptingListObjectsCompleteParams_ConnectionString_Property_Invalid = "ScriptingListObjectsCompleteParams_ConnectionString_Property_Invalid";
|
||||||
|
|
||||||
|
|
||||||
|
public const string StoredProcedureScriptParameterComment = "StoredProcedureScriptParameterComment";
|
||||||
|
|
||||||
|
|
||||||
|
public const string ScriptingGeneralError = "ScriptingGeneralError";
|
||||||
|
|
||||||
|
|
||||||
|
public const string ScriptingExecuteNotSupportedError = "ScriptingExecuteNotSupportedError";
|
||||||
|
|
||||||
|
|
||||||
public const string unavailable = "unavailable";
|
public const string unavailable = "unavailable";
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1381,6 +1381,18 @@
|
|||||||
<value>Error parsing ScriptingListObjectsCompleteParams.ConnectionString property.</value>
|
<value>Error parsing ScriptingListObjectsCompleteParams.ConnectionString property.</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="StoredProcedureScriptParameterComment" xml:space="preserve">
|
||||||
|
<value>-- TODO: Set parameter values here.</value>
|
||||||
|
<comment></comment>
|
||||||
|
</data>
|
||||||
|
<data name="ScriptingGeneralError" xml:space="preserve">
|
||||||
|
<value>An error occurred while scripting the objects.</value>
|
||||||
|
<comment></comment>
|
||||||
|
</data>
|
||||||
|
<data name="ScriptingExecuteNotSupportedError" xml:space="preserve">
|
||||||
|
<value>Scripting as Execute is only supported for Stored Procedures</value>
|
||||||
|
<comment></comment>
|
||||||
|
</data>
|
||||||
<data name="unavailable" xml:space="preserve">
|
<data name="unavailable" xml:space="preserve">
|
||||||
<value>Unavailable</value>
|
<value>Unavailable</value>
|
||||||
<comment></comment>
|
<comment></comment>
|
||||||
|
|||||||
@@ -691,7 +691,10 @@ ScriptingParams_FilePath_Property_Invalid = Invalid directory specified by the S
|
|||||||
ScriptingListObjectsCompleteParams_ConnectionString_Property_Invalid = Error parsing ScriptingListObjectsCompleteParams.ConnectionString property.
|
ScriptingListObjectsCompleteParams_ConnectionString_Property_Invalid = Error parsing ScriptingListObjectsCompleteParams.ConnectionString property.
|
||||||
|
|
||||||
|
|
||||||
|
StoredProcedureScriptParameterComment = -- TODO: Set parameter values here.
|
||||||
|
|
||||||
|
ScriptingGeneralError = An error occurred while scripting the objects.
|
||||||
|
ScriptingExecuteNotSupportedError = Scripting as Execute is only supported for Stored Procedures
|
||||||
|
|
||||||
############################################################################
|
############################################################################
|
||||||
# Admin Service
|
# Admin Service
|
||||||
|
|||||||
@@ -2312,6 +2312,21 @@
|
|||||||
<note>.
|
<note>.
|
||||||
Parameters: 0 - value (string), 1 - columnType (string) </note>
|
Parameters: 0 - value (string), 1 - columnType (string) </note>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
<trans-unit id="StoredProcedureScriptParameterComment">
|
||||||
|
<source>-- TODO: Set parameter values here.</source>
|
||||||
|
<target state="new">-- TODO: Set parameter values here.</target>
|
||||||
|
<note></note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="ScriptingGeneralError">
|
||||||
|
<source>An error occurred while scripting the objects.</source>
|
||||||
|
<target state="new">An error occurred while scripting the objects</target>
|
||||||
|
<note></note>
|
||||||
|
</trans-unit>
|
||||||
|
<trans-unit id="ScriptingExecuteNotSupportedError">
|
||||||
|
<source>Scripting as Execute is only supported for Stored Procedures</source>
|
||||||
|
<target state="new">Scripting as Execute is only supported for Stored Procedures</target>
|
||||||
|
<note></note>
|
||||||
|
</trans-unit>
|
||||||
</body>
|
</body>
|
||||||
</file>
|
</file>
|
||||||
</xliff>
|
</xliff>
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
//
|
|
||||||
// Copyright (c) Microsoft. All rights reserved.
|
|
||||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
||||||
//
|
|
||||||
|
|
||||||
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
|
|
||||||
|
|
||||||
namespace Microsoft.SqlTools.ServiceLayer.Scripting.Contracts
|
|
||||||
{
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Script as request message type
|
|
||||||
/// </summary>
|
|
||||||
public class ScriptingScriptAsRequest
|
|
||||||
{
|
|
||||||
public static readonly
|
|
||||||
RequestType<ScriptingParams, ScriptingResult> Type =
|
|
||||||
RequestType<ScriptingParams, ScriptingResult>.Create("scripting/scriptas");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// Copyright (c) Microsoft. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
//
|
||||||
|
|
||||||
|
namespace Microsoft.SqlTools.ServiceLayer.Scripting.Contracts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Scripting Operation type
|
||||||
|
/// </summary>
|
||||||
|
public enum ScriptingOperationType
|
||||||
|
{
|
||||||
|
Select = 0,
|
||||||
|
Create = 1,
|
||||||
|
Insert = 2,
|
||||||
|
Update = 3,
|
||||||
|
Delete = 4,
|
||||||
|
Execute = 5
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -101,7 +101,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting.Contracts
|
|||||||
/// ScriptCreate
|
/// ScriptCreate
|
||||||
/// ScriptDrop
|
/// ScriptDrop
|
||||||
/// ScriptCreateDrop
|
/// ScriptCreateDrop
|
||||||
/// ScriptSelect
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// The default is ScriptCreate.
|
/// The default is ScriptCreate.
|
||||||
|
|||||||
@@ -73,6 +73,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting.Contracts
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string OwnerUri { get; set; }
|
public string OwnerUri { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The script operation
|
||||||
|
/// </summary>
|
||||||
|
public ScriptingOperationType Operation { get; set; } = ScriptingOperationType.Create;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ using System.Text;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using Microsoft.SqlServer.Management.SqlScriptPublish;
|
using Microsoft.SqlServer.Management.SqlScriptPublish;
|
||||||
using Microsoft.SqlTools.ServiceLayer.Utility;
|
using Microsoft.SqlTools.ServiceLayer.Utility;
|
||||||
|
using Microsoft.SqlServer.Management.Sdk.Sfc;
|
||||||
|
|
||||||
namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||||
{
|
{
|
||||||
@@ -24,21 +25,37 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
public class ScriptAsScriptingOperation : SmoScriptingOperation
|
public class ScriptAsScriptingOperation : SmoScriptingOperation
|
||||||
{
|
{
|
||||||
private static Dictionary<string, SqlServerVersion> scriptCompatabilityMap = LoadScriptCompatabilityMap();
|
private static Dictionary<string, SqlServerVersion> scriptCompatabilityMap = LoadScriptCompatabilityMap();
|
||||||
|
/// <summary>
|
||||||
|
/// Left delimiter for an named object
|
||||||
|
/// </summary>
|
||||||
|
public const char LeftDelimiter = '[';
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// right delimiter for a named object
|
||||||
|
/// </summary>
|
||||||
|
public const char RightDelimiter = ']';
|
||||||
|
|
||||||
public ScriptAsScriptingOperation(ScriptingParams parameters, ServerConnection serverConnection): base(parameters)
|
public ScriptAsScriptingOperation(ScriptingParams parameters, ServerConnection serverConnection): base(parameters)
|
||||||
{
|
{
|
||||||
|
Validate.IsNotNull("serverConnection", serverConnection);
|
||||||
ServerConnection = serverConnection;
|
ServerConnection = serverConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ScriptAsScriptingOperation(ScriptingParams parameters) : base(parameters)
|
public ScriptAsScriptingOperation(ScriptingParams parameters) : base(parameters)
|
||||||
{
|
{
|
||||||
|
SqlConnection sqlConnection = new SqlConnection(this.Parameters.ConnectionString);
|
||||||
|
ServerConnection = new ServerConnection(sqlConnection);
|
||||||
|
disconnectAtDispose = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal ServerConnection ServerConnection { get; set; }
|
internal ServerConnection ServerConnection { get; set; }
|
||||||
|
|
||||||
|
private string serverName;
|
||||||
|
private string databaseName;
|
||||||
|
private bool disconnectAtDispose = false;
|
||||||
|
|
||||||
public override void Execute()
|
public override void Execute()
|
||||||
{
|
{
|
||||||
SqlServer.Management.Smo.Scripter scripter = null;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
this.CancellationToken.ThrowIfCancellationRequested();
|
this.CancellationToken.ThrowIfCancellationRequested();
|
||||||
@@ -54,24 +71,32 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
{
|
{
|
||||||
ServerConnection.Connect();
|
ServerConnection.Connect();
|
||||||
}
|
}
|
||||||
scripter = new SqlServer.Management.Smo.Scripter(server);
|
|
||||||
|
UrnCollection urns = CreateUrns(ServerConnection);
|
||||||
ScriptingOptions options = new ScriptingOptions();
|
ScriptingOptions options = new ScriptingOptions();
|
||||||
SetScriptBehavior(options);
|
SetScriptBehavior(options);
|
||||||
ScriptAsOptions scriptAsOptions = new ScriptAsOptions(this.Parameters.ScriptOptions);
|
PopulateAdvancedScriptOptions(this.Parameters.ScriptOptions, options);
|
||||||
PopulateAdvancedScriptOptions(scriptAsOptions, options);
|
|
||||||
options.WithDependencies = false;
|
options.WithDependencies = false;
|
||||||
|
// TODO: Not including the header by default. We have to get this option from client
|
||||||
|
options.IncludeHeaders = false;
|
||||||
|
|
||||||
|
// Scripting data is not avaialable in the scripter
|
||||||
options.ScriptData = false;
|
options.ScriptData = false;
|
||||||
SetScriptingOptions(options);
|
SetScriptingOptions(options);
|
||||||
|
|
||||||
// TODO: Not including the header by default. We have to get this option from client
|
switch (this.Parameters.Operation)
|
||||||
options.IncludeHeaders = false;
|
{
|
||||||
scripter.Options = options;
|
case ScriptingOperationType.Create:
|
||||||
scripter.Options.ScriptData = false;
|
case ScriptingOperationType.Delete: // Using Delete here is wrong. delete usually means delete rows from table but sqlopsstudio sending the operation name as delete instead of drop
|
||||||
scripter.ScriptingError += ScripterScriptingError;
|
resultScript = GenerateScriptAs(server, urns, options);
|
||||||
UrnCollection urns = CreateUrns(ServerConnection);
|
break;
|
||||||
var result = scripter.Script(urns);
|
case ScriptingOperationType.Select:
|
||||||
resultScript = GetScript(options, result);
|
resultScript = GenerateScriptSelect(server, urns);
|
||||||
|
break;
|
||||||
|
case ScriptingOperationType.Execute:
|
||||||
|
resultScript = GenerareScriptAsExecute(server, urns, options);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
this.CancellationToken.ThrowIfCancellationRequested();
|
this.CancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
@@ -88,6 +113,12 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
{
|
{
|
||||||
Success = true,
|
Success = true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.SendPlanNotificationEvent(new ScriptingPlanNotificationParams
|
||||||
|
{
|
||||||
|
ScriptingObjects = this.Parameters.ScriptingObjects,
|
||||||
|
Count = 1,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -106,18 +137,326 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
{
|
{
|
||||||
OperationId = OperationId,
|
OperationId = OperationId,
|
||||||
HasError = true,
|
HasError = true,
|
||||||
ErrorMessage = e.Message,
|
ErrorMessage = $"{SR.ScriptingGeneralError} {e.Message}",
|
||||||
ErrorDetails = e.ToString(),
|
ErrorDetails = e.ToString(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
|
{
|
||||||
|
if (disconnectAtDispose && ServerConnection != null && ServerConnection.IsOpen)
|
||||||
|
{
|
||||||
|
ServerConnection.Disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateScriptSelect(Server server, UrnCollection urns)
|
||||||
|
{
|
||||||
|
string script = string.Empty;
|
||||||
|
ScriptingObject scriptingObject = this.Parameters.ScriptingObjects[0];
|
||||||
|
Urn objectUrn = urns[0];
|
||||||
|
string typeName = objectUrn.GetNameForType(scriptingObject.Type);
|
||||||
|
|
||||||
|
// select from service broker
|
||||||
|
if (string.Compare(typeName, "ServiceBroker", StringComparison.CurrentCultureIgnoreCase) == 0)
|
||||||
|
{
|
||||||
|
script = Scripter.SelectAllValuesFromTransmissionQueue(objectUrn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// select from queues
|
||||||
|
else if (string.Compare(typeName, "Queues", StringComparison.CurrentCultureIgnoreCase) == 0 ||
|
||||||
|
string.Compare(typeName, "SystemQueues", StringComparison.CurrentCultureIgnoreCase) == 0)
|
||||||
|
{
|
||||||
|
script = Scripter.SelectAllValues(objectUrn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// select from table or view
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Database db = server.Databases[databaseName];
|
||||||
|
bool isDw = db.IsSqlDw;
|
||||||
|
script = new Scripter().SelectFromTableOrView(server, objectUrn, isDw);
|
||||||
|
}
|
||||||
|
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerareScriptAsExecute(Server server, UrnCollection urns, ScriptingOptions options)
|
||||||
|
{
|
||||||
|
string script = string.Empty;
|
||||||
|
ScriptingObject scriptingObject = this.Parameters.ScriptingObjects[0];
|
||||||
|
Urn urn = urns[0];
|
||||||
|
|
||||||
|
// get the object
|
||||||
|
StoredProcedure sp = server.GetSmoObject(urn) as StoredProcedure;
|
||||||
|
|
||||||
|
Database parentObject = server.GetSmoObject(urn.Parent) as Database;
|
||||||
|
|
||||||
|
StringBuilder executeStatement = new StringBuilder();
|
||||||
|
|
||||||
|
// list of DECLARE <variable> <type>
|
||||||
|
StringBuilder declares = new StringBuilder();
|
||||||
|
// Parameters to be passed
|
||||||
|
StringBuilder parameterList = new StringBuilder();
|
||||||
|
if (sp == null || parentObject == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(SR.ScriptingExecuteNotSupportedError);
|
||||||
|
}
|
||||||
|
WriteUseDatabase(parentObject, executeStatement, options);
|
||||||
|
|
||||||
|
// character string to put in front of each parameter. First one is just carriage return
|
||||||
|
// the rest will have a "," in front as well.
|
||||||
|
string newLine = Environment.NewLine;
|
||||||
|
string paramListPreChar = $"{newLine} ";
|
||||||
|
for (int i = 0; i < sp.Parameters.Count; i++)
|
||||||
|
{
|
||||||
|
StoredProcedureParameter spp = sp.Parameters[i];
|
||||||
|
|
||||||
|
declares.AppendFormat("DECLARE {0} {1}{2}"
|
||||||
|
, QuoteObjectName(spp.Name)
|
||||||
|
, GetDatatype(spp.DataType, options)
|
||||||
|
, newLine);
|
||||||
|
|
||||||
|
parameterList.AppendFormat("{0}{1}"
|
||||||
|
, paramListPreChar
|
||||||
|
, QuoteObjectName(spp.Name));
|
||||||
|
|
||||||
|
// if this is the first time through change the prefix to include a ","
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
paramListPreChar = $"{newLine} ,";
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark any output parameters as such.
|
||||||
|
if (spp.IsOutputParameter)
|
||||||
|
{
|
||||||
|
parameterList.Append(" OUTPUT");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// build the execute statement
|
||||||
|
if (sp.ImplementationType == ImplementationType.TransactSql)
|
||||||
|
{
|
||||||
|
executeStatement.Append("EXECUTE @RC = ");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
executeStatement.Append("EXECUTE ");
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the object name
|
||||||
|
executeStatement.Append(GenerateSchemaQualifiedName(sp.Schema, sp.Name, options.SchemaQualify));
|
||||||
|
|
||||||
|
string formatString = sp.ImplementationType == ImplementationType.TransactSql
|
||||||
|
? "DECLARE @RC int{5}{0}{5}{1}{5}{5}{2} {3}{5}{4}"
|
||||||
|
: "{0}{5}{1}{5}{5}{2} {3}{5}{4}";
|
||||||
|
|
||||||
|
script = string.Format(CultureInfo.InvariantCulture, formatString,
|
||||||
|
declares,
|
||||||
|
SR.StoredProcedureScriptParameterComment,
|
||||||
|
executeStatement,
|
||||||
|
parameterList,
|
||||||
|
CommonConstants.DefaultBatchSeperator,
|
||||||
|
newLine);
|
||||||
|
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate a schema qualified name (e.g. [schema].[objectName]) for an object if the option for SchemaQualify is true
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="schema">The schema name. May be null or empty in which case it will be ignored</param>
|
||||||
|
/// <param name="objectName">The object name.</param>
|
||||||
|
/// <param name="schemaQualify">Whether to schema qualify the object or not</param>
|
||||||
|
/// <returns>The object name, quoted as appropriate and schema-qualified if the option is set</returns>
|
||||||
|
static private string GenerateSchemaQualifiedName(string schema, string objectName, bool schemaQualify)
|
||||||
|
{
|
||||||
|
var qualifiedName = new StringBuilder();
|
||||||
|
|
||||||
|
if (schemaQualify && !String.IsNullOrEmpty(schema))
|
||||||
|
{
|
||||||
|
// schema.name
|
||||||
|
qualifiedName.AppendFormat(CultureInfo.InvariantCulture, "{0}.{1}", GetDelimitedString(schema), GetDelimitedString(objectName));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// name
|
||||||
|
qualifiedName.AppendFormat(CultureInfo.InvariantCulture, "{0}", GetDelimitedString(objectName));
|
||||||
|
}
|
||||||
|
|
||||||
|
return qualifiedName.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// getting delimited string
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">string</param>
|
||||||
|
/// <returns>string</returns>
|
||||||
|
static private string GetDelimitedString(string str)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(str))
|
||||||
|
{
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
StringBuilder qualifiedName = new StringBuilder();
|
||||||
|
qualifiedName.AppendFormat("{0}{1}{2}",
|
||||||
|
LeftDelimiter,
|
||||||
|
QuoteObjectName(str),
|
||||||
|
RightDelimiter);
|
||||||
|
return qualifiedName.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// turn a smo datatype object into a type that can be inserted into tsql, e.g. nvarchar(20)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <param name="options"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
internal static string GetDatatype(DataType type, ScriptingOptions options)
|
||||||
|
{
|
||||||
|
// string we'll return.
|
||||||
|
string rv = string.Empty;
|
||||||
|
|
||||||
|
string dataType = type.Name;
|
||||||
|
switch (type.SqlDataType)
|
||||||
|
{
|
||||||
|
// char, nchar, nchar, nvarchar, varbinary, nvarbinary are all displayed as type(length)
|
||||||
|
// length of -1 is taken to be type(max). max isn't localizable.
|
||||||
|
case SqlDataType.Char:
|
||||||
|
case SqlDataType.NChar:
|
||||||
|
case SqlDataType.VarChar:
|
||||||
|
case SqlDataType.NVarChar:
|
||||||
|
case SqlDataType.Binary:
|
||||||
|
case SqlDataType.VarBinary:
|
||||||
|
rv = string.Format(CultureInfo.InvariantCulture,
|
||||||
|
"{0}({1})",
|
||||||
|
dataType,
|
||||||
|
type.MaximumLength);
|
||||||
|
break;
|
||||||
|
case SqlDataType.VarCharMax:
|
||||||
|
case SqlDataType.NVarCharMax:
|
||||||
|
case SqlDataType.VarBinaryMax:
|
||||||
|
rv = string.Format(CultureInfo.InvariantCulture,
|
||||||
|
"{0}(max)",
|
||||||
|
dataType);
|
||||||
|
break;
|
||||||
|
// numeric and decimal are displayed as type precision,scale
|
||||||
|
case SqlDataType.Numeric:
|
||||||
|
case SqlDataType.Decimal:
|
||||||
|
rv = string.Format(CultureInfo.InvariantCulture,
|
||||||
|
"{0}({1},{2})",
|
||||||
|
dataType,
|
||||||
|
type.NumericPrecision,
|
||||||
|
type.NumericScale);
|
||||||
|
break;
|
||||||
|
//time, datetimeoffset and datetime2 are displayed as type scale
|
||||||
|
case SqlDataType.Time:
|
||||||
|
case SqlDataType.DateTimeOffset:
|
||||||
|
case SqlDataType.DateTime2:
|
||||||
|
rv = string.Format(CultureInfo.InvariantCulture,
|
||||||
|
"{0}({1})",
|
||||||
|
dataType,
|
||||||
|
type.NumericScale);
|
||||||
|
break;
|
||||||
|
// anything else is just type.
|
||||||
|
case SqlDataType.Xml:
|
||||||
|
if (type.Schema != null && type.Schema.Length > 0 && dataType != null && dataType.Length > 0)
|
||||||
|
{
|
||||||
|
rv = String.Format(CultureInfo.InvariantCulture
|
||||||
|
, "xml ({0}{2}{1}.{0}{3}{1})"
|
||||||
|
, LeftDelimiter
|
||||||
|
, RightDelimiter
|
||||||
|
, QuoteObjectName(type.Schema)
|
||||||
|
, QuoteObjectName(dataType));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = "xml";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SqlDataType.UserDefinedDataType:
|
||||||
|
case SqlDataType.UserDefinedTableType:
|
||||||
|
case SqlDataType.UserDefinedType:
|
||||||
|
//User defined types may be in a non-DBO schema so append it if necessary
|
||||||
|
rv = GenerateSchemaQualifiedName(type.Schema, dataType, options.SchemaQualify);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
rv = dataType;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Double quotes certain characters in object name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sqlObject"></param>
|
||||||
|
public static string QuoteObjectName(string sqlObject)
|
||||||
|
{
|
||||||
|
|
||||||
|
int len = sqlObject.Length;
|
||||||
|
StringBuilder result = new StringBuilder(sqlObject.Length);
|
||||||
|
for (int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
if (sqlObject[i] == ']')
|
||||||
|
{
|
||||||
|
result.Append(']');
|
||||||
|
}
|
||||||
|
result.Append(sqlObject[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteUseDatabase(Database parentObject, StringBuilder stringBuilder , ScriptingOptions options)
|
||||||
|
{
|
||||||
|
if (options.IncludeDatabaseContext)
|
||||||
|
{
|
||||||
|
string useDb = string.Format(CultureInfo.InvariantCulture, "USE {0}", CommonConstants.DefaultBatchSeperator);
|
||||||
|
if (!options.NoCommandTerminator)
|
||||||
|
{
|
||||||
|
stringBuilder.Append(useDb);
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stringBuilder.Append(useDb);
|
||||||
|
stringBuilder.Append(Environment.NewLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateScriptAs(Server server, UrnCollection urns, ScriptingOptions options)
|
||||||
|
{
|
||||||
|
SqlServer.Management.Smo.Scripter scripter = null;
|
||||||
|
string resultScript = string.Empty;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
scripter = new SqlServer.Management.Smo.Scripter(server);
|
||||||
|
|
||||||
|
scripter.Options = options;
|
||||||
|
scripter.ScriptingError += ScripterScriptingError;
|
||||||
|
var result = scripter.Script(urns);
|
||||||
|
resultScript = GetScript(options, result);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
{
|
{
|
||||||
if (scripter != null)
|
if (scripter != null)
|
||||||
{
|
{
|
||||||
scripter.ScriptingError -= this.ScripterScriptingError;
|
scripter.ScriptingError -= this.ScripterScriptingError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return resultScript;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetScript(ScriptingOptions options, StringCollection stringCollection)
|
private string GetScript(ScriptingOptions options, StringCollection stringCollection)
|
||||||
@@ -150,8 +489,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
{
|
{
|
||||||
IEnumerable<ScriptingObject> selectedObjects = new List<ScriptingObject>(this.Parameters.ScriptingObjects);
|
IEnumerable<ScriptingObject> selectedObjects = new List<ScriptingObject>(this.Parameters.ScriptingObjects);
|
||||||
|
|
||||||
string server = serverConnection.TrueName;
|
serverName = serverConnection.TrueName;
|
||||||
string database = new SqlConnectionStringBuilder(this.Parameters.ConnectionString).InitialCatalog;
|
databaseName = new SqlConnectionStringBuilder(this.Parameters.ConnectionString).InitialCatalog;
|
||||||
UrnCollection urnCollection = new UrnCollection();
|
UrnCollection urnCollection = new UrnCollection();
|
||||||
foreach (var scriptingObject in selectedObjects)
|
foreach (var scriptingObject in selectedObjects)
|
||||||
{
|
{
|
||||||
@@ -160,7 +499,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
// TODO: get the default schema
|
// TODO: get the default schema
|
||||||
scriptingObject.Schema = "dbo";
|
scriptingObject.Schema = "dbo";
|
||||||
}
|
}
|
||||||
urnCollection.Add(scriptingObject.ToUrn(server, database));
|
urnCollection.Add(scriptingObject.ToUrn(serverName, databaseName));
|
||||||
}
|
}
|
||||||
return urnCollection;
|
return urnCollection;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,11 +29,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event raised when a scripting operation has resolved which database objects will be scripted.
|
|
||||||
/// </summary>
|
|
||||||
public event EventHandler<ScriptingPlanNotificationParams> PlanNotification;
|
|
||||||
|
|
||||||
public override void Execute()
|
public override void Execute()
|
||||||
{
|
{
|
||||||
SqlScriptPublishModel publishModel = null;
|
SqlScriptPublishModel publishModel = null;
|
||||||
@@ -118,25 +113,22 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
|
|
||||||
protected override void SendCompletionNotificationEvent(ScriptingCompleteParams parameters)
|
protected override void SendCompletionNotificationEvent(ScriptingCompleteParams parameters)
|
||||||
{
|
{
|
||||||
this.SetCommonEventProperties(parameters);
|
|
||||||
base.SendCompletionNotificationEvent(parameters);
|
base.SendCompletionNotificationEvent(parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendPlanNotificationEvent(ScriptingPlanNotificationParams parameters)
|
protected override void SendPlanNotificationEvent(ScriptingPlanNotificationParams parameters)
|
||||||
{
|
{
|
||||||
this.SetCommonEventProperties(parameters);
|
base.SendPlanNotificationEvent(parameters);
|
||||||
this.PlanNotification?.Invoke(this, parameters);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void SendProgressNotificationEvent(ScriptingProgressNotificationParams parameters)
|
protected override void SendProgressNotificationEvent(ScriptingProgressNotificationParams parameters)
|
||||||
{
|
{
|
||||||
this.SetCommonEventProperties(parameters);
|
|
||||||
base.SendProgressNotificationEvent(parameters);
|
base.SendProgressNotificationEvent(parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetCommonEventProperties(ScriptingEventParams parameters)
|
protected override void SetCommonEventProperties(ScriptingEventParams parameters)
|
||||||
{
|
{
|
||||||
parameters.OperationId = this.OperationId;
|
base.SetCommonEventProperties(parameters);
|
||||||
parameters.SequenceNumber = this.eventSequenceNumber;
|
parameters.SequenceNumber = this.eventSequenceNumber;
|
||||||
this.eventSequenceNumber += 1;
|
this.eventSequenceNumber += 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
/// <param name="context"></param>
|
/// <param name="context"></param>
|
||||||
public void InitializeService(ServiceHost serviceHost)
|
public void InitializeService(ServiceHost serviceHost)
|
||||||
{
|
{
|
||||||
serviceHost.SetRequestHandler(ScriptingScriptAsRequest.Type, HandleScriptingScriptAsRequest);
|
|
||||||
serviceHost.SetRequestHandler(ScriptingRequest.Type, this.HandleScriptExecuteRequest);
|
serviceHost.SetRequestHandler(ScriptingRequest.Type, this.HandleScriptExecuteRequest);
|
||||||
serviceHost.SetRequestHandler(ScriptingCancelRequest.Type, this.HandleScriptCancelRequest);
|
serviceHost.SetRequestHandler(ScriptingCancelRequest.Type, this.HandleScriptCancelRequest);
|
||||||
serviceHost.SetRequestHandler(ScriptingListObjectsRequest.Type, this.HandleListObjectsRequest);
|
serviceHost.SetRequestHandler(ScriptingListObjectsRequest.Type, this.HandleListObjectsRequest);
|
||||||
@@ -112,81 +111,17 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles request to start the scripting operation
|
/// Handles request to start the scripting operation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task HandleScriptingScriptAsRequest(ScriptingParams parameters, RequestContext<ScriptingResult> requestContext)
|
public async Task HandleScriptExecuteRequest(ScriptingParams parameters, RequestContext<ScriptingResult> requestContext)
|
||||||
{
|
{
|
||||||
|
SmoScriptingOperation operation = null;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// if a connection string wasn't provided as a parameter then
|
// if a connection string wasn't provided as a parameter then
|
||||||
// use the owner uri property to lookup its associated ConnectionInfo
|
// use the owner uri property to lookup its associated ConnectionInfo
|
||||||
// and then build a connection string out of that
|
// and then build a connection string out of that
|
||||||
ConnectionInfo connInfo = null;
|
ConnectionInfo connInfo = null;
|
||||||
if (parameters.ConnectionString == null || parameters.ScriptOptions.ScriptCreateDrop == "ScriptSelect")
|
if (parameters.ConnectionString == null)
|
||||||
{
|
|
||||||
ScriptingService.ConnectionServiceInstance.TryFindConnection(parameters.OwnerUri, out connInfo);
|
|
||||||
if (connInfo != null)
|
|
||||||
{
|
|
||||||
connInfo.ConnectionDetails.PersistSecurityInfo = true;
|
|
||||||
parameters.ConnectionString = ConnectionService.BuildConnectionString(connInfo.ConnectionDetails);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new Exception("Could not find ConnectionInfo");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the scripting operation is for SELECT then handle that message differently
|
|
||||||
// for SELECT we'll build the SQL directly whereas other scripting operations depend on SMO
|
|
||||||
if (parameters.ScriptOptions.ScriptCreateDrop == "ScriptSelect")
|
|
||||||
{
|
|
||||||
RunSelectTask(connInfo, parameters, requestContext);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
RunScriptAsTask(connInfo, parameters, requestContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
await requestContext.SendError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RunScriptAsTask(ConnectionInfo connInfo, ScriptingParams parameters, RequestContext<ScriptingResult> requestContext)
|
|
||||||
{
|
|
||||||
ScriptAsScriptingOperation operation = new ScriptAsScriptingOperation(parameters);
|
|
||||||
ConnectionServiceInstance.ConnectionQueue.QueueBindingOperation(
|
|
||||||
key: ConnectionServiceInstance.ConnectionQueue.AddConnectionContext(connInfo, "Scripting"),
|
|
||||||
bindingTimeout: ScriptingOperationTimeout,
|
|
||||||
bindOperation: (bindingContext, cancelToken) =>
|
|
||||||
{
|
|
||||||
string script = string.Empty;
|
|
||||||
operation.ServerConnection = bindingContext.ServerConnection;
|
|
||||||
operation.ProgressNotification += (sender, e) => requestContext.SendEvent(ScriptingProgressNotificationEvent.Type, e);
|
|
||||||
operation.CompleteNotification += (sender, e) => this.SendScriptingCompleteEvent(requestContext, ScriptingCompleteEvent.Type, e, operation, parameters.ScriptDestination);
|
|
||||||
|
|
||||||
RunTask(requestContext, operation);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
timeoutOperation: (bindingContext) =>
|
|
||||||
{
|
|
||||||
this.SendScriptingCompleteEvent(requestContext, ScriptingCompleteEvent.Type, new ScriptingCompleteParams { Success = false }, operation, parameters.ScriptDestination);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handles request to start the scripting operation
|
|
||||||
/// </summary>
|
|
||||||
public async Task HandleScriptExecuteRequest(ScriptingParams parameters, RequestContext<ScriptingResult> requestContext)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// if a connection string wasn't provided as a parameter then
|
|
||||||
// use the owner uri property to lookup its associated ConnectionInfo
|
|
||||||
// and then build a connection string out of that
|
|
||||||
ConnectionInfo connInfo = null;
|
|
||||||
if (parameters.ConnectionString == null || parameters.ScriptOptions.ScriptCreateDrop == "ScriptSelect")
|
|
||||||
{
|
{
|
||||||
ScriptingService.ConnectionServiceInstance.TryFindConnection(parameters.OwnerUri, out connInfo);
|
ScriptingService.ConnectionServiceInstance.TryFindConnection(parameters.OwnerUri, out connInfo);
|
||||||
if (connInfo != null)
|
if (connInfo != null)
|
||||||
@@ -198,22 +133,22 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
throw new Exception("Could not find ConnectionInfo");
|
throw new Exception("Could not find ConnectionInfo");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the scripting operation is for SELECT then handle that message differently
|
if (!ShouldCreateScriptAsOperation(parameters))
|
||||||
// for SELECT we'll build the SQL directly whereas other scripting operations depend on SMO
|
|
||||||
if (parameters.ScriptOptions.ScriptCreateDrop == "ScriptSelect")
|
|
||||||
{
|
{
|
||||||
RunSelectTask(connInfo, parameters, requestContext);
|
operation = new ScriptingScriptOperation(parameters);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ScriptingScriptOperation operation = new ScriptingScriptOperation(parameters);
|
operation = new ScriptAsScriptingOperation(parameters);
|
||||||
operation.PlanNotification += (sender, e) => requestContext.SendEvent(ScriptingPlanNotificationEvent.Type, e).Wait();
|
|
||||||
operation.ProgressNotification += (sender, e) => requestContext.SendEvent(ScriptingProgressNotificationEvent.Type, e).Wait();
|
|
||||||
operation.CompleteNotification += (sender, e) => this.SendScriptingCompleteEvent(requestContext, ScriptingCompleteEvent.Type, e, operation, parameters.ScriptDestination);
|
|
||||||
|
|
||||||
RunTask(requestContext, operation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
operation.PlanNotification += (sender, e) => requestContext.SendEvent(ScriptingPlanNotificationEvent.Type, e).Wait();
|
||||||
|
operation.ProgressNotification += (sender, e) => requestContext.SendEvent(ScriptingProgressNotificationEvent.Type, e).Wait();
|
||||||
|
operation.CompleteNotification += (sender, e) => this.SendScriptingCompleteEvent(requestContext, ScriptingCompleteEvent.Type, e, operation, parameters.ScriptDestination);
|
||||||
|
|
||||||
|
RunTask(requestContext, operation);
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
@@ -221,6 +156,23 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool ShouldCreateScriptAsOperation(ScriptingParams parameters)
|
||||||
|
{
|
||||||
|
// Scripting as operation should be used to script one object.
|
||||||
|
// Scripting data and scripting to file is not supported by scripting as operation
|
||||||
|
// To script Select, alter and execute use scripting as operation. The other operation doesn't support those types
|
||||||
|
if( (parameters.ScriptingObjects != null && parameters.ScriptingObjects.Count == 1 && parameters.ScriptOptions != null
|
||||||
|
&& parameters.ScriptOptions.TypeOfDataToScript == "SchemaOnly" && parameters.ScriptDestination == "ToEditor") ||
|
||||||
|
parameters.Operation == ScriptingOperationType.Select || parameters.Operation == ScriptingOperationType.Execute)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles request to cancel a script operation.
|
/// Handles request to cancel a script operation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -264,87 +216,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Urn BuildScriptingObjectUrn(
|
|
||||||
Server server,
|
|
||||||
SqlConnectionStringBuilder connectionStringBuilder,
|
|
||||||
ScriptingObject scriptingObject)
|
|
||||||
{
|
|
||||||
string serverName = server.Name.ToUpper();
|
|
||||||
|
|
||||||
// remove the port from server name if specified
|
|
||||||
int commaPos = serverName.IndexOf(',');
|
|
||||||
if (commaPos >= 0)
|
|
||||||
{
|
|
||||||
serverName = serverName.Substring(0, commaPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// build the URN
|
|
||||||
string urnString = string.Format(
|
|
||||||
"Server[@Name='{0}']/Database[@Name='{1}']/{2}[@Name='{3}' {4}]",
|
|
||||||
serverName,
|
|
||||||
connectionStringBuilder.InitialCatalog,
|
|
||||||
scriptingObject.Type,
|
|
||||||
scriptingObject.Name,
|
|
||||||
scriptingObject.Schema != null ? string.Format("and @Schema = '{0}'", scriptingObject.Schema) : string.Empty);
|
|
||||||
|
|
||||||
return new Urn(urnString);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Runs the async task that performs the scripting operation.
|
|
||||||
/// </summary>
|
|
||||||
private void RunSelectTask(ConnectionInfo connInfo, ScriptingParams parameters, RequestContext<ScriptingResult> requestContext)
|
|
||||||
{
|
|
||||||
ConnectionServiceInstance.ConnectionQueue.QueueBindingOperation(
|
|
||||||
key: ConnectionServiceInstance.ConnectionQueue.AddConnectionContext(connInfo, "Scripting"),
|
|
||||||
bindingTimeout: ScriptingOperationTimeout,
|
|
||||||
bindOperation: (bindingContext, cancelToken) =>
|
|
||||||
{
|
|
||||||
string script = string.Empty;
|
|
||||||
ScriptingObject scriptingObject = parameters.ScriptingObjects[0];
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Server server = new Server(bindingContext.ServerConnection);
|
|
||||||
server.DefaultTextMode = true;
|
|
||||||
|
|
||||||
// build object URN
|
|
||||||
SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder(parameters.ConnectionString);
|
|
||||||
Urn objectUrn = BuildScriptingObjectUrn(server, connectionStringBuilder, scriptingObject);
|
|
||||||
string typeName = objectUrn.GetNameForType(scriptingObject.Type);
|
|
||||||
|
|
||||||
// select from service broker
|
|
||||||
if (string.Compare(typeName, "ServiceBroker", StringComparison.CurrentCultureIgnoreCase) == 0)
|
|
||||||
{
|
|
||||||
script = Scripter.SelectAllValuesFromTransmissionQueue(objectUrn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// select from queues
|
|
||||||
else if (string.Compare(typeName, "Queues", StringComparison.CurrentCultureIgnoreCase) == 0 ||
|
|
||||||
string.Compare(typeName, "SystemQueues", StringComparison.CurrentCultureIgnoreCase) == 0)
|
|
||||||
{
|
|
||||||
script = Scripter.SelectAllValues(objectUrn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// select from table or view
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Database db = server.Databases[connectionStringBuilder.InitialCatalog];
|
|
||||||
bool isDw = db.IsSqlDw;
|
|
||||||
script = new Scripter().SelectFromTableOrView(server, objectUrn, isDw);
|
|
||||||
}
|
|
||||||
|
|
||||||
// send script result to client
|
|
||||||
requestContext.SendResult(new ScriptingResult { Script = script }).Wait();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
requestContext.SendError(e).Wait();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Runs the async task that performs the scripting operation.
|
/// Runs the async task that performs the scripting operation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -42,16 +42,34 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public event EventHandler<ScriptingProgressNotificationParams> ProgressNotification;
|
public event EventHandler<ScriptingProgressNotificationParams> ProgressNotification;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event raised when a scripting operation has resolved which database objects will be scripted.
|
||||||
|
/// </summary>
|
||||||
|
public event EventHandler<ScriptingPlanNotificationParams> PlanNotification;
|
||||||
|
|
||||||
protected virtual void SendCompletionNotificationEvent(ScriptingCompleteParams parameters)
|
protected virtual void SendCompletionNotificationEvent(ScriptingCompleteParams parameters)
|
||||||
{
|
{
|
||||||
|
this.SetCommonEventProperties(parameters);
|
||||||
this.CompleteNotification?.Invoke(this, parameters);
|
this.CompleteNotification?.Invoke(this, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void SendProgressNotificationEvent(ScriptingProgressNotificationParams parameters)
|
protected virtual void SendProgressNotificationEvent(ScriptingProgressNotificationParams parameters)
|
||||||
{
|
{
|
||||||
|
this.SetCommonEventProperties(parameters);
|
||||||
this.ProgressNotification?.Invoke(this, parameters);
|
this.ProgressNotification?.Invoke(this, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void SendPlanNotificationEvent(ScriptingPlanNotificationParams parameters)
|
||||||
|
{
|
||||||
|
this.SetCommonEventProperties(parameters);
|
||||||
|
this.PlanNotification?.Invoke(this, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void SetCommonEventProperties(ScriptingEventParams parameters)
|
||||||
|
{
|
||||||
|
parameters.OperationId = this.OperationId;
|
||||||
|
}
|
||||||
|
|
||||||
protected string GetServerNameFromLiveInstance(string connectionString)
|
protected string GetServerNameFromLiveInstance(string connectionString)
|
||||||
{
|
{
|
||||||
string serverName = null;
|
string serverName = null;
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting
|
|||||||
public async void VerifyScriptAsCreateTable()
|
public async void VerifyScriptAsCreateTable()
|
||||||
{
|
{
|
||||||
string query = "CREATE TABLE testTable1 (c1 int)";
|
string query = "CREATE TABLE testTable1 (c1 int)";
|
||||||
string scriptCreateDrop = "ScriptCreate";
|
ScriptingOperationType scriptCreateDrop = ScriptingOperationType.Create;
|
||||||
ScriptingObject scriptingObject = new ScriptingObject
|
ScriptingObject scriptingObject = new ScriptingObject
|
||||||
{
|
{
|
||||||
Name = "testTable1",
|
Name = "testTable1",
|
||||||
@@ -101,11 +101,67 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting
|
|||||||
await VerifyScriptAs(query, scriptingObject, scriptCreateDrop, expectedScript);
|
await VerifyScriptAs(query, scriptingObject, scriptCreateDrop, expectedScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void VerifyScriptAsExecuteTableFailes()
|
||||||
|
{
|
||||||
|
string query = "CREATE TABLE testTable1 (c1 int)";
|
||||||
|
ScriptingOperationType scriptCreateDrop = ScriptingOperationType.Execute;
|
||||||
|
ScriptingObject scriptingObject = new ScriptingObject
|
||||||
|
{
|
||||||
|
Name = "testTable1",
|
||||||
|
Schema = "dbo",
|
||||||
|
Type = "Table"
|
||||||
|
};
|
||||||
|
string expectedScript = null;
|
||||||
|
|
||||||
|
await VerifyScriptAs(query, scriptingObject, scriptCreateDrop, expectedScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void VerifyScriptAsExecuteStoredProcedure()
|
||||||
|
{
|
||||||
|
string query = @"CREATE PROCEDURE testSp1
|
||||||
|
@BusinessEntityID [int],
|
||||||
|
@JobTitle [nvarchar](50),
|
||||||
|
@HireDate [datetime],
|
||||||
|
@RateChangeDate [datetime],
|
||||||
|
@Rate [money],
|
||||||
|
@PayFrequency [tinyint]
|
||||||
|
AS
|
||||||
|
BEGIN Select * from sys.all_columns END";
|
||||||
|
ScriptingOperationType scriptCreateDrop = ScriptingOperationType.Execute;
|
||||||
|
ScriptingObject scriptingObject = new ScriptingObject
|
||||||
|
{
|
||||||
|
Name = "testSp1",
|
||||||
|
Schema = "dbo",
|
||||||
|
Type = "StoredProcedure"
|
||||||
|
};
|
||||||
|
string expectedScript = "EXECUTE @RC = [dbo].[testSp1]";
|
||||||
|
|
||||||
|
await VerifyScriptAs(query, scriptingObject, scriptCreateDrop, expectedScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void VerifyScriptAsSelectTable()
|
||||||
|
{
|
||||||
|
string query = "CREATE TABLE testTable1 (c1 int)";
|
||||||
|
ScriptingOperationType scriptCreateDrop = ScriptingOperationType.Select;
|
||||||
|
ScriptingObject scriptingObject = new ScriptingObject
|
||||||
|
{
|
||||||
|
Name = "testTable1",
|
||||||
|
Schema = "dbo",
|
||||||
|
Type = "Table"
|
||||||
|
};
|
||||||
|
string expectedScript = "SELECT TOP (1000) [c1]";
|
||||||
|
|
||||||
|
await VerifyScriptAs(query, scriptingObject, scriptCreateDrop, expectedScript);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async void VerifyScriptAsCreateView()
|
public async void VerifyScriptAsCreateView()
|
||||||
{
|
{
|
||||||
string query = "CREATE VIEW testView1 AS SELECT * from sys.all_columns";
|
string query = "CREATE VIEW testView1 AS SELECT * from sys.all_columns";
|
||||||
string scriptCreateDrop = "ScriptCreate";
|
ScriptingOperationType scriptCreateDrop = ScriptingOperationType.Create;
|
||||||
ScriptingObject scriptingObject = new ScriptingObject
|
ScriptingObject scriptingObject = new ScriptingObject
|
||||||
{
|
{
|
||||||
Name = "testView1",
|
Name = "testView1",
|
||||||
@@ -121,7 +177,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting
|
|||||||
public async void VerifyScriptAsCreateStoredProcedure()
|
public async void VerifyScriptAsCreateStoredProcedure()
|
||||||
{
|
{
|
||||||
string query = "CREATE PROCEDURE testSp1 AS BEGIN Select * from sys.all_columns END";
|
string query = "CREATE PROCEDURE testSp1 AS BEGIN Select * from sys.all_columns END";
|
||||||
string scriptCreateDrop = "ScriptCreate";
|
ScriptingOperationType scriptCreateDrop = ScriptingOperationType.Create;
|
||||||
ScriptingObject scriptingObject = new ScriptingObject
|
ScriptingObject scriptingObject = new ScriptingObject
|
||||||
{
|
{
|
||||||
Name = "testSp1",
|
Name = "testSp1",
|
||||||
@@ -137,7 +193,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting
|
|||||||
public async void VerifyScriptAsDropTable()
|
public async void VerifyScriptAsDropTable()
|
||||||
{
|
{
|
||||||
string query = "CREATE TABLE testTable1 (c1 int)";
|
string query = "CREATE TABLE testTable1 (c1 int)";
|
||||||
string scriptCreateDrop = "ScriptDrop";
|
ScriptingOperationType scriptCreateDrop = ScriptingOperationType.Delete;
|
||||||
ScriptingObject scriptingObject = new ScriptingObject
|
ScriptingObject scriptingObject = new ScriptingObject
|
||||||
{
|
{
|
||||||
Name = "testTable1",
|
Name = "testTable1",
|
||||||
@@ -153,7 +209,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting
|
|||||||
public async void VerifyScriptAsDropView()
|
public async void VerifyScriptAsDropView()
|
||||||
{
|
{
|
||||||
string query = "CREATE VIEW testView1 AS SELECT * from sys.all_columns";
|
string query = "CREATE VIEW testView1 AS SELECT * from sys.all_columns";
|
||||||
string scriptCreateDrop = "ScriptDrop";
|
ScriptingOperationType scriptCreateDrop = ScriptingOperationType.Delete;
|
||||||
ScriptingObject scriptingObject = new ScriptingObject
|
ScriptingObject scriptingObject = new ScriptingObject
|
||||||
{
|
{
|
||||||
Name = "testView1",
|
Name = "testView1",
|
||||||
@@ -169,7 +225,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting
|
|||||||
public async void VerifyScriptAsDropStoredProcedure()
|
public async void VerifyScriptAsDropStoredProcedure()
|
||||||
{
|
{
|
||||||
string query = "CREATE PROCEDURE testSp1 AS BEGIN Select * from sys.all_columns END";
|
string query = "CREATE PROCEDURE testSp1 AS BEGIN Select * from sys.all_columns END";
|
||||||
string scriptCreateDrop = "ScriptDrop";
|
ScriptingOperationType scriptCreateDrop = ScriptingOperationType.Delete;
|
||||||
ScriptingObject scriptingObject = new ScriptingObject
|
ScriptingObject scriptingObject = new ScriptingObject
|
||||||
{
|
{
|
||||||
Name = "testSp1",
|
Name = "testSp1",
|
||||||
@@ -181,7 +237,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting
|
|||||||
await VerifyScriptAs(query, scriptingObject, scriptCreateDrop, expectedScript);
|
await VerifyScriptAs(query, scriptingObject, scriptCreateDrop, expectedScript);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task VerifyScriptAs(string query, ScriptingObject scriptingObject, string scriptCreateDrop, string expectedScript)
|
private async Task VerifyScriptAs(string query, ScriptingObject scriptingObject, ScriptingOperationType operation, string expectedScript)
|
||||||
{
|
{
|
||||||
var testDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, query, "ScriptingTests");
|
var testDb = await SqlTestDb.CreateNewAsync(TestServerType.OnPrem, false, null, query, "ScriptingTests");
|
||||||
try
|
try
|
||||||
@@ -196,13 +252,23 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting
|
|||||||
var scriptingParams = new ScriptingParams
|
var scriptingParams = new ScriptingParams
|
||||||
{
|
{
|
||||||
OwnerUri = queryTempFile.FilePath,
|
OwnerUri = queryTempFile.FilePath,
|
||||||
ScriptDestination = "ToEditor"
|
ScriptDestination = "ToEditor",
|
||||||
|
Operation = operation
|
||||||
};
|
};
|
||||||
|
|
||||||
|
string scriptCreateOperation = "ScriptCreate";
|
||||||
|
if(operation == ScriptingOperationType.Delete)
|
||||||
|
{
|
||||||
|
scriptCreateOperation = "ScriptDrop";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scriptCreateOperation = $"Script{operation}";
|
||||||
|
}
|
||||||
|
|
||||||
scriptingParams.ScriptOptions = new ScriptOptions
|
scriptingParams.ScriptOptions = new ScriptOptions
|
||||||
{
|
{
|
||||||
ScriptCreateDrop = scriptCreateDrop,
|
ScriptCreateDrop = scriptCreateOperation,
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
scriptingParams.ScriptingObjects = new List<ScriptingObject>
|
scriptingParams.ScriptingObjects = new List<ScriptingObject>
|
||||||
@@ -212,7 +278,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting
|
|||||||
|
|
||||||
|
|
||||||
ScriptingService service = new ScriptingService();
|
ScriptingService service = new ScriptingService();
|
||||||
await service.HandleScriptingScriptAsRequest(scriptingParams, requestContext.Object);
|
await service.HandleScriptExecuteRequest(scriptingParams, requestContext.Object);
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
await service.ScriptingTask;
|
await service.ScriptingTask;
|
||||||
|
|
||||||
@@ -235,7 +301,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Scripting
|
|||||||
|
|
||||||
private static bool VerifyScriptingResult(ScriptingResult result, string expected)
|
private static bool VerifyScriptingResult(ScriptingResult result, string expected)
|
||||||
{
|
{
|
||||||
return !string.IsNullOrEmpty(result.Script) && result.Script.Contains(expected);
|
return string.IsNullOrEmpty(expected) ? string.IsNullOrEmpty(result.Script) : !string.IsNullOrEmpty(result.Script) && result.Script.Contains(expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
|||||||
ScriptingResult result = await testService.Script(requestParams);
|
ScriptingResult result = await testService.Script(requestParams);
|
||||||
ScriptingCompleteParams parameters = await testService.Driver.WaitForEvent(ScriptingCompleteEvent.Type, TimeSpan.FromSeconds(15));
|
ScriptingCompleteParams parameters = await testService.Driver.WaitForEvent(ScriptingCompleteEvent.Type, TimeSpan.FromSeconds(15));
|
||||||
Assert.True(parameters.HasError);
|
Assert.True(parameters.HasError);
|
||||||
Assert.Equal("An error occurred while scripting the objects.", parameters.ErrorMessage);
|
Assert.True(parameters.ErrorMessage.Contains("An error occurred while scripting the objects."));
|
||||||
Assert.Contains("The Table '[dbo].[TableDoesNotExist]' does not exist on the server.", parameters.ErrorDetails);
|
Assert.Contains("The Table '[dbo].[TableDoesNotExist]' does not exist on the server.", parameters.ErrorDetails);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -297,7 +297,6 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
|||||||
OwnerUri = tempFile.FilePath,
|
OwnerUri = tempFile.FilePath,
|
||||||
ScriptOptions = new ScriptOptions
|
ScriptOptions = new ScriptOptions
|
||||||
{
|
{
|
||||||
ScriptCreateDrop = "ScriptSelect"
|
|
||||||
},
|
},
|
||||||
ScriptingObjects = new List<ScriptingObject>
|
ScriptingObjects = new List<ScriptingObject>
|
||||||
{
|
{
|
||||||
@@ -307,7 +306,8 @@ namespace Microsoft.SqlTools.ServiceLayer.TestDriver.Tests
|
|||||||
Schema = "dbo",
|
Schema = "dbo",
|
||||||
Name = "Customers",
|
Name = "Customers",
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
Operation = ScriptingOperationType.Select
|
||||||
};
|
};
|
||||||
ScriptingResult result = await testService.Script(requestParams);
|
ScriptingResult result = await testService.Script(requestParams);
|
||||||
Assert.True(result.Script.Contains("SELECT"));
|
Assert.True(result.Script.Contains("SELECT"));
|
||||||
|
|||||||
Reference in New Issue
Block a user