Merge branch 'main' into v-chrcan/issue392

This commit is contained in:
Christopher C
2021-08-30 13:29:11 -07:00
12 changed files with 256 additions and 20 deletions

View File

@@ -38,7 +38,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
/// <summary>
/// URI identifying the owner/user of the connection. Could be a file, service, resource, etc.
/// </summary>
public string OwnerUri { get; private set; }
public string OwnerUri { get; set; }
/// <summary>
/// Factory used for creating the SQL connection associated with the connection info.

View File

@@ -766,6 +766,22 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
return false;
}
/// <summary>
/// Reassign the uri associated with a connection info with a new uri.
/// </summary>
public bool ReplaceUri(string originalOwnerUri, string newOwnerUri)
{
// Lookup the ConnectionInfo owned by the URI
ConnectionInfo info;
if (!OwnerToConnectionMap.TryGetValue(originalOwnerUri, out info))
{
return false;
}
OwnerToConnectionMap.Remove(originalOwnerUri);
OwnerToConnectionMap.Add(newOwnerUri, info);
return true;
}
/// <summary>
/// Close a connection with the specified connection details.
/// </summary>

View File

@@ -30,6 +30,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Metadata.Contracts
public string Schema { get; set; }
public string Name { get; set; }
public string ParentName { get; set; }
public string ParentTypeName { get; set; }
public string Urn { get; set; }
}

View File

@@ -4,6 +4,7 @@
//
using System.Globalization;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlTools.ServiceLayer.ObjectExplorer.Nodes;
@@ -56,13 +57,13 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
{
SmoObject = smoObject;
NodeValue = smoObject.Name;
ScriptSchemaObjectBase schemaBasecObject = smoObject as ScriptSchemaObjectBase;
ScriptSchemaObjectBase schemaBaseObject = smoObject as ScriptSchemaObjectBase;
ObjectMetadata = new Metadata.Contracts.ObjectMetadata();
ObjectMetadata.Name = smoObject.Name;
try
{
if(smoObject.Urn != null)
if (smoObject.Urn != null)
{
ObjectMetadata.MetadataTypeName = smoObject.Urn.Type;
}
@@ -72,16 +73,27 @@ namespace Microsoft.SqlTools.ServiceLayer.ObjectExplorer.SmoModel
//Ignore the exception, sometimes the urn returns exception and I' not sure why
}
if (schemaBasecObject != null)
if (schemaBaseObject != null)
{
ObjectMetadata.Schema = schemaBasecObject.Schema;
ObjectMetadata.Schema = schemaBaseObject.Schema;
if (!string.IsNullOrEmpty(ObjectMetadata.Schema))
{
NodeValue = $"{ObjectMetadata.Schema}.{smoObject.Name}";
}
}
else
{
// Try to read the schema from the parent object
var parent = smoObject?.ParentCollection?.ParentInstance as ScriptSchemaObjectBase;
if (parent != null)
{
ObjectMetadata.Schema = parent.Schema;
ObjectMetadata.ParentName = parent.Name;
ObjectMetadata.ParentTypeName = parent.Urn.Type;
}
}
}
public virtual NamedSmoObject GetParentSmoObject()
{
if (SmoObject != null)

View File

@@ -0,0 +1,24 @@
//
// 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.QueryExecution.Contracts
{
/// <summary>
/// Parameters for the connection uri changed notification.
/// </summary>
public class ConnectionUriChangedParams
{
public string NewOwnerUri { get; set; }
public string OriginalOwnerUri { get; set; }
}
public class ConnectionUriChangedNotification
{
public static readonly
EventType<ConnectionUriChangedParams> Type =
EventType<ConnectionUriChangedParams>.Create("query/connectionUriChanged");
}
}

View File

@@ -385,6 +385,20 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
Batches[saveParams.BatchIndex].SaveAs(saveParams, fileFactory, successHandler, failureHandler);
}
/// <summary>
/// Changes the OwnerURI for the editor connection.
/// </summary>
public String ConnectionOwnerURI {
get
{
return this.editorConnection.OwnerUri;
}
set
{
this.editorConnection.OwnerUri = value;
}
}
#endregion
#region Private Helpers

View File

@@ -170,6 +170,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
serviceHost.SetRequestHandler(SubsetRequest.Type, HandleResultSubsetRequest);
serviceHost.SetRequestHandler(QueryDisposeRequest.Type, HandleDisposeRequest);
serviceHost.SetRequestHandler(QueryCancelRequest.Type, HandleCancelRequest);
serviceHost.SetEventHandler(ConnectionUriChangedNotification.Type, HandleConnectionUriChangedNotification);
serviceHost.SetRequestHandler(SaveResultsAsCsvRequest.Type, HandleSaveResultsAsCsvRequest);
serviceHost.SetRequestHandler(SaveResultsAsExcelRequest.Type, HandleSaveResultsAsExcelRequest);
serviceHost.SetRequestHandler(SaveResultsAsJsonRequest.Type, HandleSaveResultsAsJsonRequest);
@@ -351,6 +352,33 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
}
}
/// <summary>
/// Handles a request to change the uri associated with an active query and connection info.
/// </summary>
internal Task HandleConnectionUriChangedNotification(ConnectionUriChangedParams changeUriParams,
EventContext eventContext)
{
try {
string OriginalOwnerUri = changeUriParams.OriginalOwnerUri;
string NewOwnerUri = changeUriParams.NewOwnerUri;
// Attempt to load the query
Query query;
if(!ActiveQueries.TryRemove(OriginalOwnerUri, out query)){
throw new Exception("Uri: " + OriginalOwnerUri + " is not associated with an active query.");
}
ConnectionService.ReplaceUri(OriginalOwnerUri, NewOwnerUri);
query.ConnectionOwnerURI = NewOwnerUri;
ActiveQueries.TryAdd(NewOwnerUri, query);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Write(TraceEventType.Error, "Error encountered " + ex.ToString());
return Task.FromException(ex);
}
}
/// <summary>
/// Handles a request to get a subset of the results of this query
/// </summary>

View File

@@ -4,7 +4,6 @@
//
using System;
using System.Collections.Generic;
namespace Microsoft.SqlTools.ServiceLayer.Scripting.Contracts
{
@@ -52,13 +51,28 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting.Contracts
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets or sets the parent object name
/// </summary>
public string ParentName { get; set; }
/// <summary>
/// Gets or sets the parent object type name, such as Table, View, etc.
/// </summary>
public string ParentTypeName { get; set; }
public override string ToString()
{
string objectName = string.IsNullOrEmpty(this.Schema)
? this.Name
: this.Schema + "." + this.Name;
return objectName;
string objectName = string.Empty;
if (!string.IsNullOrEmpty(this.Schema))
{
objectName += this.Schema + ".";
}
if (!string.IsNullOrEmpty(this.ParentName))
{
objectName += this.ParentName + ".";
}
return objectName + this.Name;
}
public override int GetHashCode()
@@ -66,6 +80,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting.Contracts
return
StringComparer.OrdinalIgnoreCase.GetHashCode(this.Type ?? string.Empty) ^
StringComparer.OrdinalIgnoreCase.GetHashCode(this.Schema ?? string.Empty) ^
StringComparer.OrdinalIgnoreCase.GetHashCode(this.ParentName ?? string.Empty) ^
StringComparer.OrdinalIgnoreCase.GetHashCode(this.ParentTypeName ?? string.Empty) ^
StringComparer.OrdinalIgnoreCase.GetHashCode(this.Name ?? string.Empty);
}
@@ -87,6 +103,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting.Contracts
return
string.Equals(this.Type, other.Type, StringComparison.OrdinalIgnoreCase) &&
string.Equals(this.Schema, other.Schema, StringComparison.OrdinalIgnoreCase) &&
string.Equals(this.ParentName, other.ParentName, StringComparison.OrdinalIgnoreCase) &&
string.Equals(this.ParentTypeName, other.ParentTypeName, StringComparison.OrdinalIgnoreCase) &&
string.Equals(this.ParentTypeName, other.ParentTypeName, StringComparison.OrdinalIgnoreCase) &&
string.Equals(this.Name, other.Name, StringComparison.OrdinalIgnoreCase);
}
}

View File

@@ -7,6 +7,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.SqlScriptPublish;
@@ -100,15 +101,35 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
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[@Name='{0}']/Database[@Name='{1}']/{2}[@Name='{3}' {4}]",
server.ToUpper(),
Urn.EscapeString(database),
scriptingObject.Type,
Urn.EscapeString(scriptingObject.Name),
scriptingObject.Schema != null ? string.Format("and @Schema = '{0}'", Urn.EscapeString(scriptingObject.Schema)) : string.Empty);
StringBuilder urnBuilder = new StringBuilder();
urnBuilder.AppendFormat("Server[@Name='{0}']/", server.ToUpper());
urnBuilder.AppendFormat("Database[@Name='{0}']/", Urn.EscapeString(database));
return new Urn(urn);
bool hasParentObject = !string.IsNullOrWhiteSpace(scriptingObject.ParentName)
&& !string.IsNullOrWhiteSpace(scriptingObject.ParentTypeName);
if (hasParentObject)
{
urnBuilder.AppendFormat("{0}[@Name='{1}'", scriptingObject.ParentTypeName, Urn.EscapeString(scriptingObject.ParentName));
if (!string.IsNullOrWhiteSpace(scriptingObject.Schema))
{
urnBuilder.AppendFormat(" and @Schema = '{0}'", Urn.EscapeString(scriptingObject.Schema));
}
urnBuilder.Append("]/");
}
urnBuilder.AppendFormat("{0}[@Name='{1}'", scriptingObject.Type, Urn.EscapeString(scriptingObject.Name));
// add schema to object only if there is no parent object specified
// the parent object field is only set for objects that don't have schema themselves
// so if parent is not null then the schema filter will already be set that part of the urn above
if (!string.IsNullOrWhiteSpace(scriptingObject.Schema) && !hasParentObject)
{
urnBuilder.AppendFormat(" and @Schema = '{0}'", Urn.EscapeString(scriptingObject.Schema));
}
urnBuilder.Append("]");
return new Urn(urnBuilder.ToString());
}
/// <summary>