mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-04 01:25:43 -05:00
Merge create db work in progress (#341)
* Port over initial block of create db implementation * Test case placeholder * In-progress work * Stage changes to other machine * Add database prototype strings * Stage changes to other machine * Stage changes * Hook the database info into capabilities discovery * Stage changes * Update SMO to latest from ssms_main * Various clean-ups * Update localization files
This commit is contained in:
@@ -5,10 +5,12 @@
|
||||
|
||||
using Microsoft.SqlTools.Hosting.Protocol;
|
||||
using Microsoft.SqlTools.ServiceLayer.Admin.Contracts;
|
||||
using Microsoft.SqlTools.ServiceLayer.Connection;
|
||||
using Microsoft.SqlTools.ServiceLayer.Hosting;
|
||||
using Microsoft.SqlTools.ServiceLayer.SqlContext;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
@@ -19,6 +21,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
private static readonly Lazy<AdminService> instance = new Lazy<AdminService>(() => new AdminService());
|
||||
|
||||
private static ConnectionService connectionService = null;
|
||||
|
||||
/// <summary>
|
||||
/// Default, parameterless constructor.
|
||||
/// </summary>
|
||||
@@ -26,6 +30,26 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal for testing purposes only
|
||||
/// </summary>
|
||||
internal static ConnectionService ConnectionServiceInstance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (AdminService.connectionService == null)
|
||||
{
|
||||
AdminService.connectionService = ConnectionService.Instance;
|
||||
}
|
||||
return AdminService.connectionService;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
AdminService.connectionService = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the singleton instance object
|
||||
/// </summary>
|
||||
@@ -41,6 +65,62 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
serviceHost.SetRequestHandler(CreateDatabaseRequest.Type, HandleCreateDatabaseRequest);
|
||||
serviceHost.SetRequestHandler(CreateLoginRequest.Type, HandleCreateLoginRequest);
|
||||
serviceHost.SetRequestHandler(DefaultDatabaseInfoRequest.Type, HandleDefaultDatabaseInfoRequest);
|
||||
}
|
||||
|
||||
public static async Task HandleDefaultDatabaseInfoRequest(
|
||||
DefaultDatabaseInfoParams optionsParams,
|
||||
RequestContext<DefaultDatabaseInfoResponse> requestContext)
|
||||
{
|
||||
var response = new DefaultDatabaseInfoResponse();
|
||||
|
||||
ConnectionInfo connInfo;
|
||||
AdminService.ConnectionServiceInstance.TryFindConnection(
|
||||
optionsParams.OwnerUri,
|
||||
out connInfo);
|
||||
|
||||
XmlDocument xmlDoc = CreateDataContainerDocument(connInfo);
|
||||
char[] passwordArray = connInfo.ConnectionDetails.Password.ToCharArray();
|
||||
unsafe
|
||||
{
|
||||
fixed (char* passwordPtr = passwordArray)
|
||||
{
|
||||
var dataContainer = new CDataContainer(
|
||||
CDataContainer.ServerType.SQL,
|
||||
connInfo.ConnectionDetails.ServerName,
|
||||
false,
|
||||
connInfo.ConnectionDetails.UserName,
|
||||
new System.Security.SecureString(passwordPtr, passwordArray.Length),
|
||||
xmlDoc.InnerXml);
|
||||
|
||||
var taskHelper = new DatabaseTaskHelper();
|
||||
taskHelper.CreateDatabase(dataContainer);
|
||||
|
||||
response.DefaultDatabaseInfo = DatabaseTaskHelper.DatabasePrototypeToDatabaseInfo(taskHelper.Prototype);
|
||||
}
|
||||
}
|
||||
|
||||
await requestContext.SendResult(response);
|
||||
}
|
||||
|
||||
|
||||
private static XmlDocument CreateDataContainerDocument(ConnectionInfo connInfo)
|
||||
{
|
||||
string xml =
|
||||
string.Format(@"<?xml version=""1.0""?>
|
||||
<formdescription><params>
|
||||
<servername>{0}</servername>
|
||||
<connectionmoniker>{0} (SQLServer, user = {1})</connectionmoniker>
|
||||
<servertype>sql</servertype>
|
||||
<urn>Server[@Name='{0}']</urn>
|
||||
<itemtype>Database</itemtype>
|
||||
</params></formdescription> ",
|
||||
connInfo.ConnectionDetails.ServerName.ToUpper(),
|
||||
connInfo.ConnectionDetails.UserName);
|
||||
|
||||
var xmlDoc = new XmlDocument();
|
||||
xmlDoc.LoadXml(xml);
|
||||
return xmlDoc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
//
|
||||
// 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.Contracts;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class for providing metadata about admin services
|
||||
/// </summary>
|
||||
public class AdminServicesProviderOptionsHelper
|
||||
{
|
||||
internal const string Name = "name";
|
||||
internal const string Owner = "owner";
|
||||
internal const string Collation = "collation";
|
||||
internal const string FileGroups = "fileGroups";
|
||||
internal const string DatabaseFiles = "databaseFiles";
|
||||
internal const string PhysicalName = "physicalName";
|
||||
|
||||
internal static AdminServicesProviderOptions BuildAdminServicesProviderOptions()
|
||||
{
|
||||
return new AdminServicesProviderOptions
|
||||
{
|
||||
DatabaseInfoOptions = new ServiceOption[]
|
||||
{
|
||||
new ServiceOption
|
||||
{
|
||||
Name = AdminServicesProviderOptionsHelper.Name,
|
||||
DisplayName = "Name",
|
||||
Description = "Name of the database",
|
||||
ValueType = ServiceOption.ValueTypeString,
|
||||
IsRequired = true,
|
||||
GroupName = "General"
|
||||
},
|
||||
new ServiceOption
|
||||
{
|
||||
Name = AdminServicesProviderOptionsHelper.Owner,
|
||||
DisplayName = "Owner",
|
||||
Description = "Database owner",
|
||||
ValueType = ServiceOption.ValueTypeString,
|
||||
IsRequired = true,
|
||||
GroupName = "General"
|
||||
},
|
||||
new ServiceOption
|
||||
{
|
||||
Name = AdminServicesProviderOptionsHelper.Collation,
|
||||
DisplayName = "Collation",
|
||||
Description = "Database collation",
|
||||
ValueType = ServiceOption.ValueTypeString,
|
||||
IsRequired = true,
|
||||
GroupName = "General"
|
||||
},
|
||||
new ServiceOption
|
||||
{
|
||||
Name = AdminServicesProviderOptionsHelper.FileGroups,
|
||||
DisplayName = "File Groups",
|
||||
Description = "File groups",
|
||||
ObjectType = "FileGroupInfo",
|
||||
ValueType = ServiceOption.ValueTypeObject,
|
||||
IsRequired = true,
|
||||
IsArray = true,
|
||||
GroupName = "General"
|
||||
},
|
||||
new ServiceOption
|
||||
{
|
||||
Name = AdminServicesProviderOptionsHelper.DatabaseFiles,
|
||||
DisplayName = "Database Files",
|
||||
Description = "Database Files",
|
||||
ObjectType = "DatabaseFileInfo",
|
||||
ValueType = ServiceOption.ValueTypeObject,
|
||||
IsRequired = true,
|
||||
IsArray = true,
|
||||
GroupName = "General"
|
||||
}
|
||||
},
|
||||
FileGroupInfoOptions = new ServiceOption[]
|
||||
{
|
||||
new ServiceOption
|
||||
{
|
||||
Name = AdminServicesProviderOptionsHelper.Name,
|
||||
DisplayName = "Name",
|
||||
Description = "Name of the file group",
|
||||
ValueType = ServiceOption.ValueTypeString,
|
||||
IsRequired = true,
|
||||
GroupName = "General"
|
||||
}
|
||||
},
|
||||
DatabaseFileInfoOptions = new ServiceOption[]
|
||||
{
|
||||
new ServiceOption
|
||||
{
|
||||
Name = AdminServicesProviderOptionsHelper.Name,
|
||||
DisplayName = "Name",
|
||||
Description = "Name of the database file",
|
||||
ValueType = ServiceOption.ValueTypeString,
|
||||
IsRequired = true,
|
||||
GroupName = "General"
|
||||
},
|
||||
new ServiceOption
|
||||
{
|
||||
Name = AdminServicesProviderOptionsHelper.PhysicalName,
|
||||
DisplayName = "Physical Name",
|
||||
Description = "Physical name of the database file",
|
||||
ValueType = ServiceOption.ValueTypeString,
|
||||
IsRequired = true,
|
||||
GroupName = "General"
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,466 @@
|
||||
//
|
||||
// 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.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Microsoft.SqlServer.Diagnostics.STrace;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.Win32;
|
||||
using SizeUnits = Microsoft.SqlTools.ServiceLayer.Admin.DbSize.SizeUnits;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
public static class AzureSqlDbHelper
|
||||
{
|
||||
|
||||
private static readonly TraceContext TraceContext = TraceContext.GetTraceContext("AzureSqlDbUtils", typeof(AzureSqlDbHelper).Name);
|
||||
|
||||
/// <summary>
|
||||
/// Registry key for SSMS Azure overrides
|
||||
/// </summary>
|
||||
private static readonly string SSMSAzureRegKey =
|
||||
@"HKEY_CURRENT_USER\Software\Microsoft\SQL Server Management Studio\14.0\Azure";
|
||||
|
||||
/// <summary>
|
||||
/// Registry sub key for the AzureServiceObjectives overrides
|
||||
/// </summary>
|
||||
private const string AzureServiceObjectivesRegSubKey = @"AzureServiceObjectives";
|
||||
|
||||
/// <summary>
|
||||
/// Contains the various editions available for an Azure Database
|
||||
/// </summary>
|
||||
/// ****IMPORTANT**** - If updating this enum make sure that the other logic in this class is updated as well
|
||||
public enum AzureEdition
|
||||
{
|
||||
Web = 0,
|
||||
Business = 1,
|
||||
Basic = 2,
|
||||
Standard = 3,
|
||||
Premium = 4,
|
||||
DataWarehouse = 5,
|
||||
PremiumRS = 6
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides a mapping of Azure DB Editions to their respective size options
|
||||
/// </summary>
|
||||
/// Values below are taken from http://msdn.microsoft.com/en-us/library/dn268335.aspx
|
||||
private static readonly Dictionary<AzureEdition, KeyValuePair<int, DbSize[]>> AzureEditionDatabaseSizeMappings = new Dictionary
|
||||
<AzureEdition, KeyValuePair<int, DbSize[]>>
|
||||
{
|
||||
{
|
||||
AzureEdition.Web, new KeyValuePair<int, DbSize[]>(
|
||||
1, //1GB
|
||||
new[]
|
||||
{
|
||||
new DbSize(100, SizeUnits.MB),
|
||||
new DbSize(1, SizeUnits.GB), //Default
|
||||
new DbSize(5, SizeUnits.GB)
|
||||
})
|
||||
},
|
||||
{
|
||||
AzureEdition.Business, new KeyValuePair<int, DbSize[]>(
|
||||
0, //10GB
|
||||
new[]
|
||||
{
|
||||
new DbSize(10, SizeUnits.GB), //Default
|
||||
new DbSize(20, SizeUnits.GB),
|
||||
new DbSize(30, SizeUnits.GB),
|
||||
new DbSize(40, SizeUnits.GB),
|
||||
new DbSize(50, SizeUnits.GB),
|
||||
new DbSize(100, SizeUnits.GB),
|
||||
new DbSize(150, SizeUnits.GB)
|
||||
})
|
||||
},
|
||||
{
|
||||
AzureEdition.Basic, new KeyValuePair<int, DbSize[]>(
|
||||
3, //2GB
|
||||
new[]
|
||||
{
|
||||
new DbSize(100, SizeUnits.MB),
|
||||
new DbSize(500, SizeUnits.MB),
|
||||
new DbSize(1, SizeUnits.GB),
|
||||
new DbSize(2, SizeUnits.GB) //Default
|
||||
})
|
||||
},
|
||||
{
|
||||
AzureEdition.Standard,
|
||||
new KeyValuePair<int, DbSize[]>(
|
||||
13, //250GB
|
||||
new[]
|
||||
{
|
||||
new DbSize(100, SizeUnits.MB),
|
||||
new DbSize(500, SizeUnits.MB),
|
||||
new DbSize(1, SizeUnits.GB),
|
||||
new DbSize(2, SizeUnits.GB),
|
||||
new DbSize(5, SizeUnits.GB),
|
||||
new DbSize(10, SizeUnits.GB),
|
||||
new DbSize(20, SizeUnits.GB),
|
||||
new DbSize(30, SizeUnits.GB),
|
||||
new DbSize(40, SizeUnits.GB),
|
||||
new DbSize(50, SizeUnits.GB),
|
||||
new DbSize(100, SizeUnits.GB),
|
||||
new DbSize(150, SizeUnits.GB),
|
||||
new DbSize(200, SizeUnits.GB),
|
||||
new DbSize(250, SizeUnits.GB) //Default
|
||||
})
|
||||
},
|
||||
{
|
||||
AzureEdition.Premium,
|
||||
new KeyValuePair<int, DbSize[]>(
|
||||
16, //500GB
|
||||
new[]
|
||||
{
|
||||
new DbSize(100, SizeUnits.MB),
|
||||
new DbSize(500, SizeUnits.MB),
|
||||
new DbSize(1, SizeUnits.GB),
|
||||
new DbSize(2, SizeUnits.GB),
|
||||
new DbSize(5, SizeUnits.GB),
|
||||
new DbSize(10, SizeUnits.GB),
|
||||
new DbSize(20, SizeUnits.GB),
|
||||
new DbSize(30, SizeUnits.GB),
|
||||
new DbSize(40, SizeUnits.GB),
|
||||
new DbSize(50, SizeUnits.GB),
|
||||
new DbSize(100, SizeUnits.GB),
|
||||
new DbSize(150, SizeUnits.GB),
|
||||
new DbSize(200, SizeUnits.GB),
|
||||
new DbSize(250, SizeUnits.GB),
|
||||
new DbSize(300, SizeUnits.GB),
|
||||
new DbSize(400, SizeUnits.GB),
|
||||
new DbSize(500, SizeUnits.GB), //Default
|
||||
new DbSize(1024, SizeUnits.GB) //Following portal to display this as GB instead of 1TB
|
||||
})
|
||||
},
|
||||
|
||||
{
|
||||
AzureEdition.DataWarehouse,
|
||||
new KeyValuePair<int, DbSize[]>(
|
||||
5, //10240GB
|
||||
new[]
|
||||
{
|
||||
new DbSize(250, SizeUnits.GB),
|
||||
new DbSize(500, SizeUnits.GB),
|
||||
new DbSize(750, SizeUnits.GB),
|
||||
new DbSize(1024, SizeUnits.GB),
|
||||
new DbSize(5120, SizeUnits.GB),
|
||||
new DbSize(10240, SizeUnits.GB),
|
||||
new DbSize(20480, SizeUnits.GB),
|
||||
new DbSize(30720, SizeUnits.GB),
|
||||
new DbSize(40960, SizeUnits.GB),
|
||||
new DbSize(51200, SizeUnits.GB)
|
||||
})
|
||||
},
|
||||
{
|
||||
AzureEdition.PremiumRS,
|
||||
new KeyValuePair<int, DbSize[]>(
|
||||
16, //500GB
|
||||
new[]
|
||||
{
|
||||
new DbSize(100, SizeUnits.MB),
|
||||
new DbSize(500, SizeUnits.MB),
|
||||
new DbSize(1, SizeUnits.GB),
|
||||
new DbSize(2, SizeUnits.GB),
|
||||
new DbSize(5, SizeUnits.GB),
|
||||
new DbSize(10, SizeUnits.GB),
|
||||
new DbSize(20, SizeUnits.GB),
|
||||
new DbSize(30, SizeUnits.GB),
|
||||
new DbSize(40, SizeUnits.GB),
|
||||
new DbSize(50, SizeUnits.GB),
|
||||
new DbSize(100, SizeUnits.GB),
|
||||
new DbSize(150, SizeUnits.GB),
|
||||
new DbSize(200, SizeUnits.GB),
|
||||
new DbSize(250, SizeUnits.GB),
|
||||
new DbSize(300, SizeUnits.GB),
|
||||
new DbSize(400, SizeUnits.GB),
|
||||
new DbSize(500, SizeUnits.GB), //Default
|
||||
})
|
||||
},
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Maps Azure DB Editions to their corresponding Service Objective (Performance Level) options. These values are the default but
|
||||
/// can be overridden by use of the ImportExportWizard registry key (see static initializer above).
|
||||
///
|
||||
/// The key is the index of the default value for the list
|
||||
/// </summary>
|
||||
private static readonly Dictionary<AzureEdition, KeyValuePair<int, string[]>> AzureServiceObjectiveInfo = new Dictionary
|
||||
<AzureEdition, KeyValuePair<int, string[]>>
|
||||
{
|
||||
{AzureEdition.Basic, new KeyValuePair<int, string[]>(0, new[] {"Basic"})},
|
||||
{AzureEdition.Standard, new KeyValuePair<int, string[]>(2, new[] {"S0", "S1", "S2", "S3"})},
|
||||
{AzureEdition.Premium, new KeyValuePair<int, string[]>(0, new[] {"P1", "P2", "P4", "P6", "P11", "P15"})},
|
||||
{AzureEdition.PremiumRS, new KeyValuePair<int, string[]>(0, new []{"PRS1", "PRS2", "PRS4", "PRS6"})},
|
||||
{AzureEdition.DataWarehouse, new KeyValuePair<int, string[]>(3, new[] {"DW100", "DW200", "DW300", "DW400", "DW500", "DW600", "DW1000", "DW1200", "DW1500", "DW2000", "DW3000", "DW6000"})}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Static initializer to read in the registry key values for the Service Objective mappings, which allows the user to override the defaults set for
|
||||
/// the service objective list. We allow them to do this as a temporary measure so that if we change the service objectives in the future we
|
||||
/// can tell people to use the registry key to use the new values until an updated SSMS can be released.
|
||||
/// </summary>
|
||||
static AzureSqlDbHelper()
|
||||
{
|
||||
//foreach (AzureEdition edition in Enum.GetValues(typeof (AzureEdition)))
|
||||
//{
|
||||
// object value;
|
||||
|
||||
// try
|
||||
// {
|
||||
// value = Registry.GetValue(
|
||||
// string.Format(CultureInfo.InvariantCulture, @"{0}\{1}", SSMSAzureRegKey,
|
||||
// AzureServiceObjectivesRegSubKey), edition.ToString(), null);
|
||||
// }
|
||||
// catch (Exception e)
|
||||
// {
|
||||
// //We don't really care if we can't read in an override (just fall back to default) so log and move on
|
||||
// TraceContext.TraceVerbose("Exception reading service objective overrides for {0} - {1}", edition, e.Message);
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// if (value != null)
|
||||
// {
|
||||
// TraceContext.TraceVerbose("Found ServiceObjective override for {0}, value is {1}", edition, value);
|
||||
// //Key is in format <DefaultIndex>:<ServiceObjectiveList>
|
||||
// //e.g. 2:S0,S1,S2
|
||||
// //Only split into 2 parts since the service objectives could
|
||||
// //be changed in the future to have :'s, so only treat the first
|
||||
// //as special
|
||||
// string[] values = value.ToString().Split(new[] {':'}, 2);
|
||||
// if (values.Length != 2)
|
||||
// {
|
||||
// //Badly formatted value, ignore this one
|
||||
// TraceContext.TraceVerbose("ServiceObjective override for {0} is badly formatted - skipping", edition);
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// int defaultIndex;
|
||||
// if (!int.TryParse(values[0], out defaultIndex))
|
||||
// {
|
||||
// //Invalid default index, ignore this one
|
||||
// TraceContext.TraceVerbose("ServiceObjective override for {0} has non-parseable default index - skipping", edition);
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// //Service objectives are in a comma-separated list
|
||||
// string[] serviceObjectives = values[1].Split(',');
|
||||
// if (defaultIndex < 0 || defaultIndex >= serviceObjectives.Length)
|
||||
// {
|
||||
// //Index out of bounds, ignore this one
|
||||
// TraceContext.TraceVerbose("ServiceObjective override for {0} has out of bounds default index - skipping");
|
||||
// continue;
|
||||
// }
|
||||
// if (AzureServiceObjectiveInfo.ContainsKey(edition))
|
||||
// {
|
||||
// //Overwrite our default values if the registry key for this edition exists
|
||||
// AzureServiceObjectiveInfo[edition] = new KeyValuePair<int, string[]>(defaultIndex,
|
||||
// serviceObjectives);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// AzureServiceObjectiveInfo.Add(edition,
|
||||
// new KeyValuePair<int, string[]>(defaultIndex, serviceObjectives));
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of databases sizes applicable for the specified Azure DB edition (if such
|
||||
/// a mapping exists) as well as the index of the default size for that edition.
|
||||
///
|
||||
/// Outputs an empty array with an index of -1 if no such mapping exists
|
||||
/// </summary>
|
||||
/// <param name="edition"></param>
|
||||
/// <param name="databaseSizeInfo"></param>
|
||||
/// <returns>TRUE if a mapping exists, FALSE if it does not</returns>
|
||||
public static bool TryGetDatabaseSizeInfo(AzureEdition edition, out KeyValuePair<int, DbSize[]> databaseSizeInfo)
|
||||
{
|
||||
if (AzureEditionDatabaseSizeMappings.TryGetValue(edition, out databaseSizeInfo))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
databaseSizeInfo = new KeyValuePair<int, DbSize[]>(-1, new DbSize[0]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a KeyValuePair containing a list of the ServiceObjective names mapped to a particular Azure DB Edition
|
||||
/// (if such a mapping exists) as well as the index of the default Service Objective for that edition.
|
||||
/// Outputs an empty array with a default index of -1 if no such mapping exists.
|
||||
/// </summary>
|
||||
/// <param name="edition"></param>
|
||||
/// <param name="serviceObjectiveInfo"></param>
|
||||
/// <returns>TRUE if a mapping exists, FALSE if it did not</returns>
|
||||
public static bool TryGetServiceObjectiveInfo(AzureEdition edition,
|
||||
out KeyValuePair<int, string[]> serviceObjectiveInfo)
|
||||
{
|
||||
if (AzureServiceObjectiveInfo.TryGetValue(edition, out serviceObjectiveInfo))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
serviceObjectiveInfo = new KeyValuePair<int, string[]>(-1, new string[0]);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default database size for a specified Azure Edition
|
||||
/// </summary>
|
||||
/// <param name="edition"></param>
|
||||
/// <returns>The default size, or NULL if no default exists</returns>
|
||||
public static DbSize GetDatabaseDefaultSize(AzureEdition edition)
|
||||
{
|
||||
DbSize defaultSize = null;
|
||||
|
||||
KeyValuePair<int, DbSize[]> pair;
|
||||
|
||||
if (AzureEditionDatabaseSizeMappings.TryGetValue(edition, out pair))
|
||||
{
|
||||
defaultSize = pair.Value[pair.Key];
|
||||
}
|
||||
|
||||
return defaultSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the default Service Objective name for a particular Azure DB edition
|
||||
/// </summary>
|
||||
/// <param name="edition"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetDefaultServiceObjective(AzureEdition edition)
|
||||
{
|
||||
string defaultServiceObjective = "";
|
||||
|
||||
KeyValuePair<int, string[]> pair;
|
||||
|
||||
if (AzureServiceObjectiveInfo.TryGetValue(edition, out pair))
|
||||
{
|
||||
//Bounds check since this value can be entered by users
|
||||
if (pair.Key >= 0 && pair.Key < pair.Value.Length)
|
||||
{
|
||||
defaultServiceObjective = pair.Value[pair.Key];
|
||||
}
|
||||
}
|
||||
|
||||
return defaultServiceObjective;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the localized Azure Edition display name
|
||||
/// </summary>
|
||||
/// <param name="edition"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetAzureEditionDisplayName(AzureEdition edition)
|
||||
{
|
||||
string result;
|
||||
switch (edition)
|
||||
{
|
||||
//case AzureEdition.Business:
|
||||
// result = SR.BusinessAzureEdition;
|
||||
// break;
|
||||
//case AzureEdition.Web:
|
||||
// result = SR.WebAzureEdition;
|
||||
// break;
|
||||
//case AzureEdition.Basic:
|
||||
// result = SR.BasicAzureEdition;
|
||||
// break;
|
||||
//case AzureEdition.Standard:
|
||||
// result = SR.StandardAzureEdition;
|
||||
// break;
|
||||
//case AzureEdition.Premium:
|
||||
// result = SR.PremiumAzureEdition;
|
||||
// break;
|
||||
//case AzureEdition.DataWarehouse:
|
||||
// result = SR.DataWarehouseAzureEdition;
|
||||
// break;
|
||||
//case AzureEdition.PremiumRS:
|
||||
// result = SR.PremiumRsAzureEdition;
|
||||
// break;
|
||||
default:
|
||||
result = edition.ToString();
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses a display name back into its corresponding AzureEdition.
|
||||
/// </summary>
|
||||
/// <param name="displayName"></param>
|
||||
/// <param name="edition"></param>
|
||||
/// <returns>TRUE if the conversion succeeded, FALSE if it did not. </returns>
|
||||
public static bool TryGetAzureEditionFromDisplayName(string displayName, out AzureEdition edition)
|
||||
{
|
||||
//if (string.Compare(displayName, SR.BusinessAzureEdition, CultureInfo.CurrentUICulture, CompareOptions.None) == 0)
|
||||
//{
|
||||
// edition = AzureEdition.Business;
|
||||
//}
|
||||
//else if (string.Compare(displayName, SR.WebAzureEdition, CultureInfo.CurrentUICulture, CompareOptions.None) == 0)
|
||||
//{
|
||||
// edition = AzureEdition.Web;
|
||||
//}
|
||||
//else if (string.Compare(displayName, SR.BasicAzureEdition, CultureInfo.CurrentUICulture, CompareOptions.None) == 0)
|
||||
//{
|
||||
// edition = AzureEdition.Basic;
|
||||
//}
|
||||
//else if (string.Compare(displayName, SR.StandardAzureEdition, CultureInfo.CurrentUICulture, CompareOptions.None) == 0)
|
||||
//{
|
||||
// edition = AzureEdition.Standard;
|
||||
//}
|
||||
//else if (string.Compare(displayName, SR.PremiumAzureEdition, CultureInfo.CurrentUICulture, CompareOptions.None) == 0)
|
||||
//{
|
||||
// edition = AzureEdition.Premium;
|
||||
//}
|
||||
//else if (string.Compare(displayName, SR.DataWarehouseAzureEdition, CultureInfo.CurrentUICulture, CompareOptions.None) == 0)
|
||||
//{
|
||||
// edition = AzureEdition.DataWarehouse;
|
||||
//}
|
||||
//else if (string.Compare(displayName, SR.PremiumRsAzureEdition, CultureInfo.CurrentUICulture, CompareOptions.None) == 0)
|
||||
//{
|
||||
// edition = AzureEdition.PremiumRS;
|
||||
//}
|
||||
//else
|
||||
{
|
||||
//"Default" edition is standard - but since we're returning false the user shouldn't look at this anyways
|
||||
edition = AzureEdition.Standard;
|
||||
return false;
|
||||
}
|
||||
|
||||
// return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a list of AzureEditions that are valid values for the EDITION option
|
||||
/// when creating a database.
|
||||
/// </summary>
|
||||
/// We do this so that the AzureEdition enum can have values such as NONE or DEFAULT added
|
||||
/// without requiring clients to explicitly filter out those values themselves each time.
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<AzureEdition> GetValidAzureEditionOptions(ServerVersion version)
|
||||
{
|
||||
//Azure v12 and above doesn't have the Web and Business tiers
|
||||
if (version.Major >= 12)
|
||||
{
|
||||
return new List<AzureEdition>()
|
||||
{
|
||||
AzureEdition.Basic,
|
||||
AzureEdition.Standard,
|
||||
AzureEdition.Premium,
|
||||
AzureEdition.PremiumRS,
|
||||
AzureEdition.DataWarehouse
|
||||
};
|
||||
}
|
||||
|
||||
//Default for now is to return all values since they're currently all valid
|
||||
return Enum.GetValues(typeof(AzureEdition)).Cast<AzureEdition>();
|
||||
}
|
||||
}
|
||||
}
|
||||
717
src/Microsoft.SqlTools.ServiceLayer/Admin/Common/CUtils.cs
Normal file
717
src/Microsoft.SqlTools.ServiceLayer/Admin/Common/CUtils.cs
Normal file
@@ -0,0 +1,717 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using Microsoft.SqlServer.Management.Sdk.Sfc;
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
//using System.Drawing;
|
||||
//using System.Windows.Forms;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
//using Microsoft.NetEnterpriseServers;
|
||||
//using Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using SMO = Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlServer.Management.Diagnostics;
|
||||
//using Microsoft.SqlServer.Management.SqlMgmt;
|
||||
using System.Data.SqlClient;
|
||||
// using System.Management;
|
||||
using System.Collections;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for CUtils.
|
||||
/// </summary>
|
||||
internal class CUtils
|
||||
{
|
||||
|
||||
private const int ObjectPermissionsDeniedErrorNumber = 229;
|
||||
private const int ColumnPermissionsDeniedErrorNumber = 230;
|
||||
|
||||
public CUtils()
|
||||
{
|
||||
//
|
||||
// TODO: Add constructor logic here
|
||||
//
|
||||
}
|
||||
|
||||
|
||||
//public Bitmap LoadBitmap(string szBitmapName)
|
||||
//{
|
||||
// Bitmap bmp = null;
|
||||
// Stream s = null;
|
||||
// string strQualifiedName;
|
||||
|
||||
// strQualifiedName = typeof(CUtils).Namespace + ".Images." + szBitmapName;
|
||||
|
||||
// s = typeof(CUtils).Assembly.GetManifestResourceStream(strQualifiedName);
|
||||
|
||||
// if (s != null)
|
||||
// {
|
||||
// bmp = new Bitmap(s);
|
||||
// return bmp;
|
||||
// }
|
||||
|
||||
// return null;
|
||||
//}
|
||||
|
||||
//public Icon LoadIcon(string strName)
|
||||
//{
|
||||
|
||||
// Icon ico = null;
|
||||
// Stream s = null;
|
||||
// string strQualifiedName;
|
||||
|
||||
// strQualifiedName = typeof(CUtils).Namespace + ".Images." + strName;
|
||||
|
||||
// s = typeof(CUtils).Assembly.GetManifestResourceStream(strQualifiedName);
|
||||
|
||||
// if (s != null)
|
||||
// {
|
||||
// int iconSize = DpiUtil.GetScaledImageSize();
|
||||
// ico = new Icon(s, iconSize, iconSize);
|
||||
// return ico;
|
||||
// }
|
||||
|
||||
// return null;
|
||||
//}
|
||||
|
||||
//public void LoadAddIcon(ImageList imageList, string strName)
|
||||
//{
|
||||
// Icon ico = null;
|
||||
// Stream s = null;
|
||||
// string strQualifiedName;
|
||||
|
||||
// strQualifiedName = typeof(CUtils).Namespace + ".Images." + strName;
|
||||
|
||||
// s = typeof(CUtils).Module.Assembly.GetManifestResourceStream(strQualifiedName);
|
||||
|
||||
// if (s != null)
|
||||
// {
|
||||
// try
|
||||
// {
|
||||
// ico = new Icon(s, 16, 16);
|
||||
// imageList.Images.Add(ico);
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// if (ico != null)
|
||||
// ico.Dispose();
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
public static void UseMaster(SMO.Server server)
|
||||
{
|
||||
server.ConnectionContext.ExecuteNonQuery("use master");
|
||||
}
|
||||
|
||||
|
||||
///// <summary>
|
||||
///// returns height of my border (depending on its style)
|
||||
///// </summary>
|
||||
//public static int GetBorderHeight(BorderStyle style)
|
||||
//{
|
||||
// if (style == BorderStyle.FixedSingle)
|
||||
// {
|
||||
// return SystemInformation.BorderSize.Height;
|
||||
// }
|
||||
// else if (style == BorderStyle.Fixed3D)
|
||||
// {
|
||||
// return SystemInformation.Border3DSize.Height;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return 0;
|
||||
// }
|
||||
//}
|
||||
|
||||
//public static int GetBorderWidth(BorderStyle style)
|
||||
//{
|
||||
// if (style == BorderStyle.FixedSingle)
|
||||
// {
|
||||
// return SystemInformation.BorderSize.Width;
|
||||
// }
|
||||
// else if (style == BorderStyle.Fixed3D)
|
||||
// {
|
||||
// return SystemInformation.Border3DSize.Width;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return 0;
|
||||
// }
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Get a SMO Server object that is connected to the connection
|
||||
/// </summary>
|
||||
/// <param name="ci">Conenction info</param>
|
||||
/// <returns>Smo Server object for the connection</returns>
|
||||
public static Microsoft.SqlServer.Management.Smo.Server GetSmoServer(IManagedConnection mc)
|
||||
{
|
||||
SqlOlapConnectionInfoBase ci = mc.Connection;
|
||||
if (ci == null)
|
||||
{
|
||||
throw new ArgumentNullException("ci");
|
||||
}
|
||||
|
||||
SMO.Server server = null;
|
||||
|
||||
// see what type of connection we have been passed
|
||||
SqlConnectionInfoWithConnection ciWithCon = ci as SqlConnectionInfoWithConnection;
|
||||
|
||||
if (ciWithCon != null)
|
||||
{
|
||||
server = new SMO.Server(ciWithCon.ServerConnection);
|
||||
}
|
||||
else
|
||||
{
|
||||
SqlConnectionInfo sqlCi = ci as SqlConnectionInfo;
|
||||
if (sqlCi != null)
|
||||
{
|
||||
server = new SMO.Server(new ServerConnection(sqlCi));
|
||||
}
|
||||
}
|
||||
|
||||
if (server == null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
return server;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static int GetServerVersion(SMO.Server server)
|
||||
{
|
||||
return server.Information.Version.Major;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// validates current value of given numeric control. Shows message if the value is not valid
|
||||
/// </summary>
|
||||
/// <param name="numControl"></param>
|
||||
/// <param name="errMessageToShow"></param>
|
||||
/// <returns>true if control's value is valid, false otherwise</returns>
|
||||
//public static bool ValidateNumeric(NumericUpDown numControl, string errMessageToShow, bool displayException)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// int curValue = int.Parse(numControl.Text, System.Globalization.CultureInfo.CurrentCulture);
|
||||
// if (curValue < numControl.Minimum || curValue > numControl.Maximum)
|
||||
// {
|
||||
// if (true == displayException)
|
||||
// {
|
||||
// ExceptionMessageBox box = new ExceptionMessageBox();
|
||||
|
||||
// box.Caption = SRError.SQLWorkbench;
|
||||
// box.Message = new Exception(errMessageToShow);
|
||||
// box.Symbol = ExceptionMessageBoxSymbol.Error;
|
||||
// box.Buttons = ExceptionMessageBoxButtons.OK;
|
||||
// box.Options = ExceptionMessageBoxOptions.RightAlign;
|
||||
// box.Show(null);
|
||||
// }
|
||||
|
||||
// try
|
||||
// {
|
||||
// numControl.Value = Convert.ToDecimal(numControl.Tag, System.Globalization.CultureInfo.CurrentCulture);
|
||||
// numControl.Update();
|
||||
// numControl.Text = Convert.ToString(numControl.Value, System.Globalization.CultureInfo.CurrentCulture);
|
||||
// numControl.Refresh();
|
||||
|
||||
// }
|
||||
// catch
|
||||
// {
|
||||
|
||||
// }
|
||||
// numControl.Focus();
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// return true;
|
||||
// }
|
||||
// catch
|
||||
// {
|
||||
// if (true == displayException)
|
||||
// {
|
||||
// ExceptionMessageBox box = new ExceptionMessageBox();
|
||||
|
||||
// box.Caption = SRError.SQLWorkbench;
|
||||
// box.Message = new Exception(errMessageToShow);
|
||||
// box.Symbol = ExceptionMessageBoxSymbol.Error;
|
||||
// box.Buttons = ExceptionMessageBoxButtons.OK;
|
||||
// box.Options = ExceptionMessageBoxOptions.RightAlign;
|
||||
// box.Show(null);
|
||||
// }
|
||||
|
||||
// numControl.Focus();
|
||||
// return false;
|
||||
// }
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Determines the oldest date based on the type of time units and the number of time units
|
||||
/// </summary>
|
||||
/// <param name="numUnits"></param>
|
||||
/// <param name="typeUnits"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime GetOldestDate(int numUnits, TimeUnitType typeUnits)
|
||||
{
|
||||
DateTime result = DateTime.Now;
|
||||
|
||||
switch (typeUnits)
|
||||
{
|
||||
case TimeUnitType.Week:
|
||||
{
|
||||
result = (DateTime.Now).AddDays(-1 * 7 * numUnits);
|
||||
break;
|
||||
}
|
||||
case TimeUnitType.Month:
|
||||
{
|
||||
result = (DateTime.Now).AddMonths(-1 * numUnits);
|
||||
break;
|
||||
}
|
||||
case TimeUnitType.Year:
|
||||
{
|
||||
result = (DateTime.Now).AddYears(-1 * numUnits);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
result = (DateTime.Now).AddDays(-1 * numUnits);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string TokenizeXml(string s)
|
||||
{
|
||||
if (null == s) return String.Empty;
|
||||
|
||||
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||||
foreach (char c in s)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '<':
|
||||
sb.Append("<");
|
||||
break;
|
||||
case '>':
|
||||
sb.Append(">");
|
||||
break;
|
||||
case '&':
|
||||
sb.Append("&");
|
||||
break;
|
||||
default:
|
||||
sb.Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the SqlException out of an Enumerator exception
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
/// <returns></returns>
|
||||
public static SqlException GetSqlException(Exception e)
|
||||
{
|
||||
SqlException sqlEx = null;
|
||||
Exception exception = e;
|
||||
while (exception != null)
|
||||
{
|
||||
sqlEx = exception as SqlException;
|
||||
if (null != sqlEx)
|
||||
{
|
||||
break;
|
||||
}
|
||||
exception = exception.InnerException;
|
||||
}
|
||||
return sqlEx;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// computes the name of the machine based on server's name (as returned by smoServer.Name)
|
||||
/// </summary>
|
||||
/// <param name="sqlServerName">name of server ("",".","Server","Server\Instance",etc)</param>
|
||||
/// <returns>name of the machine hosting sql server instance</returns>
|
||||
public static string GetMachineName(string sqlServerName)
|
||||
{
|
||||
System.Diagnostics.Debug.Assert(sqlServerName != null);
|
||||
|
||||
string machineName = sqlServerName;
|
||||
if (sqlServerName.Trim().Length != 0)
|
||||
{
|
||||
// [0] = machine, [1] = instance (if any)
|
||||
return sqlServerName.Split('\\')[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have default instance of default machine
|
||||
return machineName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a SqlException is Permission denied exception
|
||||
/// </summary>
|
||||
/// <param name="sqlException"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsPermissionDeniedException(SqlException sqlException)
|
||||
{
|
||||
bool isPermDenied = false;
|
||||
if (null != sqlException.Errors)
|
||||
{
|
||||
foreach (SqlError sqlError in sqlException.Errors)
|
||||
{
|
||||
int errorNumber = GetSqlErrorNumber(sqlError);
|
||||
|
||||
if ((ObjectPermissionsDeniedErrorNumber == errorNumber) ||
|
||||
(ColumnPermissionsDeniedErrorNumber == errorNumber))
|
||||
{
|
||||
isPermDenied = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return isPermDenied;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the error number of a sql exeception
|
||||
/// </summary>
|
||||
/// <param name="sqlerror"></param>
|
||||
/// <returns></returns>
|
||||
public static int GetSqlErrorNumber(SqlError sqlerror)
|
||||
{
|
||||
return sqlerror.Number;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function doubles up specified character in a string
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <param name="cEsc"></param>
|
||||
/// <returns></returns>
|
||||
public static String EscapeString(string s, char cEsc)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(s.Length * 2);
|
||||
foreach (char c in s)
|
||||
{
|
||||
sb.Append(c);
|
||||
if (cEsc == c)
|
||||
sb.Append(c);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function doubles up ']' character in a string
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
public static String EscapeStringCBracket(string s)
|
||||
{
|
||||
return CUtils.EscapeString(s, ']');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function doubles up '\'' character in a string
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
public static String EscapeStringSQuote(string s)
|
||||
{
|
||||
return CUtils.EscapeString(s, '\'');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function removes doubled up specified character from a string
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <param name="cEsc"></param>
|
||||
/// <returns></returns>
|
||||
public static String UnEscapeString(string s, char cEsc)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(s.Length);
|
||||
bool foundBefore = false;
|
||||
foreach (char c in s)
|
||||
{
|
||||
if (cEsc == c) // character to unescape
|
||||
{
|
||||
if (foundBefore) // skip second occurrence
|
||||
{
|
||||
foundBefore = false;
|
||||
}
|
||||
else // set the flag to skip next time around
|
||||
{
|
||||
sb.Append(c);
|
||||
foundBefore = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(c);
|
||||
foundBefore = false;
|
||||
}
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function removes doubled up ']' character from a string
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
public static String UnEscapeStringCBracket(string s)
|
||||
{
|
||||
return CUtils.UnEscapeString(s, ']');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function removes doubled up '\'' character from a string
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
public static String UnEscapeStringSQuote(string s)
|
||||
{
|
||||
return CUtils.UnEscapeString(s, '\'');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to convert DMTF format to DateTime from WMI property value
|
||||
/// ManagementDateTimeConverter.ToDateTime() does not adjust time to UTC offset,
|
||||
/// hence additional step to adjust datetime.
|
||||
/// </summary>
|
||||
/// <param name="dateTimeInDMTFFormat"></param>
|
||||
/// <returns></returns>
|
||||
//public static DateTime GetDateTimeFromDMTFTime(string dateTimeInDMTFFormat)
|
||||
//{
|
||||
// string[] dateTimeInfo = dateTimeInDMTFFormat.Split(new char[] { '+', '-' });
|
||||
// DateTime dateTime = ManagementDateTimeConverter.ToDateTime(dateTimeInDMTFFormat);
|
||||
|
||||
// TimeSpan timeSpan = TimeSpan.FromMinutes(Convert.ToDouble(dateTimeInfo[1]));
|
||||
// if (dateTimeInDMTFFormat.Contains("+"))
|
||||
// {
|
||||
// dateTime = dateTime - timeSpan;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// dateTime = dateTime + timeSpan;
|
||||
// }
|
||||
// return dateTime;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Helper method to sort ManagementObjectCollection based ArchiveNumber property
|
||||
/// </summary>
|
||||
/// <param name="collection"></param>
|
||||
/// <returns></returns>
|
||||
//public static ArrayList Sort(ManagementObjectCollection collection)
|
||||
//{
|
||||
|
||||
// ArrayList array = new ArrayList();
|
||||
// array.AddRange(collection);
|
||||
// ArchiveNoComparer comparer = new ArchiveNoComparer();
|
||||
// array.Sort(comparer);
|
||||
// return array;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function to execute WQL
|
||||
/// </summary>
|
||||
/// <param name="wmiNamespace"></param>
|
||||
/// <param name="wql"></param>
|
||||
/// <returns></returns>
|
||||
//public static ManagementObjectCollection ExecuteWQL(WmiSqlMgmtConnectionInfo wmiCi, string wql)
|
||||
//{
|
||||
// ObjectQuery qry = new ObjectQuery(wql);
|
||||
// ManagementScope scope = new ManagementScope(wmiCi.Namespace, wmiCi.ConnectionOptions);
|
||||
// scope.Connect();
|
||||
// ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, qry);
|
||||
// return searcher.Get();
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Get the windows login name with the domain portion in all-caps
|
||||
/// </summary>
|
||||
/// <param name="windowsLoginName">The windows login name</param>
|
||||
/// <returns>The windows login name with the domain portion in all-caps</returns>
|
||||
public static string CanonicalizeWindowsLoginName(string windowsLoginName)
|
||||
{
|
||||
string result;
|
||||
int lastBackslashIndex = windowsLoginName.LastIndexOf("\\", StringComparison.Ordinal);
|
||||
|
||||
if (-1 != lastBackslashIndex)
|
||||
{
|
||||
string domainName = windowsLoginName.Substring(0, lastBackslashIndex).ToUpperInvariant();
|
||||
string afterDomain = windowsLoginName.Substring(lastBackslashIndex);
|
||||
|
||||
result = String.Concat(domainName, afterDomain);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = windowsLoginName;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Launches object picker and gets the user selected login
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="server"></param>
|
||||
/// <param name="errorMsgToShowForTooManyLogins"></param>
|
||||
/// <returns>Returns null in case Object picker doesn't returns any loginName</returns>
|
||||
//public static string GetWindowsLoginNameFromObjectPicker(object sender,
|
||||
// Smo.Server server,
|
||||
// string errorMsgToShowForTooManyLogins)
|
||||
//{
|
||||
// string loginName = null;
|
||||
|
||||
// ObjectPickerWrapper.TargetMachine = server.Information.NetName;
|
||||
// ObjectPickerWrapper.SingleObjectSelection = true;
|
||||
|
||||
// ObjectPickerWrapper.GetUsersList(sender);
|
||||
|
||||
// int userCount = ObjectPickerWrapper.UsersList.Count;
|
||||
|
||||
// // if the user selected one NT login, set the edit control text to the selected login
|
||||
// if (1 == userCount)
|
||||
// {
|
||||
// loginName = ObjectPickerWrapper.UsersList[0].ToString();
|
||||
|
||||
// if (loginName.Length != 0)
|
||||
// {
|
||||
// loginName = CanonicalizeWindowsLoginName(loginName);
|
||||
// }
|
||||
// }
|
||||
// // if the user selected more than one login, display an error
|
||||
// else if (1 < userCount)
|
||||
// {
|
||||
// SqlManagementUserControl sm = sender as SqlManagementUserControl;
|
||||
// if (sm != null)
|
||||
// {
|
||||
// sm.DisplayExceptionMessage(new Exception(errorMsgToShowForTooManyLogins));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// throw new InvalidOperationException(errorMsgToShowForTooManyLogins);
|
||||
// }
|
||||
// }
|
||||
|
||||
// return loginName;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Determines how a feature should behave (e.g. enabled or disabled) for a SQL instance's SKU/edition.
|
||||
/// </summary>
|
||||
/// <param name="server">A SMO Server object connected to a local or remote SQL instance</param>
|
||||
/// <param name="setting">The setting to check (one of the feature constants used in settings.dat)</param>
|
||||
/// <returns>The value of the setting (e.g. SqlbootConst.SKU_YES, SqlbootConst.VALUE_UNLIMITED, etc)</returns>
|
||||
//public static uint QueryRemoteSqlProductValue(ServerConnection serverConnection, uint setting)
|
||||
//{
|
||||
// if (serverConnection == null)
|
||||
// {
|
||||
// throw new ArgumentNullException("serverConnection");
|
||||
// }
|
||||
|
||||
// // The instance could be remote, so we use GetSettingValueForSKUAbsolute because it allows us to
|
||||
// // query the client-side SQLBOOT.DLL to ask what the setting's value would be for the server's SKU.
|
||||
// // (Most other SQLBOOT APIs can only be used for locally-installed instances.)
|
||||
// // First we must retrieve the server's edition ID (SKU ID).
|
||||
// int editionId = (int)serverConnection.ExecuteScalar("SELECT SERVERPROPERTY('EditionId') AS EditionId");
|
||||
|
||||
// // Then ask SQLBOOT what the setting's value should be for that SKU.
|
||||
// uint value = Sqlboot.GetSettingValueForSKUAbsolute(setting, unchecked((uint)editionId));
|
||||
// return value;
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enum of time units types ( used in cleaning up history based on age )
|
||||
/// </summary>
|
||||
internal enum TimeUnitType
|
||||
{
|
||||
Day,
|
||||
Week,
|
||||
Month,
|
||||
Year
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// class to sort files based on archivenumber
|
||||
/// </summary>
|
||||
//internal class ArchiveNoComparer : IComparer
|
||||
//{
|
||||
// public int Compare(Object x, Object y)
|
||||
// {
|
||||
// ManagementObject lhs = x as ManagementObject;
|
||||
// ManagementObject rhs = y as ManagementObject;
|
||||
|
||||
// if (null == lhs || null == rhs)
|
||||
// {
|
||||
// throw new ArgumentException("Object is not of type ManagementObject");
|
||||
// }
|
||||
|
||||
// UInt32 l = Convert.ToUInt32(lhs.Properties["archivenumber"].Value);
|
||||
// UInt32 r = Convert.ToUInt32(rhs.Properties["archivenumber"].Value);
|
||||
|
||||
// int retVal = l.CompareTo(r);
|
||||
|
||||
// return retVal;
|
||||
// }
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Object used to populate default language in
|
||||
/// database and user dialogs.
|
||||
/// </summary>
|
||||
internal class LanguageDisplay
|
||||
{
|
||||
private SMO.Language language;
|
||||
|
||||
public string LanguageAlias
|
||||
{
|
||||
get
|
||||
{
|
||||
return language.Alias;
|
||||
}
|
||||
}
|
||||
|
||||
public SMO.Language Language
|
||||
{
|
||||
get
|
||||
{
|
||||
return language;
|
||||
}
|
||||
}
|
||||
|
||||
public LanguageDisplay(SMO.Language language)
|
||||
{
|
||||
this.language = language;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return language.Alias;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
2203
src/Microsoft.SqlTools.ServiceLayer/Admin/Common/DataContainer.cs
Normal file
2203
src/Microsoft.SqlTools.ServiceLayer/Admin/Common/DataContainer.cs
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,315 @@
|
||||
//
|
||||
// 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.ComponentModel;
|
||||
using System.Resources;
|
||||
// using Microsoft.SqlServer.Management.SqlMgmt;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlServer.Management.Sdk.Sfc;
|
||||
using Microsoft.SqlServer.Management.Diagnostics;
|
||||
|
||||
// using DisplayNameAttribute = Microsoft.SqlServer.Management.SqlMgmt.DisplayNameAttribute;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
/// <summary>
|
||||
/// Database properties for SqlServer 2008
|
||||
/// </summary>
|
||||
[TypeConverter(typeof(DynamicValueTypeConverter))]
|
||||
// [StringResourceClass(typeof(Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseOptionsSR))]
|
||||
internal class DatabasePrototype100 : DatabasePrototype90
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether vardecimal compression is enabled on the server
|
||||
/// </summary>
|
||||
[Category("Category_Misc"),
|
||||
DisplayNameAttribute("Property_VarDecimalEnabled")]
|
||||
public bool VarDecimalEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.varDecimalEnabled;
|
||||
}
|
||||
//there is no set for user database in katmai. By default it's true.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether database is encrypted or not
|
||||
/// </summary>
|
||||
[Category("Category_State"),
|
||||
DisplayNameAttribute("Property_EncryptionEnabled")]
|
||||
public bool EncryptionEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.encryptionEnabled;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.encryptionEnabled = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Honor Broker Priority
|
||||
/// </summary>
|
||||
[Category("Category_ServiceBroker"),
|
||||
DisplayNameAttribute("Property_HonorBrokerPriority")]
|
||||
public bool HonorBrokerPriority
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.honorBrokerPriority;
|
||||
}
|
||||
}
|
||||
|
||||
[Category("Category_DatabaseScopedConfigurations")]
|
||||
[DisplayNameAttribute("Property_MaxDop")]
|
||||
public int MaxDop
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.maxDop;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.maxDop = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
[Category("Category_DatabaseScopedConfigurations")]
|
||||
[DisplayNameAttribute("Property_MaxDopForSecondary")]
|
||||
public int? MaxDopForSecondary
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.maxDopForSecondary;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.maxDopForSecondary = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
[Category("Category_DatabaseScopedConfigurations"),
|
||||
DisplayNameAttribute("Property_LegacyCardinalityEstimation")]
|
||||
//TypeConverter(typeof(DatabaseScopedConfigurationOnOffTypes))]
|
||||
public string LegacyCardinalityEstimationDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetDatabaseScopedConfigDisplayText(this.currentState.legacyCardinalityEstimation);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.legacyCardinalityEstimation = SetDatabaseScopedConfigHelper(value, forSecondary: false);
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
[Category("Category_DatabaseScopedConfigurations"),
|
||||
DisplayNameAttribute("Property_LegacyCardinalityEstimationForSecondary")]
|
||||
//TypeConverter(typeof(DatabaseScopedConfigurationOnOffTypes))]
|
||||
public String LegacyCardinalityEstimationForSecondaryDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetDatabaseScopedConfigDisplayText(this.currentState.legacyCardinalityEstimationForSecondary);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.legacyCardinalityEstimationForSecondary = SetDatabaseScopedConfigHelper(value, forSecondary: true);
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
[Category("Category_DatabaseScopedConfigurations"),
|
||||
DisplayNameAttribute("Property_ParameterSniffing")]
|
||||
//TypeConverter(typeof(DatabaseScopedConfigurationOnOffTypes))]
|
||||
public string ParameterSniffingDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetDatabaseScopedConfigDisplayText(this.currentState.parameterSniffing);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.parameterSniffing = SetDatabaseScopedConfigHelper(value, forSecondary: false);
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
[Category("Category_DatabaseScopedConfigurations"),
|
||||
DisplayNameAttribute("Property_ParameterSniffingForSecondary")]
|
||||
//TypeConverter(typeof(DatabaseScopedConfigurationOnOffTypes))]
|
||||
public String ParameterSniffingForSecondaryDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetDatabaseScopedConfigDisplayText(this.currentState.parameterSniffingForSecondary);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.parameterSniffingForSecondary = SetDatabaseScopedConfigHelper(value, forSecondary: true);
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
[Category("Category_DatabaseScopedConfigurations"),
|
||||
DisplayNameAttribute("Property_QueryOptimizerHotfixes")]
|
||||
//TypeConverter(typeof(DatabaseScopedConfigurationOnOffTypes))]
|
||||
public String QueryOptimizerHotfixesDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetDatabaseScopedConfigDisplayText(this.currentState.queryOptimizerHotfixes);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.queryOptimizerHotfixes = SetDatabaseScopedConfigHelper(value, forSecondary: false);
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
[Category("Category_DatabaseScopedConfigurations"),
|
||||
DisplayNameAttribute("Property_QueryOptimizerHotfixesForSecondary")]
|
||||
//TypeConverter(typeof(DatabaseScopedConfigurationOnOffTypes))]
|
||||
public String QueryOptimizerHotfixesForSecondaryDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetDatabaseScopedConfigDisplayText(this.currentState.queryOptimizerHotfixesForSecondary);
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.queryOptimizerHotfixesForSecondary = SetDatabaseScopedConfigHelper(value, forSecondary: true);
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
public DatabasePrototype100(CDataContainer context) : base(context) { }
|
||||
|
||||
/// <summary>
|
||||
/// Commit changes to the database
|
||||
/// </summary>
|
||||
/// <param name="db">The database whose properties we are changing</param>
|
||||
protected override void SaveProperties(Database db)
|
||||
{
|
||||
base.SaveProperties(db);
|
||||
if (!this.Exists || this.originalState.encryptionEnabled != this.currentState.encryptionEnabled)
|
||||
{
|
||||
db.EncryptionEnabled = this.currentState.encryptionEnabled;
|
||||
}
|
||||
|
||||
// Check if we support database scoped configurations in this database. Since these were all added at the same time,
|
||||
// only check if MaxDop is supported rather than each individual property.
|
||||
if (db.IsSupportedProperty("MaxDop"))
|
||||
{
|
||||
if (!this.Exists || (db.MaxDop != this.MaxDop))
|
||||
{
|
||||
db.MaxDop = this.MaxDop;
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.MaxDopForSecondary != this.MaxDopForSecondary))
|
||||
{
|
||||
db.MaxDopForSecondary = this.MaxDopForSecondary;
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.LegacyCardinalityEstimation != this.currentState.legacyCardinalityEstimation))
|
||||
{
|
||||
db.LegacyCardinalityEstimation = this.currentState.legacyCardinalityEstimation;
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.LegacyCardinalityEstimationForSecondary != this.currentState.legacyCardinalityEstimationForSecondary))
|
||||
{
|
||||
db.LegacyCardinalityEstimationForSecondary = this.currentState.legacyCardinalityEstimationForSecondary;
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.ParameterSniffing != this.currentState.parameterSniffing))
|
||||
{
|
||||
db.ParameterSniffing = this.currentState.parameterSniffing;
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.ParameterSniffingForSecondary != this.currentState.parameterSniffingForSecondary))
|
||||
{
|
||||
db.ParameterSniffingForSecondary = this.currentState.parameterSniffingForSecondary;
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.QueryOptimizerHotfixes != this.currentState.queryOptimizerHotfixes))
|
||||
{
|
||||
db.QueryOptimizerHotfixes = this.currentState.queryOptimizerHotfixes;
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.QueryOptimizerHotfixesForSecondary != this.currentState.queryOptimizerHotfixesForSecondary))
|
||||
{
|
||||
db.QueryOptimizerHotfixesForSecondary = this.currentState.queryOptimizerHotfixesForSecondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Helper Methods
|
||||
|
||||
/// <summary>
|
||||
/// Gets the display text for a database scoped configuration setting.
|
||||
/// </summary>
|
||||
/// <param name="onOffValue">The database scoped configuration setting value.</param>
|
||||
/// <returns>A string from the resource manager representing the value.</returns>
|
||||
private string GetDatabaseScopedConfigDisplayText(DatabaseScopedConfigurationOnOff onOffValue)
|
||||
{
|
||||
ResourceManager manager = new ResourceManager("Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseStrings", typeof(DatabasePrototype).GetAssembly());
|
||||
string result = null;
|
||||
|
||||
switch (onOffValue)
|
||||
{
|
||||
case DatabaseScopedConfigurationOnOff.Off:
|
||||
result = manager.GetString("prototype.db.prop.databasescopedconfig.value.off");
|
||||
break;
|
||||
|
||||
case DatabaseScopedConfigurationOnOff.On:
|
||||
result = manager.GetString("prototype.db.prop.databasescopedconfig.value.on");
|
||||
break;
|
||||
|
||||
case DatabaseScopedConfigurationOnOff.Primary:
|
||||
result = manager.GetString("prototype.db.prop.databasescopedconfig.value.primary");
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Translates a string to a database scoped configuration enum value for the set method.
|
||||
/// </summary>
|
||||
/// <param name="displayText">The display text.</param>
|
||||
/// <param name="forSecondary">Whether this is for a secondary in which case "PRIMARY" is allowable.</param>
|
||||
/// <returns>The database scoped configuration enum value that matches the display text.</returns>
|
||||
private DatabaseScopedConfigurationOnOff SetDatabaseScopedConfigHelper(string displayText, bool forSecondary)
|
||||
{
|
||||
ResourceManager manager = new ResourceManager("Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseStrings", typeof(DatabasePrototype).GetAssembly());
|
||||
|
||||
if (displayText == manager.GetString("prototype.db.prop.databasescopedconfig.value.off"))
|
||||
{
|
||||
return DatabaseScopedConfigurationOnOff.Off;
|
||||
}
|
||||
else if (displayText == manager.GetString("prototype.db.prop.databasescopedconfig.value.on") || !forSecondary)
|
||||
{
|
||||
return DatabaseScopedConfigurationOnOff.On;
|
||||
}
|
||||
else
|
||||
{
|
||||
return DatabaseScopedConfigurationOnOff.Primary;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System.ComponentModel;
|
||||
// using System.Drawing.Design;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
// using Microsoft.SqlServer.Management.SqlMgmt;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlServer.Management.Sdk.Sfc;
|
||||
|
||||
// using DisplayNameAttribute = Microsoft.SqlServer.Management.SqlMgmt.DisplayNameAttribute;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
/// <summary>
|
||||
/// Database properties for SqlServer 2011
|
||||
/// </summary>
|
||||
[TypeConverter(typeof(DynamicValueTypeConverter))]
|
||||
// [StringResourceClass(typeof(Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseOptionsSR))]
|
||||
internal class DatabasePrototype110 : DatabasePrototype100 //, ILanguageLcidWithConnectionInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Database compatibility level
|
||||
/// </summary>
|
||||
[Browsable(false)]
|
||||
public ContainmentType DatabaseContainmentType
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.databaseContainmentType;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.databaseContainmentType = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
[Category("Category_ContainedDatabases"),
|
||||
DisplayNameAttribute("Property_DefaultFullTextLanguageLcid")]
|
||||
public int DefaultFullTextLanguageLcid
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.defaultFulltextLanguageLcid;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.defaultFulltextLanguageLcid = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
//[
|
||||
//// Editor(typeof(DefaultLanguageEditor), typeof(UITypeEditor)),
|
||||
//Category("Category_ContainedDatabases"),
|
||||
//DisplayNameAttribute("Property_DefaultLanguage")
|
||||
//]
|
||||
//public LanguageChoice DefaultLanguage
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// return LanguageUtils.GetLanguageChoiceAlias(this.context.Server,
|
||||
// this.currentState.defaultLanguageLcid);
|
||||
// }
|
||||
// set
|
||||
// {
|
||||
// this.currentState.defaultLanguageLcid = value.lcid;
|
||||
// this.NotifyObservers();
|
||||
// }
|
||||
//}
|
||||
|
||||
[Category("Category_ContainedDatabases"),
|
||||
DisplayNameAttribute("Property_NestedTriggersEnabled")]
|
||||
public bool NestedTriggersEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.nestedTriggersEnabled;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.nestedTriggersEnabled = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
[Category("Category_ContainedDatabases"),
|
||||
DisplayNameAttribute("Property_TransformNoiseWords")]
|
||||
public bool TransformNoiseWords
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.transformNoiseWords;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.transformNoiseWords = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
[Category("Category_ContainedDatabases"),
|
||||
DisplayNameAttribute("Property_TwoDigitYearCutoff")]
|
||||
public int TwoDigitYearCutoff
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.twoDigitYearCutoff;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.twoDigitYearCutoff = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
[Category("Category_Recovery"),
|
||||
DisplayNameAttribute("Property_TargetRecoveryTime")]
|
||||
public int TargetRecoveryTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.targetRecoveryTime;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.targetRecoveryTime = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
[Category("Category_Misc"),
|
||||
DisplayNameAttribute("Property_DelayedDurability")]
|
||||
public DelayedDurability DelayedDurability
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.delayedDurability;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.delayedDurability = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
public DatabasePrototype110(CDataContainer context)
|
||||
: base(context)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Commit changes to the database
|
||||
/// </summary>
|
||||
/// <param name="db">The database whose properties we are changing</param>
|
||||
protected override void SaveProperties(Database db)
|
||||
{
|
||||
base.SaveProperties(db);
|
||||
|
||||
if (db.IsSupportedProperty("ContainmentType"))
|
||||
{
|
||||
if (!this.Exists || (db.ContainmentType != this.DatabaseContainmentType))
|
||||
{
|
||||
db.ContainmentType = this.DatabaseContainmentType;
|
||||
}
|
||||
|
||||
if (this.DatabaseContainmentType != ContainmentType.None)
|
||||
{
|
||||
if (!this.Exists || (db.DefaultFullTextLanguage.Lcid != this.DefaultFullTextLanguageLcid))
|
||||
{
|
||||
db.DefaultFullTextLanguage.Lcid = this.DefaultFullTextLanguageLcid;
|
||||
}
|
||||
|
||||
//if (!this.Exists || (db.DefaultLanguage.Lcid != this.DefaultLanguage.lcid))
|
||||
//{
|
||||
// db.DefaultLanguage.Lcid = this.DefaultLanguage.lcid;
|
||||
//}
|
||||
|
||||
if (!this.Exists || (db.NestedTriggersEnabled != this.NestedTriggersEnabled))
|
||||
{
|
||||
db.NestedTriggersEnabled = this.NestedTriggersEnabled;
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.TransformNoiseWords != this.TransformNoiseWords))
|
||||
{
|
||||
db.TransformNoiseWords = this.TransformNoiseWords;
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.TwoDigitYearCutoff != this.TwoDigitYearCutoff))
|
||||
{
|
||||
db.TwoDigitYearCutoff = this.TwoDigitYearCutoff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (db.IsSupportedProperty("TargetRecoveryTime"))
|
||||
{
|
||||
if (!this.Exists || (db.TargetRecoveryTime != this.TargetRecoveryTime))
|
||||
{
|
||||
db.TargetRecoveryTime = this.TargetRecoveryTime;
|
||||
}
|
||||
}
|
||||
|
||||
if (db.IsSupportedProperty("DelayedDurability"))
|
||||
{
|
||||
if (!this.Exists || (db.DelayedDurability != this.DelayedDurability))
|
||||
{
|
||||
db.DelayedDurability = this.DelayedDurability;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region ILanguageLcidWithConnectionInfo Members
|
||||
|
||||
//int ILanguageLcidWithConnectionInfo.Lcid
|
||||
//{
|
||||
// get { return this.DefaultLanguage.lcid; }
|
||||
//}
|
||||
|
||||
//ServerConnection ILanguageLcidWithConnectionInfo.Connection
|
||||
//{
|
||||
// get { return this.context.ServerConnection; }
|
||||
//}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,285 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Resources;
|
||||
//using Microsoft.SqlServer.Management.SqlMgmt;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlServer.Management.Sdk.Sfc;
|
||||
using Microsoft.SqlServer.Management.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
|
||||
//using DisplayNameAttribute = Microsoft.SqlServer.Management.SqlMgmt.DisplayNameAttribute;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
/// <summary>
|
||||
/// Database Prototype for SqlServer 2000 and later servers
|
||||
/// </summary>
|
||||
//[TypeConverter(typeof(DynamicValueTypeConverter))]
|
||||
//[StringResourceClass(typeof(Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseOptionsSR))]
|
||||
internal class DatabasePrototype80 : DatabasePrototype, IDynamicValues
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether the database is read-only
|
||||
/// </summary>
|
||||
[
|
||||
Category("Category_State"),
|
||||
DisplayNameAttribute("Property_ReadOnly")
|
||||
]
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.isReadOnly;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.isReadOnly = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether torn page detection is enabled
|
||||
/// </summary>
|
||||
[Category("Category_Recovery"),
|
||||
DisplayNameAttribute("Property_PageVerify"),
|
||||
TypeConverter(typeof(PageVerifyTypes80))]
|
||||
public virtual string PageVerifyDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
ResourceManager manager = new ResourceManager("Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseStrings", typeof(DatabasePrototype80).GetAssembly());
|
||||
string result = null;
|
||||
|
||||
switch (this.currentState.pageVerify)
|
||||
{
|
||||
case PageVerify.Checksum:
|
||||
|
||||
result = manager.GetString("prototype.db.prop.pageVerify.value.checksum");
|
||||
break;
|
||||
|
||||
case PageVerify.None:
|
||||
|
||||
result = manager.GetString("prototype.db.prop.pageVerify.value.none");
|
||||
break;
|
||||
|
||||
case PageVerify.TornPageDetection:
|
||||
|
||||
result = manager.GetString("prototype.db.prop.pageVerify.value.tornPageDetection");
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
ResourceManager manager = new ResourceManager("Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseStrings", typeof(DatabasePrototype80).GetAssembly());
|
||||
if (value == manager.GetString("prototype.db.prop.pageVerify.value.checksum"))
|
||||
{
|
||||
this.currentState.pageVerify = PageVerify.Checksum;
|
||||
}
|
||||
else if (value == manager.GetString("prototype.db.prop.pageVerify.value.none"))
|
||||
{
|
||||
this.currentState.pageVerify = PageVerify.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.currentState.pageVerify = PageVerify.TornPageDetection;
|
||||
}
|
||||
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ANSI Padding enabled
|
||||
/// </summary>
|
||||
[Category("Category_Misc"),
|
||||
DisplayNameAttribute("Property_ANSIPadding")]
|
||||
public bool AnsiPadding
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.ansiPadding;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.ansiPadding = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use ANSI warnings
|
||||
/// </summary>
|
||||
[Category("Category_Misc"),
|
||||
DisplayNameAttribute("Property_ANSIWarnings")]
|
||||
public bool AnsiWarnings
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.ansiWarnings;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.ansiWarnings = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arithabort
|
||||
/// </summary>
|
||||
[Category("Category_Misc"),
|
||||
DisplayNameAttribute("Property_ArithAbort")]
|
||||
public bool Arithabort
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.arithabort;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.arithabort = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether contatenating a null string yields a null result
|
||||
/// </summary>
|
||||
[Category("Category_Misc"),
|
||||
DisplayNameAttribute("Property_ConcatNullYieldsNull")]
|
||||
public bool ConcatNullYieldsNull
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.concatNullYieldsNull;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.concatNullYieldsNull = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Numeric Roundabout
|
||||
/// </summary>
|
||||
[Category("Category_Misc"),
|
||||
DisplayNameAttribute("Property_NumericRoundAbort")]
|
||||
public bool NumericRoundAbort
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.numericRoundAbort;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.numericRoundAbort = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public DatabasePrototype80(CDataContainer context) : base(context) { }
|
||||
|
||||
/// <summary>
|
||||
/// Commit property changes to the database
|
||||
/// </summary>
|
||||
/// <param name="db">The database whose properties we are changing</param>
|
||||
protected override void SaveProperties(Database db)
|
||||
{
|
||||
base.SaveProperties(db);
|
||||
|
||||
ResourceManager manager = new ResourceManager("Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseStrings", typeof(DatabasePrototype).GetAssembly());
|
||||
|
||||
// never set the real database collation to "<server default>" - there is no
|
||||
// real collation with that name. "<server default>" is only valid for new
|
||||
// databases and just means "don't set the collation".
|
||||
if ((!this.Exists || (this.Exists && (db.Collation != this.Collation))) &&
|
||||
(this.originalState.defaultCollation != this.Collation))
|
||||
{
|
||||
db.Collation = this.Collation;
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.DatabaseOptions.AnsiPaddingEnabled != this.AnsiPadding))
|
||||
{
|
||||
db.DatabaseOptions.AnsiPaddingEnabled = this.AnsiPadding;
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.DatabaseOptions.AnsiWarningsEnabled != this.AnsiWarnings))
|
||||
{
|
||||
db.DatabaseOptions.AnsiWarningsEnabled = this.AnsiWarnings;
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.DatabaseOptions.ArithmeticAbortEnabled != this.Arithabort))
|
||||
{
|
||||
db.DatabaseOptions.ArithmeticAbortEnabled = this.Arithabort;
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.DatabaseOptions.ConcatenateNullYieldsNull != this.ConcatNullYieldsNull))
|
||||
{
|
||||
db.DatabaseOptions.ConcatenateNullYieldsNull = this.ConcatNullYieldsNull;
|
||||
}
|
||||
|
||||
if (db.IsSupportedProperty("PageVerify"))
|
||||
{
|
||||
if (!this.Exists || (db.DatabaseOptions.PageVerify != this.currentState.pageVerify))
|
||||
{
|
||||
db.DatabaseOptions.PageVerify = this.currentState.pageVerify;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.DatabaseOptions.NumericRoundAbortEnabled != this.NumericRoundAbort))
|
||||
{
|
||||
db.DatabaseOptions.NumericRoundAbortEnabled = this.NumericRoundAbort;
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.DatabaseOptions.ReadOnly != this.IsReadOnly))
|
||||
{
|
||||
db.DatabaseOptions.ReadOnly = this.IsReadOnly;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#region IDynamicValues Members
|
||||
|
||||
public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
|
||||
{
|
||||
TypeConverter.StandardValuesCollection result = null;
|
||||
|
||||
if (context.PropertyDescriptor.Name == "PageVerifyDisplay")
|
||||
{
|
||||
ResourceManager manager = new ResourceManager("Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseStrings", typeof(DatabasePrototype80).GetAssembly());
|
||||
List<string> standardValues = new List<string>();
|
||||
|
||||
if (this.IsYukonOrLater)
|
||||
{
|
||||
standardValues.Add(manager.GetString("prototype.db.prop.pageVerify.value.checksum"));
|
||||
}
|
||||
|
||||
standardValues.Add(manager.GetString("prototype.db.prop.pageVerify.value.tornPageDetection"));
|
||||
standardValues.Add(manager.GetString("prototype.db.prop.pageVerify.value.none"));
|
||||
|
||||
result = new TypeConverter.StandardValuesCollection(standardValues);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = base.GetStandardValues(context);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System.ComponentModel;
|
||||
// using Microsoft.SqlServer.Management.SqlMgmt;
|
||||
using Microsoft.SqlServer.Management.Sdk.Sfc;
|
||||
|
||||
// using DisplayNameAttribute = Microsoft.SqlServer.Management.SqlMgmt.DisplayNameAttribute;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
/// <summary>
|
||||
/// Database Prototype for SqlServer 2000 SP3 and later servers
|
||||
/// </summary>
|
||||
[TypeConverter(typeof(DynamicValueTypeConverter))]
|
||||
//[StringResourceClass(typeof(Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseOptionsSR))]
|
||||
internal class DatabasePrototype80SP3 : DatabasePrototype80
|
||||
{
|
||||
/// <summary>
|
||||
/// ANSI Padding enabled
|
||||
/// </summary>
|
||||
[Category("Category_Misc"),
|
||||
DisplayNameAttribute("Property_DBChaining")]
|
||||
public bool DbChaining
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.dbChaining;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public DatabasePrototype80SP3(CDataContainer context) : base(context) { }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Resources;
|
||||
// using Microsoft.SqlServer.Management.SqlMgmt;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlServer.Management.Sdk.Sfc;
|
||||
using Microsoft.SqlServer.Management.Diagnostics;
|
||||
using System.Collections.Generic;
|
||||
|
||||
// using DisplayNameAttribute = Microsoft.SqlServer.Management.SqlMgmt.DisplayNameAttribute;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
/// <summary>
|
||||
/// Database Prototype for SqlServer 2005 and later servers
|
||||
/// </summary>
|
||||
//[TypeConverter(typeof(DynamicValueTypeConverter))]
|
||||
//[StringResourceClass(typeof(Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseOptionsSR))]
|
||||
internal class DatabasePrototype90 : DatabasePrototype80SP3, IDynamicValues
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether torn page detection is enabled
|
||||
/// </summary>
|
||||
[Category("Category_Automatic"),
|
||||
DisplayNameAttribute("Property_AutoUpdateStateAsync")]
|
||||
public bool AutoUpdateStatisticsAsync
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.autoUpdateStatisticsAsync;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.autoUpdateStatisticsAsync = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether torn page detection is enabled
|
||||
/// </summary>
|
||||
[Category("Category_Recovery"),
|
||||
DisplayNameAttribute("Property_PageVerify"),
|
||||
TypeConverter(typeof(PageVerifyTypes90))]
|
||||
public override string PageVerifyDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
ResourceManager manager = new ResourceManager("Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseStrings", typeof(DatabasePrototype80).GetAssembly());
|
||||
string result = null;
|
||||
|
||||
switch (this.currentState.pageVerify)
|
||||
{
|
||||
case PageVerify.Checksum:
|
||||
|
||||
result = manager.GetString("prototype.db.prop.pageVerify.value.checksum");
|
||||
break;
|
||||
|
||||
case PageVerify.None:
|
||||
|
||||
result = manager.GetString("prototype.db.prop.pageVerify.value.none");
|
||||
break;
|
||||
|
||||
case PageVerify.TornPageDetection:
|
||||
|
||||
result = manager.GetString("prototype.db.prop.pageVerify.value.tornPageDetection");
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
ResourceManager manager = new ResourceManager("Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseStrings", typeof(DatabasePrototype80).GetAssembly());
|
||||
if (value == manager.GetString("prototype.db.prop.pageVerify.value.checksum"))
|
||||
{
|
||||
this.currentState.pageVerify = PageVerify.Checksum;
|
||||
}
|
||||
else if (value == manager.GetString("prototype.db.prop.pageVerify.value.none"))
|
||||
{
|
||||
this.currentState.pageVerify = PageVerify.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.currentState.pageVerify = PageVerify.TornPageDetection;
|
||||
}
|
||||
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Use ANSI warnings
|
||||
/// </summary>
|
||||
[Category("Category_Misc"),
|
||||
DisplayNameAttribute("Property_Trustworthy")]
|
||||
public bool Trustworthy
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.trustworthy;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Arithabort
|
||||
/// </summary>
|
||||
[Category("Category_Misc"),
|
||||
DisplayNameAttribute("Property_DateCorrelationOptimization")]
|
||||
public bool DateCorrelationOptimization
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.dateCorrelationOptimization;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.dateCorrelationOptimization = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AllowSnapshotIsolation
|
||||
/// </summary>
|
||||
[Category("Category_Misc"),
|
||||
DisplayNameAttribute("Property_AllowSnapshotIsolation")]
|
||||
public bool AllowSnapshotIsolation
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.allowSnapshotIsolation;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.allowSnapshotIsolation = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// IsReadCommittedSnapshotOn
|
||||
/// </summary>
|
||||
[Category("Category_Misc"),
|
||||
DisplayNameAttribute("Property_IsReadCommittedSnapshotOn")]
|
||||
public bool IsReadCommittedSnapshotOn
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.isReadCommittedSnapshotOn;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.isReadCommittedSnapshotOn = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// BrokerEnabled
|
||||
/// </summary>
|
||||
[Category("Category_ServiceBroker"),
|
||||
DisplayNameAttribute("Property_BrokerEnabled")]
|
||||
public bool BrokerEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.brokerEnabled;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.brokerEnabled = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether contatenating a null string yields a null result
|
||||
/// </summary>
|
||||
[Category("Category_Misc"),
|
||||
DisplayNameAttribute("Property_Parameterization")]
|
||||
[TypeConverter(typeof(ParameterizationTypes))]
|
||||
public string Parameterization
|
||||
{
|
||||
get
|
||||
{
|
||||
ResourceManager manager = new ResourceManager("Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseStrings", typeof(DatabasePrototype90).GetAssembly());
|
||||
string result = this.currentState.parameterization ?
|
||||
manager.GetString("prototype.db.prop.parameterization.value.forced") :
|
||||
manager.GetString("prototype.db.prop.parameterization.value.simple");
|
||||
|
||||
return result;
|
||||
}
|
||||
set
|
||||
{
|
||||
ResourceManager manager = new ResourceManager("Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseStrings", typeof(DatabasePrototype90).GetAssembly());
|
||||
this.currentState.parameterization = (value == manager.GetString("prototype.db.prop.parameterization.value.forced"));
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Service Broker Guid
|
||||
/// </summary>
|
||||
[Category("Category_ServiceBroker"),
|
||||
DisplayNameAttribute("Property_ServiceBrokerGUID")]
|
||||
public System.Guid ServiceBrokerGuid
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.serviceBrokerGuid;
|
||||
}
|
||||
}
|
||||
|
||||
public DatabasePrototype90(CDataContainer context) : base(context) { }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Commit property changes to the database
|
||||
/// </summary>
|
||||
/// <param name="db">The database whose properties we are changing</param>
|
||||
protected override void SaveProperties(Database db)
|
||||
{
|
||||
base.SaveProperties(db);
|
||||
|
||||
if (!this.Exists || (db.DatabaseOptions.AutoUpdateStatisticsAsync != this.AutoUpdateStatisticsAsync))
|
||||
{
|
||||
db.DatabaseOptions.AutoUpdateStatisticsAsync = this.AutoUpdateStatisticsAsync;
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.DatabaseOptions.DateCorrelationOptimization != this.DateCorrelationOptimization))
|
||||
{
|
||||
db.DatabaseOptions.DateCorrelationOptimization = this.DateCorrelationOptimization;
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.DatabaseOptions.IsParameterizationForced != this.currentState.parameterization))
|
||||
{
|
||||
db.DatabaseOptions.IsParameterizationForced = this.currentState.parameterization;
|
||||
}
|
||||
if (db.IsSupportedProperty("BrokerEnabled"))
|
||||
{
|
||||
if (!this.Exists || (db.DatabaseOptions.BrokerEnabled != this.currentState.brokerEnabled))
|
||||
{
|
||||
db.DatabaseOptions.BrokerEnabled = this.currentState.brokerEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.Exists || (db.IsReadCommittedSnapshotOn != this.IsReadCommittedSnapshotOn))
|
||||
{
|
||||
db.IsReadCommittedSnapshotOn = this.IsReadCommittedSnapshotOn;
|
||||
}
|
||||
}
|
||||
|
||||
#region IDynamicValues Members
|
||||
|
||||
public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
|
||||
{
|
||||
TypeConverter.StandardValuesCollection result = null;
|
||||
|
||||
if (context.PropertyDescriptor.Name == "Parameterization")
|
||||
{
|
||||
ResourceManager manager = new ResourceManager("Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseStrings", typeof(DatabasePrototype90).GetAssembly());
|
||||
List<string> standardValues = new List<string>();
|
||||
standardValues.Add(manager.GetString("prototype.db.prop.parameterization.value.forced"));
|
||||
standardValues.Add(manager.GetString("prototype.db.prop.parameterization.value.simple"));
|
||||
result = new TypeConverter.StandardValuesCollection(standardValues);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = base.GetStandardValues(context);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System.ComponentModel;
|
||||
// using Microsoft.SqlServer.Management.SqlMgmt;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlServer.Management.Sdk.Sfc;
|
||||
|
||||
// using DisplayNameAttribute = Microsoft.SqlServer.Management.SqlMgmt.DisplayNameAttribute;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
/// <summary>
|
||||
/// Database Prototype for SqlServer 2005 Enterprise SP2 and later servers
|
||||
/// </summary>
|
||||
[TypeConverter(typeof(DynamicValueTypeConverter))]
|
||||
//[StringResourceClass(typeof(Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseOptionsSR))]
|
||||
internal class DatabasePrototype90EnterpriseSP2 : DatabasePrototype90
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether vardecimal compression is enabled on the server
|
||||
/// </summary>
|
||||
[Category("Category_Misc"),
|
||||
DisplayNameAttribute("Property_VarDecimalEnabled")]
|
||||
public bool VarDecimalEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.varDecimalEnabled;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
this.currentState.varDecimalEnabled = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
public DatabasePrototype90EnterpriseSP2(CDataContainer context) : base(context) { }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Commit property changes to the database
|
||||
/// </summary>
|
||||
/// <param name="db">The database whose properties we are changing</param>
|
||||
protected override void SaveProperties(Database db)
|
||||
{
|
||||
base.SaveProperties(db);
|
||||
|
||||
// changing decimal compression status is very expensive, so
|
||||
// only set a value for vardecimal compression if its value has changed
|
||||
if (this.originalState.varDecimalEnabled != this.currentState.varDecimalEnabled)
|
||||
{
|
||||
db.IsVarDecimalStorageFormatEnabled = this.currentState.varDecimalEnabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,393 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Text;
|
||||
//using System.Windows.Forms;
|
||||
//using Microsoft.SqlServer.Management.AzureSqlDbUtils;
|
||||
//using Microsoft.SqlServer.Management.SqlMgmt;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlServer.Management.Sdk.Sfc;
|
||||
using Microsoft.SqlServer.Management.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Data.SqlClient;
|
||||
|
||||
//using DisplayNameAttribute = Microsoft.SqlServer.Management.SqlMgmt.DisplayNameAttribute;
|
||||
using AzureEdition = Microsoft.SqlTools.ServiceLayer.Admin.AzureSqlDbHelper.AzureEdition;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
/// <summary>
|
||||
/// Database properties for SQL Azure DB.
|
||||
/// Business/Web editions are up to compat level 100 now
|
||||
/// </summary>
|
||||
[TypeConverter(typeof(DynamicValueTypeConverter))]
|
||||
//[StringResourceClass(typeof(Microsoft.SqlServer.Management.SqlManagerUI.CreateDatabaseOptionsSR))]
|
||||
internal class DatabasePrototypeAzure : DatabasePrototype100
|
||||
{
|
||||
|
||||
#region Constants
|
||||
|
||||
public const string Category_Azure = "Category_Azure";
|
||||
public const string Property_AzureMaxSize = "Property_AzureMaxSize";
|
||||
public const string Property_AzureCurrentServiceLevelObjective = "Property_AzureCurrentServiceLevelObjective";
|
||||
public const string Property_AzureConfiguredServiceLevelObjective = "Property_AzureConfiguredServiceLevelObjective";
|
||||
public const string Property_AzureEdition = "Property_AzureEdition";
|
||||
#endregion Constants
|
||||
|
||||
public DatabasePrototypeAzure(CDataContainer context, DatabaseEngineEdition editionToCreate = DatabaseEngineEdition.SqlDatabase)
|
||||
: base(context)
|
||||
{
|
||||
EditionToCreate = editionToCreate;
|
||||
}
|
||||
|
||||
#region Properties
|
||||
|
||||
//private DesignableObject wrapper;
|
||||
|
||||
//[Browsable(false)]
|
||||
//public DesignableObject Wrapper
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// return wrapper;
|
||||
// }
|
||||
// set
|
||||
// {
|
||||
// this.wrapper = value;
|
||||
// //Now that we have a new wrapper make sure to update the dynamic visibility for the SLO options
|
||||
// SetServiceLevelObjectiveOptionVisibility();
|
||||
|
||||
// }
|
||||
//}
|
||||
|
||||
[Category(Category_Azure),
|
||||
DisplayNameAttribute(Property_AzureMaxSize)]
|
||||
//TypeConverter(typeof(DynamicValuesConverter))]
|
||||
public string MaxSize
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.maxSize == null ? null : this.currentState.maxSize.ToString();
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.maxSize = DbSize.ParseDbSize(value);
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
[Category(Category_Azure),
|
||||
DisplayNameAttribute(Property_AzureCurrentServiceLevelObjective)]
|
||||
//TypeConverter(typeof(DynamicValuesConverter))]
|
||||
public string CurrentServiceLevelObjective
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.currentServiceLevelObjective;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.currentState.currentServiceLevelObjective = value;
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
|
||||
[Category(Category_Azure),
|
||||
DisplayNameAttribute(Property_AzureConfiguredServiceLevelObjective)]
|
||||
public string ConfiguredServiceLevelObjective
|
||||
{
|
||||
//This value is read only because it's changed by changing the current SLO,
|
||||
//we just expose this to show if the DB is currently transitioning
|
||||
get
|
||||
{
|
||||
return this.currentState.configuredServiceLevelObjective;
|
||||
}
|
||||
}
|
||||
|
||||
[Browsable(false)]
|
||||
public AzureEdition AzureEdition
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentState.azureEdition;
|
||||
}
|
||||
}
|
||||
|
||||
[Category(Category_Azure),
|
||||
DisplayNameAttribute(Property_AzureEdition)]
|
||||
// TypeConverter(typeof(DynamicValuesConverter))]
|
||||
//We have a separate property here so that the AzureEdition enum value is still exposed
|
||||
//(This property is for the name displayed in the drop down menu, which needs to be a string for casting purposes)
|
||||
public string AzureEditionDisplay
|
||||
{
|
||||
get
|
||||
{
|
||||
return AzureSqlDbHelper.GetAzureEditionDisplayName(this.currentState.azureEdition);
|
||||
}
|
||||
set
|
||||
{
|
||||
AzureEdition edition;
|
||||
if (AzureSqlDbHelper.TryGetAzureEditionFromDisplayName(value, out edition))
|
||||
{
|
||||
if (edition == this.currentState.azureEdition)
|
||||
{ //No changes, return early since we don't need to do any of the changes below
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentState.azureEdition = edition;
|
||||
// this.SetServiceLevelObjectiveOptionVisibility();
|
||||
this.CurrentServiceLevelObjective = AzureSqlDbHelper.GetDefaultServiceObjective(edition);
|
||||
this.MaxSize = AzureSqlDbHelper.GetDatabaseDefaultSize(edition).ToString();
|
||||
this.NotifyObservers();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override IList<FilegroupPrototype> Filegroups
|
||||
{
|
||||
get { return Enumerable.Empty<FilegroupPrototype>().ToList(); }
|
||||
}
|
||||
|
||||
|
||||
public override IList<DatabaseFilePrototype> Files
|
||||
{
|
||||
get { return Enumerable.Empty<DatabaseFilePrototype>().ToList(); }
|
||||
}
|
||||
|
||||
[Browsable(false)]
|
||||
public override bool HideFileSettings
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
[Browsable(false)]
|
||||
public override bool AllowScripting
|
||||
{
|
||||
get { return this.ServerVersion.Major > 11 && this.AzureEdition != AzureEdition.DataWarehouse; }
|
||||
}
|
||||
|
||||
#endregion Properties
|
||||
|
||||
/// <summary>
|
||||
/// Sets the visibility of the SLO options based on the current configured Edition
|
||||
/// </summary>
|
||||
//private void SetServiceLevelObjectiveOptionVisibility()
|
||||
//{
|
||||
// if (this.wrapper == null)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (this.AzureEdition == AzureEdition.Business || this.AzureEdition == AzureEdition.Web)
|
||||
// { //Business and Web editions don't support SLO so hide those options
|
||||
// this.wrapper.SetupDynamicVisibility(Property_AzureCurrentServiceLevelObjective, false);
|
||||
// this.wrapper.SetupDynamicVisibility(Property_AzureConfiguredServiceLevelObjective, false);
|
||||
// }
|
||||
// else
|
||||
// { //Reset SLO options to visible in case they were hidden before
|
||||
// this.wrapper.SetupDynamicVisibility(Property_AzureCurrentServiceLevelObjective, true);
|
||||
// this.wrapper.SetupDynamicVisibility(Property_AzureConfiguredServiceLevelObjective, true);
|
||||
// }
|
||||
//}
|
||||
|
||||
#region DatabasePrototype overrides
|
||||
|
||||
/// <summary>
|
||||
/// Commit changes to the database
|
||||
/// </summary>
|
||||
/// <param name="marshallingControl">The control through which UI interactions are to be marshalled</param>
|
||||
/// <returns>The SMO database object that was created or modified</returns>
|
||||
//public override Database ApplyChanges(Control marshallingControl)
|
||||
//{
|
||||
// // For v12 Non-DW DBs lets use SMO
|
||||
// if (this.ServerVersion.Major >= 12 && this.AzureEdition != AzureEdition.DataWarehouse)
|
||||
// {
|
||||
// return base.ApplyChanges(marshallingControl);
|
||||
// }
|
||||
|
||||
// //Note : We purposely don't call base.ApplyChanges() here since SMO doesn't fully support Azure yet and so will throw
|
||||
// //an error if we try to modify the Database object directly
|
||||
// string alterDbPropertiesStatement = DatabasePrototypeAzure.CreateModifyAzureDbOptionsStatement(this.Name, this.AzureEdition, this.MaxSize, this.CurrentServiceLevelObjective);
|
||||
// if (this.AzureEdition == AzureEdition.DataWarehouse)
|
||||
// {
|
||||
// alterDbPropertiesStatement = DatabasePrototypeAzure.CreateModifySqlDwDbOptionsStatement(this.Name, this.MaxSize, this.CurrentServiceLevelObjective);
|
||||
// }
|
||||
|
||||
// string alterAzureDbRecursiveTriggersEnabledStatement = DatabasePrototypeAzure.CreateAzureDbSetRecursiveTriggersStatement(this.Name, this.RecursiveTriggers);
|
||||
// string alterAzureDbIsReadOnlyStatement = DatabasePrototypeAzure.CreateAzureDbSetIsReadOnlyStatement(this.Name, this.IsReadOnly);
|
||||
|
||||
// Database db = this.GetDatabase();
|
||||
|
||||
// //Altering the DB needs to be done on the master DB
|
||||
// using (var conn = new SqlConnection(this.context.ServerConnection.GetDatabaseConnection("master").ConnectionString))
|
||||
// {
|
||||
// var cmd = new SqlCommand();
|
||||
// cmd.Connection = conn;
|
||||
// conn.Open();
|
||||
|
||||
// //Only run the alter statements for modifications made. This is mostly to allow the non-Azure specific
|
||||
// //properties to be updated when a SLO change is in progress, but it also is beneficial to save trips to the
|
||||
// //server whenever we can (especially when Azure is concerned)
|
||||
// if (currentState.azureEdition != originalState.azureEdition ||
|
||||
// currentState.currentServiceLevelObjective != originalState.currentServiceLevelObjective ||
|
||||
// currentState.maxSize != originalState.maxSize)
|
||||
// {
|
||||
// cmd.CommandText = alterDbPropertiesStatement;
|
||||
// cmd.ExecuteNonQuery();
|
||||
// }
|
||||
|
||||
// if (currentState.recursiveTriggers != originalState.recursiveTriggers)
|
||||
// {
|
||||
// cmd.CommandText = alterAzureDbRecursiveTriggersEnabledStatement;
|
||||
// cmd.ExecuteNonQuery();
|
||||
// }
|
||||
|
||||
// if (currentState.isReadOnly != originalState.isReadOnly)
|
||||
// {
|
||||
// cmd.CommandText = alterAzureDbIsReadOnlyStatement;
|
||||
// cmd.ExecuteNonQuery();
|
||||
// }
|
||||
// }
|
||||
|
||||
// //Because we didn't use SMO to do the alter we should refresh the DB object so it picks up the correct properties
|
||||
// db.Refresh();
|
||||
|
||||
// // For properties that are supported in Database.Alter(), call SaveProperties, and then alter the DB.
|
||||
// //
|
||||
// if (this.AzureEdition != AzureEdition.DataWarehouse)
|
||||
// {
|
||||
// this.SaveProperties(db);
|
||||
// db.Alter(TerminationClause.FailOnOpenTransactions);
|
||||
// }
|
||||
// return db;
|
||||
//}
|
||||
|
||||
#endregion DatabasePrototype overrides
|
||||
|
||||
protected override void SaveProperties(Database db)
|
||||
{
|
||||
base.SaveProperties(db);
|
||||
if (this.ServerVersion.Major >= 12 && this.AzureEdition != AzureEdition.DataWarehouse)
|
||||
{
|
||||
if (!this.Exists || (this.originalState.maxSize != this.currentState.maxSize))
|
||||
{
|
||||
db.MaxSizeInBytes = this.currentState.maxSize.SizeInBytes;
|
||||
}
|
||||
|
||||
if (!this.Exists || (this.originalState.azureEdition != this.currentState.azureEdition))
|
||||
{
|
||||
db.AzureEdition = this.currentState.azureEdition.ToString();
|
||||
}
|
||||
|
||||
if (!this.Exists || (this.originalState.currentServiceLevelObjective != this.currentState.currentServiceLevelObjective))
|
||||
{
|
||||
db.AzureServiceObjective = this.currentState.currentServiceLevelObjective;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private const string AlterDbStatementFormat =
|
||||
@"ALTER DATABASE [{0}] {1}";
|
||||
|
||||
private const string ModifyAzureDbStatementFormat = @"MODIFY (EDITION = '{0}', MAXSIZE={1} {2})";
|
||||
private const string ModifySqlDwDbStatementFormat = @"MODIFY (MAXSIZE={0} {1})";
|
||||
private const string AzureServiceLevelObjectiveOptionFormat = @"SERVICE_OBJECTIVE = '{0}'";
|
||||
private const string SetReadOnlyOption = @"SET READ_ONLY";
|
||||
private const string SetReadWriteOption = @"SET READ_WRITE";
|
||||
private const string SetRecursiveTriggersOptionFormat = @"SET RECURSIVE_TRIGGERS {0}";
|
||||
private const string On = @"ON";
|
||||
private const string Off = @"OFF";
|
||||
|
||||
/// <summary>
|
||||
/// Creates an ALTER DATABASE statement to modify the Read-Only status of the target DB
|
||||
/// </summary>
|
||||
/// <param name="dbName"></param>
|
||||
/// <param name="isReadOnly"></param>
|
||||
/// <returns></returns>
|
||||
protected static string CreateAzureDbSetIsReadOnlyStatement(string dbName, bool isReadOnly)
|
||||
{
|
||||
return CreateAzureAlterDbStatement(dbName,
|
||||
string.Format(CultureInfo.InvariantCulture,
|
||||
isReadOnly ? SetReadOnlyOption : SetReadWriteOption));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an ALTER DATABASE statement to modify the RECURSIVE_TRIGGERS option of the target DB
|
||||
/// </summary>
|
||||
/// <param name="dbName"></param>
|
||||
/// <param name="recursiveTriggersEnabled"></param>
|
||||
/// <returns></returns>
|
||||
protected static string CreateAzureDbSetRecursiveTriggersStatement(string dbName, bool recursiveTriggersEnabled)
|
||||
{
|
||||
return CreateAzureAlterDbStatement(dbName,
|
||||
string.Format(CultureInfo.InvariantCulture,
|
||||
DatabasePrototypeAzure.SetRecursiveTriggersOptionFormat,
|
||||
recursiveTriggersEnabled ? DatabasePrototypeAzure.On : DatabasePrototypeAzure.Off));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an ALTER DATABASE statement to modify the Azure Database properties (Edition, MaxSize and Service Level Objective)
|
||||
/// for the target database
|
||||
/// </summary>
|
||||
/// <param name="dbName"></param>
|
||||
/// <param name="edition"></param>
|
||||
/// <param name="maxSize"></param>
|
||||
/// <param name="serviceLevelObjective"></param>
|
||||
/// <returns></returns>
|
||||
protected static string CreateModifyAzureDbOptionsStatement(string dbName, AzureEdition edition, string maxSize, string serviceLevelObjective)
|
||||
{
|
||||
//We might not have a SLO since some editions don't support it
|
||||
string sloOption = string.IsNullOrEmpty(serviceLevelObjective) ?
|
||||
string.Empty : ", " + string.Format(CultureInfo.InvariantCulture, AzureServiceLevelObjectiveOptionFormat, serviceLevelObjective);
|
||||
|
||||
return CreateAzureAlterDbStatement(dbName,
|
||||
string.Format(CultureInfo.InvariantCulture,
|
||||
ModifyAzureDbStatementFormat,
|
||||
edition,
|
||||
maxSize,
|
||||
sloOption));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an ALTER DATABASE statement to modify the Azure DataWarehouse properties (MaxSize and Service Level Objective)
|
||||
/// for the target database
|
||||
/// </summary>
|
||||
/// <param name="dbName">Name of the database</param>
|
||||
/// <param name="maxSize">MaxSize of the database</param>
|
||||
/// <param name="serviceLevelObjective">New SLO of the database</param>
|
||||
/// <returns>Sql Statement to Alter the database.</returns>
|
||||
protected static string CreateModifySqlDwDbOptionsStatement(string dbName, string maxSize, string serviceLevelObjective)
|
||||
{
|
||||
//We might not have a SLO since some editions don't support it
|
||||
string sloOption = string.IsNullOrEmpty(serviceLevelObjective) ?
|
||||
string.Empty : ", " + string.Format(CultureInfo.InvariantCulture, AzureServiceLevelObjectiveOptionFormat, serviceLevelObjective);
|
||||
|
||||
return CreateAzureAlterDbStatement(dbName,
|
||||
string.Format(CultureInfo.InvariantCulture,
|
||||
ModifySqlDwDbStatementFormat,
|
||||
maxSize,
|
||||
sloOption));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the ALTER DATABASE statement from the given op
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static string CreateAzureAlterDbStatement(string dbName, string options)
|
||||
{
|
||||
return string.Format(CultureInfo.InvariantCulture, AlterDbStatementFormat,
|
||||
CUtils.EscapeString(CUtils.EscapeString(dbName, ']'), '\''),
|
||||
options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlTools.ServiceLayer.Admin.Contracts;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
public class DatabaseTaskHelper
|
||||
{
|
||||
private DatabasePrototype prototype;
|
||||
|
||||
private XmlDocument document;
|
||||
|
||||
public CDataContainer DataContainer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Expose database prototype to internal classes
|
||||
/// </summary>
|
||||
public DatabasePrototype Prototype
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.prototype;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.prototype = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void CreateDatabase(CDataContainer context)
|
||||
{
|
||||
InitializeDataMembers(context);
|
||||
}
|
||||
|
||||
private void InitializeDataMembers(CDataContainer context)
|
||||
{
|
||||
if (context != null)
|
||||
{
|
||||
this.DataContainer = context;
|
||||
this.document = context.Document;
|
||||
|
||||
int majorVersionNumber = context.Server.Information.Version.Major;
|
||||
Version sql2000sp3 = new Version(8, 0, 760);
|
||||
Version sql2005sp2 = new Version(9, 0, 3000);
|
||||
|
||||
if (context.Server.DatabaseEngineType == DatabaseEngineType.SqlAzureDatabase)
|
||||
{
|
||||
this.prototype = new DatabasePrototypeAzure(context);
|
||||
}
|
||||
else if (Utils.IsSql11OrLater(context.Server.Version.Major))
|
||||
{
|
||||
this.prototype = new DatabasePrototype110(context);
|
||||
}
|
||||
else if (majorVersionNumber == 10)
|
||||
{
|
||||
this.prototype = new DatabasePrototype100(context);
|
||||
}
|
||||
else if ((sql2005sp2 <= context.Server.Information.Version) &&
|
||||
(context.Server.Information.EngineEdition == Edition.EnterpriseOrDeveloper))
|
||||
{
|
||||
this.prototype = new DatabasePrototype90EnterpriseSP2(context);
|
||||
}
|
||||
else if (8 < majorVersionNumber)
|
||||
{
|
||||
this.prototype = new DatabasePrototype90(context);
|
||||
}
|
||||
else if (sql2000sp3 <= context.Server.Information.Version)
|
||||
{
|
||||
this.prototype = new DatabasePrototype80SP3(context);
|
||||
}
|
||||
else if (7 < majorVersionNumber)
|
||||
{
|
||||
this.prototype = new DatabasePrototype80(context);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.prototype = new DatabasePrototype(context);
|
||||
}
|
||||
|
||||
this.prototype.Initialize();
|
||||
|
||||
//this.databasesCreated = new ArrayList();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.DataContainer = null;
|
||||
this.document = null;
|
||||
this.prototype = null;
|
||||
//this.databasesCreated = null;
|
||||
}
|
||||
}
|
||||
|
||||
internal static DatabaseInfo DatabasePrototypeToDatabaseInfo(DatabasePrototype prototype)
|
||||
{
|
||||
var databaseInfo = new DatabaseInfo();
|
||||
databaseInfo.Options.Add(AdminServicesProviderOptionsHelper.Name, prototype.Name);
|
||||
databaseInfo.Options.Add(AdminServicesProviderOptionsHelper.Owner, prototype.Owner);
|
||||
databaseInfo.Options.Add(AdminServicesProviderOptionsHelper.Collation, prototype.Collation);
|
||||
|
||||
for (int i = 0; i < prototype.Filegroups.Count; ++i)
|
||||
{
|
||||
var fileGroup = prototype.Filegroups[i];
|
||||
string itemPrefix = AdminServicesProviderOptionsHelper.FileGroups + "." + i + ".";
|
||||
databaseInfo.Options.Add(itemPrefix + AdminServicesProviderOptionsHelper.Name, fileGroup.Name);
|
||||
|
||||
}
|
||||
|
||||
for (int i = 0; i < prototype.Files.Count; ++i)
|
||||
{
|
||||
var file = prototype.Files[i];
|
||||
string itemPrefix = AdminServicesProviderOptionsHelper.DatabaseFiles + "." + i + ".";
|
||||
databaseInfo.Options.Add(itemPrefix + AdminServicesProviderOptionsHelper.Name, file.Name);
|
||||
databaseInfo.Options.Add(itemPrefix + AdminServicesProviderOptionsHelper.PhysicalName, file.PhysicalName);
|
||||
}
|
||||
|
||||
return databaseInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
173
src/Microsoft.SqlTools.ServiceLayer/Admin/Common/DbSize.cs
Normal file
173
src/Microsoft.SqlTools.ServiceLayer/Admin/Common/DbSize.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
//
|
||||
// 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.Text;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper class to describe the size of an Azure database
|
||||
/// </summary>
|
||||
public class DbSize
|
||||
{
|
||||
public enum SizeUnits
|
||||
{
|
||||
MB,
|
||||
GB,
|
||||
TB
|
||||
}
|
||||
|
||||
#region Member Vars
|
||||
|
||||
private readonly int size;
|
||||
private readonly SizeUnits sizeUnit;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
public DbSize(int size, SizeUnits sizeUnit)
|
||||
{
|
||||
this.size = size;
|
||||
this.sizeUnit = sizeUnit;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor
|
||||
/// </summary>
|
||||
public DbSize(DbSize copy)
|
||||
{
|
||||
this.size = copy.Size;
|
||||
this.sizeUnit = copy.SizeUnit;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Size of the DB
|
||||
/// </summary>
|
||||
public int Size
|
||||
{
|
||||
get
|
||||
{
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Units that the size is measured in
|
||||
/// </summary>
|
||||
public SizeUnits SizeUnit
|
||||
{
|
||||
get
|
||||
{
|
||||
return sizeUnit;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the number of bytes represented by the DbSize
|
||||
/// </summary>
|
||||
public double SizeInBytes
|
||||
{
|
||||
get
|
||||
{
|
||||
var sizeBase = Convert.ToDouble(this.size);
|
||||
switch (SizeUnit)
|
||||
{
|
||||
case SizeUnits.MB:
|
||||
return sizeBase*1024.0*1024.0;
|
||||
case SizeUnits.GB:
|
||||
return sizeBase*1024.0*1024.0*1024.0;
|
||||
case SizeUnits.TB:
|
||||
return sizeBase*1024.0*1024.0*1024.0*1024.0;
|
||||
}
|
||||
throw new InvalidOperationException("SR.UnknownSizeUnit(SizeUnit.ToString())");
|
||||
}
|
||||
}
|
||||
#region Object Overrides
|
||||
/// <summary>
|
||||
/// Displays the size in the format ####UU (e.g. 100GB)
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return size + sizeUnit.ToString();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null || GetType() != obj.GetType())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this == (DbSize)obj;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.size.GetHashCode() ^ this.sizeUnit.GetHashCode();
|
||||
}
|
||||
|
||||
#endregion Object Overrides
|
||||
|
||||
/// <summary>
|
||||
/// Parses a string in the format ####UU into a DbSize object. The number of
|
||||
/// numeric characters must be parseable into an int and the last two characters
|
||||
/// mapped to one of the SizeUnits enum values.
|
||||
/// </summary>
|
||||
/// <param name="dbSizeString"></param>
|
||||
/// <returns></returns>
|
||||
public static DbSize ParseDbSize(string dbSizeString)
|
||||
{
|
||||
if (dbSizeString == null || dbSizeString.Length < 3)
|
||||
{ //Sanity check
|
||||
throw new ArgumentException("DbSize string must be at least 3 characters (#UU)");
|
||||
}
|
||||
int size;
|
||||
//Try and parse all but the last two characters into the size
|
||||
if (int.TryParse(dbSizeString.Substring(0, dbSizeString.Length - 2), out size))
|
||||
{
|
||||
//Get the unit portion (last two characters)
|
||||
string unitPortion = dbSizeString.Substring(dbSizeString.Length - 2 );
|
||||
SizeUnits unit;
|
||||
if (Enum.TryParse(unitPortion, true, out unit))
|
||||
{
|
||||
return new DbSize(size, unit);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("DbSize string does not contain a valid unit portion");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException("DbSize string does not contain a valid numeric portion");
|
||||
}
|
||||
}
|
||||
|
||||
public static bool operator ==(DbSize x, DbSize y)
|
||||
{
|
||||
if(ReferenceEquals(x, y))
|
||||
{ //Both null or both same instance, are equal
|
||||
return true;
|
||||
}
|
||||
|
||||
if((object)x == null || (object)y == null)
|
||||
{ //Only one null, never equal (cast to object to avoid infinite loop of ==)
|
||||
return false;
|
||||
}
|
||||
|
||||
return x.size == y.size && x.sizeUnit == y.sizeUnit;
|
||||
}
|
||||
|
||||
public static bool operator !=(DbSize x, DbSize y)
|
||||
{
|
||||
return !(x == y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
namespace System
|
||||
{
|
||||
internal interface ICloneable
|
||||
{
|
||||
object Clone();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlServer.Management.Diagnostics;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Provides connection and enumerator context for a node
|
||||
/// </summary>
|
||||
public interface IManagedConnection : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Connection information.
|
||||
/// </summary>
|
||||
SqlOlapConnectionInfoBase Connection
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Free any resources for this connection
|
||||
/// </summary>
|
||||
void Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// interface used by the objectexplorer. Allows us to "pool" the main connection
|
||||
/// </summary>
|
||||
internal interface IManagedConnection2 : IManagedConnection
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of IManagedConnection. Allows the use of a direct or indirect connection
|
||||
/// in the object explorer that takes care of the connection.
|
||||
/// </summary>
|
||||
internal class ManagedConnection : IManagedConnection2
|
||||
{
|
||||
#region private members
|
||||
private bool connectionAddedToActiveConnections = false;
|
||||
private bool closeOnDispose = false;
|
||||
private SqlOlapConnectionInfoBase connection;
|
||||
private bool closed = false;
|
||||
#endregion
|
||||
|
||||
#region Construction
|
||||
/// <summary>
|
||||
/// Create a new managed connection
|
||||
/// </summary>
|
||||
/// <param name="connection">connection wish to manage</param>
|
||||
public ManagedConnection(SqlOlapConnectionInfoBase connection)
|
||||
: this(connection, false)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// create a new managed connection.
|
||||
/// </summary>
|
||||
/// <param name="connection">connection</param>
|
||||
/// <param name="attemptToPool">true if we are going to try and reuse the
|
||||
/// connection if possible</param>
|
||||
public ManagedConnection(SqlOlapConnectionInfoBase sourceConnection, bool attemptToPool)
|
||||
{
|
||||
// parameter check
|
||||
if (sourceConnection == null)
|
||||
{
|
||||
throw new ArgumentNullException("sourceConnection");
|
||||
}
|
||||
|
||||
// see if the connection can restrict access (single user mode)
|
||||
IRestrictedAccess access = sourceConnection as IRestrictedAccess;
|
||||
// see if it is cloneable
|
||||
ICloneable cloneable = sourceConnection as ICloneable;
|
||||
lock (ActiveConnections)
|
||||
{
|
||||
// if it's not single user mode then we can see if the object can be cloned
|
||||
if (access == null || access.SingleConnection == false)
|
||||
{
|
||||
// if we are going to attempt to pool, see if the connection is in use
|
||||
if (attemptToPool && !ActiveConnections.Contains(SharedConnectionUtil.GetConnectionKeyName(sourceConnection)))
|
||||
{
|
||||
// add it to the hashtable to indicate use.
|
||||
ActiveConnections.Add(SharedConnectionUtil.GetConnectionKeyName(sourceConnection), sourceConnection);
|
||||
this.connection = sourceConnection;
|
||||
this.closeOnDispose = false;
|
||||
this.connectionAddedToActiveConnections = true;
|
||||
}
|
||||
else if (cloneable != null)
|
||||
{
|
||||
this.connection = (SqlOlapConnectionInfoBase)cloneable.Clone();
|
||||
this.closeOnDispose = true;
|
||||
}
|
||||
else if (sourceConnection is SqlConnectionInfoWithConnection)
|
||||
{
|
||||
this.connection = ((SqlConnectionInfoWithConnection)sourceConnection).Copy();
|
||||
this.closeOnDispose = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// if everything else has failed just use to passed in connection.
|
||||
if (this.connection == null)
|
||||
{
|
||||
this.connection = sourceConnection;
|
||||
}
|
||||
|
||||
// always set the lock timeout to prevent the shell from not responding
|
||||
if (this.connection is SqlConnectionInfoWithConnection)
|
||||
{
|
||||
// set lock_timeout to 10 seconds
|
||||
((SqlConnectionInfoWithConnection)this.connection).ServerConnection.LockTimeout = 10;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IDisposable implementation
|
||||
public void Dispose()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IManagedConnection implementation
|
||||
/// <summary>
|
||||
/// Connection
|
||||
/// </summary>
|
||||
public SqlOlapConnectionInfoBase Connection
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.connection;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Close the current connection if applicable.
|
||||
/// </summary>
|
||||
public void Close()
|
||||
{
|
||||
if (this.closed)
|
||||
return;
|
||||
|
||||
if (this.closeOnDispose)
|
||||
{
|
||||
IDisposable disp = this.connection as IDisposable;
|
||||
if (disp != null)
|
||||
{
|
||||
disp.Dispose();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we are not closing the connection and it is a sql connection then ensure it
|
||||
// is left in the master database.
|
||||
SqlConnectionInfoWithConnection sqlConnection = this.connection as SqlConnectionInfoWithConnection;
|
||||
if (sqlConnection != null && sqlConnection.ServerConnection.DatabaseEngineType == DatabaseEngineType.Standalone)
|
||||
{
|
||||
try
|
||||
{
|
||||
sqlConnection.ServerConnection.ExecuteNonQuery("use [master]");
|
||||
}
|
||||
// don't error if this fails
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
}
|
||||
if (this.connectionAddedToActiveConnections)
|
||||
{
|
||||
lock (ActiveConnections)
|
||||
{
|
||||
ActiveConnections.Remove(SharedConnectionUtil.GetConnectionKeyName(connection));
|
||||
}
|
||||
}
|
||||
|
||||
this.connection = null;
|
||||
this.closed = true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region static helpers
|
||||
/// <summary>
|
||||
/// hashtable we use to keep track of actively used main connections
|
||||
/// </summary>
|
||||
private static Hashtable activeConnections = null;
|
||||
private Hashtable ActiveConnections
|
||||
{
|
||||
get
|
||||
{
|
||||
if (activeConnections == null)
|
||||
{
|
||||
activeConnections = new Hashtable();
|
||||
}
|
||||
return activeConnections;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
/// <summary>
|
||||
/// To access DataModelingSandbox from NavigableItem
|
||||
/// </summary>
|
||||
public interface ISandboxLoader
|
||||
{
|
||||
/// <summary>
|
||||
/// Get sandbox
|
||||
/// </summary>
|
||||
/// <returns>DataModelingSandbox object associated with this NavigableItem</returns>
|
||||
object GetSandbox();
|
||||
|
||||
/// <summary>
|
||||
/// Refresh sandbox data associated with this NavigableItem
|
||||
/// </summary>
|
||||
void RefreshSandboxData();
|
||||
|
||||
/// <summary>
|
||||
/// Delete sandbox from cache
|
||||
/// </summary>
|
||||
void DeleteSandbox();
|
||||
}
|
||||
}
|
||||
488
src/Microsoft.SqlTools.ServiceLayer/Admin/Common/STParameters.cs
Normal file
488
src/Microsoft.SqlTools.ServiceLayer/Admin/Common/STParameters.cs
Normal file
@@ -0,0 +1,488 @@
|
||||
//
|
||||
// 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.Xml;
|
||||
using System.Collections;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
/// <summary>
|
||||
/// SqlTools Parameters, used to define what goes into starting up a Workbench Form
|
||||
/// AKA a dbCommander, AKA a "dialog"
|
||||
/// These parameters are xml snippets
|
||||
/// </summary>
|
||||
public class STParameters
|
||||
{
|
||||
public XmlDocument m_doc;
|
||||
|
||||
/// <summary>
|
||||
/// The data type we are interested in
|
||||
/// </summary>
|
||||
public enum STType { eNULL, eInt, eLong, eString };
|
||||
|
||||
/// <summary>
|
||||
/// default constructor
|
||||
/// </summary>
|
||||
public STParameters()
|
||||
{
|
||||
//
|
||||
// TODO: Add constructor logic here
|
||||
//
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="xmlDoc">The xml snippet used to control the dbCommander</param>
|
||||
public STParameters(XmlDocument xmlDoc)
|
||||
{
|
||||
m_doc = xmlDoc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changing the xml snippet we are using
|
||||
/// </summary>
|
||||
/// <param name="xmlDoc">the new xml snippet</param>
|
||||
public void SetDocument(XmlDocument xmlDoc)
|
||||
{
|
||||
m_doc = xmlDoc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Access to the xml we are using for dbCommander parameters
|
||||
/// </summary>
|
||||
/// <returns>our current parameters</returns>
|
||||
public XmlDocument GetDocument()
|
||||
{
|
||||
return m_doc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search for an xml tag, and return its value
|
||||
/// </summary>
|
||||
/// <param name="parameterName">the xml tag name</param>
|
||||
/// <param name="value">the value of that tag</param>
|
||||
/// <returns>flag that is true if the data was found, false if not</returns>
|
||||
public bool GetBaseParam(string parameterName, ref object value)
|
||||
{
|
||||
XmlNodeList nodeList = null;
|
||||
bool parameterExists;
|
||||
|
||||
if (m_doc == null)
|
||||
return false;
|
||||
|
||||
parameterExists = false;
|
||||
nodeList = m_doc.GetElementsByTagName(parameterName);
|
||||
|
||||
if (nodeList.Count > 1)
|
||||
{
|
||||
value = null;
|
||||
}
|
||||
else if (nodeList.Count != 0) // anything there?
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlNode node = nodeList.Item(0);
|
||||
if (null != node)
|
||||
{
|
||||
value = node.InnerText as object;
|
||||
parameterExists = true;
|
||||
}
|
||||
}
|
||||
catch (Exception /*e*/)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return parameterExists;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds an existing xml tag, and sets it to a new value, or if the tag is not found
|
||||
/// create it and set it's value
|
||||
/// </summary>
|
||||
/// <param name="parameterName">tag name</param>
|
||||
/// <param name="value">new value</param>
|
||||
/// <returns>flag that is true if the tag was set, false if not</returns>
|
||||
public bool SetBaseParam(string parameterName, object value)
|
||||
{
|
||||
XmlNodeList nodeList;
|
||||
bool success = false;
|
||||
|
||||
nodeList = m_doc.GetElementsByTagName(parameterName);
|
||||
|
||||
if (nodeList.Count == 1)
|
||||
{
|
||||
try
|
||||
{
|
||||
nodeList.Item(0).InnerText = (string)value;
|
||||
success = true;
|
||||
}
|
||||
catch (InvalidCastException /*e*/)
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (nodeList.Count == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlElement xmlElement = m_doc.CreateElement(parameterName);
|
||||
XmlNode root = m_doc.DocumentElement;
|
||||
|
||||
nodeList = m_doc.GetElementsByTagName("params");
|
||||
|
||||
if (nodeList.Count == 1 && value is string)
|
||||
{
|
||||
xmlElement.InnerText = (string)value;
|
||||
nodeList.Item(0).InsertAfter(xmlElement, nodeList.Item(0).LastChild);
|
||||
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
string sz = e.ToString();
|
||||
success = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return success;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get back an interger parameter.
|
||||
/// NOTE: if the tag exists, but it contains non-numeric data, this will throw
|
||||
/// An exception of type 'System.FormatException'
|
||||
/// with Additional information: Could not find any parsible digits.
|
||||
/// </summary>
|
||||
/// <param name="parameterName">xml tag name for the parameter of interest</param>
|
||||
/// <param name="iValue">out value of parameter</param>
|
||||
/// <returns>flag that is true if the data was found, false if not</returns>
|
||||
public bool GetParam(string parameterName, out int value)
|
||||
{
|
||||
bool parameterExists = false;
|
||||
|
||||
value = 0;
|
||||
|
||||
try
|
||||
{
|
||||
object oAux = null;
|
||||
|
||||
if (parameterExists = GetBaseParam(parameterName, ref oAux))
|
||||
{
|
||||
try
|
||||
{
|
||||
value = Convert.ToInt32((string)oAux, 10); // data is always a string, it is the value of XmlNode.InnerText
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
Debug.WriteLine(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Non numeric data in tag: {0}", parameterName));
|
||||
Debug.WriteLine(e.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InvalidCastException /*e*/)
|
||||
{
|
||||
}
|
||||
|
||||
return parameterExists;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Accessor for a boolean parameter
|
||||
/// NOTE: if the tag exists, but it contains non-numeric data, this will throw
|
||||
/// An exception of type 'System.FormatException'
|
||||
/// with Additional information: Could not find any parsible digits.
|
||||
/// </summary>
|
||||
/// <param name="parameterName">xml tag name for the parameter of interest</param>
|
||||
/// <param name="value">out value of parameter</param>
|
||||
/// <returns>flag that is true if the data was found, false if not</returns>
|
||||
public bool GetParam(string parameterName, ref bool value)
|
||||
{
|
||||
bool parameterExists = false;
|
||||
|
||||
value = false;
|
||||
|
||||
try
|
||||
{
|
||||
object oAux = null;
|
||||
if (parameterExists = GetBaseParam(parameterName, ref oAux))
|
||||
{
|
||||
try
|
||||
{
|
||||
value = Convert.ToBoolean((string)oAux, System.Globalization.CultureInfo.InvariantCulture); // data is always a string, it is the value of XmlNode.InnerText
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
Debug.WriteLine(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Non boolean data in tag: {0}", parameterName));
|
||||
Debug.WriteLine(e.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InvalidCastException /*e*/)
|
||||
{
|
||||
}
|
||||
|
||||
return parameterExists;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Accessor to a string parameter
|
||||
/// </summary>
|
||||
/// <param name="parameterName">xml tag name for the parameter of interest</param>
|
||||
/// <param name="value">out value of parameter</param>
|
||||
/// <returns>flag that is true if the data was found, false if not</returns>
|
||||
public bool GetParam(string parameterName, ref string value)
|
||||
{
|
||||
bool parameterExists;
|
||||
|
||||
value = "";
|
||||
parameterExists = false;
|
||||
|
||||
try
|
||||
{
|
||||
object oAux = null;
|
||||
|
||||
if (parameterExists = GetBaseParam(parameterName, ref oAux))
|
||||
{
|
||||
value = (string)oAux;
|
||||
}
|
||||
}
|
||||
catch (InvalidCastException /*e*/)
|
||||
{
|
||||
}
|
||||
|
||||
return parameterExists;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Accessor to long parameter (Int64)
|
||||
/// NOTE: if the tag exists, but it contains non-numeric data, this will throw
|
||||
/// An exception of type 'System.FormatException'
|
||||
/// with Additional information: Could not find any parsible digits.
|
||||
/// </summary>
|
||||
/// <param name="parameterName">xml tag name for the parameter of interest</param>
|
||||
/// <param name="value">out value of parameter</param>
|
||||
/// <returns>flag that is true if the data was found, false if not</returns>
|
||||
public bool GetParam(string parameterName, out long value)
|
||||
{
|
||||
bool parameterExists = false;
|
||||
|
||||
value = 0;
|
||||
|
||||
try
|
||||
{
|
||||
object oAux = null;
|
||||
|
||||
if (parameterExists = GetBaseParam(parameterName, ref oAux))
|
||||
{
|
||||
try
|
||||
{
|
||||
value = Convert.ToInt64((string)oAux, 10); // data is always a string, it is the value of XmlNode.InnerText
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
Debug.WriteLine(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Non numeric data in tag: {0}", parameterName));
|
||||
Debug.WriteLine(e.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InvalidCastException /*e*/)
|
||||
{
|
||||
}
|
||||
|
||||
return parameterExists;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set an int (Int32) parameter
|
||||
/// </summary>
|
||||
/// <param name="parameterName">tag name for parameter</param>
|
||||
/// <param name="value">integer value</param>
|
||||
/// <returns>true if set was successful, false if not</returns>
|
||||
public bool SetParam(string parameterName, int value)
|
||||
{
|
||||
bool success;
|
||||
|
||||
success = SetBaseParam(parameterName, (object)value);
|
||||
|
||||
return success;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a string parameter
|
||||
/// </summary>
|
||||
/// <param name="parameterName">tag name for parameter</param>
|
||||
/// <param name="value">string value</param>
|
||||
/// <returns>true if set was successful, false if not</returns>
|
||||
public bool SetParam(string parameterName, string value)
|
||||
{
|
||||
bool success;
|
||||
|
||||
success = SetBaseParam(parameterName, (object)value);
|
||||
|
||||
return success;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a long (Int64) parameter
|
||||
/// </summary>
|
||||
/// <param name="parameterName">tag name for parameter</param>
|
||||
/// <param name="value">long value</param>
|
||||
/// <returns>true if set was successful, false if not</returns>
|
||||
public bool SetParam(string parameterName, long value)
|
||||
{
|
||||
bool success;
|
||||
|
||||
success = SetBaseParam(parameterName, (object)value);
|
||||
|
||||
return success;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a string collection parameter
|
||||
/// </summary>
|
||||
/// <param name="parameterName">name of collection</param>
|
||||
/// <param name="list">collection that gets filled up with parameters</param>
|
||||
/// <param name="getInnerXml">true if we want to get at inner nodes, false if not</param>
|
||||
/// <returns>true if parameter(s) exist</returns>
|
||||
public bool GetParam(string parameterName, System.Collections.Specialized.StringCollection list, bool getInnerXml)
|
||||
{
|
||||
/// necessary for OALP objects path that is in an XML form
|
||||
if (true == getInnerXml)
|
||||
{
|
||||
XmlNodeList nodeList;
|
||||
bool parameterExists;
|
||||
long lCount;
|
||||
|
||||
parameterExists = false;
|
||||
nodeList = m_doc.GetElementsByTagName(parameterName);
|
||||
|
||||
list.Clear();
|
||||
|
||||
lCount = nodeList.Count;
|
||||
|
||||
if (lCount > 0)
|
||||
{
|
||||
parameterExists = true;
|
||||
|
||||
for (long i = 0; i < lCount; i++)
|
||||
{
|
||||
list.Add(nodeList.Item((int)i).InnerXml);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
parameterExists = false;
|
||||
}
|
||||
|
||||
return parameterExists;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetParam(parameterName, list);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Access to a collection of parameters
|
||||
/// </summary>
|
||||
/// <param name="parameterName">name of collection</param>
|
||||
/// <param name="list">list to fill with parameters</param>
|
||||
/// <returns>parameter(s) exist</returns>
|
||||
public bool GetParam(string parameterName, System.Collections.Specialized.StringCollection list)
|
||||
{
|
||||
XmlNodeList nodeList;
|
||||
bool parameterExists;
|
||||
long lCount;
|
||||
|
||||
parameterExists = false;
|
||||
nodeList = m_doc.GetElementsByTagName(parameterName);
|
||||
|
||||
list.Clear();
|
||||
|
||||
lCount = nodeList.Count;
|
||||
|
||||
if (lCount > 0)
|
||||
{
|
||||
parameterExists = true;
|
||||
|
||||
for (long i = 0; i < lCount; i++)
|
||||
{
|
||||
list.Add(nodeList.Item((int)i).InnerText);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
parameterExists = false;
|
||||
}
|
||||
|
||||
return parameterExists;
|
||||
}
|
||||
|
||||
public bool GetParam(string parameterName, ref ArrayList list)
|
||||
{
|
||||
System.Collections.Specialized.StringCollection stringList = new System.Collections.Specialized.StringCollection();
|
||||
bool parameterExists = GetParam(parameterName, stringList);
|
||||
list.Clear();
|
||||
if (!parameterExists)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < stringList.Count; i++)
|
||||
{
|
||||
list.Add(stringList[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function does nothing but return false
|
||||
/// </summary>
|
||||
/// <param name="parameterName">ignored</param>
|
||||
/// <param name="type">ignored</param>
|
||||
/// <returns>always false</returns>
|
||||
public bool GetParamType(string parameterName, STType type)
|
||||
{
|
||||
bool whatever = false;
|
||||
|
||||
return whatever;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function does nothing but return false
|
||||
/// </summary>
|
||||
/// <param name="parameterName">ignored</param>
|
||||
/// <param name="type">ignored</param>
|
||||
/// <returns>always false</returns>
|
||||
public bool SetParamType(string parameterName, STType type)
|
||||
{
|
||||
bool whatever = false;
|
||||
|
||||
return whatever;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// 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 Microsoft.SqlServer.Management.AzureCredential;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
//using Microsoft.SqlServer.Management.Smo.RegSvrEnum;
|
||||
using SFC = Microsoft.SqlServer.Management.Sdk.Sfc;
|
||||
//using Microsoft.SqlServer.StorageClient;
|
||||
//using Microsoft.SqlServer.Management.SqlMgmt;
|
||||
|
||||
/// <summary>
|
||||
/// Summary description for SharedConectionUtil
|
||||
/// Moved GetConnectionName static call in a public class acessible for both
|
||||
/// OEXM and OE
|
||||
/// </summary>
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
internal class SharedConnectionUtil
|
||||
{
|
||||
public SharedConnectionUtil()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="ci"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetConnectionKeyName(SqlOlapConnectionInfoBase ci)
|
||||
{
|
||||
|
||||
//// Note that these strings are not localized. The returned string is used by OE in a
|
||||
//// hash of connections so it can tell if it already has such a connection open. This
|
||||
//// string is never seen by the user. For the string seen by the user, see
|
||||
//// ServerNameHandler.cs.
|
||||
string displayName = String.Format(System.Globalization.CultureInfo.InvariantCulture, "{0} (", ci.ServerName);
|
||||
|
||||
if (!string.IsNullOrEmpty(ci.DatabaseName))
|
||||
{
|
||||
displayName += ", " + ci.DatabaseName;
|
||||
}
|
||||
|
||||
return displayName;
|
||||
|
||||
//switch (ci.ServerType)
|
||||
//{
|
||||
// case ConnectionType.AzureStorage:
|
||||
// AzureStorageConnectionInfo azureCI = ci as AzureStorageConnectionInfo;
|
||||
// displayName = "AzureStorage," + azureCI.BlobClient.BaseUri;
|
||||
// break;
|
||||
// case ConnectionType.AzureAccount:
|
||||
// if (ci is CertificateBasedAuthenticationInfo)
|
||||
// {
|
||||
// displayName = "AzureSubscription," + (ci as CertificateBasedAuthenticationInfo).SubscriptionId;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// displayName = "AzureSubscription";
|
||||
// }
|
||||
// break;
|
||||
// case ConnectionType.Sql:
|
||||
// displayName += "SQLServer";
|
||||
// SqlConnectionInfo sqlCi = ci as SqlConnectionInfo;
|
||||
// if (sqlCi.UseIntegratedSecurity == true)
|
||||
// {
|
||||
// displayName += ", trusted";
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// displayName += String.Format(System.Globalization.CultureInfo.InvariantCulture, ", user = {0}", sqlCi.UserName);
|
||||
// //In Cloud a user can have access to only a few UDBs without access to master DB
|
||||
// // and hence need to show different OE hierarchy trees for each DB
|
||||
// //Same is the case with a contained user.
|
||||
|
||||
|
||||
// if (ServerInfoCache.GetDatabaseEngineType(ci.ServerName) == DatabaseEngineType.SqlAzureDatabase
|
||||
// || SFC.ExecuteSql.GetDatabaseEngineType(ci) == DatabaseEngineType.SqlAzureDatabase
|
||||
// || SFC.ExecuteSql.IsContainedAuthentication(ci))
|
||||
// {
|
||||
// if (!string.IsNullOrEmpty(ci.DatabaseName))
|
||||
// {
|
||||
// displayName += ", " + ci.DatabaseName;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// break;
|
||||
// case ConnectionType.Olap:
|
||||
// displayName += "OLAP";
|
||||
// break;
|
||||
// case ConnectionType.SqlCE:
|
||||
// displayName += "SqlCE";
|
||||
// break;
|
||||
// case ConnectionType.ReportServer:
|
||||
// displayName += "Rs";
|
||||
// displayName += String.Format(System.Globalization.CultureInfo.InvariantCulture, ", connection = {0}", ci.ConnectionString);
|
||||
// break;
|
||||
// case ConnectionType.IntegrationServer:
|
||||
// displayName += "SSIS";
|
||||
// break;
|
||||
//}
|
||||
//displayName += ")";
|
||||
//return displayName;
|
||||
}
|
||||
}
|
||||
}
|
||||
410
src/Microsoft.SqlTools.ServiceLayer/Admin/Common/Utils.cs
Normal file
410
src/Microsoft.SqlTools.ServiceLayer/Admin/Common/Utils.cs
Normal file
@@ -0,0 +1,410 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
|
||||
//extern alias VSShell2;
|
||||
//extern alias VSShell2Iop;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Globalization;
|
||||
using Microsoft.SqlServer.Management.Diagnostics;
|
||||
using SMO = Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
//using VSShell2Iop.Microsoft.VisualStudio.Shell.Interop;
|
||||
//using VSShell2.Microsoft.VisualStudio.Shell;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin
|
||||
{
|
||||
/// <summary>
|
||||
/// Internal reusable helpers
|
||||
/// </summary>
|
||||
internal class Utils
|
||||
{
|
||||
/// <summary>
|
||||
/// only static methods
|
||||
/// </summary>
|
||||
private Utils() { }
|
||||
|
||||
/// <summary>
|
||||
/// returns all instances of the given custom attribute on a given object
|
||||
/// </summary>
|
||||
/// <param name="objectToGetAttributeFrom"></param>
|
||||
/// <param name="customAttribute"></param>
|
||||
/// <returns></returns>
|
||||
public static Attribute GetCustomAttribute(object objectToGetAttributeFrom, Type customAttribute)
|
||||
{
|
||||
//first, see if the object implemented this interface to override standard behavior
|
||||
System.Reflection.ICustomAttributeProvider attribProvider = objectToGetAttributeFrom as System.Reflection.ICustomAttributeProvider;
|
||||
if (attribProvider == null)
|
||||
{
|
||||
//if not, get it from its type
|
||||
attribProvider = (System.Reflection.ICustomAttributeProvider)objectToGetAttributeFrom.GetType();
|
||||
}
|
||||
|
||||
object[] attribs = attribProvider.GetCustomAttributes(customAttribute, true);
|
||||
if (attribs != null && attribs.Length > 0)
|
||||
{
|
||||
//NOTE: important that we'll always use the first one in collection.
|
||||
//Our implementation of ICustomAttributeProvider knows about that and
|
||||
//relies on this behavior
|
||||
return attribs[0] as Attribute;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// called to create SqlConnectionInfo out of the given CDataContainer object
|
||||
/// </summary>
|
||||
/// <param name="dc"></param>
|
||||
/// <returns></returns>
|
||||
public static SqlConnectionInfo GetSqlConnectionInfoFromDataContainer(CDataContainer dc)
|
||||
{
|
||||
if (dc != null)
|
||||
{
|
||||
// we may have been given conneciton information by the object explorer. in which case there is no need
|
||||
// to build it ourselves.
|
||||
SqlConnectionInfo result = dc.ConnectionInfo as SqlConnectionInfo;
|
||||
if (result == null)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static int InitialTreeViewWidth
|
||||
{
|
||||
get
|
||||
{
|
||||
return 175;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to set the CLR thread name.
|
||||
/// Will not throw if the name is already set.
|
||||
/// </summary>
|
||||
/// <param name="name"></param>
|
||||
public static void TrySetThreadName(String name)
|
||||
{
|
||||
try
|
||||
{
|
||||
System.Threading.Thread.CurrentThread.Name = name;
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{ }
|
||||
}
|
||||
|
||||
public static bool IsKatmaiOrLater(int version)
|
||||
{
|
||||
return (10 <= version);
|
||||
}
|
||||
|
||||
public static bool IsKjOrLater(ServerVersion version)
|
||||
{
|
||||
return (version.Major > 10
|
||||
|| (version.Major == 10 && version.Minor >= 50));
|
||||
}
|
||||
|
||||
public static bool IsSql11OrLater(ServerVersion version)
|
||||
{
|
||||
return IsSql11OrLater(version.Major);
|
||||
}
|
||||
|
||||
public static bool IsSql11OrLater(int versionMajor)
|
||||
{
|
||||
return (versionMajor >= 11);
|
||||
}
|
||||
|
||||
public static bool IsSql12OrLater(ServerVersion version)
|
||||
{
|
||||
return IsSql12OrLater(version.Major);
|
||||
}
|
||||
|
||||
public static bool IsSql12OrLater(int versionMajor)
|
||||
{
|
||||
return (versionMajor >= 12);
|
||||
}
|
||||
|
||||
public static bool IsSql13OrLater(ServerVersion version)
|
||||
{
|
||||
return IsSql13OrLater(version.Major);
|
||||
}
|
||||
|
||||
public static bool IsSql13OrLater(int versionMajor)
|
||||
{
|
||||
return (versionMajor >= 13);
|
||||
}
|
||||
|
||||
public static bool IsSql14OrLater(ServerVersion version)
|
||||
{
|
||||
return IsSql14OrLater(version.Major);
|
||||
}
|
||||
|
||||
public static bool IsSql14OrLater(int versionMajor)
|
||||
{
|
||||
return (versionMajor >= 14);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the version is SQL 2016 SP1 or later.
|
||||
/// </summary>
|
||||
/// <param name="version"></param>
|
||||
/// <returns>true if the version is SQL 2016 SP1 or later, false otherwise</returns>
|
||||
public static bool IsSql13SP1OrLater(Version version)
|
||||
{
|
||||
return (version >= new Version(13, 0, 3510));
|
||||
}
|
||||
|
||||
public static bool IsXTPSupportedOnServer(SMO.Server server)
|
||||
{
|
||||
bool isXTPSupported = false;
|
||||
|
||||
if (server.ConnectionContext.ExecuteScalar("SELECT SERVERPROPERTY('IsXTPSupported')") != DBNull.Value)
|
||||
{
|
||||
isXTPSupported = server.IsXTPSupported;
|
||||
}
|
||||
|
||||
return isXTPSupported;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if given database has memory optimized filegroup on given server.
|
||||
/// </summary>
|
||||
/// <param name="server"></param>
|
||||
/// <param name="dbName"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasMemoryOptimizedFileGroup(SMO.Server server, string dbName)
|
||||
{
|
||||
bool hasMemoryOptimizedFileGroup = false;
|
||||
|
||||
if (server.ServerType != DatabaseEngineType.SqlAzureDatabase)
|
||||
{
|
||||
string query = string.Format(CultureInfo.InvariantCulture,
|
||||
"select top 1 1 from [{0}].sys.filegroups where type = 'FX'",
|
||||
CUtils.EscapeString(dbName, ']'));
|
||||
if (server.ConnectionContext.ExecuteScalar(query) != null)
|
||||
{
|
||||
hasMemoryOptimizedFileGroup = true;
|
||||
}
|
||||
}
|
||||
|
||||
return hasMemoryOptimizedFileGroup;
|
||||
}
|
||||
|
||||
public static bool IsPolybasedInstalledOnServer(SMO.Server server)
|
||||
{
|
||||
bool isPolybaseInstalled = false;
|
||||
|
||||
if (server.IsSupportedProperty("IsPolyBaseInstalled"))
|
||||
{
|
||||
isPolybaseInstalled = server.IsPolyBaseInstalled;
|
||||
}
|
||||
|
||||
return isPolybaseInstalled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if current user has given permission on given server.
|
||||
/// </summary>
|
||||
/// <param name="server"></param>
|
||||
/// <param name="permissionName"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasPermissionOnServer(SMO.Server server, string permissionName)
|
||||
{
|
||||
return Convert.ToBoolean(server.ConnectionContext.ExecuteScalar(
|
||||
string.Format(CultureInfo.InvariantCulture,
|
||||
"SELECT HAS_PERMS_BY_NAME(null, null, '{0}');",
|
||||
permissionName)));
|
||||
}
|
||||
|
||||
public static bool FilestreamEnabled(SMO.Server svr)
|
||||
{
|
||||
bool result = false;
|
||||
if (svr != null)
|
||||
{
|
||||
if (IsKatmaiOrLater(svr.Information.Version.Major)
|
||||
&& svr.ServerType != DatabaseEngineType.SqlAzureDatabase) //Azure doesn't support filestream
|
||||
{
|
||||
if (svr.Configuration.FilestreamAccessLevel.RunValue != 0)
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function returns true if SSMS is the running application
|
||||
/// and if it contains only the core relational packages.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
//public static bool IsSsmsMinimalSet()
|
||||
//{
|
||||
// IVsShell vsShell = Package.GetGlobalService(typeof(SVsShell)) as IVsShell;
|
||||
// const string guidSqlStudioPkgString = "04401ff3-8b0f-4d2d-85eb-2a3542867a8b";
|
||||
// Guid guidSqlStudioPkg = new Guid(guidSqlStudioPkgString);
|
||||
|
||||
|
||||
// //Applications like 'AS Migration wizard' are non-ssms/non-VS shell applications
|
||||
// if (vsShell == null)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// IVsPackage ssmsPackage;
|
||||
// vsShell.IsPackageLoaded(ref guidSqlStudioPkg, out ssmsPackage);
|
||||
|
||||
// return ((ssmsPackage != null) &&
|
||||
// !AreExtendedFeaturesAvailable());
|
||||
// }
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// This function checks if extended SSMS packages are loaded
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
//public static bool AreExtendedFeaturesAvailable()
|
||||
//{
|
||||
// return Microsoft.SqlServer.Management.UI.VSIntegration.SsmsInformation.CanShowNonExpressFeatures;
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Execute a static method by reflection
|
||||
/// </summary>
|
||||
/// <param name="assemblyShortName">The short name of the assembly, like Microsoft.SqlServer.Management.RegisteredServersUI.dll</param>
|
||||
/// <param name="className">The fully qualified name of the class, like Microsoft.SqlServer.Management.RegisteredServers.Utils</param>
|
||||
/// <param name="methodName">THe name of the static method to call, like DoSomething</param>
|
||||
/// <param name="parameters">params array of arguments to pass to the method</param>
|
||||
/// <returns></returns>
|
||||
//public static object ReflectionExecuteStatic(
|
||||
// string assemblyShortName,
|
||||
// string className,
|
||||
// string methodName,
|
||||
// params object[] parameters)
|
||||
//{
|
||||
// STrace.Params(
|
||||
// SqlMgmtDiag.TName,
|
||||
// "Utils.ReflectionExecuteStatic(string, string, string, object[])",
|
||||
// "assemblyShortName='{0}', className='{1}', methodName='{2}'",
|
||||
// assemblyShortName,
|
||||
// className,
|
||||
// methodName);
|
||||
|
||||
// Assembly assembly = Assembly.Load(
|
||||
// Microsoft.SqlServer.Management.SqlMgmt.AssemblyLoadUtil.GetFullAssemblyName(assemblyShortName));
|
||||
|
||||
// if (assembly == null)
|
||||
// {
|
||||
// STrace.LogExThrow();
|
||||
// throw new ArgumentException("Couldn't load assembly by reflection");
|
||||
// }
|
||||
|
||||
// Type type = assembly.GetType(className);
|
||||
// if (type == null)
|
||||
// {
|
||||
// STrace.LogExThrow();
|
||||
// throw new ArgumentException("Couldn't find class by reflection");
|
||||
// }
|
||||
|
||||
// // if we need to call a polymorphic method, use type.GetMethod(string, BindingFlags, null, Type[], null)
|
||||
// MethodInfo method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
|
||||
// if (method == null)
|
||||
// {
|
||||
// STrace.LogExThrow();
|
||||
// throw new ArgumentException("Couldn't find method by reflection");
|
||||
// }
|
||||
|
||||
// return method.Invoke(null, parameters);
|
||||
//}
|
||||
|
||||
public static bool IsYukonOrAbove(SMO.Server server)
|
||||
{
|
||||
return server.Version.Major >= 9;
|
||||
}
|
||||
|
||||
public static bool IsBelowYukon(SMO.Server server)
|
||||
{
|
||||
return server.Version.Major < 9;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Some calendars, such as the UmAlQuraCalendar, support an upper date range that is earlier than MaxValue.
|
||||
/// In these cases, trying to access MaxValue in variable assignments or formatting and parsing operations can throw
|
||||
/// an ArgumentOutOfRangeException. Rather than retrieving the value of DateTime.MaxValue, you can retrieve the value
|
||||
/// of the specified culture's latest valid date value from the
|
||||
/// System.Globalization.CultureInfo.DateTimeFormat.Calendar.MaxSupportedDateTime property.
|
||||
/// http://msdn.microsoft.com/en-us/library/system.datetime.maxvalue(v=VS.90).aspx
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
//public static DateTime GetMaxCultureDateTime()
|
||||
//{
|
||||
// CultureInfo currentCulture = System.Threading.Thread.CurrentThread.CU;
|
||||
// return currentCulture.DateTimeFormat.Calendar.MaxSupportedDateTime;
|
||||
//}
|
||||
|
||||
public static string MakeSqlBracket(string s)
|
||||
{
|
||||
return "[" + s.Replace("]", "]]") + "]";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays F1 Help link
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider">Service provider to display help</param>
|
||||
/// <param name="dialogF1Keyword">F1 help link</param>
|
||||
//public static void DisplayHelp(IServiceProvider serviceProvider, string dialogF1Keyword)
|
||||
//{
|
||||
// if (serviceProvider == null)
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// IHelpService helpService = (IHelpService)serviceProvider.GetService(typeof(IHelpService));
|
||||
// if (helpService == null)
|
||||
// {
|
||||
// IHelpProvider helpProvider = (IHelpProvider)serviceProvider.GetService(typeof(IHelpProvider));
|
||||
// if (helpProvider != null)
|
||||
// {
|
||||
// helpProvider.DisplayTopicFromF1Keyword(dialogF1Keyword);
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// helpService.DisplayHelp(dialogF1Keyword);
|
||||
// }
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public reusable helpers
|
||||
/// </summary>
|
||||
public class SqlMgmtUtils
|
||||
{
|
||||
/// <summary>
|
||||
/// only static methods
|
||||
/// </summary>
|
||||
private SqlMgmtUtils() { }
|
||||
|
||||
/// <summary>
|
||||
/// Returns whether the server is in AS Azure
|
||||
/// </summary>
|
||||
/// <param name="serverName"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsASAzure(string serverName)
|
||||
{
|
||||
return !string.IsNullOrEmpty(serverName) && serverName.StartsWith("asazure://", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,6 @@
|
||||
//
|
||||
|
||||
using Microsoft.SqlTools.Hosting.Protocol.Contracts;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin.Contracts
|
||||
{
|
||||
|
||||
@@ -3,10 +3,24 @@
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using Microsoft.SqlTools.Utility;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Admin.Contracts
|
||||
{
|
||||
public class DatabaseInfo
|
||||
{
|
||||
public string Name { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the options
|
||||
/// </summary>
|
||||
public Dictionary<string, object> Options { get; set; }
|
||||
|
||||
public DatabaseInfo()
|
||||
{
|
||||
Options = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// 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.Admin.Contracts
|
||||
{
|
||||
|
||||
public class DefaultDatabaseInfoParams
|
||||
{
|
||||
public string OwnerUri { get; set; }
|
||||
}
|
||||
|
||||
public class DefaultDatabaseInfoResponse
|
||||
{
|
||||
public DatabaseInfo DefaultDatabaseInfo { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class DefaultDatabaseInfoRequest
|
||||
{
|
||||
public static readonly
|
||||
RequestType<DefaultDatabaseInfoParams, DefaultDatabaseInfoResponse> Type =
|
||||
RequestType<DefaultDatabaseInfoParams, DefaultDatabaseInfoResponse>.Create("admin/defaultdatabaseinfo");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user