Fix scripting of users on SQL DB (#2014)

* Fix scripting of users on SQL DB

* Minor typos

* Add null checks
This commit is contained in:
Karl Burtram
2023-04-19 08:36:38 -07:00
committed by GitHub
parent 648d7dbd3c
commit 96c4b82ab5
3 changed files with 86 additions and 28 deletions

View File

@@ -18,7 +18,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
/// </summary>
public class ManagementActionBase : IDisposable, IExecutionAwareManagementAction
{
#region Members
#region Members
/// <summary>
/// service provider of our host. We should direct all host-specific requests to the services
@@ -31,24 +31,35 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
/// </summary>
private ExecutionMode m_executionMode = ExecutionMode.Success;
/// <summary>
/// indicates that this is a database level operation, which on SQL DB will require an alternate
/// execution manager to capture sql for scripting
/// </summary>
private bool isDatabaseOperation = false;
/// <summary>
/// Parent database object to use for database operations
/// </summary>
private Database parentDb = null;
/// <summary>
/// data container with initialization-related information
/// </summary>
private CDataContainer dataContainer;
//whether we assume complete ownership over it.
//We set this member once the dataContainer is set to be non-null
private bool ownDataContainer = true;
private bool ownDataContainer = true;
//SMO Server connection that MUST be used for all enumerator calls
//We'll get this object out of CDataContainer, that must be initialized
//property by the initialization code
private ServerConnection serverConnection;
private ServerConnection serverConnection;
private ExecutionHandlerDelegate cachedExecutionHandlerDelegate;
#endregion
#endregion
#region Constructors
#region Constructors
/// <summary>
/// Constructor
@@ -57,9 +68,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
{
}
#endregion
#endregion
#region IDisposable implementation
#region IDisposable implementation
void IDisposable.Dispose()
{
@@ -84,12 +95,12 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
}
}
#endregion
#endregion
#region IObjectWithSite implementation
#region IObjectWithSite implementation
public virtual void SetSite(IServiceProvider sp)
{
{
if (sp == null)
{
throw new ArgumentNullException("sp");
@@ -141,7 +152,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
{
// we take over execution here. We substitute the server here for SQL containers
if (this.DataContainer.ContainerServerType == CDataContainer.ServerType.SQL)
{
{
ExecuteForSql(executionInfo, out executionResult);
return false; // execution of the entire action was done here
}
@@ -176,7 +187,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
{
return true;
}
#endregion
#endregion
/// <summary>
@@ -210,7 +221,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
//ask the framework to do normal execution by calling OnRunNow methods
//of the views one by one
executionResult = ExecutionMode.Success;
return true;
return true;
}
/// <summary>
@@ -255,6 +266,26 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
}
}
protected bool IsDatabaseOperation
{
get
{
return this.isDatabaseOperation;
}
set
{
this.isDatabaseOperation = value;
}
}
protected Database ParentDb
{
get
{
return this.parentDb;
}
}
/// <summary>
/// SMO Server connection that MUST be used for all enumerator calls
/// We'll get this object out of CDataContainer, that must be initialized
@@ -385,6 +416,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
sc = sqlDialogSubject.ExecutionManager.ConnectionContext.CapturedSql.Text;
}
// for SQL DB database-level operations the script could be on the database object's execution manager
if (sc.Count == 0 && this.isDatabaseOperation && this.parentDb != null
&& this.DataContainer.Server.ServerType == DatabaseEngineType.SqlAzureDatabase)
{
sc = this.parentDb.ExecutionManager.ConnectionContext.CapturedSql.Text;
}
StringBuilder script = new StringBuilder(4096);
if (sc != null)
{
@@ -452,6 +490,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
sqlDialogSubject.ExecutionManager.ConnectionContext.SqlExecutionModes = newMode;
}
if (this.isDatabaseOperation)
{
this.parentDb = this.DataContainer.Server.GetSmoObject(this.DataContainer.ParentUrn) as Database;
if (this.parentDb != null && this.DataContainer.Server.ServerType == DatabaseEngineType.SqlAzureDatabase)
{
this.parentDb.ExecutionManager.ConnectionContext.SqlExecutionModes = newMode;
}
}
executionResult = DoPreProcessExecutionAndRunViews(executionInfo.RunType);
if (isScripting)
@@ -465,10 +512,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
finally
{
GetServerConnectionForScript().SqlExecutionModes = executionModeOriginal;
if (this.parentDb != null && this.isDatabaseOperation && this.DataContainer.Server.ServerType == DatabaseEngineType.SqlAzureDatabase)
{
this.parentDb.ExecutionManager.ConnectionContext.SqlExecutionModes = executionModeOriginal;
}
if (isScripting)
{
{
GetServerConnectionForScript().CapturedSql.Clear();
if (this.parentDb != null && this.isDatabaseOperation && this.DataContainer.Server.ServerType == DatabaseEngineType.SqlAzureDatabase)
{
this.parentDb.ExecutionManager.ConnectionContext.CapturedSql.Clear();
}
}
if (sqlDialogSubject != null)