mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-01-14 09:59:48 -05:00
Fix some issues with Script As Select (#474)
This commit is contained in:
@@ -16,7 +16,6 @@ using Microsoft.SqlTools.Hosting.Protocol;
|
||||
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||
using Microsoft.SqlTools.ServiceLayer.Hosting;
|
||||
using Microsoft.SqlTools.ServiceLayer.LanguageServices;
|
||||
using Microsoft.SqlTools.ServiceLayer.Metadata.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Scripting.Contracts;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
@@ -39,8 +38,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||
|
||||
private static ConnectionService connectionService = null;
|
||||
|
||||
private static LanguageService languageServices = null;
|
||||
|
||||
private readonly Lazy<ConcurrentDictionary<string, ScriptingOperation>> operations =
|
||||
new Lazy<ConcurrentDictionary<string, ScriptingOperation>>(() => new ConcurrentDictionary<string, ScriptingOperation>());
|
||||
|
||||
@@ -65,24 +62,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal for testing purposes only
|
||||
/// </summary>
|
||||
internal static LanguageService LanguageServiceInstance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (languageServices == null)
|
||||
{
|
||||
languageServices = LanguageService.Instance;
|
||||
}
|
||||
return languageServices;
|
||||
}
|
||||
set
|
||||
{
|
||||
languageServices = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The collection of active operations
|
||||
@@ -108,61 +87,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles request to get select script for an smo object
|
||||
/// </summary>
|
||||
private void HandleScriptSelectRequest(ScriptingParams parameters, RequestContext<ScriptingResult> requestContext)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
string script = String.Empty;
|
||||
ScriptingObject scriptingObject = parameters.ScriptingObjects[0];
|
||||
|
||||
// convert owner uri received from parameters to lookup for its
|
||||
// associated connection and build a connection string out of it
|
||||
SqlConnection sqlConn = new SqlConnection(parameters.ConnectionString);
|
||||
ServerConnection serverConn = new ServerConnection(sqlConn);
|
||||
Server server = new Server(serverConn);
|
||||
server.DefaultTextMode = true;
|
||||
SqlConnectionStringBuilder connStringBuilder = new SqlConnectionStringBuilder(parameters.ConnectionString);
|
||||
string urnString = string.Format(
|
||||
"Server[@Name='{0}']/Database[@Name='{1}']/{2}[@Name='{3}' {4}]",
|
||||
server.Name.ToUpper(),
|
||||
connStringBuilder.InitialCatalog,
|
||||
scriptingObject.Type,
|
||||
scriptingObject.Name,
|
||||
scriptingObject.Schema != null ? string.Format("and @Schema = '{0}'", scriptingObject.Schema) : string.Empty);
|
||||
Urn urn = new Urn(urnString);
|
||||
string name = urn.GetNameForType(scriptingObject.Type);
|
||||
if (string.Compare(name, "ServiceBroker", StringComparison.CurrentCultureIgnoreCase) == 0)
|
||||
{
|
||||
script = Scripter.SelectAllValuesFromTransmissionQueue(urn);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.Compare(name, "Queues", StringComparison.CurrentCultureIgnoreCase) == 0 ||
|
||||
string.Compare(name, "SystemQueues", StringComparison.CurrentCultureIgnoreCase) == 0)
|
||||
{
|
||||
script = Scripter.SelectAllValues(urn);
|
||||
}
|
||||
else
|
||||
{
|
||||
Database db = server.Databases[connStringBuilder.InitialCatalog];
|
||||
bool isDw = db.IsSqlDw;
|
||||
script = new Scripter().SelectFromTableOrView(server, urn, isDw);
|
||||
}
|
||||
}
|
||||
requestContext.SendResult(new ScriptingResult { Script = script});
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
requestContext.SendError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles request to execute start the list objects operation.
|
||||
/// </summary>
|
||||
@@ -171,7 +95,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||
try
|
||||
{
|
||||
ScriptingListObjectsOperation operation = new ScriptingListObjectsOperation(parameters);
|
||||
operation.CompleteNotification += (sender, e) => this.SendEvent(requestContext, ScriptingListObjectsCompleteEvent.Type, e);
|
||||
operation.CompleteNotification += (sender, e) => requestContext.SendEvent(ScriptingListObjectsCompleteEvent.Type, e);
|
||||
|
||||
RunTask(requestContext, operation);
|
||||
|
||||
@@ -184,36 +108,40 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles request to execute start the script operation.
|
||||
/// Handles request to start the scripting operation
|
||||
/// </summary>
|
||||
public async Task HandleScriptExecuteRequest(ScriptingParams parameters, RequestContext<ScriptingResult> requestContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
// convert owner uri received from parameters to lookup for its
|
||||
// associated connection and build a connection string out of it
|
||||
// if a connection string doesn't already exist
|
||||
// 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;
|
||||
ScriptingService.ConnectionServiceInstance.TryFindConnection(parameters.OwnerUri, out connInfo);
|
||||
if (parameters.ConnectionString == null)
|
||||
{
|
||||
ConnectionInfo connInfo;
|
||||
ScriptingService.ConnectionServiceInstance.TryFindConnection(
|
||||
parameters.OwnerUri, out connInfo);
|
||||
if (connInfo != null)
|
||||
{
|
||||
parameters.ConnectionString = ConnectionService.BuildConnectionString(connInfo.ConnectionDetails);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception("Could not find ConnectionInfo");
|
||||
}
|
||||
}
|
||||
|
||||
// if the scripting operation is for select
|
||||
|
||||
// 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(parameters, requestContext);
|
||||
RunSelectTask(connInfo, parameters, requestContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScriptingScriptOperation operation = new ScriptingScriptOperation(parameters);
|
||||
operation.PlanNotification += (sender, e) => this.SendEvent(requestContext, ScriptingPlanNotificationEvent.Type, e);
|
||||
operation.ProgressNotification += (sender, e) => this.SendEvent(requestContext, ScriptingProgressNotificationEvent.Type, e);
|
||||
operation.PlanNotification += (sender, e) => requestContext.SendEvent(ScriptingPlanNotificationEvent.Type, e);
|
||||
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);
|
||||
@@ -271,30 +199,85 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a JSON-RPC event.
|
||||
/// </summary>
|
||||
private void SendEvent<TParams>(IEventSender requestContext, EventType<TParams> eventType, TParams parameters)
|
||||
private Urn BuildScriptingObjectUrn(
|
||||
Server server,
|
||||
SqlConnectionStringBuilder connectionStringBuilder,
|
||||
ScriptingObject scriptingObject)
|
||||
{
|
||||
Task.Run(async () => await requestContext.SendEvent(eventType, parameters));
|
||||
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(ScriptingParams parameters, RequestContext<ScriptingResult> requestContext)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
try
|
||||
private void RunSelectTask(ConnectionInfo connInfo, ScriptingParams parameters, RequestContext<ScriptingResult> requestContext)
|
||||
{
|
||||
ConnectionServiceInstance.ConnectionQueue.QueueBindingOperation(
|
||||
key: ConnectionServiceInstance.ConnectionQueue.AddConnectionContext(connInfo),
|
||||
bindingTimeout: ScriptingOperationTimeout,
|
||||
bindOperation: (bindingContext, cancelToken) =>
|
||||
{
|
||||
this.HandleScriptSelectRequest(parameters, requestContext);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
requestContext.SendError(e);
|
||||
}
|
||||
});
|
||||
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 });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
requestContext.SendError(e);
|
||||
}
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user