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:
Karl Burtram
2017-05-09 17:56:32 -07:00
committed by GitHub
parent 137335ffd5
commit 2e9843cec1
48 changed files with 16102 additions and 1446 deletions

View File

@@ -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>

View File

@@ -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"
}
}
};
}
}
}

View File

@@ -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>();
}
}
}

View 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("&lt;");
break;
case '>':
sb.Append("&gt;");
break;
case '&':
sb.Append("&amp;");
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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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
}
}

View File

@@ -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) { }
}
}

View File

@@ -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
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}
}

View 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);
}
}
}

View File

@@ -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();
}
}

View File

@@ -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
}
}

View File

@@ -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();
}
}

View 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;
}
}
}

View File

@@ -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;
}
}
}

View 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);
}
}
}

View File

@@ -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
{

View File

@@ -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>();
}
}
}

View File

@@ -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");
}
}