mirror of
https://github.com/ckaczor/sqltoolsservice.git
synced 2026-02-11 10:38:32 -05:00
Add Agent Job and Job Step request handlers (#635)
* Stage changes * Fix update job request handler * WIP * Additional agent handler updates * Setup agent job step create test * Fix Step update handler
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
//
|
||||
// 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.Text;
|
||||
using System.IO;
|
||||
using System.Data;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.SqlServer.Management.Sdk.Sfc;
|
||||
using Microsoft.SqlServer.Management.Smo;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlServer.Management.Diagnostics;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
{
|
||||
/// <summary>
|
||||
/// Helper static class for the BrowseFolder dialog
|
||||
/// </summary>
|
||||
internal static class BrowseFolderHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Get the initial directory for the browse folder dialog
|
||||
/// </summary>
|
||||
/// <param name="serverConnection">The connection to the server</param>
|
||||
/// <returns></returns>
|
||||
public static string GetBrowseStartPath(ServerConnection serverConnection)
|
||||
{
|
||||
string result = String.Empty;
|
||||
|
||||
// if (US.Current.SSMS.TaskForms.ServerFileSystem.LastPath.TryGetValue(serverConnection.TrueName, out result))
|
||||
// {
|
||||
// return result;
|
||||
// }
|
||||
|
||||
if ((result == null) || (result.Length == 0))
|
||||
{
|
||||
// try and fetch the default location from SMO...
|
||||
Microsoft.SqlServer.Management.Smo.Server server = new Microsoft.SqlServer.Management.Smo.Server(serverConnection);
|
||||
result = server.Settings.DefaultFile;
|
||||
|
||||
if ((result == null) || (result.Length == 0))
|
||||
{
|
||||
// if the default file property doesn't return a string,
|
||||
// use the location of the model database's data file.
|
||||
Enumerator enumerator = new Enumerator();
|
||||
Request request = new Request();
|
||||
request.Urn = "Server/Database[@Name='model']/FileGroup[@Name='PRIMARY']/File";
|
||||
request.Fields = new string[1] {"FileName"};
|
||||
DataSet dataSet = enumerator.Process(serverConnection, request);
|
||||
|
||||
if (0 < dataSet.Tables[0].Rows.Count)
|
||||
{
|
||||
string path = dataSet.Tables[0].Rows[0][0].ToString();
|
||||
result = PathWrapper.GetDirectoryName(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Static class with Utility functions dealing with filenames
|
||||
/// </summary>
|
||||
internal static class FileNameHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Checks whether a filename has invalid characters
|
||||
/// </summary>
|
||||
/// <param name="testName">filename to check</param>
|
||||
/// <returns>true if filename has only valid characters</returns>
|
||||
internal static bool IsValidFilename(string testName)
|
||||
{
|
||||
bool isValid = false;
|
||||
if (!string.IsNullOrEmpty(testName))
|
||||
{
|
||||
Regex containsBadCharacter = new Regex("[" + Regex.Escape(new String(Path.GetInvalidFileNameChars())) + "]");
|
||||
isValid = !containsBadCharacter.IsMatch(testName);
|
||||
}
|
||||
return isValid;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
173
src/Microsoft.SqlTools.ServiceLayer/Management/Common/DbSize.cs
Normal file
173
src/Microsoft.SqlTools.ServiceLayer/Management/Common/DbSize.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
{
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,12 +111,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
/// <summary>
|
||||
/// handler that we delegate execution related tasks to
|
||||
/// </summary>
|
||||
private ExecutionHandlerDelegate panelExecutionHandler;
|
||||
|
||||
/// <summary>
|
||||
/// class that describes available views
|
||||
/// </summary>
|
||||
private ISqlControlCollection viewsHolder;
|
||||
private ExecutionHandlerDelegate executionHandlerDelegate;
|
||||
|
||||
/// <summary>
|
||||
/// class that describes available views that is also aware of execution
|
||||
@@ -133,11 +128,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
/// </summary>
|
||||
private StringBuilder script;
|
||||
|
||||
/// <summary>
|
||||
/// index of the panel that is being executed
|
||||
/// </summary>
|
||||
private int currentlyExecutingPanelIndex;
|
||||
|
||||
/// <summary>
|
||||
/// creates instance of the class and returns service provider that aggregates the provider
|
||||
/// provider with extra services
|
||||
@@ -152,7 +142,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
public ExecutonHandler(IExecutionAwareManagementAction managementAction)
|
||||
{
|
||||
this.managementAction = managementAction;
|
||||
this.panelExecutionHandler = new ExecutionHandlerDelegate(managementAction);
|
||||
this.executionHandlerDelegate = new ExecutionHandlerDelegate(managementAction);
|
||||
}
|
||||
|
||||
#region public interface
|
||||
@@ -194,7 +184,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
{
|
||||
// reset some internal vars
|
||||
this.executionResult = ExecutionMode.Failure;
|
||||
this.currentlyExecutingPanelIndex = -1; // will become 0 if we're executing on view by view basis
|
||||
|
||||
// ensure that we have valid StringBulder for scripting
|
||||
if (IsScripting(runType))
|
||||
@@ -220,7 +209,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
// NOTE: post process action is done in finally block below
|
||||
|
||||
// start executing
|
||||
this.executionResult = this.panelExecutionHandler.Run(runType, sender);
|
||||
this.executionResult = this.executionHandlerDelegate.Run(runType, sender);
|
||||
}
|
||||
#region error handling
|
||||
|
||||
@@ -238,7 +227,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ProcessExceptionDuringExecution(e, this.currentlyExecutingPanelIndex);
|
||||
ProcessExceptionDuringExecution(e);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -272,7 +261,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
|
||||
//otherwise do cancel ourselves
|
||||
// if everything goes OK, Run() method will return with Cancel result
|
||||
this.panelExecutionHandler.Cancel(sender);
|
||||
this.executionHandlerDelegate.Cancel(sender);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -333,10 +322,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
/// helper function that is called when we caught an exception during execution
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
/// <param name="failedViewIndex">-1 indicates that we don't know</param>
|
||||
private void ProcessExceptionDuringExecution(Exception e, int failedViewIndex)
|
||||
private void ProcessExceptionDuringExecution(Exception ex)
|
||||
{
|
||||
//show the error
|
||||
// show the error
|
||||
this.executionResult = ExecutionMode.Failure;
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
//
|
||||
// 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;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlServer.Management.Diagnostics;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
{
|
||||
|
||||
/// <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
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,11 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
/// </summary>
|
||||
private IServiceProvider serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// execution mode by default for now is success
|
||||
/// </summary>
|
||||
private ExecutionMode m_executionMode = ExecutionMode.Success;
|
||||
|
||||
/// <summary>
|
||||
/// data container with initialization-related information
|
||||
/// </summary>
|
||||
@@ -52,7 +57,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
//property by the initialization code
|
||||
private ServerConnection serverConnection;
|
||||
|
||||
private ExecutionHandlerDelegate cachedPanelExecutionHandler;
|
||||
private ExecutionHandlerDelegate cachedExecutionHandlerDelegate;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -71,8 +76,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
//BUGBUG - do we need finalizer
|
||||
Dispose(true);//call protected virtual method
|
||||
// BUGBUG - do we need finalizer
|
||||
Dispose(true); // call protected virtual method
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -103,27 +108,26 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
throw new ArgumentNullException("sp");
|
||||
}
|
||||
|
||||
//allow to be sited only once
|
||||
// allow to be sited only once
|
||||
if (this.serviceProvider == null)
|
||||
{
|
||||
//cache the service provider
|
||||
// cache the service provider
|
||||
this.serviceProvider = sp;
|
||||
|
||||
//call protected virtual method to enable derived classes to do initialization
|
||||
//OnHosted();
|
||||
// call protected virtual method to enable derived classes to do initialization
|
||||
// OnHosted();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IExecutionAwareSqlControlCollection implementation
|
||||
#region IExecutionAwareManagementAction implementation
|
||||
|
||||
/// <summary>
|
||||
/// called before dialog's host executes actions on all panels in the dialog one by one.
|
||||
/// called before management action executes onRun method.
|
||||
/// If something fails inside this function and the execution should be aborted,
|
||||
/// it can either raise an exception [in which case the framework will show message box with exception text]
|
||||
/// it can either raise an exception [in which case the framework will fail with exception text]
|
||||
/// or set executionResult out parameter to be ExecutionMode.Failure
|
||||
/// NOTE: it might be called from worker thread
|
||||
/// </summary>
|
||||
/// <param name="executionInfo">information about execution action</param>
|
||||
/// <param name="executionResult">result of the execution</param>
|
||||
@@ -149,10 +153,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
}
|
||||
}
|
||||
|
||||
if (DataContainer != null)
|
||||
if (this.DataContainer != null)
|
||||
{
|
||||
// we take over execution here. We substitute the server here for SQL containers
|
||||
if (DataContainer.ContainerServerType == CDataContainer.ServerType.SQL)
|
||||
if (this.DataContainer.ContainerServerType == CDataContainer.ServerType.SQL)
|
||||
{
|
||||
ExecuteForSql(executionInfo, out executionResult);
|
||||
return false; // execution of the entire action was done here
|
||||
@@ -199,13 +203,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
{
|
||||
get
|
||||
{
|
||||
//by default we own it
|
||||
// by default we own it
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// called by IExecutionAwareSqlControlCollection.PreProcessExecution to enable derived
|
||||
/// called by IExecutionAwareManagementAction.PreProcessExecution to enable derived
|
||||
/// classes to take over execution of the dialog and do entire execution in this method
|
||||
/// rather than having the framework to execute dialog views one by one.
|
||||
///
|
||||
@@ -226,8 +230,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// called after dialog's host executes actions on all panels in the dialog one by one
|
||||
/// NOTE: it might be called from worker thread
|
||||
/// called after management action executes onRun method.
|
||||
/// </summary>
|
||||
/// <param name="executionMode">result of the execution</param>
|
||||
/// <param name="runType">type of execution</param>
|
||||
@@ -235,34 +238,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
{
|
||||
//nothing to do in the base class
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// called before dialog's host executes OnReset method on all panels in the dialog one by one
|
||||
/// NOTE: it might be called from worker thread
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// true if regular execution should take place, false if everything
|
||||
/// has been done by this function
|
||||
/// </returns>
|
||||
/// <returns></returns>
|
||||
protected virtual bool DoPreProcessReset()
|
||||
{
|
||||
if ((this.dataContainer != null) && this.dataContainer.IsNewObject)
|
||||
{
|
||||
this.dataContainer.Reset();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// called after dialog's host executes OnReset method on all panels in the dialog one by one
|
||||
/// NOTE: it might be called from worker thread
|
||||
/// </summary>
|
||||
protected virtual void DoPostProcessReset()
|
||||
{
|
||||
//nothing in the base class
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called to intercept scripting operation
|
||||
@@ -344,7 +319,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
if (DoPreProcessExecution(runType, out executionResult))
|
||||
{
|
||||
// true return value means that we need to do execution ourselves
|
||||
executionResult = PanelExecutionHandler.Run(runType, this);
|
||||
executionResult = ExecutionHandlerDelegate.Run(runType, this);
|
||||
}
|
||||
|
||||
return executionResult;
|
||||
@@ -446,18 +421,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
private void ExecuteForSql(PreProcessExecutionInfo executionInfo, out ExecutionMode executionResult)
|
||||
{
|
||||
Microsoft.SqlServer.Management.Smo.Server oldServer = null;
|
||||
if (NeedToSwitchServer)
|
||||
if (this.NeedToSwitchServer)
|
||||
{
|
||||
// We use a new instance of the SMO Server object every time we script
|
||||
// so that any changes that are made to the SMO server while scripting are
|
||||
// not kept when the script operation is completed.
|
||||
oldServer = DataContainer.Server;
|
||||
oldServer = this.DataContainer.Server;
|
||||
|
||||
//BUGBUG - see if we can use copy ctor instead
|
||||
DataContainer.Server = new Microsoft.SqlServer.Management.Smo.Server(DataContainer.ServerConnection);
|
||||
// BUGBUG - see if we can use copy ctor instead
|
||||
this.DataContainer.Server = new Microsoft.SqlServer.Management.Smo.Server(DataContainer.ServerConnection);
|
||||
}
|
||||
|
||||
string szScript = null;
|
||||
string script = null;
|
||||
bool isScripting = IsScripting(executionInfo.RunType);
|
||||
var executionModeOriginal = GetServerConnectionForScript().SqlExecutionModes;
|
||||
// For Azure the ExecutionManager is different depending on which ExecutionManager
|
||||
@@ -499,7 +474,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
{
|
||||
if (executionResult == ExecutionMode.Success)
|
||||
{
|
||||
szScript = BuildSqlScript();
|
||||
script = BuildSqlScript();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -524,13 +499,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
//see if we need to restore the server
|
||||
if (oldServer != null)
|
||||
{
|
||||
DataContainer.Server = oldServer;
|
||||
this.DataContainer.Server = oldServer;
|
||||
}
|
||||
}
|
||||
|
||||
if (isScripting)
|
||||
{
|
||||
executionInfo.Script = szScript;
|
||||
executionInfo.Script = script;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -538,112 +513,18 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
/// returns internal helper class that we delegate execution of the panels one by one when
|
||||
/// we do it ourselves during scripting
|
||||
/// </summary>
|
||||
private ExecutionHandlerDelegate PanelExecutionHandler
|
||||
private ExecutionHandlerDelegate ExecutionHandlerDelegate
|
||||
{
|
||||
get
|
||||
{
|
||||
if (this.cachedPanelExecutionHandler == null)
|
||||
if (this.cachedExecutionHandlerDelegate == null)
|
||||
{
|
||||
this.cachedPanelExecutionHandler = new ExecutionHandlerDelegate(this);
|
||||
this.cachedExecutionHandlerDelegate = new ExecutionHandlerDelegate(this);
|
||||
}
|
||||
return this.cachedPanelExecutionHandler;
|
||||
return this.cachedExecutionHandlerDelegate;
|
||||
}
|
||||
}
|
||||
|
||||
// #region ICustomAttributeProvider
|
||||
// object[] System.Reflection.ICustomAttributeProvider.GetCustomAttributes(bool inherit)
|
||||
// {
|
||||
// //we merge attributes from 2 sources: type attributes and the derived classes, giving preference
|
||||
// //to the derived classes
|
||||
// return GetMergedArray(DoGetCustomAttributes(inherit), GetType().GetCustomAttributes(inherit));
|
||||
// }
|
||||
// object[] System.Reflection.ICustomAttributeProvider.GetCustomAttributes(Type attributeType, bool inherit)
|
||||
// {
|
||||
// //we merge attributes from 2 sources: type attributes and the derived classes, giving preference
|
||||
// //to the derived classes
|
||||
// return GetMergedArray(DoGetCustomAttributes(attributeType, inherit),
|
||||
// GetType().GetCustomAttributes(attributeType, inherit));
|
||||
// }
|
||||
// bool System.Reflection.ICustomAttributeProvider.IsDefined(Type attributeType, bool inherit)
|
||||
// {
|
||||
// //we merge attributes from 2 sources: type attributes and the derived classes, giving preference
|
||||
// //to the derived classes
|
||||
// if (!DoIsDefined(attributeType, inherit))
|
||||
// {
|
||||
// return GetType().IsDefined(attributeType, inherit);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// #endregion
|
||||
// #region ICustomAttributeProvider helpers
|
||||
// protected virtual object[] DoGetCustomAttributes(bool inherit)
|
||||
// {
|
||||
// return GetMergedArray(DoGetCustomAttributes(typeof(ScriptTypeAttribute), inherit),
|
||||
// DoGetCustomAttributes(typeof(DialogScriptableAttribute), inherit));
|
||||
// }
|
||||
// protected virtual object[] DoGetCustomAttributes(Type attributeType, bool inherit)
|
||||
// {
|
||||
// //if the type specifies this attribute, we don't bother - it overrides
|
||||
// //our behavior
|
||||
// object[] typeAttribs = GetType().GetCustomAttributes(attributeType, inherit);
|
||||
// if (typeAttribs != null && typeAttribs.Length > 0)
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
// //we expose default custom attribute for script type
|
||||
// if (attributeType.Equals(typeof(ScriptTypeAttribute)))
|
||||
// {
|
||||
// string scriptType = ScriptType;
|
||||
// if (scriptType != null)
|
||||
// {
|
||||
// return new object[] {new ScriptTypeAttribute(scriptType)};
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
// }
|
||||
// else if (attributeType.Equals(typeof(DialogScriptableAttribute)))
|
||||
// {
|
||||
// bool canScriptToWindow = true;
|
||||
// bool canScriptToFile = true;
|
||||
// bool canScriptToClipboard = true;
|
||||
// bool canScriptToJob = true;
|
||||
// GetScriptableOptions(out canScriptToWindow,
|
||||
// out canScriptToFile,
|
||||
// out canScriptToClipboard,
|
||||
// out canScriptToJob);
|
||||
// return new object[] {new DialogScriptableAttribute(canScriptToWindow,
|
||||
// canScriptToFile,
|
||||
// canScriptToClipboard,
|
||||
// canScriptToJob)};
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
// protected virtual bool DoIsDefined(Type attributeType, bool inherit)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// /// <summary>
|
||||
// /// detects whether script types are applicable for this dlg or not. By default
|
||||
// /// the framework relies on DialogScriptableAttribute set on the dlg class and won't
|
||||
// /// call this method if the attribute is specified
|
||||
// /// By default we assume that all script types are enabled
|
||||
// /// </summary>
|
||||
// /// <param name="?"></param>
|
||||
// /// <param name="?"></param>
|
||||
// /// <param name="?"></param>
|
||||
// protected virtual void GetScriptableOptions(out bool canScriptToWindow,
|
||||
// out bool canScriptToFile,
|
||||
// out bool canScriptToClipboard,
|
||||
// out bool canScriptToJob)
|
||||
// {
|
||||
// canScriptToWindow = canScriptToFile = canScriptToClipboard = canScriptToJob = true;
|
||||
// }
|
||||
// #endregion
|
||||
protected IServiceProvider ServiceProvider
|
||||
{
|
||||
get
|
||||
@@ -656,35 +537,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
return this.serviceProvider;
|
||||
}
|
||||
}
|
||||
// /// <summary>
|
||||
// /// returns combination of the given 2 arrays
|
||||
// /// </summary>
|
||||
// /// <param name="array1"></param>
|
||||
// /// <param name="array2"></param>
|
||||
// /// <returns></returns>
|
||||
// protected object[] GetMergedArray(object[] array1, object[] array2)
|
||||
// {
|
||||
// if (array1 == null)
|
||||
// {
|
||||
// return array2;
|
||||
// }
|
||||
// else if (array2 == null)
|
||||
// {
|
||||
// return array1;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// object[] finalReturnValue = new object[array1.Length + array2.Length];
|
||||
// array1.CopyTo(finalReturnValue, 0);
|
||||
// array2.CopyTo(finalReturnValue, array1.Length);
|
||||
// return finalReturnValue;
|
||||
// }
|
||||
// }
|
||||
|
||||
/// <summary>
|
||||
/// execution mode by default for now is success
|
||||
/// </summary>
|
||||
private ExecutionMode m_executionMode = ExecutionMode.Success;
|
||||
|
||||
/// <summary>
|
||||
/// execution mode accessor
|
||||
@@ -737,7 +589,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
/// <param name="sender"></param>
|
||||
public virtual string OnScript(object sender)
|
||||
{
|
||||
//redirect to the single scripting virtual method by default
|
||||
// redirect to the single scripting virtual method by default
|
||||
return Script();
|
||||
}
|
||||
|
||||
@@ -758,7 +610,6 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// performs custom action wen user requests a cancel
|
||||
/// this is called from the UI thread and generally executes
|
||||
@@ -779,6 +630,5 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
// this.dataContainer.Server.Cancel();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.Management
|
||||
{
|
||||
/// <summary>
|
||||
/// SqlTools Parameters, used to define what goes into starting up a Workbench Form
|
||||
/// AKA a dbCommander, AKA a "dialog"
|
||||
/// These parameters are xml snippets
|
||||
/// </summary>
|
||||
public class STParameters
|
||||
{
|
||||
public XmlDocument m_doc;
|
||||
|
||||
/// <summary>
|
||||
/// The data type we are interested in
|
||||
/// </summary>
|
||||
public enum STType { eNULL, eInt, eLong, eString };
|
||||
|
||||
/// <summary>
|
||||
/// default constructor
|
||||
/// </summary>
|
||||
public STParameters()
|
||||
{
|
||||
//
|
||||
// TODO: Add constructor logic here
|
||||
//
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="xmlDoc">The xml snippet used to control the dbCommander</param>
|
||||
public STParameters(XmlDocument xmlDoc)
|
||||
{
|
||||
m_doc = xmlDoc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changing the xml snippet we are using
|
||||
/// </summary>
|
||||
/// <param name="xmlDoc">the new xml snippet</param>
|
||||
public void SetDocument(XmlDocument xmlDoc)
|
||||
{
|
||||
m_doc = xmlDoc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Access to the xml we are using for dbCommander parameters
|
||||
/// </summary>
|
||||
/// <returns>our current parameters</returns>
|
||||
public XmlDocument GetDocument()
|
||||
{
|
||||
return m_doc;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search for an xml tag, and return its value
|
||||
/// </summary>
|
||||
/// <param name="parameterName">the xml tag name</param>
|
||||
/// <param name="value">the value of that tag</param>
|
||||
/// <returns>flag that is true if the data was found, false if not</returns>
|
||||
public bool GetBaseParam(string parameterName, ref object value)
|
||||
{
|
||||
XmlNodeList nodeList = null;
|
||||
bool parameterExists;
|
||||
|
||||
if (m_doc == null)
|
||||
return false;
|
||||
|
||||
parameterExists = false;
|
||||
nodeList = m_doc.GetElementsByTagName(parameterName);
|
||||
|
||||
if (nodeList.Count > 1)
|
||||
{
|
||||
value = null;
|
||||
}
|
||||
else if (nodeList.Count != 0) // anything there?
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlNode node = nodeList.Item(0);
|
||||
if (null != node)
|
||||
{
|
||||
value = node.InnerText as object;
|
||||
parameterExists = true;
|
||||
}
|
||||
}
|
||||
catch (Exception /*e*/)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return parameterExists;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds an existing xml tag, and sets it to a new value, or if the tag is not found
|
||||
/// create it and set it's value
|
||||
/// </summary>
|
||||
/// <param name="parameterName">tag name</param>
|
||||
/// <param name="value">new value</param>
|
||||
/// <returns>flag that is true if the tag was set, false if not</returns>
|
||||
public bool SetBaseParam(string parameterName, object value)
|
||||
{
|
||||
XmlNodeList nodeList;
|
||||
bool success = false;
|
||||
|
||||
nodeList = m_doc.GetElementsByTagName(parameterName);
|
||||
|
||||
if (nodeList.Count == 1)
|
||||
{
|
||||
try
|
||||
{
|
||||
nodeList.Item(0).InnerText = (string)value;
|
||||
success = true;
|
||||
}
|
||||
catch (InvalidCastException /*e*/)
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (nodeList.Count == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlElement xmlElement = m_doc.CreateElement(parameterName);
|
||||
XmlNode root = m_doc.DocumentElement;
|
||||
|
||||
nodeList = m_doc.GetElementsByTagName("params");
|
||||
|
||||
if (nodeList.Count == 1 && value is string)
|
||||
{
|
||||
xmlElement.InnerText = (string)value;
|
||||
nodeList.Item(0).InsertAfter(xmlElement, nodeList.Item(0).LastChild);
|
||||
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
string sz = e.ToString();
|
||||
success = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return success;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get back an interger parameter.
|
||||
/// NOTE: if the tag exists, but it contains non-numeric data, this will throw
|
||||
/// An exception of type 'System.FormatException'
|
||||
/// with Additional information: Could not find any parsible digits.
|
||||
/// </summary>
|
||||
/// <param name="parameterName">xml tag name for the parameter of interest</param>
|
||||
/// <param name="iValue">out value of parameter</param>
|
||||
/// <returns>flag that is true if the data was found, false if not</returns>
|
||||
public bool GetParam(string parameterName, out int value)
|
||||
{
|
||||
bool parameterExists = false;
|
||||
|
||||
value = 0;
|
||||
|
||||
try
|
||||
{
|
||||
object oAux = null;
|
||||
|
||||
if (parameterExists = GetBaseParam(parameterName, ref oAux))
|
||||
{
|
||||
try
|
||||
{
|
||||
value = Convert.ToInt32((string)oAux, 10); // data is always a string, it is the value of XmlNode.InnerText
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
Debug.WriteLine(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Non numeric data in tag: {0}", parameterName));
|
||||
Debug.WriteLine(e.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InvalidCastException /*e*/)
|
||||
{
|
||||
}
|
||||
|
||||
return parameterExists;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Accessor for a boolean parameter
|
||||
/// NOTE: if the tag exists, but it contains non-numeric data, this will throw
|
||||
/// An exception of type 'System.FormatException'
|
||||
/// with Additional information: Could not find any parsible digits.
|
||||
/// </summary>
|
||||
/// <param name="parameterName">xml tag name for the parameter of interest</param>
|
||||
/// <param name="value">out value of parameter</param>
|
||||
/// <returns>flag that is true if the data was found, false if not</returns>
|
||||
public bool GetParam(string parameterName, ref bool value)
|
||||
{
|
||||
bool parameterExists = false;
|
||||
|
||||
value = false;
|
||||
|
||||
try
|
||||
{
|
||||
object oAux = null;
|
||||
if (parameterExists = GetBaseParam(parameterName, ref oAux))
|
||||
{
|
||||
try
|
||||
{
|
||||
value = Convert.ToBoolean((string)oAux, System.Globalization.CultureInfo.InvariantCulture); // data is always a string, it is the value of XmlNode.InnerText
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
Debug.WriteLine(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Non boolean data in tag: {0}", parameterName));
|
||||
Debug.WriteLine(e.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InvalidCastException /*e*/)
|
||||
{
|
||||
}
|
||||
|
||||
return parameterExists;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Accessor to a string parameter
|
||||
/// </summary>
|
||||
/// <param name="parameterName">xml tag name for the parameter of interest</param>
|
||||
/// <param name="value">out value of parameter</param>
|
||||
/// <returns>flag that is true if the data was found, false if not</returns>
|
||||
public bool GetParam(string parameterName, ref string value)
|
||||
{
|
||||
bool parameterExists;
|
||||
|
||||
value = "";
|
||||
parameterExists = false;
|
||||
|
||||
try
|
||||
{
|
||||
object oAux = null;
|
||||
|
||||
if (parameterExists = GetBaseParam(parameterName, ref oAux))
|
||||
{
|
||||
value = (string)oAux;
|
||||
}
|
||||
}
|
||||
catch (InvalidCastException /*e*/)
|
||||
{
|
||||
}
|
||||
|
||||
return parameterExists;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Accessor to long parameter (Int64)
|
||||
/// NOTE: if the tag exists, but it contains non-numeric data, this will throw
|
||||
/// An exception of type 'System.FormatException'
|
||||
/// with Additional information: Could not find any parsible digits.
|
||||
/// </summary>
|
||||
/// <param name="parameterName">xml tag name for the parameter of interest</param>
|
||||
/// <param name="value">out value of parameter</param>
|
||||
/// <returns>flag that is true if the data was found, false if not</returns>
|
||||
public bool GetParam(string parameterName, out long value)
|
||||
{
|
||||
bool parameterExists = false;
|
||||
|
||||
value = 0;
|
||||
|
||||
try
|
||||
{
|
||||
object oAux = null;
|
||||
|
||||
if (parameterExists = GetBaseParam(parameterName, ref oAux))
|
||||
{
|
||||
try
|
||||
{
|
||||
value = Convert.ToInt64((string)oAux, 10); // data is always a string, it is the value of XmlNode.InnerText
|
||||
}
|
||||
catch (FormatException e)
|
||||
{
|
||||
Debug.WriteLine(String.Format(System.Globalization.CultureInfo.CurrentCulture, "Non numeric data in tag: {0}", parameterName));
|
||||
Debug.WriteLine(e.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (InvalidCastException /*e*/)
|
||||
{
|
||||
}
|
||||
|
||||
return parameterExists;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Set an int (Int32) parameter
|
||||
/// </summary>
|
||||
/// <param name="parameterName">tag name for parameter</param>
|
||||
/// <param name="value">integer value</param>
|
||||
/// <returns>true if set was successful, false if not</returns>
|
||||
public bool SetParam(string parameterName, int value)
|
||||
{
|
||||
bool success;
|
||||
|
||||
success = SetBaseParam(parameterName, (object)value);
|
||||
|
||||
return success;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a string parameter
|
||||
/// </summary>
|
||||
/// <param name="parameterName">tag name for parameter</param>
|
||||
/// <param name="value">string value</param>
|
||||
/// <returns>true if set was successful, false if not</returns>
|
||||
public bool SetParam(string parameterName, string value)
|
||||
{
|
||||
bool success;
|
||||
|
||||
success = SetBaseParam(parameterName, (object)value);
|
||||
|
||||
return success;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a long (Int64) parameter
|
||||
/// </summary>
|
||||
/// <param name="parameterName">tag name for parameter</param>
|
||||
/// <param name="value">long value</param>
|
||||
/// <returns>true if set was successful, false if not</returns>
|
||||
public bool SetParam(string parameterName, long value)
|
||||
{
|
||||
bool success;
|
||||
|
||||
success = SetBaseParam(parameterName, (object)value);
|
||||
|
||||
return success;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a string collection parameter
|
||||
/// </summary>
|
||||
/// <param name="parameterName">name of collection</param>
|
||||
/// <param name="list">collection that gets filled up with parameters</param>
|
||||
/// <param name="getInnerXml">true if we want to get at inner nodes, false if not</param>
|
||||
/// <returns>true if parameter(s) exist</returns>
|
||||
public bool GetParam(string parameterName, System.Collections.Specialized.StringCollection list, bool getInnerXml)
|
||||
{
|
||||
/// necessary for OALP objects path that is in an XML form
|
||||
if (true == getInnerXml)
|
||||
{
|
||||
XmlNodeList nodeList;
|
||||
bool parameterExists;
|
||||
long lCount;
|
||||
|
||||
parameterExists = false;
|
||||
nodeList = m_doc.GetElementsByTagName(parameterName);
|
||||
|
||||
list.Clear();
|
||||
|
||||
lCount = nodeList.Count;
|
||||
|
||||
if (lCount > 0)
|
||||
{
|
||||
parameterExists = true;
|
||||
|
||||
for (long i = 0; i < lCount; i++)
|
||||
{
|
||||
list.Add(nodeList.Item((int)i).InnerXml);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
parameterExists = false;
|
||||
}
|
||||
|
||||
return parameterExists;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetParam(parameterName, list);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Access to a collection of parameters
|
||||
/// </summary>
|
||||
/// <param name="parameterName">name of collection</param>
|
||||
/// <param name="list">list to fill with parameters</param>
|
||||
/// <returns>parameter(s) exist</returns>
|
||||
public bool GetParam(string parameterName, System.Collections.Specialized.StringCollection list)
|
||||
{
|
||||
XmlNodeList nodeList;
|
||||
bool parameterExists;
|
||||
long lCount;
|
||||
|
||||
parameterExists = false;
|
||||
nodeList = m_doc.GetElementsByTagName(parameterName);
|
||||
|
||||
list.Clear();
|
||||
|
||||
lCount = nodeList.Count;
|
||||
|
||||
if (lCount > 0)
|
||||
{
|
||||
parameterExists = true;
|
||||
|
||||
for (long i = 0; i < lCount; i++)
|
||||
{
|
||||
list.Add(nodeList.Item((int)i).InnerText);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
parameterExists = false;
|
||||
}
|
||||
|
||||
return parameterExists;
|
||||
}
|
||||
|
||||
public bool GetParam(string parameterName, ref ArrayList list)
|
||||
{
|
||||
System.Collections.Specialized.StringCollection stringList = new System.Collections.Specialized.StringCollection();
|
||||
bool parameterExists = GetParam(parameterName, stringList);
|
||||
list.Clear();
|
||||
if (!parameterExists)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < stringList.Count; i++)
|
||||
{
|
||||
list.Add(stringList[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function does nothing but return false
|
||||
/// </summary>
|
||||
/// <param name="parameterName">ignored</param>
|
||||
/// <param name="type">ignored</param>
|
||||
/// <returns>always false</returns>
|
||||
public bool GetParamType(string parameterName, STType type)
|
||||
{
|
||||
bool whatever = false;
|
||||
|
||||
return whatever;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function does nothing but return false
|
||||
/// </summary>
|
||||
/// <param name="parameterName">ignored</param>
|
||||
/// <param name="type">ignored</param>
|
||||
/// <returns>always false</returns>
|
||||
public bool SetParamType(string parameterName, STType type)
|
||||
{
|
||||
bool whatever = false;
|
||||
|
||||
return whatever;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
//
|
||||
|
||||
using System;
|
||||
//using Microsoft.SqlServer.Management.AzureCredential;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
//using Microsoft.SqlServer.Management.Smo.RegSvrEnum;
|
||||
using SFC = Microsoft.SqlServer.Management.Sdk.Sfc;
|
||||
//using Microsoft.SqlServer.StorageClient;
|
||||
//using Microsoft.SqlServer.Management.SqlMgmt;
|
||||
|
||||
/// <summary>
|
||||
/// Summary description for SharedConectionUtil
|
||||
/// Moved GetConnectionName static call in a public class acessible for both
|
||||
/// OEXM and OE
|
||||
/// </summary>
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// //
|
||||
// // Copyright (c) Microsoft. All rights reserved.
|
||||
// // Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
// //
|
||||
|
||||
// using System;
|
||||
|
||||
// /// <summary>
|
||||
// /// Defines static values for both Yukon and Shiloh
|
||||
// /// </summary>
|
||||
// namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
// {
|
||||
// public class SqlLimits
|
||||
// {
|
||||
// internal SqlLimits()
|
||||
// {
|
||||
// }
|
||||
|
||||
// //Define Version 9 Limits
|
||||
// //Currently MAX is the same for both nVarchar and Varchar.
|
||||
// public static readonly int VarcharMax = 1073741824;
|
||||
// public static readonly int SysName = 128;
|
||||
|
||||
// //Define Pre-Version 9 Limits
|
||||
// public static readonly int CommandDimensionMaxLength=3200;
|
||||
// }
|
||||
// }
|
||||
657
src/Microsoft.SqlTools.ServiceLayer/Management/Common/Utils.cs
Normal file
657
src/Microsoft.SqlTools.ServiceLayer/Management/Common/Utils.cs
Normal file
@@ -0,0 +1,657 @@
|
||||
//
|
||||
// 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;
|
||||
using System.Data.SqlClient;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
using Microsoft.SqlServer.Management.Common;
|
||||
using Microsoft.SqlServer.Management.Diagnostics;
|
||||
using Microsoft.SqlServer.Management.Sdk.Sfc;
|
||||
using SMO = Microsoft.SqlServer.Management.Smo;
|
||||
|
||||
namespace Microsoft.SqlTools.ServiceLayer.Management
|
||||
{
|
||||
/// <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;
|
||||
}
|
||||
|
||||
public static bool IsYukonOrAbove(SMO.Server server)
|
||||
{
|
||||
return server.Version.Major >= 9;
|
||||
}
|
||||
|
||||
public static bool IsBelowYukon(SMO.Server server)
|
||||
{
|
||||
return server.Version.Major < 9;
|
||||
}
|
||||
|
||||
public static string MakeSqlBracket(string s)
|
||||
{
|
||||
return "[" + s.Replace("]", "]]") + "]";
|
||||
}
|
||||
}
|
||||
|
||||
/// <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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <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 static void UseMaster(SMO.Server server)
|
||||
{
|
||||
server.ConnectionContext.ExecuteNonQuery("use master");
|
||||
}
|
||||
|
||||
/// <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>
|
||||
/// Determines the oldest date based on the type of time units and the number of time units
|
||||
/// </summary>
|
||||
/// <param name="numUnits"></param>
|
||||
/// <param name="typeUnits"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime GetOldestDate(int numUnits, TimeUnitType typeUnits)
|
||||
{
|
||||
DateTime result = DateTime.Now;
|
||||
|
||||
switch (typeUnits)
|
||||
{
|
||||
case TimeUnitType.Week:
|
||||
{
|
||||
result = (DateTime.Now).AddDays(-1 * 7 * numUnits);
|
||||
break;
|
||||
}
|
||||
case TimeUnitType.Month:
|
||||
{
|
||||
result = (DateTime.Now).AddMonths(-1 * numUnits);
|
||||
break;
|
||||
}
|
||||
case TimeUnitType.Year:
|
||||
{
|
||||
result = (DateTime.Now).AddYears(-1 * numUnits);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
result = (DateTime.Now).AddDays(-1 * numUnits);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static string TokenizeXml(string s)
|
||||
{
|
||||
if (null == s) return String.Empty;
|
||||
|
||||
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||||
foreach (char c in s)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '<':
|
||||
sb.Append("<");
|
||||
break;
|
||||
case '>':
|
||||
sb.Append(">");
|
||||
break;
|
||||
case '&':
|
||||
sb.Append("&");
|
||||
break;
|
||||
default:
|
||||
sb.Append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to get the SqlException out of an Enumerator exception
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
/// <returns></returns>
|
||||
public static SqlException GetSqlException(Exception e)
|
||||
{
|
||||
SqlException sqlEx = null;
|
||||
Exception exception = e;
|
||||
while (exception != null)
|
||||
{
|
||||
sqlEx = exception as SqlException;
|
||||
if (null != sqlEx)
|
||||
{
|
||||
break;
|
||||
}
|
||||
exception = exception.InnerException;
|
||||
}
|
||||
return sqlEx;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// computes the name of the machine based on server's name (as returned by smoServer.Name)
|
||||
/// </summary>
|
||||
/// <param name="sqlServerName">name of server ("",".","Server","Server\Instance",etc)</param>
|
||||
/// <returns>name of the machine hosting sql server instance</returns>
|
||||
public static string GetMachineName(string sqlServerName)
|
||||
{
|
||||
System.Diagnostics.Debug.Assert(sqlServerName != null);
|
||||
|
||||
string machineName = sqlServerName;
|
||||
if (sqlServerName.Trim().Length != 0)
|
||||
{
|
||||
// [0] = machine, [1] = instance (if any)
|
||||
return sqlServerName.Split('\\')[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have default instance of default machine
|
||||
return machineName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if a SqlException is Permission denied exception
|
||||
/// </summary>
|
||||
/// <param name="sqlException"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsPermissionDeniedException(SqlException sqlException)
|
||||
{
|
||||
bool isPermDenied = false;
|
||||
if (null != sqlException.Errors)
|
||||
{
|
||||
foreach (SqlError sqlError in sqlException.Errors)
|
||||
{
|
||||
int errorNumber = GetSqlErrorNumber(sqlError);
|
||||
|
||||
if ((ObjectPermissionsDeniedErrorNumber == errorNumber) ||
|
||||
(ColumnPermissionsDeniedErrorNumber == errorNumber))
|
||||
{
|
||||
isPermDenied = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return isPermDenied;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the error number of a sql exeception
|
||||
/// </summary>
|
||||
/// <param name="sqlerror"></param>
|
||||
/// <returns></returns>
|
||||
public static int GetSqlErrorNumber(SqlError sqlerror)
|
||||
{
|
||||
return sqlerror.Number;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function doubles up specified character in a string
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <param name="cEsc"></param>
|
||||
/// <returns></returns>
|
||||
public static String EscapeString(string s, char cEsc)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(s.Length * 2);
|
||||
foreach (char c in s)
|
||||
{
|
||||
sb.Append(c);
|
||||
if (cEsc == c)
|
||||
sb.Append(c);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function doubles up ']' character in a string
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
public static String EscapeStringCBracket(string s)
|
||||
{
|
||||
return CUtils.EscapeString(s, ']');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function doubles up '\'' character in a string
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
public static String EscapeStringSQuote(string s)
|
||||
{
|
||||
return CUtils.EscapeString(s, '\'');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function removes doubled up specified character from a string
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <param name="cEsc"></param>
|
||||
/// <returns></returns>
|
||||
public static String UnEscapeString(string s, char cEsc)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(s.Length);
|
||||
bool foundBefore = false;
|
||||
foreach (char c in s)
|
||||
{
|
||||
if (cEsc == c) // character to unescape
|
||||
{
|
||||
if (foundBefore) // skip second occurrence
|
||||
{
|
||||
foundBefore = false;
|
||||
}
|
||||
else // set the flag to skip next time around
|
||||
{
|
||||
sb.Append(c);
|
||||
foundBefore = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(c);
|
||||
foundBefore = false;
|
||||
}
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function removes doubled up ']' character from a string
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
public static String UnEscapeStringCBracket(string s)
|
||||
{
|
||||
return CUtils.UnEscapeString(s, ']');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Function removes doubled up '\'' character from a string
|
||||
/// </summary>
|
||||
/// <param name="s"></param>
|
||||
/// <returns></returns>
|
||||
public static String UnEscapeStringSQuote(string s)
|
||||
{
|
||||
return CUtils.UnEscapeString(s, '\'');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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>
|
||||
/// Enum of time units types ( used in cleaning up history based on age )
|
||||
/// </summary>
|
||||
internal enum TimeUnitType
|
||||
{
|
||||
Day,
|
||||
Week,
|
||||
Month,
|
||||
Year
|
||||
}
|
||||
|
||||
/// <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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user