Address warnings and (some) nullables (#2013)

This commit is contained in:
Cheena Malhotra
2023-04-18 20:57:13 -07:00
committed by GitHub
parent d56f2309da
commit 648d7dbd3c
83 changed files with 674 additions and 588 deletions

View File

@@ -413,22 +413,19 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource.Kusto
{ {
var returnList = new List<DataSourceObjectMetadata>(); var returnList = new List<DataSourceObjectMetadata>();
if (_folderMetadata.ContainsKey(key)) if (_folderMetadata.TryGetValue(key, out IEnumerable<FolderMetadata>? folderMetadata))
{ {
returnList.AddRange(_folderMetadata[key] returnList.AddRange(folderMetadata.OrderBy(x => x.PrettyName, StringComparer.OrdinalIgnoreCase));
.OrderBy(x => x.PrettyName, StringComparer.OrdinalIgnoreCase));
} }
if (_tableMetadata.ContainsKey(key)) if (_tableMetadata.TryGetValue(key, out IEnumerable<TableMetadata>? tableMetadata))
{ {
returnList.AddRange(_tableMetadata[key] returnList.AddRange(tableMetadata.OrderBy(x => x.PrettyName, StringComparer.OrdinalIgnoreCase));
.OrderBy(x => x.PrettyName, StringComparer.OrdinalIgnoreCase));
} }
if (_functionMetadata.ContainsKey(key)) if (_functionMetadata.TryGetValue(key, out IEnumerable<FunctionMetadata>? functionMetadata))
{ {
returnList.AddRange(_functionMetadata[key] returnList.AddRange(functionMetadata.OrderBy(x => x.PrettyName, StringComparer.OrdinalIgnoreCase));
.OrderBy(x => x.PrettyName, StringComparer.OrdinalIgnoreCase));
} }
return returnList; return returnList;
@@ -515,16 +512,15 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource.Kusto
private IEnumerable<DataSourceObjectMetadata> GetTableSchema(TableMetadata tableMetadata) private IEnumerable<DataSourceObjectMetadata> GetTableSchema(TableMetadata tableMetadata)
{ {
var key = GenerateMetadataKey(tableMetadata.DatabaseName, tableMetadata.Name); var key = GenerateMetadataKey(tableMetadata.DatabaseName, tableMetadata.Name);
if (_columnMetadata.ContainsKey(key)) if (_columnMetadata.TryGetValue(key, out IEnumerable<DataSourceObjectMetadata>? metadata))
{ {
return _columnMetadata[key]; return metadata;
} }
SetTableSchema(tableMetadata); SetTableSchema(tableMetadata);
return _columnMetadata.ContainsKey(key) return _columnMetadata.TryGetValue(key, out IEnumerable<DataSourceObjectMetadata>? columnMetadata)
? _columnMetadata[key] ? columnMetadata : Enumerable.Empty<DataSourceObjectMetadata>();
: Enumerable.Empty<DataSourceObjectMetadata>();
} }
private void SetTableSchema(TableMetadata tableMetadata) private void SetTableSchema(TableMetadata tableMetadata)
@@ -683,9 +679,9 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource.Kusto
Urn = $"{tableKey}.{table.TableName}" Urn = $"{tableKey}.{table.TableName}"
}; };
if (tableFolders.ContainsKey(tableKey.ToString())) if (tableFolders.TryGetValue(tableKey.ToString(), out List<TableMetadata>? tableMetadataList))
{ {
tableFolders[tableKey.ToString()].Add(tableMetadata); tableMetadataList.Add(tableMetadata);
} }
else else
{ {

View File

@@ -12,7 +12,7 @@ using Microsoft.Kusto.ServiceLayer.DataSource.Metadata;
namespace Microsoft.Kusto.ServiceLayer.DataSource namespace Microsoft.Kusto.ServiceLayer.DataSource
{ {
public static class KustoQueryUtils public static partial class KustoQueryUtils
{ {
public const string StatementSeparator = "\n | "; // Start each statement on a new line. Not required by Kusto, but doing this for readability of scripts generated from here. public const string StatementSeparator = "\n | "; // Start each statement on a new line. Not required by Kusto, but doing this for readability of scripts generated from here.
@@ -30,7 +30,6 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
} }
string result = name; string result = name;
Regex rx = new Regex("[^_a-zA-Z0-9]");
string [] kustoKeywordList = {"and", "anomalychart", "areachart", "asc", "barchart", "between", "bool", "boolean", "by", string [] kustoKeywordList = {"and", "anomalychart", "areachart", "asc", "barchart", "between", "bool", "boolean", "by",
"columnchart", "consume", "contains", "containscs", "count", "date", "datetime", "default", "desc", "distinct", "columnchart", "consume", "contains", "containscs", "count", "date", "datetime", "default", "desc", "distinct",
"double", "dynamic", "endswith", "evaluate", "extend", "false", "filter", "find", "first", "flags", "float", "double", "dynamic", "endswith", "evaluate", "extend", "false", "filter", "find", "first", "flags", "float",
@@ -41,7 +40,7 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
"take", "time", "timechart", "timeline", "timepivot", "timespan", "to", "top", "toscalar", "true", "union", "take", "time", "timechart", "timeline", "timepivot", "timespan", "to", "top", "toscalar", "true", "union",
"unstacked", "viewers", "where", "withsource"}; // add more keywords here "unstacked", "viewers", "where", "withsource"}; // add more keywords here
var escapeName = rx.IsMatch(name) || kustoKeywordList.Any(name.Contains) || alwaysEscape; var escapeName = GetNameRegex().IsMatch(name) || kustoKeywordList.Any(name.Contains) || alwaysEscape;
if (escapeName) if (escapeName)
{ {
if (name.IndexOf('"') > -1) if (name.IndexOf('"') > -1)
@@ -79,14 +78,14 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
public static void SafeAdd<T>(this Dictionary<string, Dictionary<string, T>> dictionary, string key, public static void SafeAdd<T>(this Dictionary<string, Dictionary<string, T>> dictionary, string key,
T metadata) where T : DataSourceObjectMetadata T metadata) where T : DataSourceObjectMetadata
{ {
if (dictionary.ContainsKey(key)) if (dictionary.TryGetValue(key, out Dictionary<string, T>? metadataCollection))
{ {
if (dictionary[key].ContainsKey(metadata.Name)) if (metadataCollection.ContainsKey(metadata.Name))
{ {
return; return;
} }
dictionary[key].Add(metadata.Name, metadata); metadataCollection.Add(metadata.Name, metadata);
} }
else else
{ {
@@ -97,14 +96,14 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
public static void SafeAdd<T>(this Dictionary<string, SortedDictionary<string, DataSourceObjectMetadata>> dictionary, string key, public static void SafeAdd<T>(this Dictionary<string, SortedDictionary<string, DataSourceObjectMetadata>> dictionary, string key,
T node) where T : DataSourceObjectMetadata T node) where T : DataSourceObjectMetadata
{ {
if (dictionary.ContainsKey(key)) if (dictionary.TryGetValue(key, out SortedDictionary<string, DataSourceObjectMetadata>? metadataCollection))
{ {
if (dictionary[key].ContainsKey(node.PrettyName)) if (metadataCollection.ContainsKey(node.PrettyName))
{ {
return; return;
} }
dictionary[key].Add(node.PrettyName, node); metadataCollection.Add(node.PrettyName, node);
} }
else else
{ {
@@ -123,9 +122,9 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
public static void AddRange<T>(this ConcurrentDictionary<string, IEnumerable<T>> dictionary, string key, public static void AddRange<T>(this ConcurrentDictionary<string, IEnumerable<T>> dictionary, string key,
List<T> metadatas) where T : DataSourceObjectMetadata List<T> metadatas) where T : DataSourceObjectMetadata
{ {
if (dictionary.ContainsKey(key)) if (dictionary.TryGetValue(key, out IEnumerable<T>? value))
{ {
metadatas.AddRange(dictionary[key]); metadatas.AddRange(value);
} }
dictionary[key] = metadatas.OrderBy(x => x.PrettyName, StringComparer.OrdinalIgnoreCase).ToList(); dictionary[key] = metadatas.OrderBy(x => x.PrettyName, StringComparer.OrdinalIgnoreCase).ToList();
@@ -133,11 +132,16 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource
public static string ParseDatabaseName(string databaseName) public static string ParseDatabaseName(string databaseName)
{ {
var regex = new Regex(@"(?<=\().+?(?=\))"); var regex = GetDatabaseNameRegex();
return regex.IsMatch(databaseName) return regex.IsMatch(databaseName)
? regex.Match(databaseName).Value ? regex.Match(databaseName).Value
: databaseName; : databaseName;
} }
[GeneratedRegex("(?<=\\().+?(?=\\))")]
private static partial Regex GetDatabaseNameRegex();
[GeneratedRegex("[^_a-zA-Z0-9]")]
private static partial Regex GetNameRegex();
} }
} }

View File

@@ -22,7 +22,7 @@ using Microsoft.Kusto.ServiceLayer.Workspace.Contracts;
namespace Microsoft.Kusto.ServiceLayer.DataSource.Monitor namespace Microsoft.Kusto.ServiceLayer.DataSource.Monitor
{ {
public class MonitorDataSource : DataSourceBase public partial class MonitorDataSource : DataSourceBase
{ {
private readonly MonitorClient _monitorClient; private readonly MonitorClient _monitorClient;
private readonly IntellisenseClientBase _intellisenseClient; private readonly IntellisenseClientBase _intellisenseClient;
@@ -158,7 +158,7 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource.Monitor
private string ParseWorkspaceId(string workspace) private string ParseWorkspaceId(string workspace)
{ {
var regex = new Regex(@"(?<=\().+?(?=\))"); var regex = GetWorkspaceIdRegex();
return regex.IsMatch(workspace) return regex.IsMatch(workspace)
? regex.Match(workspace).Value ? regex.Match(workspace).Value
@@ -227,5 +227,8 @@ namespace Microsoft.Kusto.ServiceLayer.DataSource.Monitor
} }
}; };
} }
[GeneratedRegex("(?<=\\().+?(?=\\))")]
private static partial Regex GetWorkspaceIdRegex();
} }
} }

View File

@@ -198,11 +198,9 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
{ {
lock (this._bindingContextLock) lock (this._bindingContextLock)
{ {
if (this.BindingContextMap.ContainsKey(key)) if (this.BindingContextMap.TryGetValue(key, out IBindingContext? bindingContext))
{ {
// disconnect existing connection // disconnect existing connection
var bindingContext = this.BindingContextMap[key];
// remove key from the map // remove key from the map
this.BindingContextMap.Remove(key); this.BindingContextMap.Remove(key);
this.BindingContextTasks.Remove(bindingContext); this.BindingContextTasks.Remove(bindingContext);

View File

@@ -1011,13 +1011,13 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
/// </summary> /// </summary>
/// <param name="uri"></param> /// <param name="uri"></param>
/// <param name="createIfNotExists">Creates a new instance if one doesn't exist</param> /// <param name="createIfNotExists">Creates a new instance if one doesn't exist</param>
internal ScriptParseInfo GetScriptParseInfo(string uri, bool createIfNotExists = false) internal ScriptParseInfo? GetScriptParseInfo(string uri, bool createIfNotExists = false)
{ {
lock (this.parseMapLock) lock (this.parseMapLock)
{ {
if (this.ScriptParseInfoMap.ContainsKey(uri)) if (this.ScriptParseInfoMap.TryGetValue(uri, out ScriptParseInfo? scriptParseInfo))
{ {
return this.ScriptParseInfoMap[uri]; return scriptParseInfo;
} }
else if (createIfNotExists) else if (createIfNotExists)
{ {
@@ -1091,7 +1091,7 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
} }
// If there is a single statement on the line, track it so that we can return it regardless of where the user's cursor is // If there is a single statement on the line, track it so that we can return it regardless of where the user's cursor is
SqlStatement lineStatement = null; SqlStatement? lineStatement = null;
bool? lineHasSingleStatement = null; bool? lineHasSingleStatement = null;
// check if the batch matches parameters // check if the batch matches parameters
@@ -1125,7 +1125,7 @@ namespace Microsoft.Kusto.ServiceLayer.LanguageServices
if (lineHasSingleStatement == true) if (lineHasSingleStatement == true)
{ {
return lineStatement.Sql; return lineStatement?.Sql ?? string.Empty;
} }
} }
} }

View File

@@ -13,8 +13,8 @@
<PreserveCompilationContext>true</PreserveCompilationContext> <PreserveCompilationContext>true</PreserveCompilationContext>
<DebugType>portable</DebugType> <DebugType>portable</DebugType>
<RuntimeIdentifiers>$(ToolsServiceTargetRuntimes)</RuntimeIdentifiers> <RuntimeIdentifiers>$(ToolsServiceTargetRuntimes)</RuntimeIdentifiers>
<!-- TODO FIX THESE WARNINGS ASAP --> <!-- False alerts, disabled due to issue: https://github.com/dotnet/roslyn/issues/65850 -->
<NoWarn>$(NoWarn);SYSLIB1045;CA1311;CA1854</NoWarn> <NoWarn>$(NoWarn);CS8795</NoWarn>
<AssemblyTitle>SqlTools Kusto Editor Services Host Protocol Library</AssemblyTitle> <AssemblyTitle>SqlTools Kusto Editor Services Host Protocol Library</AssemblyTitle>
<Description>Provides message types and client/server APIs for the SqlTools Kusto Editor Services JSON protocol.</Description> <Description>Provides message types and client/server APIs for the SqlTools Kusto Editor Services JSON protocol.</Description>
</PropertyGroup> </PropertyGroup>

View File

@@ -3,6 +3,8 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
// //
#nullable disable
using Microsoft.Kusto.ServiceLayer.QueryExecution.Contracts; using Microsoft.Kusto.ServiceLayer.QueryExecution.Contracts;
using Microsoft.Kusto.ServiceLayer.QueryExecution.DataStorage; using Microsoft.Kusto.ServiceLayer.QueryExecution.DataStorage;
using Microsoft.Kusto.ServiceLayer.Utility; using Microsoft.Kusto.ServiceLayer.Utility;
@@ -24,7 +26,7 @@ namespace Microsoft.Kusto.ServiceLayer.QueryExecution
/// Class that represents a resultset the was generated from a query. Contains logic for /// Class that represents a resultset the was generated from a query. Contains logic for
/// storing and retrieving results. Is contained by a Batch class. /// storing and retrieving results. Is contained by a Batch class.
/// </summary> /// </summary>
public class ResultSet : IDisposable public partial class ResultSet : IDisposable
{ {
#region Constants #region Constants
@@ -343,7 +345,7 @@ namespace Microsoft.Kusto.ServiceLayer.QueryExecution
// Verify the request hasn't been cancelled // Verify the request hasn't been cancelled
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
StorageDataReader dataReader = new StorageDataReader(dbDataReader); var dataReader = new StorageDataReader(dbDataReader);
// Open a writer for the file // Open a writer for the file
// //
@@ -478,7 +480,7 @@ namespace Microsoft.Kusto.ServiceLayer.QueryExecution
} }
// Create the new task // Create the new task
Task saveAsTask = new Task(async () => var saveAsTask = new Task(async () =>
{ {
try try
{ {
@@ -602,7 +604,7 @@ namespace Microsoft.Kusto.ServiceLayer.QueryExecution
// //
sendResultsSemphore.Wait(); sendResultsSemphore.Wait();
ResultSet currentResultSetSnapshot = (ResultSet) MemberwiseClone(); var currentResultSetSnapshot = (ResultSet) MemberwiseClone();
if (LastUpdatedSummary == null) // We need to send results available message. if (LastUpdatedSummary == null) // We need to send results available message.
{ {
// Fire off results Available task and await it // Fire off results Available task and await it
@@ -677,13 +679,12 @@ namespace Microsoft.Kusto.ServiceLayer.QueryExecution
{ {
if (Columns?.Length > 0 && RowCount != 0) if (Columns?.Length > 0 && RowCount != 0)
{ {
Regex regex = new Regex(@"({.*?})");
var row = GetRow(0); var row = GetRow(0);
for (int i = 0; i < Columns.Length; i++) for (int i = 0; i < Columns.Length; i++)
{ {
if (Columns[i].DataTypeName.Equals("nvarchar")) if (Columns[i].DataTypeName.Equals("nvarchar"))
{ {
if (regex.IsMatch(row[i].DisplayValue)) if (GetJsonRegex().IsMatch(row[i].DisplayValue))
{ {
Columns[i].IsJson = true; Columns[i].IsJson = true;
} }
@@ -726,7 +727,7 @@ namespace Microsoft.Kusto.ServiceLayer.QueryExecution
// Returning false from .ReadAsync means there aren't any rows. // Returning false from .ReadAsync means there aren't any rows.
// Create a storage data reader, read it, make sure there were results // Create a storage data reader, read it, make sure there were results
StorageDataReader dataReader = new StorageDataReader(dbDataReader); var dataReader = new StorageDataReader(dbDataReader);
if (!await dataReader.ReadAsync(CancellationToken.None)) if (!await dataReader.ReadAsync(CancellationToken.None))
{ {
throw new InvalidOperationException(SR.QueryServiceResultSetAddNoRows); throw new InvalidOperationException(SR.QueryServiceResultSetAddNoRows);
@@ -742,6 +743,9 @@ namespace Microsoft.Kusto.ServiceLayer.QueryExecution
} }
} }
[GeneratedRegex("({.*?})")]
private static partial Regex GetJsonRegex();
#endregion #endregion
} }
} }

View File

@@ -99,7 +99,7 @@ namespace Microsoft.Kusto.ServiceLayer.Scripting
// Leaving the server name blank will automatically match whatever the server SMO is running against. // Leaving the server name blank will automatically match whatever the server SMO is running against.
string urn = string.Format( string urn = string.Format(
"Server[@Name='{0}']/Database[@Name='{1}']/{2}[@Name='{3}' {4}]", "Server[@Name='{0}']/Database[@Name='{1}']/{2}[@Name='{3}' {4}]",
server.ToUpper(), server.ToUpper(System.Globalization.CultureInfo.InvariantCulture),
Urn.EscapeString(database), Urn.EscapeString(database),
scriptingObject.Type, scriptingObject.Type,
Urn.EscapeString(scriptingObject.Name), Urn.EscapeString(scriptingObject.Name),

View File

@@ -32,12 +32,6 @@ namespace Microsoft.Kusto.ServiceLayer.Utility
public bool CanReadFromDisk { get; private set; } public bool CanReadFromDisk { get; private set; }
public string LowercaseClientUri public string LowercaseClientUri => ClientUri?.ToLower(System.Globalization.CultureInfo.InvariantCulture);
{
get
{
return ClientUri?.ToLower();
}
}
} }
} }

View File

@@ -14,11 +14,11 @@ namespace Microsoft.Kusto.ServiceLayer.Utility.SqlScriptFormatters
/// <summary> /// <summary>
/// Provides utilities for converting from SQL script syntax into POCOs. /// Provides utilities for converting from SQL script syntax into POCOs.
/// </summary> /// </summary>
public static class FromSqlScript public static partial class FromSqlScript
{ {
// Regex: optionally starts with N, captures string wrapped in single quotes // Regex: optionally starts with N, captures string wrapped in single quotes
private static readonly Regex StringRegex = new Regex("^N?'(.*)'$", RegexOptions.Compiled); private static readonly Regex StringRegex = GetStringRegex();
private static readonly Regex BracketRegex = new Regex(@"^\[(.*)\]$", RegexOptions.Compiled); private static readonly Regex BracketRegex = GetBracketRegex();
/// <summary> /// <summary>
/// Decodes a multipart identifier as used in a SQL script into an array of the multiple /// Decodes a multipart identifier as used in a SQL script into an array of the multiple
@@ -33,8 +33,8 @@ namespace Microsoft.Kusto.ServiceLayer.Utility.SqlScriptFormatters
/// </exception> /// </exception>
public static string[] DecodeMultipartIdentifier(string multipartIdentifier) public static string[] DecodeMultipartIdentifier(string multipartIdentifier)
{ {
StringBuilder sb = new StringBuilder(); var sb = new StringBuilder();
List<string> namedParts = new List<string>(); var namedParts = new List<string>();
bool insideBrackets = false; bool insideBrackets = false;
bool bracketsClosed = false; bool bracketsClosed = false;
for (int i = 0; i < multipartIdentifier.Length; i++) for (int i = 0; i < multipartIdentifier.Length; i++)
@@ -152,6 +152,11 @@ namespace Microsoft.Kusto.ServiceLayer.Utility.SqlScriptFormatters
return value.Replace(new string(escapeCharacter, 2), escapeCharacter.ToString()); return value.Replace(new string(escapeCharacter, 2), escapeCharacter.ToString());
} }
[GeneratedRegex("^N?'(.*)'$", RegexOptions.Compiled)]
private static partial Regex GetStringRegex();
[GeneratedRegex("^\\[(.*)\\]$", RegexOptions.Compiled)]
private static partial Regex GetBracketRegex();
#endregion #endregion
} }
} }

View File

@@ -25,7 +25,7 @@ namespace Microsoft.Kusto.ServiceLayer.Workspace.Contracts
/// </summary> /// </summary>
public string Id public string Id
{ {
get { return this.ClientUri.ToLower(); } get { return this.ClientUri.ToLower(System.Globalization.CultureInfo.InvariantCulture); }
} }
/// <summary> /// <summary>

View File

@@ -21,7 +21,7 @@ namespace Microsoft.Kusto.ServiceLayer.Workspace
/// Manages a "workspace" of script files that are open for a particular /// Manages a "workspace" of script files that are open for a particular
/// editing session. Also helps to navigate references between ScriptFiles. /// editing session. Also helps to navigate references between ScriptFiles.
/// </summary> /// </summary>
public class Workspace : IDisposable public partial class Workspace : IDisposable
{ {
#region Private Fields #region Private Fields
@@ -115,8 +115,8 @@ namespace Microsoft.Kusto.ServiceLayer.Workspace
} }
// This method allows FileNotFoundException to bubble up // This method allows FileNotFoundException to bubble up
// if the file isn't found. // if the file isn't found.
using (FileStream fileStream = new FileStream(resolvedFile.FilePath, FileMode.Open, FileAccess.Read)) using (var fileStream = new FileStream(resolvedFile.FilePath, FileMode.Open, FileAccess.Read))
using (StreamReader streamReader = new StreamReader(fileStream, Encoding.UTF8)) using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
{ {
scriptFile = new ScriptFile(resolvedFile.FilePath, resolvedFile.ClientUri,streamReader); scriptFile = new ScriptFile(resolvedFile.FilePath, resolvedFile.ClientUri,streamReader);
@@ -148,7 +148,7 @@ namespace Microsoft.Kusto.ServiceLayer.Workspace
// Client sent the path in URI format, extract the local path and trim // Client sent the path in URI format, extract the local path and trim
// any extraneous slashes // any extraneous slashes
Uri fileUri = new Uri(clientUri); var fileUri = new Uri(clientUri);
filePath = fileUri.LocalPath; filePath = fileUri.LocalPath;
if (filePath.StartsWith("//") || filePath.StartsWith("\\\\") || filePath.StartsWith("/")) if (filePath.StartsWith("//") || filePath.StartsWith("\\\\") || filePath.StartsWith("/"))
{ {
@@ -206,7 +206,7 @@ namespace Microsoft.Kusto.ServiceLayer.Workspace
return path; return path;
} }
return Regex.Replace(path, @"`(?=[ \[\]])", ""); return GetEscapeRegex().Replace(path, "");
} }
/// <summary> /// <summary>
@@ -361,6 +361,9 @@ namespace Microsoft.Kusto.ServiceLayer.Workspace
{ {
} }
[GeneratedRegex("`(?=[ \\[\\]])")]
private static partial Regex GetEscapeRegex();
#endregion #endregion
} }
} }

View File

@@ -1,45 +1,47 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<AssemblyName>MicrosoftSqlToolsCredentials</AssemblyName> <AssemblyName>MicrosoftSqlToolsCredentials</AssemblyName>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<EnableDefaultItems>false</EnableDefaultItems> <EnableDefaultItems>false</EnableDefaultItems>
<ValidateExecutableReferencesMatchSelfContained>false</ValidateExecutableReferencesMatchSelfContained> <ValidateExecutableReferencesMatchSelfContained>false</ValidateExecutableReferencesMatchSelfContained>
<EnableDefaultCompileItems>false</EnableDefaultCompileItems> <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
<EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems> <EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems>
<EmbeddedResourceUseDependentUponConvention>false</EmbeddedResourceUseDependentUponConvention> <EmbeddedResourceUseDependentUponConvention>false</EmbeddedResourceUseDependentUponConvention>
<EnableDefaultNoneItems>false</EnableDefaultNoneItems> <EnableDefaultNoneItems>false</EnableDefaultNoneItems>
<DefineConstants>$(DefineConstants);NETCOREAPP1_0</DefineConstants> <DefineConstants>$(DefineConstants);NETCOREAPP1_0</DefineConstants>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PreserveCompilationContext>true</PreserveCompilationContext> <PreserveCompilationContext>true</PreserveCompilationContext>
<RuntimeIdentifiers>$(ToolsServiceTargetRuntimes)</RuntimeIdentifiers> <RuntimeIdentifiers>$(ToolsServiceTargetRuntimes)</RuntimeIdentifiers>
<AssemblyTitle>SqlTools Editor Services Credentials Manager Library</AssemblyTitle> <AssemblyTitle>SqlTools Editor Services Credentials Manager Library</AssemblyTitle>
<Description>Provides message types and client/server APIs for the SqlTools Credential Services JSON protocol.</Description> <Description>Provides message types and client/server APIs for the SqlTools Credential Services JSON protocol.</Description>
<!-- TODO FIX THESE WARNINGS ASAP --> <!-- SYSLIB1054: Use LibraryImportAttribute instead of DllImportAttribute to generate p/invoke marshalling code at compile time.
This is a Diagnostic Alert .NET 7 onwards.Changing to LibraryImportAttribute would require additional code changes,
therefore this warning is suppressed.-->
<NoWarn>$(NoWarn);SYSLIB1054</NoWarn> <NoWarn>$(NoWarn);SYSLIB1054</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="**\*.cs" Exclude="**/obj/**/*.cs" /> <Compile Include="**\*.cs" Exclude="**/obj/**/*.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json"/> <PackageReference Include="Newtonsoft.Json"/>
<PackageReference Include="Microsoft.Extensions.DependencyModel" /> <PackageReference Include="Microsoft.Extensions.DependencyModel" />
<PackageReference Include="System.IO.Packaging" /> <PackageReference Include="System.IO.Packaging" />
<PackageReference Include="System.Runtime.Loader" /> <PackageReference Include="System.Runtime.Loader" />
<PackageReference Include="System.Composition" /> <PackageReference Include="System.Composition" />
<PackageReference Include="System.Security.Permissions" /> <PackageReference Include="System.Security.Permissions" />
<PackageReference Include="System.Text.Encoding.CodePages"/> <PackageReference Include="System.Text.Encoding.CodePages"/>
<PackageReference Include="System.Reactive.Core" /> <PackageReference Include="System.Reactive.Core" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<InternalsVisibleTo Include="Microsoft.SqlTools.ServiceLayer.UnitTests" /> <InternalsVisibleTo Include="Microsoft.SqlTools.ServiceLayer.UnitTests" />
<InternalsVisibleTo Include="Microsoft.SqlTools.ServiceLayer.IntegrationTests" /> <InternalsVisibleTo Include="Microsoft.SqlTools.ServiceLayer.IntegrationTests" />
<InternalsVisibleTo Include="Microsoft.SqlTools.ServiceLayer.Test.Common" /> <InternalsVisibleTo Include="Microsoft.SqlTools.ServiceLayer.Test.Common" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="../Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj" /> <ProjectReference Include="../Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Localization\*.resx" /> <EmbeddedResource Include="Localization\*.resx" />
<None Include="Localization\sr.strings" /> <None Include="Localization\sr.strings" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -408,7 +408,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
/// <summary> /// <summary>
/// Internal implementation class to implement IBatchEventHandlers /// Internal implementation class to implement IBatchEventHandlers
/// </summary> /// </summary>
internal class BatchEventNotificationHandler : IBatchEventsHandler internal sealed class BatchEventNotificationHandler : IBatchEventsHandler
{ {
public void OnBatchError(object sender, BatchErrorEventArgs args) public void OnBatchError(object sender, BatchErrorEventArgs args)
{ {
@@ -477,7 +477,7 @@ namespace Microsoft.SqlTools.ServiceLayer.BatchParser
} }
#endregion #endregion
private class BatchInfo private sealed class BatchInfo
{ {
public BatchInfo(int startLine, int startColumn, string batchText, SqlCmdCommand sqlCmdCommand, int repeatCount = 1) public BatchInfo(int startLine, int startColumn, string batchText, SqlCmdCommand sqlCmdCommand, int repeatCount = 1)
{ {

View File

@@ -32,7 +32,7 @@
<Version>$(VersionPrefix)</Version> <Version>$(VersionPrefix)</Version>
<FileVersion>$(VersionPrefix)</FileVersion> <FileVersion>$(VersionPrefix)</FileVersion>
<InformationalVersion>$(VersionPrefix)</InformationalVersion> <InformationalVersion>$(VersionPrefix)</InformationalVersion>
<!-- TODO FIX THESE WARNINGS ASAP --> <!-- Disable CA1852 (Seal internal types) as it depends on SrGen Tool -->
<NoWarn>$(NoWarn);CA1852</NoWarn> <NoWarn>$(NoWarn);CA1852</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -374,7 +374,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection
/// <summary> /// <summary>
/// This class is used as value in the dictionary to ensure that the type of value is correct. /// This class is used as value in the dictionary to ensure that the type of value is correct.
/// </summary> /// </summary>
private class AmbientValue private sealed class AmbientValue
{ {
private readonly Type _type; private readonly Type _type;
private readonly bool _isTypeNullable; private readonly bool _isTypeNullable;

View File

@@ -45,7 +45,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection
} }
#region CacheKey implementation #region CacheKey implementation
internal class CacheKey : IEquatable<CacheKey> internal sealed class CacheKey : IEquatable<CacheKey>
{ {
private string dataSource; private string dataSource;
private string dbName; private string dbName;

View File

@@ -407,7 +407,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection
} }
} }
internal class ExponentialDelayRetryPolicy : RetryPolicy internal sealed class ExponentialDelayRetryPolicy : RetryPolicy
{ {
private readonly int _maxRetryCount; private readonly int _maxRetryCount;
private readonly double _intervalFactor; private readonly double _intervalFactor;

View File

@@ -10,7 +10,7 @@
<StartupObject /> <StartupObject />
<Description>Provides the default for SqlTools applications.</Description> <Description>Provides the default for SqlTools applications.</Description>
<Copyright><EFBFBD> Microsoft Corporation. All rights reserved.</Copyright> <Copyright><EFBFBD> Microsoft Corporation. All rights reserved.</Copyright>
<!-- TODO FIX THESE WARNINGS ASAP --> <!-- Disable CA1852 (Seal internal types) as it depends on SrGen Tool -->
<NoWarn>$(NoWarn);CA1852</NoWarn> <NoWarn>$(NoWarn);CA1852</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -12,15 +12,15 @@
<EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems> <EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems>
<EmbeddedResourceUseDependentUponConvention>false</EmbeddedResourceUseDependentUponConvention> <EmbeddedResourceUseDependentUponConvention>false</EmbeddedResourceUseDependentUponConvention>
<RuntimeIdentifiers>$(ToolsServiceTargetRuntimes)</RuntimeIdentifiers> <RuntimeIdentifiers>$(ToolsServiceTargetRuntimes)</RuntimeIdentifiers>
<!-- TODO FIX THESE WARNINGS ASAP --> <!-- Disable CA1852 (Seal internal types) as it depends on SrGen Tool -->
<NoWarn>$(NoWarn);CA1852</NoWarn> <NoWarn>$(NoWarn);CA1852</NoWarn>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>TRACE;DEBUG;NETCOREAPP1_0;NETCOREAPP2_0</DefineConstants> <DefineConstants>TRACE;DEBUG;NETCOREAPP1_0;NETCOREAPP2_0</DefineConstants>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Text.Encoding.CodePages"/> <PackageReference Include="System.Text.Encoding.CodePages" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Microsoft.SqlTools.Hosting\Microsoft.SqlTools.Hosting.csproj" /> <ProjectReference Include="..\Microsoft.SqlTools.Hosting\Microsoft.SqlTools.Hosting.csproj" />

View File

@@ -16,7 +16,7 @@ namespace Microsoft.SqlTools.ResourceProvider
/// <summary> /// <summary>
/// Main application class for the executable that supports the resource provider and identity services /// Main application class for the executable that supports the resource provider and identity services
/// </summary> /// </summary>
internal class Program internal sealed class Program
{ {
private const string ServiceName = "SqlToolsResourceProviderService.exe"; private const string ServiceName = "SqlToolsResourceProviderService.exe";

View File

@@ -3,8 +3,6 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
// //
#nullable disable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
@@ -51,9 +49,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
return Name.GetHashCode(); return Name.GetHashCode();
} }
public override bool Equals(object obj) public override bool Equals(object? obj)
{ {
return obj is AzureEdition && ((AzureEdition)obj).Name.Equals(Name); return obj is AzureEdition edition && edition.Name.Equals(Name);
} }
public static bool operator ==(AzureEdition left, AzureEdition right) public static bool operator ==(AzureEdition left, AzureEdition right)
@@ -82,7 +80,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
var azureEdition = var azureEdition =
AzureServiceObjectiveInfo.Keys.FirstOrDefault( AzureServiceObjectiveInfo.Keys.FirstOrDefault(
key => key.Name.ToLowerInvariant().Equals(edition.ToLowerInvariant())); key => key.Name.ToLowerInvariant().Equals(edition.ToLowerInvariant()));
if (azureEdition != null) if (azureEdition! != null)
{ {
return azureEdition; return azureEdition;
} }
@@ -358,9 +356,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Admin
/// <returns>StorageAccountType string value for the current storageType</returns> /// <returns>StorageAccountType string value for the current storageType</returns>
public static string GetStorageAccountTypeFromString(string storageAccountType) public static string GetStorageAccountTypeFromString(string storageAccountType)
{ {
if (bsrAPIToUIValueMapping.ContainsKey(storageAccountType)) if (bsrAPIToUIValueMapping.TryGetValue(storageAccountType, out string? value))
{ {
return bsrAPIToUIValueMapping[storageAccountType]; return value;
} }
return storageAccountType; return storageAccountType;
} }

View File

@@ -1100,7 +1100,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
} }
const string UrnFormatStr = "Server/JobServer[@Name='{0}']/Job[@Name='{1}']/Schedule[@Name='{2}']"; const string UrnFormatStr = "Server/JobServer[@Name='{0}']/Job[@Name='{1}']/Schedule[@Name='{2}']";
string serverName = dataContainer.Server.Name.ToUpper(); string serverName = dataContainer.Server.Name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
string scheduleUrn = string.Format(UrnFormatStr, serverName, jobData.Job.Name, schedule.Name); string scheduleUrn = string.Format(UrnFormatStr, serverName, jobData.Job.Name, schedule.Name);
STParameters param = new STParameters(dataContainer.Document); STParameters param = new STParameters(dataContainer.Document);
@@ -1132,7 +1132,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
ConnectionServiceInstance.TryFindConnection(ownerUri, out connInfo); ConnectionServiceInstance.TryFindConnection(ownerUri, out connInfo);
dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true); dataContainer = CDataContainer.CreateDataContainer(connInfo, databaseExists: true);
XmlDocument jobDoc = CreateJobXmlDocument(dataContainer.Server.Name.ToUpper(), jobName); XmlDocument jobDoc = CreateJobXmlDocument(dataContainer.Server.Name.ToUpper(System.Globalization.CultureInfo.InvariantCulture), jobName);
dataContainer.Init(jobDoc.InnerXml); dataContainer.Init(jobDoc.InnerXml);
STParameters param = new STParameters(dataContainer.Document); STParameters param = new STParameters(dataContainer.Document);
@@ -1487,9 +1487,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
{ {
string jobRuntime = jobHistory.RunDate.ToString("yyyyMMddHHmmss"); string jobRuntime = jobHistory.RunDate.ToString("yyyyMMddHHmmss");
AgentNotebookHistoryInfo notebookHistory = jobHistory; AgentNotebookHistoryInfo notebookHistory = jobHistory;
if (notebookHistoriesDict.ContainsKey(jobRuntime)) if (notebookHistoriesDict.TryGetValue(jobRuntime, out DataRow dataRow))
{ {
notebookHistory.MaterializedNotebookId = (int)notebookHistoriesDict[jobRuntime]["materialized_id"]; notebookHistory.MaterializedNotebookId = (int)dataRow["materialized_id"];
notebookHistory.MaterializedNotebookErrorInfo = notebookHistoriesDict[jobRuntime]["notebook_error"] as string; notebookHistory.MaterializedNotebookErrorInfo = notebookHistoriesDict[jobRuntime]["notebook_error"] as string;
notebookHistory.MaterializedNotebookName = notebookHistoriesDict[jobRuntime]["notebook_name"] as string; notebookHistory.MaterializedNotebookName = notebookHistoriesDict[jobRuntime]["notebook_name"] as string;
notebookHistory.MaterializedNotebookPin = (bool)notebookHistoriesDict[jobRuntime]["pin"]; notebookHistory.MaterializedNotebookPin = (bool)notebookHistoriesDict[jobRuntime]["pin"];

View File

@@ -3,8 +3,6 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
// //
#nullable disable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
@@ -32,54 +30,56 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
{ {
this.data = data; this.data = data;
var availableSystems = var availableSystems =
dataContainer.Server.JobServer.EnumSubSystems() dataContainer.Server?.JobServer.EnumSubSystems()
.Rows.OfType<DataRow>() .Rows.OfType<DataRow>()
.Select(r => (AgentSubSystem)Convert.ToInt32(r["subsystem_id"])); .Select(r => (AgentSubSystem)Convert.ToInt32(r["subsystem_id"]));
if (availableSystems != null)
foreach (var agentSubSystemId in availableSystems)
{ {
var agentSubSystem = CreateJobStepSubSystem(agentSubSystemId, dataContainer, data); foreach (var agentSubSystemId in availableSystems)
// The server might have some new subsystem we don't know about, just ignore it.
if (agentSubSystem != null)
{ {
subSystems[agentSubSystemId] = agentSubSystem; var agentSubSystem = CreateJobStepSubSystem(agentSubSystemId, dataContainer, data);
// The server might have some new subsystem we don't know about, just ignore it.
if (agentSubSystem != null)
{
subSystems[agentSubSystemId] = agentSubSystem;
}
} }
} }
} }
public JobStepSubSystem[] AvailableSubSystems public JobStepSubSystem[] AvailableSubSystems
{ {
get { return this.subSystems.Keys.OrderBy(k => (int) k).Select(k => this.subSystems[k]).ToArray(); } get { return this.subSystems.Keys.OrderBy(k => (int)k).Select(k => this.subSystems[k]).ToArray(); }
} }
public JobStepSubSystem Lookup(AgentSubSystem key) public JobStepSubSystem Lookup(AgentSubSystem key)
{ {
JobStepSubSystem rv = null; JobStepSubSystem rv = null;
if (this.subSystems.ContainsKey(key)) if (this.subSystems.TryGetValue(key, out JobStepSubSystem? value))
{ {
return this.subSystems[key]; return value;
} }
return rv; return rv;
} }
private static TypeConverter typeConverter = TypeDescriptor.GetConverter(typeof (AgentSubSystem)); private static TypeConverter typeConverter = TypeDescriptor.GetConverter(typeof(AgentSubSystem));
// Returns name of the subsystem for a given enum value // Returns name of the subsystem for a given enum value
public static string LookupFriendlyName(AgentSubSystem key) public static string LookupFriendlyName(AgentSubSystem key)
{ {
return (string)typeConverter.ConvertToString((Enum)key); return (string)typeConverter.ConvertToString((Enum)key);
} }
// Returns name of the subsystem for a given enum value // Returns name of the subsystem for a given enum value
public static string LookupName(AgentSubSystem key) public static string LookupName(AgentSubSystem key)
{ {
// Have to subtract first enum value to bring the // Have to subtract first enum value to bring the
// index to 0-based index // index to 0-based index
return typeConverter.ConvertToInvariantString((Enum) key); return typeConverter.ConvertToInvariantString((Enum)key);
} }
private static JobStepSubSystem CreateJobStepSubSystem( private static JobStepSubSystem CreateJobStepSubSystem(
AgentSubSystem agentSubSystem, AgentSubSystem agentSubSystem,
CDataContainer dataContainer, CDataContainer dataContainer,
JobStepData data) JobStepData data)
{ {
switch (agentSubSystem) switch (agentSubSystem)

View File

@@ -95,7 +95,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
if (jobData.Job != null) if (jobData.Job != null)
{ {
const string UrnFormatStr = "Server/JobServer[@Name='{0}']/Job[@Name='{1}']/Step[@Name='{2}']"; const string UrnFormatStr = "Server/JobServer[@Name='{0}']/Job[@Name='{1}']/Step[@Name='{2}']";
string serverName = this.DataContainer.Server.Name.ToUpper(); string serverName = this.DataContainer.Server.Name.ToUpper(System.Globalization.CultureInfo.InvariantCulture);
string urn = string.Format(UrnFormatStr, serverName, jobData.Job.Name, stepName); string urn = string.Format(UrnFormatStr, serverName, jobData.Job.Name, stepName);
jobStep = jobData.Job.Parent.Parent.GetSmoObject(urn) as JobStep; jobStep = jobData.Job.Parent.Parent.GetSmoObject(urn) as JobStep;
} }

View File

@@ -24,7 +24,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
/// simple job schedule structure. /// simple job schedule structure.
/// </summary> /// </summary>
public struct SimpleJobSchedule public partial struct SimpleJobSchedule
{ {
#region consts #region consts
private const int EndOfDay = 235959; private const int EndOfDay = 235959;
@@ -44,7 +44,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
private FrequencyTypes frequencyTypes; private FrequencyTypes frequencyTypes;
private FrequencySubDayTypes frequencySubDayTypes; private FrequencySubDayTypes frequencySubDayTypes;
private FrequencyRelativeIntervals frequencyRelativeIntervals; private FrequencyRelativeIntervals frequencyRelativeIntervals;
private System.Boolean isEnabled; private bool isEnabled;
#endregion #endregion
#region Init #region Init
@@ -100,7 +100,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
public static DateTime ConvertIntToDateTime(int source) public static DateTime ConvertIntToDateTime(int source)
{ {
return new DateTime(source / 10000 return new DateTime(source / 10000
, (source / 100) % 100 , source / 100 % 100
, source % 100); , source % 100);
} }
/// <summary> /// <summary>
@@ -126,7 +126,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
public static TimeSpan ConvertIntToTimeSpan(int source) public static TimeSpan ConvertIntToTimeSpan(int source)
{ {
return new TimeSpan(source / 10000 return new TimeSpan(source / 10000
, (source / 100) % 100 , source / 100 % 100
, source % 100); , source % 100);
} }
/// <summary> /// <summary>
@@ -150,13 +150,13 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
/// <returns>JobScheduleData object</returns> /// <returns>JobScheduleData object</returns>
public JobScheduleData ToJobScheduleData() public JobScheduleData ToJobScheduleData()
{ {
JobScheduleData data = new JobScheduleData(); var data = new JobScheduleData();
data.Name = this.Name; data.Name = this.Name;
data.Enabled = this.IsEnabled; data.Enabled = this.IsEnabled;
data.ActiveStartDate = SimpleJobSchedule.ConvertIntToDateLocalized(this.ActiveStartDate); data.ActiveStartDate = ConvertIntToDateLocalized(this.ActiveStartDate);
data.ActiveStartTime = SimpleJobSchedule.ConvertIntToTimeSpan(this.ActiveStartTimeOfDay); data.ActiveStartTime = ConvertIntToTimeSpan(this.ActiveStartTimeOfDay);
data.ActiveEndDate = SimpleJobSchedule.ConvertIntToDateLocalized(this.ActiveEndDate); data.ActiveEndDate = ConvertIntToDateLocalized(this.ActiveEndDate);
data.ActiveEndTime = SimpleJobSchedule.ConvertIntToTimeSpan(this.ActiveEndTimeOfDay); data.ActiveEndTime = ConvertIntToTimeSpan(this.ActiveEndTimeOfDay);
data.FrequencyTypes = this.FrequencyTypes; data.FrequencyTypes = this.FrequencyTypes;
data.FrequencyInterval = this.FrequencyInterval; data.FrequencyInterval = this.FrequencyInterval;
data.FrequencyRecurranceFactor = this.FrequencyRecurrenceFactor; data.FrequencyRecurranceFactor = this.FrequencyRecurrenceFactor;
@@ -173,15 +173,15 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
/// <returns>new SimpleJobSchedule</returns> /// <returns>new SimpleJobSchedule</returns>
public static SimpleJobSchedule FromJobScheduleData(JobScheduleData source) public static SimpleJobSchedule FromJobScheduleData(JobScheduleData source)
{ {
SimpleJobSchedule schedule = new SimpleJobSchedule(); var schedule = new SimpleJobSchedule();
schedule.Name = source.Name; schedule.Name = source.Name;
schedule.ID = source.ID; schedule.ID = source.ID;
schedule.IsEnabled = source.Enabled; schedule.IsEnabled = source.Enabled;
schedule.ActiveStartDate = SimpleJobSchedule.ConvertDateTimeToInt(source.ActiveStartDate); schedule.ActiveStartDate = ConvertDateTimeToInt(source.ActiveStartDate);
schedule.ActiveStartTimeOfDay = SimpleJobSchedule.ConvertTimeSpanToInt(source.ActiveStartTime); schedule.ActiveStartTimeOfDay = ConvertTimeSpanToInt(source.ActiveStartTime);
schedule.ActiveEndDate = SimpleJobSchedule.ConvertDateTimeToInt(source.ActiveEndDate); schedule.ActiveEndDate = ConvertDateTimeToInt(source.ActiveEndDate);
schedule.ActiveEndTimeOfDay = SimpleJobSchedule.ConvertTimeSpanToInt(source.ActiveEndTime); schedule.ActiveEndTimeOfDay = ConvertTimeSpanToInt(source.ActiveEndTime);
schedule.FrequencyTypes = source.FrequencyTypes; schedule.FrequencyTypes = source.FrequencyTypes;
schedule.FrequencyInterval = source.FrequencyInterval; schedule.FrequencyInterval = source.FrequencyInterval;
schedule.FrequencyRecurrenceFactor = source.FrequencyRecurranceFactor; schedule.FrequencyRecurrenceFactor = source.FrequencyRecurranceFactor;
@@ -293,7 +293,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
return string.Empty; return string.Empty;
} }
StringBuilder daysOfWeek = new StringBuilder(); var daysOfWeek = new StringBuilder();
// Start matching with Monday. GetLocalizedDaysOfWeek() must start with Monday too. // Start matching with Monday. GetLocalizedDaysOfWeek() must start with Monday too.
WeekDays dayOfWeek = WeekDays.Monday; WeekDays dayOfWeek = WeekDays.Monday;
foreach (string localizedDayOfWeek in GetLocalizedDaysOfWeek()) foreach (string localizedDayOfWeek in GetLocalizedDaysOfWeek())
@@ -309,7 +309,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
// There's no easy way to advance to the next enum value, so since we know // There's no easy way to advance to the next enum value, so since we know
// it's a bitfield mask we do a left shift ourselves. // it's a bitfield mask we do a left shift ourselves.
int nextDay = ((int)dayOfWeek) << 1; int nextDay = (int)dayOfWeek << 1;
dayOfWeek = (WeekDays)nextDay; dayOfWeek = (WeekDays)nextDay;
if (dayOfWeek > WeekDays.Saturday) if (dayOfWeek > WeekDays.Saturday)
{ {
@@ -449,7 +449,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
{ {
get get
{ {
MonthlyRelativeWeekDays relativeDays = (MonthlyRelativeWeekDays) this.FrequencyInterval; var relativeDays = (MonthlyRelativeWeekDays) this.FrequencyInterval;
switch (relativeDays) switch (relativeDays)
{ {
@@ -671,10 +671,10 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
/// <returns></returns> /// <returns></returns>
string ExpandFormatString(string format) string ExpandFormatString(string format)
{ {
StringBuilder stringBuilder = new StringBuilder(); var stringBuilder = new StringBuilder();
int lastIndex = 0; int lastIndex = 0;
MatchCollection matches = Regex.Matches(format, @"\{(?<property>\w+)\}"); MatchCollection matches = GetPropertyDescriptorRegex().Matches(format);
if (matches.Count > 0) if (matches.Count > 0)
{ {
@@ -687,7 +687,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
if (property != null) if (property != null)
{ {
object propertyValue = property.GetValue(this); object propertyValue = property.GetValue(this);
propertyValue = propertyValue != null ? propertyValue.ToString() : String.Empty; propertyValue = propertyValue != null ? propertyValue.ToString() : string.Empty;
stringBuilder.Append(format.Substring(lastIndex, match.Index - lastIndex)); stringBuilder.Append(format.Substring(lastIndex, match.Index - lastIndex));
stringBuilder.Append(propertyValue as string); stringBuilder.Append(propertyValue as string);
@@ -705,6 +705,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Agent
return new string[] { "SR.Monday", "SR.Tuesday", "SR.Wednesday", "SR.Thursday", "SR.Friday", "SR.Saturday", "SR.Sunday" }; return new string[] { "SR.Monday", "SR.Tuesday", "SR.Wednesday", "SR.Thursday", "SR.Friday", "SR.Saturday", "SR.Sunday" };
} }
[GeneratedRegex("\\{(?<property>\\w+)\\}")]
private static partial Regex GetPropertyDescriptorRegex();
#endregion #endregion
} }

View File

@@ -102,7 +102,7 @@ namespace Microsoft.SqlTools.ServiceLayer.AzureFunctions
return a.ArgumentList return a.ArgumentList
?.Arguments ?.Arguments
.Where(a => a.Expression.Kind() == SyntaxKind.StringLiteralExpression && a.NameEquals == null) // Operations are string literals who don't have a name (Route is always a named param) .Where(a => a.Expression.Kind() == SyntaxKind.StringLiteralExpression && a.NameEquals == null) // Operations are string literals who don't have a name (Route is always a named param)
.Select(a => a.ToString().TrimStringQuotes().ToUpper()) // upper case for consistent naming .Select(a => a.ToString().TrimStringQuotes().ToUpper(System.Globalization.CultureInfo.InvariantCulture)) // upper case for consistent naming
.ToArray(); .ToArray();
} }

View File

@@ -1420,7 +1420,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
{ {
// Secure Enclaves is not mapped to SqlConnection, it's only used for throwing validation errors // Secure Enclaves is not mapped to SqlConnection, it's only used for throwing validation errors
// when Enclave Attestation Protocol is missing. // when Enclave Attestation Protocol is missing.
switch (connectionDetails.SecureEnclaves.ToUpper()) switch (connectionDetails.SecureEnclaves.ToUpper(CultureInfo.InvariantCulture))
{ {
case "ENABLED": case "ENABLED":
if (string.IsNullOrEmpty(connectionDetails.EnclaveAttestationProtocol)) if (string.IsNullOrEmpty(connectionDetails.EnclaveAttestationProtocol))
@@ -1437,7 +1437,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
if (!string.IsNullOrEmpty(connectionDetails.EnclaveAttestationProtocol)) if (!string.IsNullOrEmpty(connectionDetails.EnclaveAttestationProtocol))
{ {
if (connectionBuilder.ColumnEncryptionSetting != SqlConnectionColumnEncryptionSetting.Enabled if (connectionBuilder.ColumnEncryptionSetting != SqlConnectionColumnEncryptionSetting.Enabled
|| string.IsNullOrEmpty(connectionDetails.SecureEnclaves) || connectionDetails.SecureEnclaves.ToUpper() == "DISABLED") || string.IsNullOrEmpty(connectionDetails.SecureEnclaves) || connectionDetails.SecureEnclaves.ToUpper(CultureInfo.InvariantCulture) == "DISABLED")
{ {
throw new ArgumentException(SR.ConnectionServiceConnStringInvalidAlwaysEncryptedOptionCombination); throw new ArgumentException(SR.ConnectionServiceConnStringInvalidAlwaysEncryptedOptionCombination);
} }
@@ -1454,7 +1454,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Connection
if (!string.IsNullOrEmpty(connectionDetails.EnclaveAttestationUrl)) if (!string.IsNullOrEmpty(connectionDetails.EnclaveAttestationUrl))
{ {
if (connectionBuilder.ColumnEncryptionSetting != SqlConnectionColumnEncryptionSetting.Enabled if (connectionBuilder.ColumnEncryptionSetting != SqlConnectionColumnEncryptionSetting.Enabled
|| string.IsNullOrEmpty(connectionDetails.SecureEnclaves) || connectionDetails.SecureEnclaves.ToUpper() == "DISABLED") || string.IsNullOrEmpty(connectionDetails.SecureEnclaves) || connectionDetails.SecureEnclaves.ToUpper(CultureInfo.InvariantCulture) == "DISABLED")
{ {
throw new ArgumentException(SR.ConnectionServiceConnStringInvalidAlwaysEncryptedOptionCombination); throw new ArgumentException(SR.ConnectionServiceConnStringInvalidAlwaysEncryptedOptionCombination);
} }

View File

@@ -65,7 +65,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DacFx
/// </summary> /// </summary>
public static ModelTypeClass MapType(string type) public static ModelTypeClass MapType(string type)
{ {
switch (type.ToLower()) switch (type.ToLower(System.Globalization.CultureInfo.InvariantCulture))
{ {
case "table": case "table":
return ModelSchema.Table; return ModelSchema.Table;

View File

@@ -3,8 +3,6 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information. // Licensed under the MIT license. See LICENSE file in the project root for full license information.
// //
#nullable disable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
@@ -49,9 +47,9 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
/// <returns></returns> /// <returns></returns>
public RestorePlanDetailInfo CreateOptionInfo(string optionKey, IRestoreDatabaseTaskDataObject restoreDataObject) public RestorePlanDetailInfo CreateOptionInfo(string optionKey, IRestoreDatabaseTaskDataObject restoreDataObject)
{ {
if(optionBuilders.ContainsKey(optionKey)) if (optionBuilders.TryGetValue(optionKey, out OptionBuilder? value))
{ {
return Create(optionKey, restoreDataObject, optionBuilders[optionKey]); return Create(optionKey, restoreDataObject, value);
} }
else else
{ {
@@ -68,9 +66,9 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
/// <param name="optionInfo"></param> /// <param name="optionInfo"></param>
public void UpdateOption(string optionKey, IRestoreDatabaseTaskDataObject restoreDataObject, RestorePlanDetailInfo optionInfo) public void UpdateOption(string optionKey, IRestoreDatabaseTaskDataObject restoreDataObject, RestorePlanDetailInfo optionInfo)
{ {
if (optionBuilders.ContainsKey(optionKey)) if (optionBuilders.TryGetValue(optionKey, out OptionBuilder? value))
{ {
var builder = optionBuilders[optionKey]; var builder = value;
var currentValue = builder.CurrentValueFunction(restoreDataObject); var currentValue = builder.CurrentValueFunction(restoreDataObject);
var defaultValue = builder.DefaultValueFunction(restoreDataObject); var defaultValue = builder.DefaultValueFunction(restoreDataObject);
var validateResult = builder.ValidateFunction(restoreDataObject, currentValue, defaultValue); var validateResult = builder.ValidateFunction(restoreDataObject, currentValue, defaultValue);
@@ -102,9 +100,8 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
{ {
if (restoreDataObject != null) if (restoreDataObject != null)
{ {
if (optionBuilders.ContainsKey(optionKey)) if (optionBuilders.TryGetValue(optionKey, out OptionBuilder? builder))
{ {
var builder = optionBuilders[optionKey];
if (restoreDataObject.RestoreParams != null && restoreDataObject.RestoreParams.Options.ContainsKey(optionKey)) if (restoreDataObject.RestoreParams != null && restoreDataObject.RestoreParams.Options.ContainsKey(optionKey))
{ {
try try
@@ -149,15 +146,14 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
public string ValidateOption(string optionKey, IRestoreDatabaseTaskDataObject restoreDataObject) public string ValidateOption(string optionKey, IRestoreDatabaseTaskDataObject restoreDataObject)
{ {
string errorMessage = string.Empty; string errorMessage = string.Empty;
if (optionBuilders.ContainsKey(optionKey)) if (optionBuilders.TryGetValue(optionKey, out OptionBuilder? builder))
{ {
var builder = optionBuilders[optionKey];
var currentValue = builder.CurrentValueFunction(restoreDataObject); var currentValue = builder.CurrentValueFunction(restoreDataObject);
var defaultValue = builder.DefaultValueFunction(restoreDataObject); var defaultValue = builder.DefaultValueFunction(restoreDataObject);
OptionValidationResult result = optionBuilders[optionKey].ValidateFunction(restoreDataObject, currentValue, defaultValue); OptionValidationResult result = optionBuilders[optionKey].ValidateFunction(restoreDataObject, currentValue, defaultValue);
if (result.IsReadOnly) if (result.IsReadOnly)
{ {
if(!ValueEqualsDefault(currentValue, defaultValue)) if (!ValueEqualsDefault(currentValue, defaultValue))
{ {
builder.SetValueFunction(restoreDataObject, defaultValue); builder.SetValueFunction(restoreDataObject, defaultValue);
errorMessage = $"{optionKey} is ready only and cannot be modified"; errorMessage = $"{optionKey} is ready only and cannot be modified";
@@ -180,15 +176,11 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
private bool ValueEqualsDefault(object currentValue, object defaultValue) private bool ValueEqualsDefault(object currentValue, object defaultValue)
{ {
if(currentValue == null && defaultValue == null) if (currentValue == null)
{ {
return true; return defaultValue == null;
} }
if(currentValue == null && defaultValue != null) else if (defaultValue == null)
{
return false;
}
if (currentValue != null && defaultValue == null)
{ {
return false; return false;
} }
@@ -200,311 +192,311 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
{ {
Register(RestoreOptionsHelper.RelocateDbFiles, Register(RestoreOptionsHelper.RelocateDbFiles,
new OptionBuilder new OptionBuilder
{ (
DefaultValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => defaultValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return false; return false;
}, },
CurrentValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => currentValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.RelocateAllFiles; return restoreDataObject.RelocateAllFiles;
}, },
ValidateFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) => validateFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) =>
{ {
return new OptionValidationResult return new OptionValidationResult
{ {
IsReadOnly = restoreDataObject.DbFiles.Count == 0 IsReadOnly = restoreDataObject.DbFiles.Count == 0
}; };
}, },
SetValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object value) => setValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object value) =>
{ {
restoreDataObject.RelocateAllFiles = restoreDataObject.RestoreParams.GetOptionValue<bool>(RestoreOptionsHelper.RelocateDbFiles); restoreDataObject.RelocateAllFiles = restoreDataObject.RestoreParams.GetOptionValue<bool>(RestoreOptionsHelper.RelocateDbFiles);
return true; return true;
} }
}); ));
Register(RestoreOptionsHelper.DataFileFolder, Register(RestoreOptionsHelper.DataFileFolder,
new OptionBuilder new OptionBuilder
{ (
DefaultValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => defaultValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.DefaultDataFileFolder; return restoreDataObject.DefaultDataFileFolder;
}, },
CurrentValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => currentValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.DataFilesFolder; return restoreDataObject.DataFilesFolder;
}, },
ValidateFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) => validateFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) =>
{ {
return new OptionValidationResult return new OptionValidationResult
{ {
IsReadOnly = !restoreDataObject.RelocateAllFiles IsReadOnly = !restoreDataObject.RelocateAllFiles
}; };
}, },
SetValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object value) => setValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object value) =>
{ {
restoreDataObject.DataFilesFolder = GetValueAs<string>(value); restoreDataObject.DataFilesFolder = GetValueAs<string>(value);
return true; return true;
} }
}); ));
Register(RestoreOptionsHelper.LogFileFolder, Register(RestoreOptionsHelper.LogFileFolder,
new OptionBuilder new OptionBuilder
{ (
DefaultValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => defaultValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.DefaultLogFileFolder; return restoreDataObject.DefaultLogFileFolder;
}, },
CurrentValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => currentValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.LogFilesFolder; return restoreDataObject.LogFilesFolder;
}, },
ValidateFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) => validateFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) =>
{ {
return new OptionValidationResult return new OptionValidationResult
{ {
IsReadOnly = !restoreDataObject.RelocateAllFiles IsReadOnly = !restoreDataObject.RelocateAllFiles
}; };
}, },
SetValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object value) => setValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object value) =>
{ {
restoreDataObject.LogFilesFolder = GetValueAs<string>(value); restoreDataObject.LogFilesFolder = GetValueAs<string>(value);
return true; return true;
} }
}); ));
Register(RestoreOptionsHelper.ReplaceDatabase, Register(RestoreOptionsHelper.ReplaceDatabase,
new OptionBuilder new OptionBuilder
{ (
DefaultValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => defaultValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return false; return false;
}, },
CurrentValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => currentValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.RestoreOptions.ReplaceDatabase; return restoreDataObject.RestoreOptions.ReplaceDatabase;
}, },
ValidateFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) => validateFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) =>
{ {
return new OptionValidationResult(); return new OptionValidationResult();
}, },
SetValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object value) => setValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object value) =>
{ {
restoreDataObject.RestoreOptions.ReplaceDatabase = GetValueAs<bool>(value); restoreDataObject.RestoreOptions.ReplaceDatabase = GetValueAs<bool>(value);
return true; return true;
} }
}); ));
Register(RestoreOptionsHelper.KeepReplication, Register(RestoreOptionsHelper.KeepReplication,
new OptionBuilder new OptionBuilder
{ (
DefaultValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => defaultValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return false; return false;
}, },
CurrentValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => currentValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.RestoreOptions.KeepReplication; return restoreDataObject.RestoreOptions.KeepReplication;
}, },
ValidateFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) => validateFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) =>
{ {
return new OptionValidationResult() return new OptionValidationResult()
{ {
IsReadOnly = restoreDataObject.RestoreOptions.RecoveryState == DatabaseRecoveryState.WithNoRecovery IsReadOnly = restoreDataObject.RestoreOptions.RecoveryState == DatabaseRecoveryState.WithNoRecovery
}; };
}, },
SetValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object value) => setValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object value) =>
{ {
restoreDataObject.RestoreOptions.KeepReplication = GetValueAs<bool>(value); restoreDataObject.RestoreOptions.KeepReplication = GetValueAs<bool>(value);
return true; return true;
} }
}); ));
Register(RestoreOptionsHelper.SetRestrictedUser, Register(RestoreOptionsHelper.SetRestrictedUser,
new OptionBuilder new OptionBuilder
{ (
DefaultValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => defaultValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return false; return false;
}, },
CurrentValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => currentValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.RestoreOptions.SetRestrictedUser; return restoreDataObject.RestoreOptions.SetRestrictedUser;
}, },
ValidateFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) => validateFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) =>
{ {
return new OptionValidationResult() return new OptionValidationResult()
{ {
}; };
}, },
SetValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object value) => setValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object value) =>
{ {
restoreDataObject.RestoreOptions.SetRestrictedUser = GetValueAs<bool>(value); restoreDataObject.RestoreOptions.SetRestrictedUser = GetValueAs<bool>(value);
return true; return true;
} }
}); ));
Register(RestoreOptionsHelper.RecoveryState, Register(RestoreOptionsHelper.RecoveryState,
new OptionBuilder new OptionBuilder
{ (
DefaultValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => defaultValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return DatabaseRecoveryState.WithRecovery.ToString(); return DatabaseRecoveryState.WithRecovery.ToString();
}, },
CurrentValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => currentValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.RestoreOptions.RecoveryState.ToString(); return restoreDataObject.RestoreOptions.RecoveryState.ToString();
}, },
ValidateFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) => validateFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) =>
{ {
return new OptionValidationResult() return new OptionValidationResult()
{ {
}; };
}, },
SetValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object value) => setValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object value) =>
{ {
restoreDataObject.RestoreOptions.RecoveryState = GetValueAs<DatabaseRecoveryState>(value); restoreDataObject.RestoreOptions.RecoveryState = GetValueAs<DatabaseRecoveryState>(value);
return true; return true;
} }
}); ));
Register(RestoreOptionsHelper.StandbyFile, Register(RestoreOptionsHelper.StandbyFile,
new OptionBuilder new OptionBuilder
{ (
DefaultValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => defaultValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.DefaultStandbyFile; return restoreDataObject.DefaultStandbyFile;
}, },
CurrentValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => currentValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.RestoreOptions.StandByFile; return restoreDataObject.RestoreOptions.StandByFile;
}, },
ValidateFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) => validateFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) =>
{ {
return new OptionValidationResult() return new OptionValidationResult()
{ {
IsReadOnly = restoreDataObject.RestoreOptions.RecoveryState != DatabaseRecoveryState.WithStandBy IsReadOnly = restoreDataObject.RestoreOptions.RecoveryState != DatabaseRecoveryState.WithStandBy
}; };
}, },
SetValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object value) => setValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object value) =>
{ {
restoreDataObject.RestoreOptions.StandByFile = GetValueAs<string>(value); restoreDataObject.RestoreOptions.StandByFile = GetValueAs<string>(value);
return true; return true;
} }
}); ));
Register(RestoreOptionsHelper.BackupTailLog, Register(RestoreOptionsHelper.BackupTailLog,
new OptionBuilder new OptionBuilder
{ (
DefaultValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => defaultValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.IsTailLogBackupPossible; return restoreDataObject.IsTailLogBackupPossible;
}, },
CurrentValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => currentValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.BackupTailLog; return restoreDataObject.BackupTailLog;
}, },
ValidateFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) => validateFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) =>
{ {
return new OptionValidationResult() return new OptionValidationResult()
{ {
IsReadOnly = !restoreDataObject.IsTailLogBackupPossible IsReadOnly = !restoreDataObject.IsTailLogBackupPossible
}; };
}, },
SetValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object value) => setValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object value) =>
{ {
restoreDataObject.BackupTailLog = GetValueAs<bool>(value); restoreDataObject.BackupTailLog = GetValueAs<bool>(value);
return true; return true;
} }
}); ));
Register(RestoreOptionsHelper.TailLogBackupFile, Register(RestoreOptionsHelper.TailLogBackupFile,
new OptionBuilder new OptionBuilder
{ (
DefaultValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => defaultValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.DefaultTailLogbackupFile; return restoreDataObject.DefaultTailLogbackupFile;
}, },
CurrentValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => currentValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.TailLogBackupFile; return restoreDataObject.TailLogBackupFile;
}, },
ValidateFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) => validateFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) =>
{ {
return new OptionValidationResult() return new OptionValidationResult()
{ {
IsReadOnly = !restoreDataObject.BackupTailLog | !restoreDataObject.IsTailLogBackupPossible IsReadOnly = !restoreDataObject.BackupTailLog | !restoreDataObject.IsTailLogBackupPossible
}; };
}, },
SetValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object value) => setValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object value) =>
{ {
restoreDataObject.TailLogBackupFile = GetValueAs<string>(value); restoreDataObject.TailLogBackupFile = GetValueAs<string>(value);
return true; return true;
} }
}); ));
Register(RestoreOptionsHelper.TailLogWithNoRecovery, Register(RestoreOptionsHelper.TailLogWithNoRecovery,
new OptionBuilder new OptionBuilder
{ (
DefaultValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => defaultValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.IsTailLogBackupWithNoRecoveryPossible; return restoreDataObject.IsTailLogBackupWithNoRecoveryPossible;
}, },
CurrentValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => currentValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.TailLogWithNoRecovery; return restoreDataObject.TailLogWithNoRecovery;
}, },
ValidateFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) => validateFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) =>
{ {
return new OptionValidationResult() return new OptionValidationResult()
{ {
IsReadOnly = !restoreDataObject.BackupTailLog | !restoreDataObject.IsTailLogBackupWithNoRecoveryPossible IsReadOnly = !restoreDataObject.BackupTailLog | !restoreDataObject.IsTailLogBackupWithNoRecoveryPossible
}; };
}, },
SetValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object value) => setValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object value) =>
{ {
restoreDataObject.TailLogWithNoRecovery = GetValueAs<bool>(value); restoreDataObject.TailLogWithNoRecovery = GetValueAs<bool>(value);
return true; return true;
} }
}); ));
Register(RestoreOptionsHelper.CloseExistingConnections, Register(RestoreOptionsHelper.CloseExistingConnections,
new OptionBuilder new OptionBuilder
{ (
DefaultValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => defaultValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return false; return false;
}, },
CurrentValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => currentValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.CloseExistingConnections; return restoreDataObject.CloseExistingConnections;
}, },
ValidateFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) => validateFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) =>
{ {
return new OptionValidationResult() return new OptionValidationResult()
{ {
IsReadOnly = !restoreDataObject.CanDropExistingConnections IsReadOnly = !restoreDataObject.CanDropExistingConnections
}; };
}, },
SetValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object value) => setValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object value) =>
{ {
restoreDataObject.CloseExistingConnections = GetValueAs<bool>(value); restoreDataObject.CloseExistingConnections = GetValueAs<bool>(value);
return true; return true;
} }
}); ));
Register(RestoreOptionsHelper.SourceDatabaseName, Register(RestoreOptionsHelper.SourceDatabaseName,
new OptionBuilder new OptionBuilder
{ (
DefaultValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => defaultValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.DefaultSourceDbName; return restoreDataObject.DefaultSourceDbName;
}, },
CurrentValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => currentValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.SourceDatabaseName; return restoreDataObject.SourceDatabaseName;
}, },
ValidateFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) => validateFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) =>
{ {
string errorMessage = string.Empty; string errorMessage = string.Empty;
var sourceDbNames = restoreDataObject.SourceDbNames; var sourceDbNames = restoreDataObject.SourceDbNames;
@@ -514,41 +506,41 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
} }
return new OptionValidationResult() return new OptionValidationResult()
{ {
ErrorMessage = errorMessage ErrorMessage = errorMessage
}; };
}, },
SetValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object value) => setValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object value) =>
{ {
restoreDataObject.SourceDatabaseName = GetValueAs<string>(value); restoreDataObject.SourceDatabaseName = GetValueAs<string>(value);
return true; return true;
} }
}); ));
Register(RestoreOptionsHelper.TargetDatabaseName, Register(RestoreOptionsHelper.TargetDatabaseName,
new OptionBuilder new OptionBuilder
{ (
DefaultValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => defaultValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.OverwriteTargetDatabase ? restoreDataObject.DefaultSourceDbName : restoreDataObject.DefaultTargetDbName; return restoreDataObject.OverwriteTargetDatabase ? restoreDataObject.DefaultSourceDbName : restoreDataObject.DefaultTargetDbName;
}, },
CurrentValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject) => currentValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject) =>
{ {
return restoreDataObject.TargetDatabaseName; return restoreDataObject.TargetDatabaseName;
}, },
ValidateFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) => validateFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object currentValue, object defaultValue) =>
{ {
return new OptionValidationResult() return new OptionValidationResult()
{ {
IsReadOnly = false IsReadOnly = false
}; };
}, },
SetValueFunction = (IRestoreDatabaseTaskDataObject restoreDataObject, object value) => setValueFunction: (IRestoreDatabaseTaskDataObject restoreDataObject, object value) =>
{ {
restoreDataObject.TargetDatabaseName = GetValueAs<string>(value); restoreDataObject.TargetDatabaseName = GetValueAs<string>(value);
return true; return true;
} }
}); ));
} }
internal T GetValueAs<T>(object value) internal T GetValueAs<T>(object value)
@@ -562,7 +554,7 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
} }
private RestorePlanDetailInfo Create( private RestorePlanDetailInfo Create(
string optionKey, string optionKey,
IRestoreDatabaseTaskDataObject restoreDataObject, IRestoreDatabaseTaskDataObject restoreDataObject,
OptionBuilder optionBuilder) OptionBuilder optionBuilder)
{ {
@@ -587,6 +579,14 @@ namespace Microsoft.SqlTools.ServiceLayer.DisasterRecovery.RestoreOperation
public Func<IRestoreDatabaseTaskDataObject, object, object, OptionValidationResult> ValidateFunction { get; set; } public Func<IRestoreDatabaseTaskDataObject, object, object, OptionValidationResult> ValidateFunction { get; set; }
public Func<IRestoreDatabaseTaskDataObject, object> CurrentValueFunction { get; set; } public Func<IRestoreDatabaseTaskDataObject, object> CurrentValueFunction { get; set; }
public Func<IRestoreDatabaseTaskDataObject, object, bool> SetValueFunction { get; set; } public Func<IRestoreDatabaseTaskDataObject, object, bool> SetValueFunction { get; set; }
public OptionBuilder(Func<IRestoreDatabaseTaskDataObject, object> defaultValueFunction, Func<IRestoreDatabaseTaskDataObject, object, object, OptionValidationResult> validateFunction, Func<IRestoreDatabaseTaskDataObject, object> currentValueFunction, Func<IRestoreDatabaseTaskDataObject, object, bool> setValueFunction)
{
this.DefaultValueFunction = defaultValueFunction;
this.ValidateFunction = validateFunction;
this.CurrentValueFunction = currentValueFunction;
this.SetValueFunction = setValueFunction;
}
} }
internal class OptionValidationResult internal class OptionValidationResult

View File

@@ -18,11 +18,11 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
/// <summary> /// <summary>
/// Representation of a cell that should have a value inserted or updated /// Representation of a cell that should have a value inserted or updated
/// </summary> /// </summary>
public sealed class CellUpdate public sealed partial class CellUpdate
{ {
private const string NullString = @"NULL"; private const string NullString = @"NULL";
private const string TextNullString = @"'NULL'"; private const string TextNullString = @"'NULL'";
private static readonly Regex HexRegex = new Regex("0x[0-9A-F]+", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex HexRegex = GetCharacterRegex();
private static readonly TimeSpan MaxTimespan = TimeSpan.FromHours(24); private static readonly TimeSpan MaxTimespan = TimeSpan.FromHours(24);
/// <summary> /// <summary>
@@ -231,7 +231,7 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
private void ProcessTimespanColumn(string valueAsString) private void ProcessTimespanColumn(string valueAsString)
{ {
TimeSpan ts = TimeSpan.Parse(valueAsString, CultureInfo.CurrentCulture); var ts = TimeSpan.Parse(valueAsString, CultureInfo.CurrentCulture);
if (ts >= MaxTimespan) if (ts >= MaxTimespan)
{ {
throw new InvalidOperationException(SR.EditDataTimeOver24Hrs); throw new InvalidOperationException(SR.EditDataTimeOver24Hrs);
@@ -270,6 +270,9 @@ namespace Microsoft.SqlTools.ServiceLayer.EditData.UpdateManagement
ValueAsString = valueAsString; ValueAsString = valueAsString;
} }
[GeneratedRegex("0x[0-9A-F]+", RegexOptions.IgnoreCase | RegexOptions.Compiled)]
private static partial Regex GetCharacterRegex();
#endregion #endregion
} }
} }

View File

@@ -18,7 +18,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan.ShowPlan
/// <summary> /// <summary>
/// Base class for building hierarchy of Graph objects from ShowPlan Record Set /// Base class for building hierarchy of Graph objects from ShowPlan Record Set
/// </summary> /// </summary>
internal abstract class DataReaderNodeBuilder: INodeBuilder internal abstract partial class DataReaderNodeBuilder: INodeBuilder
{ {
#region Constructor #region Constructor
@@ -41,7 +41,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan.ShowPlan
/// <returns>An array of AnalysisServices Graph objects.</returns> /// <returns>An array of AnalysisServices Graph objects.</returns>
public ShowPlanGraph[] Execute(object dataSource) public ShowPlanGraph[] Execute(object dataSource)
{ {
IDataReader reader = dataSource as IDataReader; var reader = dataSource as IDataReader;
if (reader == null) if (reader == null)
{ {
@@ -49,7 +49,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan.ShowPlan
throw new ArgumentException(SR.Keys.UnknownShowPlanSource); throw new ArgumentException(SR.Keys.UnknownShowPlanSource);
} }
List<ShowPlanGraph> graphs = new List<ShowPlanGraph>(); var graphs = new List<ShowPlanGraph>();
Dictionary<int, Node> currentGraphNodes = null; Dictionary<int, Node> currentGraphNodes = null;
NodeBuilderContext context = null; NodeBuilderContext context = null;
@@ -174,7 +174,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan.ShowPlan
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
if (names[i] != null && !((values[i] is DBNull) || values[i] == null)) if (names[i] != null && !(values[i] is DBNull || values[i] == null))
{ {
node[names[i]] = values[i]; node[names[i]] = values[i];
} }
@@ -220,7 +220,7 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan.ShowPlan
string argument = node["Argument"] as string; string argument = node["Argument"] as string;
if (argument != null) if (argument != null)
{ {
Match match = argumentObjectExpression.Match(argument); Match match = GetargumentObjectExpressionRegex().Match(argument);
if (match != Match.Empty) if (match != Match.Empty)
{ {
node["Object"] = match.Groups["Object"].Value; node["Object"] = match.Groups["Object"].Value;
@@ -236,8 +236,8 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan.ShowPlan
} }
// Remove spaces and other special characters from physical and logical names // Remove spaces and other special characters from physical and logical names
physicalOpType = operatorReplaceExpression.Replace(physicalOpType, ""); physicalOpType = GetOperatorReplaceExpressionRegex().Replace(physicalOpType, "");
logicalOpType = operatorReplaceExpression.Replace(logicalOpType, ""); logicalOpType = GetOperatorReplaceExpressionRegex().Replace(logicalOpType, "");
Operation physicalOp = OperationTable.GetPhysicalOperation(physicalOpType); Operation physicalOp = OperationTable.GetPhysicalOperation(physicalOpType);
Operation logicalOp = OperationTable.GetLogicalOperation(logicalOpType); Operation logicalOp = OperationTable.GetLogicalOperation(logicalOpType);
@@ -290,8 +290,11 @@ namespace Microsoft.SqlTools.ServiceLayer.ExecutionPlan.ShowPlan
#region Private members #region Private members
private static Regex operatorReplaceExpression = new Regex(@"[ \-]", RegexOptions.CultureInvariant | RegexOptions.Compiled); [GeneratedRegex("[ \\-]", RegexOptions.Compiled | RegexOptions.CultureInvariant)]
private static Regex argumentObjectExpression = new Regex(@"OBJECT:\((?<Object>[^\)]*)\)", RegexOptions.CultureInvariant | RegexOptions.Compiled); private static partial Regex GetOperatorReplaceExpressionRegex();
[GeneratedRegex("OBJECT:\\((?<Object>[^\\)]*)\\)", RegexOptions.Compiled | RegexOptions.CultureInvariant)]
private static partial Regex GetargumentObjectExpressionRegex();
#endregion #endregion
} }

View File

@@ -191,10 +191,9 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
{ {
lock (this.bindingContextLock) lock (this.bindingContextLock)
{ {
if (this.BindingContextMap.ContainsKey(key)) if (this.BindingContextMap.TryGetValue(key, out IBindingContext? bindingContext))
{ {
// disconnect existing connection // disconnect existing connection
var bindingContext = this.BindingContextMap[key];
if (bindingContext.ServerConnection != null && bindingContext.ServerConnection.IsOpen) if (bindingContext.ServerConnection != null && bindingContext.ServerConnection.IsOpen)
{ {
// Disconnecting can take some time so run it in a separate task so that it doesn't block removal // Disconnecting can take some time so run it in a separate task so that it doesn't block removal

View File

@@ -19,9 +19,10 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Completion
/// <summary> /// <summary>
/// Creates a completion item from SQL parser declaration item /// Creates a completion item from SQL parser declaration item
/// </summary> /// </summary>
public class SqlCompletionItem public partial class SqlCompletionItem
{ {
private static Regex ValidSqlNameRegex = new Regex(@"^[\p{L}_@#][\p{L}\p{N}@$#_]{0,127}$"); [GeneratedRegex("^[\\p{L}_@#][\\p{L}\\p{N}@$#_]{0,127}$")]
private static partial Regex GetValidSqlNameRegex();
private static DelimitedIdentifier BracketedIdentifiers = new DelimitedIdentifier { Start = "[", End = "]" }; private static DelimitedIdentifier BracketedIdentifiers = new DelimitedIdentifier { Start = "[", End = "]" };
private static DelimitedIdentifier FunctionPostfix = new DelimitedIdentifier { Start = "", End = "()" }; private static DelimitedIdentifier FunctionPostfix = new DelimitedIdentifier { Start = "", End = "()" };
private static DelimitedIdentifier[] DelimitedIdentifiers = private static DelimitedIdentifier[] DelimitedIdentifiers =
@@ -79,7 +80,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Completion
case DeclarationType.Schema: case DeclarationType.Schema:
// Only quote if we need to - i.e. if this isn't a valid name (has characters that need escaping such as [) // Only quote if we need to - i.e. if this isn't a valid name (has characters that need escaping such as [)
// or if it's a reserved word // or if it's a reserved word
if (!ValidSqlNameRegex.IsMatch(DeclarationTitle) || AutoCompleteHelper.IsReservedWord(InsertText)) if (!GetValidSqlNameRegex().IsMatch(DeclarationTitle) || AutoCompleteHelper.IsReservedWord(InsertText))
{ {
InsertText = WithDelimitedIdentifier(BracketedIdentifiers, DeclarationTitle); InsertText = WithDelimitedIdentifier(BracketedIdentifiers, DeclarationTitle);
} }
@@ -197,7 +198,7 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices.Completion
int startColumn, int startColumn,
int endColumn) int endColumn)
{ {
CompletionItem item = new CompletionItem() var item = new CompletionItem()
{ {
Label = label, Label = label,
Kind = kind, Kind = kind,

View File

@@ -1869,10 +1869,10 @@ namespace Microsoft.SqlTools.ServiceLayer.LanguageServices
{ {
lock (this.parseMapLock) lock (this.parseMapLock)
{ {
if (this.ScriptParseInfoMap.ContainsKey(uri)) if (this.ScriptParseInfoMap.TryGetValue(uri, out ScriptParseInfo value))
{ {
Logger.Verbose($"Found ScriptParseInfo for uri {uri}"); Logger.Verbose($"Found ScriptParseInfo for uri {uri}");
return this.ScriptParseInfoMap[uri]; return value;
} }
else if (createIfNotExists) else if (createIfNotExists)
{ {

View File

@@ -1191,7 +1191,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
<urn>Server[@Name='{0}']</urn> <urn>Server[@Name='{0}']</urn>
<itemtype>Database</itemtype> <itemtype>Database</itemtype>
</params></formdescription> ", </params></formdescription> ",
connInfo.ConnectionDetails.ServerName.ToUpper(), connInfo.ConnectionDetails.ServerName.ToUpper(CultureInfo.InvariantCulture),
connInfo.ConnectionDetails.UserName); connInfo.ConnectionDetails.UserName);
} }
else else
@@ -1205,7 +1205,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Management
<urn>Server[@Name='{0}']</urn> <urn>Server[@Name='{0}']</urn>
<database>{2}</database> <database>{2}</database>
</params></formdescription> ", </params></formdescription> ",
connInfo.ConnectionDetails.ServerName.ToUpper(), connInfo.ConnectionDetails.ServerName.ToUpper(CultureInfo.InvariantCulture),
connInfo.ConnectionDetails.UserName, connInfo.ConnectionDetails.UserName,
connInfo.ConnectionDetails.DatabaseName); connInfo.ConnectionDetails.DatabaseName);
} }

View File

@@ -12,10 +12,10 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PreserveCompilationContext>true</PreserveCompilationContext> <PreserveCompilationContext>true</PreserveCompilationContext>
<RuntimeIdentifiers>$(ToolsServiceTargetRuntimes)</RuntimeIdentifiers> <RuntimeIdentifiers>$(ToolsServiceTargetRuntimes)</RuntimeIdentifiers>
<!-- TODO FIX THESE WARNINGS ASAP -->
<NoWarn>$(NoWarn);SYSLIB1045;CA1311;CA1854;CS8600;CS8603;CS8625</NoWarn>
<AssemblyTitle>SqlTools Editor Services Host Protocol Library</AssemblyTitle> <AssemblyTitle>SqlTools Editor Services Host Protocol Library</AssemblyTitle>
<Description>Provides message types and client/server APIs for the SqlTools Editor Services JSON protocol.</Description> <Description>Provides message types and client/server APIs for the SqlTools Editor Services JSON protocol.</Description>
<!-- False alerts, disabled due to issue: https://github.com/dotnet/roslyn/issues/65850 -->
<NoWarn>$(NoWarn);CS8795</NoWarn>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>

View File

@@ -114,9 +114,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Profiler
if ((currentEvent.Name.Equals("sql_batch_completed") if ((currentEvent.Name.Equals("sql_batch_completed")
|| currentEvent.Name.Equals("sql_batch_starting")) || currentEvent.Name.Equals("sql_batch_starting"))
&& currentEvent.Values.ContainsKey("batch_text")) && currentEvent.Values.TryGetValue("batch_text", out string value))
{ {
return currentEvent.Values["batch_text"].Contains("SELECT target_data FROM sys.dm_xe_session_targets") return value.Contains("SELECT target_data FROM sys.dm_xe_session_targets")
|| currentEvent.Values["batch_text"].Contains("SELECT target_data FROM sys.dm_xe_database_session_targets"); || currentEvent.Values["batch_text"].Contains("SELECT target_data FROM sys.dm_xe_database_session_targets");
} }

View File

@@ -19,10 +19,12 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
/// <summary> /// <summary>
/// Writer for exporting results to a Markdown table. /// Writer for exporting results to a Markdown table.
/// </summary> /// </summary>
public class SaveAsMarkdownFileStreamWriter : SaveAsStreamWriter public partial class SaveAsMarkdownFileStreamWriter : SaveAsStreamWriter
{ {
private const string Delimiter = "|"; private const string Delimiter = "|";
private static readonly Regex NewlineRegex = new Regex(@"(\r\n|\n|\r)", RegexOptions.Compiled);
[GeneratedRegex("(\\r\\n|\\n|\\r)", RegexOptions.Compiled)]
private static partial Regex GetNewLineRegex();
private readonly Encoding _encoding; private readonly Encoding _encoding;
private readonly string _lineSeparator; private readonly string _lineSeparator;
@@ -72,7 +74,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
this.WriteLine($"{Delimiter}{rowLine}{Delimiter}"); this.WriteLine($"{Delimiter}{rowLine}{Delimiter}");
} }
internal static string EncodeMarkdownField(string? field) internal static string EncodeMarkdownField(string field)
{ {
// Special case for nulls // Special case for nulls
if (field == null) if (field == null)
@@ -89,7 +91,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
// @TODO: Allow option to encode multiple whitespace characters as &nbsp; // @TODO: Allow option to encode multiple whitespace characters as &nbsp;
// Replace newlines with br tags, since cell values must be single line // Replace newlines with br tags, since cell values must be single line
field = NewlineRegex.Replace(field, @"<br />"); field = GetNewLineRegex().Replace(field, @"<br />");
return field; return field;
} }

View File

@@ -25,7 +25,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
/// Class that represents a resultset the was generated from a query. Contains logic for /// Class that represents a resultset the was generated from a query. Contains logic for
/// storing and retrieving results. Is contained by a Batch class. /// storing and retrieving results. Is contained by a Batch class.
/// </summary> /// </summary>
public class ResultSet : IDisposable public partial class ResultSet : IDisposable
{ {
#region Constants #region Constants
@@ -279,7 +279,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
// ReSharper disable once AccessToDisposedClosure The lambda is used immediately in string.Join call // ReSharper disable once AccessToDisposedClosure The lambda is used immediately in string.Join call
IEnumerable<string> rowValues = fileOffsets.Select(rowOffset => fileStreamReader.ReadRow(rowOffset, 0, Columns)[0].DisplayValue); IEnumerable<string> rowValues = fileOffsets.Select(rowOffset => fileStreamReader.ReadRow(rowOffset, 0, Columns)[0].DisplayValue);
string singleString = string.Join(string.Empty, rowValues); string singleString = string.Join(string.Empty, rowValues);
DbCellValue cellValue = new DbCellValue var cellValue = new DbCellValue
{ {
DisplayValue = singleString, DisplayValue = singleString,
IsNull = false, IsNull = false,
@@ -369,7 +369,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
// Verify the request hasn't been cancelled // Verify the request hasn't been cancelled
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
StorageDataReader dataReader = new StorageDataReader(dbDataReader); var dataReader = new StorageDataReader(dbDataReader);
// Open a writer for the file // Open a writer for the file
// //
@@ -514,7 +514,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
} }
// Create the new task // Create the new task
Task saveAsTask = new Task(async () => var saveAsTask = new Task(async () =>
{ {
try try
{ {
@@ -638,7 +638,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
// //
sendResultsSemphore.Wait(); sendResultsSemphore.Wait();
ResultSet currentResultSetSnapshot = (ResultSet) MemberwiseClone(); var currentResultSetSnapshot = (ResultSet) MemberwiseClone();
if (LastUpdatedSummary == null) // We need to send results available message. if (LastUpdatedSummary == null) // We need to send results available message.
{ {
// Fire off results Available task and await it // Fire off results Available task and await it
@@ -739,13 +739,12 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
{ {
if (Columns?.Length > 0 && RowCount != 0) if (Columns?.Length > 0 && RowCount != 0)
{ {
Regex regex = new Regex(@"({.*?})");
var row = GetRow(0); var row = GetRow(0);
for (int i = 0; i < Columns.Length; i++) for (int i = 0; i < Columns.Length; i++)
{ {
if (Columns[i].DataTypeName.Equals("nvarchar")) if (Columns[i].DataTypeName.Equals("nvarchar"))
{ {
if (regex.IsMatch(row[i].DisplayValue)) if (GetJsonRegex().IsMatch(row[i].DisplayValue))
{ {
Columns[i].IsJson = true; Columns[i].IsJson = true;
} }
@@ -788,7 +787,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
// Returning false from .ReadAsync means there aren't any rows. // Returning false from .ReadAsync means there aren't any rows.
// Create a storage data reader, read it, make sure there were results // Create a storage data reader, read it, make sure there were results
StorageDataReader dataReader = new StorageDataReader(dbDataReader); var dataReader = new StorageDataReader(dbDataReader);
if (!await dataReader.ReadAsync(CancellationToken.None)) if (!await dataReader.ReadAsync(CancellationToken.None))
{ {
throw new InvalidOperationException(SR.QueryServiceResultSetAddNoRows); throw new InvalidOperationException(SR.QueryServiceResultSetAddNoRows);
@@ -804,6 +803,9 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
} }
} }
[GeneratedRegex("({.*?})")]
private static partial Regex GetJsonRegex();
#endregion #endregion
} }
} }

View File

@@ -22,7 +22,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
/// <summary> /// <summary>
/// Internal class for utilities shared between multiple schema compare operations /// Internal class for utilities shared between multiple schema compare operations
/// </summary> /// </summary>
internal static class SchemaCompareUtils internal static partial class SchemaCompareUtils
{ {
internal static DiffEntry CreateDiffEntry(SchemaDifference difference, DiffEntry parent) internal static DiffEntry CreateDiffEntry(SchemaDifference difference, DiffEntry parent)
{ {
@@ -31,7 +31,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
return null; return null;
} }
DiffEntry diffEntry = new DiffEntry(); var diffEntry = new DiffEntry();
diffEntry.UpdateAction = difference.UpdateAction; diffEntry.UpdateAction = difference.UpdateAction;
diffEntry.DifferenceType = difference.DifferenceType; diffEntry.DifferenceType = difference.DifferenceType;
diffEntry.Name = difference.Name; diffEntry.Name = difference.Name;
@@ -86,8 +86,8 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
{ {
return null; return null;
} }
ObjectIdentifier id = new ObjectIdentifier(sourceObj.NameParts); var id = new ObjectIdentifier(sourceObj.NameParts);
SchemaComparisonExcludedObjectId excludedObjId = new SchemaComparisonExcludedObjectId(sourceObj.SqlObjectType, id); var excludedObjId = new SchemaComparisonExcludedObjectId(sourceObj.SqlObjectType, id);
return excludedObjId; return excludedObjId;
} }
catch (ArgumentException) catch (ArgumentException)
@@ -145,7 +145,7 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
// remove leading and trailing whitespace // remove leading and trailing whitespace
script = script.Trim(); script = script.Trim();
// replace all multiple spaces with single space // replace all multiple spaces with single space
script = Regex.Replace(script, " {2,}", " "); script = GetScriptRegex().Replace(script, " ");
} }
return script; return script;
} }
@@ -159,5 +159,8 @@ namespace Microsoft.SqlTools.ServiceLayer.SchemaCompare
} }
return script; return script;
} }
[GeneratedRegex(" {2,}")]
private static partial Regex GetScriptRegex();
} }
} }

View File

@@ -189,7 +189,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
string tokenType = GetTokenTypeFromQuickInfo(quickInfoText, tokenText, caseSensitivity); string tokenType = GetTokenTypeFromQuickInfo(quickInfoText, tokenText, caseSensitivity);
if (tokenType != null) if (tokenType != null)
{ {
if (sqlObjectTypesFromQuickInfo.ContainsKey(tokenType.ToLowerInvariant())) if (sqlObjectTypesFromQuickInfo.TryGetValue(tokenType.ToLowerInvariant(), out string sqlObjectType))
{ {
// With SqlLogin authentication, the defaultSchema property throws an Exception when accessed. // With SqlLogin authentication, the defaultSchema property throws an Exception when accessed.
// This workaround ensures that a schema name is present by attempting // This workaround ensures that a schema name is present by attempting
@@ -203,8 +203,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
Location[] locations = GetSqlObjectDefinition( Location[] locations = GetSqlObjectDefinition(
tokenText, tokenText,
schemaName, schemaName,
sqlObjectTypesFromQuickInfo[tokenType.ToLowerInvariant()] sqlObjectType);
);
DefinitionResult result = new DefinitionResult DefinitionResult result = new DefinitionResult
{ {
IsErrorResult = this.error, IsErrorResult = this.error,
@@ -232,7 +231,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
/// <returns></returns> /// <returns></returns>
internal DefinitionResult GetDefinitionUsingDeclarationType(DeclarationType type, string databaseQualifiedName, string tokenText, string schemaName) internal DefinitionResult GetDefinitionUsingDeclarationType(DeclarationType type, string databaseQualifiedName, string tokenText, string schemaName)
{ {
if (sqlObjectTypes.ContainsKey(type)) if (sqlObjectTypes.TryGetValue(type, out string sqlObjectType))
{ {
// With SqlLogin authentication, the defaultSchema property throws an Exception when accessed. // With SqlLogin authentication, the defaultSchema property throws an Exception when accessed.
// This workaround ensures that a schema name is present by attempting // This workaround ensures that a schema name is present by attempting
@@ -246,8 +245,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
Location[] locations = GetSqlObjectDefinition( Location[] locations = GetSqlObjectDefinition(
tokenText, tokenText,
schemaName, schemaName,
sqlObjectTypes[type] sqlObjectType);
);
DefinitionResult result = new DefinitionResult DefinitionResult result = new DefinitionResult
{ {
IsErrorResult = this.error, IsErrorResult = this.error,
@@ -288,7 +286,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
string[] lines = File.ReadAllLines(tempFileName); string[] lines = File.ReadAllLines(tempFileName);
int lineCount = 0; int lineCount = 0;
string createSyntax = null; string createSyntax = null;
if (objectScriptMap.ContainsKey(objectType.ToLower())) if (objectScriptMap.ContainsKey(objectType.ToLower(System.Globalization.CultureInfo.InvariantCulture)))
{ {
createSyntax = string.Format("CREATE"); createSyntax = string.Format("CREATE");
foreach (string line in lines) foreach (string line in lines)

View File

@@ -102,7 +102,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Scripting
// Leaving the server name blank will automatically match whatever the server SMO is running against. // Leaving the server name blank will automatically match whatever the server SMO is running against.
StringBuilder urnBuilder = new StringBuilder(); StringBuilder urnBuilder = new StringBuilder();
urnBuilder.AppendFormat("Server[@Name='{0}']/", server.ToUpper()); urnBuilder.AppendFormat("Server[@Name='{0}']/", server.ToUpper(System.Globalization.CultureInfo.InvariantCulture));
urnBuilder.AppendFormat("Database[@Name='{0}']/", Urn.EscapeString(database)); urnBuilder.AppendFormat("Database[@Name='{0}']/", Urn.EscapeString(database));
bool hasParentObject = !string.IsNullOrWhiteSpace(scriptingObject.ParentName) bool hasParentObject = !string.IsNullOrWhiteSpace(scriptingObject.ParentName)

View File

@@ -38,9 +38,9 @@ namespace Microsoft.SqlTools.ServiceLayer.TableDesigner
public T GetValue(string displayName) public T GetValue(string displayName)
{ {
if (this.Mapping.ContainsKey(displayName)) if (this.Mapping.TryGetValue(displayName, out T value))
{ {
return this.Mapping[displayName]; return value;
} }
else else
{ {

View File

@@ -38,7 +38,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility
{ {
get get
{ {
return ClientUri?.ToLower(); return ClientUri?.ToLower(System.Globalization.CultureInfo.InvariantCulture);
} }
} }
} }

View File

@@ -16,11 +16,14 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility.SqlScriptFormatters
/// <summary> /// <summary>
/// Provides utilities for converting from SQL script syntax into POCOs. /// Provides utilities for converting from SQL script syntax into POCOs.
/// </summary> /// </summary>
public static class FromSqlScript public static partial class FromSqlScript
{ {
// Regex: optionally starts with N, captures string wrapped in single quotes // Regex: optionally starts with N, captures string wrapped in single quotes
private static readonly Regex StringRegex = new Regex("^N?'(.*)'$", RegexOptions.Compiled); [GeneratedRegex("^N?'(.*)'$", RegexOptions.Compiled)]
private static readonly Regex BracketRegex = new Regex(@"^\[(.*)\]$", RegexOptions.Compiled); private static partial Regex GetStringRegex();
[GeneratedRegex("^\\[(.*)\\]$", RegexOptions.Compiled)]
private static partial Regex GetBracketRegex();
/// <summary> /// <summary>
/// Decodes a multipart identifier as used in a SQL script into an array of the multiple /// Decodes a multipart identifier as used in a SQL script into an array of the multiple
@@ -35,8 +38,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility.SqlScriptFormatters
/// </exception> /// </exception>
public static string[] DecodeMultipartIdentifier(string multipartIdentifier) public static string[] DecodeMultipartIdentifier(string multipartIdentifier)
{ {
StringBuilder sb = new StringBuilder(); var sb = new StringBuilder();
List<string> namedParts = new List<string>(); var namedParts = new List<string>();
bool insideBrackets = false; bool insideBrackets = false;
bool bracketsClosed = false; bool bracketsClosed = false;
for (int i = 0; i < multipartIdentifier.Length; i++) for (int i = 0; i < multipartIdentifier.Length; i++)
@@ -122,7 +125,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility.SqlScriptFormatters
literal = literal.Trim('(', ')'); literal = literal.Trim('(', ')');
// Attempt to unwrap inverted commas around a string // Attempt to unwrap inverted commas around a string
Match match = StringRegex.Match(literal); Match match = GetStringRegex().Match(literal);
if (match.Success) if (match.Success)
{ {
// Like: N'stuff' or 'stuff' // Like: N'stuff' or 'stuff'
@@ -136,7 +139,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Utility.SqlScriptFormatters
/// </summary> /// </summary>
/// <param name="identifer">Identifier to check.</param> /// <param name="identifer">Identifier to check.</param>
/// <returns>Boolean indicating if identifier is escaped with brackets.</returns> /// <returns>Boolean indicating if identifier is escaped with brackets.</returns>
public static bool IsIdentifierBracketed(string identifer) => BracketRegex.IsMatch(identifer); public static bool IsIdentifierBracketed(string identifer) => GetBracketRegex().IsMatch(identifer);
#region Private Helpers #region Private Helpers

View File

@@ -27,7 +27,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace.Contracts
/// </summary> /// </summary>
public string Id public string Id
{ {
get { return this.ClientUri.ToLower(); } get { return this.ClientUri.ToLower(System.Globalization.CultureInfo.InvariantCulture); }
} }
/// <summary> /// <summary>

View File

@@ -23,7 +23,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
/// Manages a "workspace" of script files that are open for a particular /// Manages a "workspace" of script files that are open for a particular
/// editing session. Also helps to navigate references between ScriptFiles. /// editing session. Also helps to navigate references between ScriptFiles.
/// </summary> /// </summary>
public class Workspace : IDisposable public partial class Workspace : IDisposable
{ {
#region Private Fields #region Private Fields
@@ -117,8 +117,8 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
} }
// This method allows FileNotFoundException to bubble up // This method allows FileNotFoundException to bubble up
// if the file isn't found. // if the file isn't found.
using (FileStream fileStream = new FileStream(resolvedFile.FilePath, FileMode.Open, FileAccess.Read)) using (var fileStream = new FileStream(resolvedFile.FilePath, FileMode.Open, FileAccess.Read))
using (StreamReader streamReader = new StreamReader(fileStream, Encoding.UTF8)) using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
{ {
scriptFile = new ScriptFile(resolvedFile.FilePath, resolvedFile.ClientUri,streamReader); scriptFile = new ScriptFile(resolvedFile.FilePath, resolvedFile.ClientUri,streamReader);
@@ -150,7 +150,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
// Client sent the path in URI format, extract the local path and trim // Client sent the path in URI format, extract the local path and trim
// any extraneous slashes // any extraneous slashes
Uri fileUri = new Uri(clientUri); var fileUri = new Uri(clientUri);
filePath = fileUri.LocalPath; filePath = fileUri.LocalPath;
if (filePath.StartsWith("//") || filePath.StartsWith("\\\\") || filePath.StartsWith("/")) if (filePath.StartsWith("//") || filePath.StartsWith("\\\\") || filePath.StartsWith("/"))
{ {
@@ -208,7 +208,7 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
return path; return path;
} }
return Regex.Replace(path, @"`(?=[ \[\]])", ""); return GetEscapeRegex().Replace(path, "");
} }
/// <summary> /// <summary>
@@ -363,6 +363,9 @@ namespace Microsoft.SqlTools.ServiceLayer.Workspace
{ {
} }
[GeneratedRegex("`(?=[ \\[\\]])")]
private static partial Regex GetEscapeRegex();
#endregion #endregion
} }
} }

View File

@@ -15,7 +15,7 @@ using System.IO;
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.AzureFunctions namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.AzureFunctions
{ {
class AzureFunctionsServiceTests internal sealed class AzureFunctionsServiceTests
{ {
private string testAzureFunctionsFolder = Path.Combine("..", "..", "..", "AzureFunctions", "AzureFunctionTestFiles"); private string testAzureFunctionsFolder = Path.Combine("..", "..", "..", "AzureFunctions", "AzureFunctionTestFiles");

View File

@@ -29,14 +29,14 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
/// </summary> /// </summary>
public class ReliableConnectionTests public class ReliableConnectionTests
{ {
internal class TestDataTransferErrorDetectionStrategy : DataTransferErrorDetectionStrategy internal sealed class TestDataTransferErrorDetectionStrategy : DataTransferErrorDetectionStrategy
{ {
public bool InvokeCanRetrySqlException(SqlException exception) public bool InvokeCanRetrySqlException(SqlException exception)
{ {
return CanRetrySqlException(exception); return CanRetrySqlException(exception);
} }
} }
internal class TestSqlAzureTemporaryAndIgnorableErrorDetectionStrategy : SqlAzureTemporaryAndIgnorableErrorDetectionStrategy internal sealed class TestSqlAzureTemporaryAndIgnorableErrorDetectionStrategy : SqlAzureTemporaryAndIgnorableErrorDetectionStrategy
{ {
public TestSqlAzureTemporaryAndIgnorableErrorDetectionStrategy() public TestSqlAzureTemporaryAndIgnorableErrorDetectionStrategy()
: base (new int[] { 100 }) : base (new int[] { 100 })
@@ -54,7 +54,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
} }
} }
internal class TestFixedDelayPolicy : FixedDelayPolicy internal sealed class TestFixedDelayPolicy : FixedDelayPolicy
{ {
public TestFixedDelayPolicy( public TestFixedDelayPolicy(
IErrorDetectionStrategy strategy, IErrorDetectionStrategy strategy,
@@ -77,7 +77,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
} }
} }
internal class TestProgressiveRetryPolicy : ProgressiveRetryPolicy internal sealed class TestProgressiveRetryPolicy : ProgressiveRetryPolicy
{ {
public TestProgressiveRetryPolicy( public TestProgressiveRetryPolicy(
IErrorDetectionStrategy strategy, IErrorDetectionStrategy strategy,
@@ -97,7 +97,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
} }
} }
internal class TestTimeBasedRetryPolicy : TimeBasedRetryPolicy internal sealed class TestTimeBasedRetryPolicy : TimeBasedRetryPolicy
{ {
public TestTimeBasedRetryPolicy( public TestTimeBasedRetryPolicy(
IErrorDetectionStrategy strategy, IErrorDetectionStrategy strategy,
@@ -916,7 +916,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.Connection
command.UpdatedRowSource = UpdateRowSource.None; command.UpdatedRowSource = UpdateRowSource.None;
Assert.AreEqual(UpdateRowSource.None, command.UpdatedRowSource); Assert.AreEqual(UpdateRowSource.None, command.UpdatedRowSource);
Assert.NotNull(command.GetUnderlyingCommand()); Assert.NotNull(command.GetUnderlyingCommand());
Assert.Throws<InvalidOperationException>(() => command.ValidateConnectionIsSet()); Assert.Throws<InvalidOperationException>(command.ValidateConnectionIsSet);
command.Prepare(); command.Prepare();
Assert.NotNull(command.CreateParameter()); Assert.NotNull(command.CreateParameter());
command.Cancel(); command.Cancel();

View File

@@ -30,7 +30,7 @@ using static Microsoft.SqlTools.ServiceLayer.IntegrationTests.Utility.LiveConnec
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.DisasterRecovery namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.DisasterRecovery
{ {
class BackupRestoreUrlTests internal sealed class BackupRestoreUrlTests
{ {
/// <summary> /// <summary>
/// Create simple backup test /// Create simple backup test

View File

@@ -574,7 +574,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.DisasterRecovery
string backUpFilePath = string.Empty; string backUpFilePath = string.Empty;
if (backupFileNames != null) if (backupFileNames != null)
{ {
var filePaths = backupFileNames.Select(x => GetBackupFilePath(x)); var filePaths = backupFileNames.Select(GetBackupFilePath);
backUpFilePath = filePaths.Aggregate((current, next) => current + " ," + next); backUpFilePath = filePaths.Aggregate((current, next) => current + " ," + next);
} }

View File

@@ -368,7 +368,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
await langService.HandleDidChangeLanguageFlavorNotification(new LanguageFlavorChangeParams await langService.HandleDidChangeLanguageFlavorNotification(new LanguageFlavorChangeParams
{ {
Uri = scriptFile.ClientUri, Uri = scriptFile.ClientUri,
Language = LanguageService.SQL_LANG.ToLower(), Language = LanguageService.SQL_LANG.ToLower(System.Globalization.CultureInfo.InvariantCulture),
Flavor = "MSSQL" Flavor = "MSSQL"
}, eventContextSql.Object); }, eventContextSql.Object);
await langService.DelayedDiagnosticsTask; // to ensure completion and validation before moveing to next step await langService.DelayedDiagnosticsTask; // to ensure completion and validation before moveing to next step
@@ -379,7 +379,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.LanguageServer
await langService.HandleDidChangeLanguageFlavorNotification(new LanguageFlavorChangeParams await langService.HandleDidChangeLanguageFlavorNotification(new LanguageFlavorChangeParams
{ {
Uri = scriptFile.ClientUri, Uri = scriptFile.ClientUri,
Language = LanguageService.SQL_CMD_LANG.ToLower(), Language = LanguageService.SQL_CMD_LANG.ToLower(System.Globalization.CultureInfo.InvariantCulture),
Flavor = "MSSQL" Flavor = "MSSQL"
}, eventContextSqlCmd.Object); }, eventContextSqlCmd.Object);
await langService.DelayedDiagnosticsTask; await langService.DelayedDiagnosticsTask;

View File

@@ -6,8 +6,6 @@
<PackageId>Microsoft.SqlTools.ServiceLayer.IntegrationTests</PackageId> <PackageId>Microsoft.SqlTools.ServiceLayer.IntegrationTests</PackageId>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles> <GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<DefineConstants>$(DefineConstants);TRACE</DefineConstants> <DefineConstants>$(DefineConstants);TRACE</DefineConstants>
<!-- TODO FIX THESE WARNINGS ASAP -->
<NoWarn>$(NoWarn);SYSLIB1045;IDE0200;IDE0230;CA1311;CA1852;CA1854</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="../../src/Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj" /> <ProjectReference Include="../../src/Microsoft.SqlTools.Hosting/Microsoft.SqlTools.Hosting.csproj" />

View File

@@ -28,7 +28,7 @@ using static Microsoft.SqlTools.ServiceLayer.ObjectExplorer.ObjectExplorerServic
namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
{ {
public class ObjectExplorerServiceTests public partial class ObjectExplorerServiceTests
{ {
private ObjectExplorerService _service = TestServiceProvider.Instance.ObjectExplorerService; private ObjectExplorerService _service = TestServiceProvider.Instance.ObjectExplorerService;
@@ -124,10 +124,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
{ {
var query = ""; var query = "";
string databaseName = "#testDb#"; string databaseName = "#testDb#";
await RunTest(databaseName, query, "TestDb", async (testDbName, session) => await RunTest(databaseName, query, "TestDb", ExpandAndVerifyDatabaseNode);
{
await ExpandAndVerifyDatabaseNode(testDbName, session);
});
} }
[Test] [Test]
@@ -376,7 +373,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName); ConnectParams connectParams = TestServiceProvider.Instance.ConnectionProfileService.GetConnectionParameters(TestServerType.OnPrem, databaseName);
//connectParams.Connection.Pooling = false; //connectParams.Connection.Pooling = false;
ConnectionDetails details = connectParams.Connection; ConnectionDetails details = connectParams.Connection;
string uri = ObjectExplorerService.GenerateUri(details); string uri = GenerateUri(details);
var session = await _service.DoCreateSession(details, uri); var session = await _service.DoCreateSession(details, uri);
Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "OE session created for database: {0}", databaseName)); Console.WriteLine(string.Format(CultureInfo.InvariantCulture, "OE session created for database: {0}", databaseName));
@@ -387,10 +384,10 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
{ {
Assert.That(session, Is.Not.Null, nameof(session)); Assert.That(session, Is.Not.Null, nameof(session));
Assert.That(session.Root, Is.Not.Null, nameof(session.Root)); Assert.That(session.Root, Is.Not.Null, nameof(session.Root));
NodeInfo nodeInfo = session.Root.ToNodeInfo(); var nodeInfo = session.Root.ToNodeInfo();
Assert.That(nodeInfo.IsLeaf, Is.False, "Should not be a leaf node"); Assert.That(nodeInfo.IsLeaf, Is.False, "Should not be a leaf node");
NodeInfo? databaseNode = null; NodeInfo databaseNode = null;
if (serverNode) if (serverNode)
{ {
@@ -435,7 +432,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
{ {
Assert.NotNull(session); Assert.NotNull(session);
Assert.NotNull(session.Root); Assert.NotNull(session.Root);
NodeInfo nodeInfo = session.Root.ToNodeInfo(); var nodeInfo = session.Root.ToNodeInfo();
Assert.AreEqual(false, nodeInfo.IsLeaf); Assert.AreEqual(false, nodeInfo.IsLeaf);
Assert.AreEqual(nodeInfo.NodeType, NodeTypes.Database.ToString()); Assert.AreEqual(nodeInfo.NodeType, NodeTypes.Database.ToString());
Assert.True(nodeInfo.Label.Contains(databaseName)); Assert.True(nodeInfo.Label.Contains(databaseName));
@@ -457,7 +454,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
Console.WriteLine($"Session closed uri:{uri}"); Console.WriteLine($"Session closed uri:{uri}");
} }
private async Task ExpandTree(NodeInfo node, ObjectExplorerSession session, StringBuilder? stringBuilder = null, bool verifySystemObjects = false) private async Task ExpandTree(NodeInfo node, ObjectExplorerSession session, StringBuilder stringBuilder = null, bool verifySystemObjects = false)
{ {
if (node != null && !node.IsLeaf) if (node != null && !node.IsLeaf)
{ {
@@ -552,7 +549,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
private async Task<bool> VerifyObjectExplorerTest(string databaseName, string testDbPrefix, string queryFileName, string baselineFileName, bool verifySystemObjects = false) private async Task<bool> VerifyObjectExplorerTest(string databaseName, string testDbPrefix, string queryFileName, string baselineFileName, bool verifySystemObjects = false)
{ {
var query = string.IsNullOrEmpty(queryFileName) ? string.Empty : LoadScript(queryFileName); var query = string.IsNullOrEmpty(queryFileName) ? string.Empty : LoadScript(queryFileName);
StringBuilder stringBuilder = new StringBuilder(); var stringBuilder = new StringBuilder();
await RunTest(databaseName, query, testDbPrefix, async (testDbName, session) => await RunTest(databaseName, query, testDbPrefix, async (testDbName, session) =>
{ {
await ExpandServerNodeAndVerifyDatabaseHierachy(testDbName, session, false); await ExpandServerNodeAndVerifyDatabaseHierachy(testDbName, session, false);
@@ -564,7 +561,7 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
// Dropped ledger objects have a randomly generated GUID appended to their name when they are deleted // Dropped ledger objects have a randomly generated GUID appended to their name when they are deleted
// For testing purposes, those guids need to be replaced with a deterministic string // For testing purposes, those guids need to be replaced with a deterministic string
actual = Regex.Replace(actual, "[A-Z0-9]{32}", "<<NonDeterministic>>"); actual = GetBaselineRegex().Replace(actual, "<<NonDeterministic>>");
// Write output to a bin directory for easier comparison // Write output to a bin directory for easier comparison
string assemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? string.Empty; string assemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? string.Empty;
@@ -640,5 +637,8 @@ namespace Microsoft.SqlTools.ServiceLayer.IntegrationTests.ObjectExplorer
FileInfo inputFile = GetBaseLineFile(fileName); FileInfo inputFile = GetBaseLineFile(fileName);
return TestUtilities.ReadTextAndNormalizeLineEndings(inputFile.FullName); return TestUtilities.ReadTextAndNormalizeLineEndings(inputFile.FullName);
} }
[GeneratedRegex("[A-Z0-9]{32}")]
private static partial Regex GetBaselineRegex();
} }
} }

View File

@@ -113,7 +113,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.AutoParameterization
// SQL greater than 300000 characters should throw // SQL greater than 300000 characters should throw
string bigSql = string.Concat(Repeat(element: sqlLength_300, count: 1100)); string bigSql = string.Concat(Repeat(element: sqlLength_300, count: 1100));
DbCommand command2 = new SqlCommand { CommandText = bigSql }; DbCommand command2 = new SqlCommand { CommandText = bigSql };
Assert.Throws<ParameterizationScriptTooLargeException>(() => command2.Parameterize()); Assert.Throws<ParameterizationScriptTooLargeException>(command2.Parameterize);
} }
/// <summary> /// <summary>
@@ -128,7 +128,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.AutoParameterization
string sql = string.Concat(Repeat(element: invalidSql, count: 1000)); string sql = string.Concat(Repeat(element: invalidSql, count: 1000));
DbCommand command = new SqlCommand { CommandText = sql }; DbCommand command = new SqlCommand { CommandText = sql };
Assert.Throws<ParameterizationParsingException>(() => command.Parameterize()); Assert.Throws<ParameterizationParsingException>(command.Parameterize);
} }
/// <summary> /// <summary>
@@ -149,7 +149,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.AutoParameterization
GO"; GO";
DbCommand command = new SqlCommand { CommandText = sql }; DbCommand command = new SqlCommand { CommandText = sql };
Assert.Throws<ParameterizationFormatException>(() => command.Parameterize()); Assert.Throws<ParameterizationFormatException>(command.Parameterize);
} }
/// <summary> /// <summary>

View File

@@ -15,7 +15,7 @@ using Azure.Storage.Sas;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.DisasterRecovery namespace Microsoft.SqlTools.ServiceLayer.UnitTests.DisasterRecovery
{ {
class SharedAccessSignatureCreatorTests internal sealed class SharedAccessSignatureCreatorTests
{ {
[Test] [Test]
public void GetServiceSasUriForContainerReturnsNullWhenCannotGenerateSasUri() public void GetServiceSasUriForContainerReturnsNullWhenCannotGenerateSasUri()

View File

@@ -105,8 +105,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
yield return new object[] {"0x000", new byte[] {0x00, 0x00}, "0x0000"}; // Base16, odd yield return new object[] {"0x000", new byte[] {0x00, 0x00}, "0x0000"}; // Base16, odd
// Single byte tests // Single byte tests
yield return new object[] {"50", new byte[] {0x32}, "0x32"}; // Base10 yield return new object[] {"50", "2"u8.ToArray(), "0x32"}; // Base10
yield return new object[] {"050", new byte[] {0x32}, "0x32"}; // Base10, leading zeros yield return new object[] {"050", "2"u8.ToArray(), "0x32"}; // Base10, leading zeros
yield return new object[] {"0xF0", new byte[] {0xF0}, "0xF0"}; // Base16 yield return new object[] {"0xF0", new byte[] {0xF0}, "0xF0"}; // Base16
yield return new object[] {"0x0F", new byte[] {0x0F}, "0x0F"}; // Base16, leading zeros yield return new object[] {"0x0F", new byte[] {0x0F}, "0x0F"}; // Base16, leading zeros
yield return new object[] {"0xF", new byte[] {0x0F}, "0x0F"}; // Base16, odd yield return new object[] {"0xF", new byte[] {0x0F}, "0x0F"}; // Base16, odd
@@ -296,7 +296,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
return new DbColumnWrapper(new CellUpdateTestDbColumn(typeof(T), dataTypeName, allowNull, colSize)); return new DbColumnWrapper(new CellUpdateTestDbColumn(typeof(T), dataTypeName, allowNull, colSize));
} }
private class CellUpdateTestDbColumn : DbColumn private sealed class CellUpdateTestDbColumn : DbColumn
{ {
public CellUpdateTestDbColumn(Type dataType, string dataTypeName, bool allowNull = true, int? colSize = null) public CellUpdateTestDbColumn(Type dataType, string dataTypeName, bool allowNull = true, int? colSize = null)
{ {

View File

@@ -21,18 +21,18 @@ using NUnit.Framework;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
public class RowCreateTests public partial class RowCreateTests
{ {
[Test] [Test]
public async Task RowCreateConstruction() public async Task RowCreateConstruction()
{ {
// Setup: Create the values to store // Setup: Create the values to store
const long rowId = 100; const long rowId = 100;
Common.TestDbColumnsWithTableMetadata data = new Common.TestDbColumnsWithTableMetadata(false, false, 0, 0); var data = new Common.TestDbColumnsWithTableMetadata(false, false, 0, 0);
ResultSet rs = await Common.GetResultSet(data.DbColumns, false); ResultSet rs = await Common.GetResultSet(data.DbColumns, false);
// If: I create a RowCreate instance // If: I create a RowCreate instance
RowCreate rc = new RowCreate(rowId, rs, data.TableMetadata); var rc = new RowCreate(rowId, rs, data.TableMetadata);
// Then: The values I provided should be available // Then: The values I provided should be available
Assert.AreEqual(rowId, rc.RowId); Assert.AreEqual(rowId, rc.RowId);
@@ -67,7 +67,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
// Setup: Generate the parameters for the row create // Setup: Generate the parameters for the row create
var data = new Common.TestDbColumnsWithTableMetadata(false, includeIdentity, defaultCols, nullableCols); var data = new Common.TestDbColumnsWithTableMetadata(false, includeIdentity, defaultCols, nullableCols);
var rs = await Common.GetResultSet(data.DbColumns, includeIdentity); var rs = await Common.GetResultSet(data.DbColumns, includeIdentity);
RowCreate rc = new RowCreate(100, rs, data.TableMetadata); var rc = new RowCreate(100, rs, data.TableMetadata);
// If: I ask for a script to be generated without setting any values // If: I ask for a script to be generated without setting any values
// Then: An exception should be thrown for missing cells // Then: An exception should be thrown for missing cells
@@ -116,11 +116,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: // Setup:
// ... Generate the parameters for the row create // ... Generate the parameters for the row create
Common.TestDbColumnsWithTableMetadata data = new Common.TestDbColumnsWithTableMetadata(false, includeIdentity, colsWithDefaultConstraints, colsThatAllowNull); var data = new Common.TestDbColumnsWithTableMetadata(false, includeIdentity, colsWithDefaultConstraints, colsThatAllowNull);
ResultSet rs = await Common.GetResultSet(data.DbColumns, includeIdentity); ResultSet rs = await Common.GetResultSet(data.DbColumns, includeIdentity);
// ... Create a row create and set the appropriate number of cells // ... Create a row create and set the appropriate number of cells
RowCreate rc = new RowCreate(100, rs, data.TableMetadata); var rc = new RowCreate(100, rs, data.TableMetadata);
Common.AddCells(rc, valuesToSkipSetting); Common.AddCells(rc, valuesToSkipSetting);
// If: I ask for the script for the row insert // If: I ask for the script for the row insert
@@ -139,8 +139,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
if (expectedOutput == null) if (expectedOutput == null)
{ {
// If expected output was null make sure we match the default values reges // If expected output was null make sure we match the default values reges
Regex r = new Regex(@"INSERT INTO (.+) DEFAULT VALUES"); Match m = GetInsert1Regex().Match(sql);
Match m = r.Match(sql);
Assert.True(m.Success); Assert.True(m.Success);
// Table name matches // Table name matches
@@ -149,8 +148,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
else else
{ {
// Do the whole validation // Do the whole validation
Regex r = new Regex(@"INSERT INTO (.+)\((.+)\) VALUES \((.+)\)"); Match m = GetInsert2Regex().Match(sql);
Match m = r.Match(sql);
Assert.True(m.Success); Assert.True(m.Success);
// Table name matches // Table name matches
@@ -174,14 +172,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
// Setup: // Setup:
// ... Generate the parameters for the row create // ... Generate the parameters for the row create
const long rowId = 100; const long rowId = 100;
Common.TestDbColumnsWithTableMetadata data = new Common.TestDbColumnsWithTableMetadata(false, includeIdentity, 0, 0); var data = new Common.TestDbColumnsWithTableMetadata(false, includeIdentity, 0, 0);
ResultSet rs = await Common.GetResultSet(data.DbColumns, includeIdentity); ResultSet rs = await Common.GetResultSet(data.DbColumns, includeIdentity);
// ... Setup a db reader for the result of an insert // ... Setup a db reader for the result of an insert
var newRowReader = Common.GetNewRowDataReader(data.DbColumns, includeIdentity); var newRowReader = Common.GetNewRowDataReader(data.DbColumns, includeIdentity);
// If: I ask for the change to be applied // If: I ask for the change to be applied
RowCreate rc = new RowCreate(rowId, rs, data.TableMetadata); var rc = new RowCreate(rowId, rs, data.TableMetadata);
await rc.ApplyChanges(newRowReader); await rc.ApplyChanges(newRowReader);
// Then: The result set should have an additional row in it // Then: The result set should have an additional row in it
@@ -226,9 +224,9 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: // Setup:
// ... Generate the row create object // ... Generate the row create object
Common.TestDbColumnsWithTableMetadata data = new Common.TestDbColumnsWithTableMetadata(false, includeIdentity, defaultCols, nullableCols); var data = new Common.TestDbColumnsWithTableMetadata(false, includeIdentity, defaultCols, nullableCols);
ResultSet rs = await Common.GetResultSet(data.DbColumns, includeIdentity); ResultSet rs = await Common.GetResultSet(data.DbColumns, includeIdentity);
RowCreate rc = new RowCreate(100, rs, data.TableMetadata); var rc = new RowCreate(100, rs, data.TableMetadata);
// ... Create a mock db connection for building the command // ... Create a mock db connection for building the command
var mockConn = new TestSqlConnection(); var mockConn = new TestSqlConnection();
@@ -280,14 +278,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: // Setup:
// ... Generate the parameters for the row create // ... Generate the parameters for the row create
Common.TestDbColumnsWithTableMetadata data = new Common.TestDbColumnsWithTableMetadata(false, includeIdentity, defaultCols, nullableCols); var data = new Common.TestDbColumnsWithTableMetadata(false, includeIdentity, defaultCols, nullableCols);
ResultSet rs = await Common.GetResultSet(data.DbColumns, includeIdentity); ResultSet rs = await Common.GetResultSet(data.DbColumns, includeIdentity);
// ... Mock db connection for building the command // ... Mock db connection for building the command
var mockConn = new TestSqlConnection(null); var mockConn = new TestSqlConnection(null);
// ... Create a row create and set the appropriate number of cells // ... Create a row create and set the appropriate number of cells
RowCreate rc = new RowCreate(100, rs, data.TableMetadata); var rc = new RowCreate(100, rs, data.TableMetadata);
Common.AddCells(rc, valuesToSkip); Common.AddCells(rc, valuesToSkip);
// If: I ask for the command for the row insert // If: I ask for the command for the row insert
@@ -311,8 +309,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
Assert.AreEqual(3, splitSql.Length); Assert.AreEqual(3, splitSql.Length);
// Check the declare statement first // Check the declare statement first
Regex declareRegex = new Regex(@"^DECLARE @(.+) TABLE \((.+)\)$"); Match declareMatch = GetDeclareRegex().Match(splitSql[0]);
Match declareMatch = declareRegex.Match(splitSql[0]);
Assert.True(declareMatch.Success); Assert.True(declareMatch.Success);
// Declared table name matches // Declared table name matches
@@ -327,7 +324,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
if (expectedOutput.ExpectedInColumns == 0 || expectedOutput.ExpectedInValues == 0) if (expectedOutput.ExpectedInColumns == 0 || expectedOutput.ExpectedInValues == 0)
{ {
// If expected output was null make sure we match the default values reges // If expected output was null make sure we match the default values reges
Regex insertRegex = new Regex(@"^INSERT INTO (.+) OUTPUT (.+) INTO @(.+) DEFAULT VALUES$"); var insertRegex = GetInsertRegex();
Match insertMatch = insertRegex.Match(splitSql[1]); Match insertMatch = insertRegex.Match(splitSql[1]);
Assert.True(insertMatch.Success); Assert.True(insertMatch.Success);
@@ -347,7 +344,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
else else
{ {
// Do the whole validation // Do the whole validation
Regex insertRegex = new Regex(@"^INSERT INTO (.+)\((.+)\) OUTPUT (.+) INTO @(.+) VALUES \((.+)\)$"); var insertRegex = GetInsertFullRegex();
Match insertMatch = insertRegex.Match(splitSql[1]); Match insertMatch = insertRegex.Match(splitSql[1]);
Assert.True(insertMatch.Success); Assert.True(insertMatch.Success);
@@ -380,7 +377,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
} }
// Check the select statement last // Check the select statement last
Regex selectRegex = new Regex(@"^SELECT (.+) FROM @(.+)$"); var selectRegex = GetSelectRegex();
Match selectMatch = selectRegex.Match(splitSql[2]); Match selectMatch = selectRegex.Match(splitSql[2]);
Assert.True(selectMatch.Success); Assert.True(selectMatch.Success);
@@ -425,9 +422,9 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: Generate a row create with default values // Setup: Generate a row create with default values
const long rowId = 100; const long rowId = 100;
Common.TestDbColumnsWithTableMetadata data = new Common.TestDbColumnsWithTableMetadata(false, false, 3, 0); var data = new Common.TestDbColumnsWithTableMetadata(false, false, 3, 0);
ResultSet rs = await Common.GetResultSet(data.DbColumns, false); ResultSet rs = await Common.GetResultSet(data.DbColumns, false);
RowCreate rc = new RowCreate(rowId, rs, data.TableMetadata); var rc = new RowCreate(rowId, rs, data.TableMetadata);
// If: I request an edit row from the row create // If: I request an edit row from the row create
EditRow er = rc.GetEditRow(null); EditRow er = rc.GetEditRow(null);
@@ -451,9 +448,9 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: Generate a row create with an identity column // Setup: Generate a row create with an identity column
const long rowId = 100; const long rowId = 100;
Common.TestDbColumnsWithTableMetadata data = new Common.TestDbColumnsWithTableMetadata(false, true, 0, 0); var data = new Common.TestDbColumnsWithTableMetadata(false, true, 0, 0);
ResultSet rs = await Common.GetResultSet(data.DbColumns, true); ResultSet rs = await Common.GetResultSet(data.DbColumns, true);
RowCreate rc = new RowCreate(rowId, rs, data.TableMetadata); var rc = new RowCreate(rowId, rs, data.TableMetadata);
// If: I request an edit row from the row created // If: I request an edit row from the row created
EditRow er = rc.GetEditRow(null); EditRow er = rc.GetEditRow(null);
@@ -573,7 +570,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
var etm = Common.GetCustomEditTableMetadata(cols); var etm = Common.GetCustomEditTableMetadata(cols);
// ... Create the row create // ... Create the row create
RowCreate rc = new RowCreate(100, rs, etm); var rc = new RowCreate(100, rs, etm);
// If: I set a cell in the newly created row to something that will be corrected // If: I set a cell in the newly created row to something that will be corrected
EditUpdateCellResult eucr = rc.SetCell(0, "1000"); EditUpdateCellResult eucr = rc.SetCell(0, "1000");
@@ -644,9 +641,9 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: // Setup:
// ... Generate the parameters for the row create // ... Generate the parameters for the row create
Common.TestDbColumnsWithTableMetadata data = new Common.TestDbColumnsWithTableMetadata(false, false, defaultCols, 0); var data = new Common.TestDbColumnsWithTableMetadata(false, false, defaultCols, 0);
ResultSet rs = await Common.GetResultSet(data.DbColumns, false); ResultSet rs = await Common.GetResultSet(data.DbColumns, false);
RowCreate rc = new RowCreate(100, rs, data.TableMetadata); var rc = new RowCreate(100, rs, data.TableMetadata);
// If: I attempt to revert a cell that has not been set // If: I attempt to revert a cell that has not been set
EditRevertCellResult result = rc.RevertCell(0); EditRevertCellResult result = rc.RevertCell(0);
@@ -673,9 +670,9 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: // Setup:
// ... Generate the parameters for the row create // ... Generate the parameters for the row create
Common.TestDbColumnsWithTableMetadata data = new Common.TestDbColumnsWithTableMetadata(false, false, defaultCols, 0); var data = new Common.TestDbColumnsWithTableMetadata(false, false, defaultCols, 0);
ResultSet rs = await Common.GetResultSet(data.DbColumns, false); ResultSet rs = await Common.GetResultSet(data.DbColumns, false);
RowCreate rc = new RowCreate(100, rs, data.TableMetadata); var rc = new RowCreate(100, rs, data.TableMetadata);
rc.SetCell(0, "1"); rc.SetCell(0, "1");
// If: I attempt to revert a cell that was set // If: I attempt to revert a cell that was set
@@ -720,5 +717,25 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
public int ExpectedInValues { get; } public int ExpectedInValues { get; }
public int ExpectedOutColumns { get; } public int ExpectedOutColumns { get; }
} }
#region Generated Regex
[GeneratedRegex("INSERT INTO (.+) DEFAULT VALUES")]
private static partial Regex GetInsert1Regex();
[GeneratedRegex("INSERT INTO (.+)\\((.+)\\) VALUES \\((.+)\\)")]
private static partial Regex GetInsert2Regex();
[GeneratedRegex("^DECLARE @(.+) TABLE \\((.+)\\)$")]
private static partial Regex GetDeclareRegex();
[GeneratedRegex("^INSERT INTO (.+) OUTPUT (.+) INTO @(.+) DEFAULT VALUES$")]
private static partial Regex GetInsertRegex();
[GeneratedRegex("^INSERT INTO (.+)\\((.+)\\) OUTPUT (.+) INTO @(.+) VALUES \\((.+)\\)$")]
private static partial Regex GetInsertFullRegex();
[GeneratedRegex("^SELECT (.+) FROM @(.+)$")]
private static partial Regex GetSelectRegex();
#endregion
} }
} }

View File

@@ -251,7 +251,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
return resultSet; return resultSet;
} }
private class RowEditTester : RowEditBase private sealed class RowEditTester : RowEditBase
{ {
public RowEditTester(ResultSet rs, EditTableMetadata meta) : base(0, rs, meta) { } public RowEditTester(ResultSet rs, EditTableMetadata meta) : base(0, rs, meta) { }

View File

@@ -21,7 +21,7 @@ using NUnit.Framework;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
public class RowUpdateTests public partial class RowUpdateTests
{ {
[Test] [Test]
public async Task RowUpdateConstruction() public async Task RowUpdateConstruction()
@@ -32,7 +32,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
var rs = await Common.GetResultSet(data.DbColumns, false); var rs = await Common.GetResultSet(data.DbColumns, false);
// If: I create a RowUpdate instance // If: I create a RowUpdate instance
RowUpdate rc = new RowUpdate(rowId, rs, data.TableMetadata); var rc = new RowUpdate(rowId, rs, data.TableMetadata);
// Then: The values I provided should be available // Then: The values I provided should be available
Assert.AreEqual(rowId, rc.RowId); Assert.AreEqual(rowId, rc.RowId);
@@ -61,7 +61,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
// If: // If:
// ... I add updates to all the cells in the row // ... I add updates to all the cells in the row
RowUpdate ru = new RowUpdate(0, rs, data.TableMetadata); var ru = new RowUpdate(0, rs, data.TableMetadata);
Common.AddCells(ru, 1); Common.AddCells(ru, 1);
// ... Then I update a cell back to it's old value // ... Then I update a cell back to it's old value
@@ -83,8 +83,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
Assert.True(eucr.IsRowDirty); Assert.True(eucr.IsRowDirty);
// ... It should be formatted as an update script // ... It should be formatted as an update script
Regex r = new Regex(@"UPDATE .+ SET (.*) WHERE"); var m = GetUpdateRegex().Match(ru.GetScript());
var m = r.Match(ru.GetScript());
// ... It should have 2 updates // ... It should have 2 updates
string updates = m.Groups[1].Value; string updates = m.Groups[1].Value;
@@ -102,7 +101,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
// If: // If:
// ... I add updates to one cell in the row // ... I add updates to one cell in the row
RowUpdate ru = new RowUpdate(0, rs, data.TableMetadata); var ru = new RowUpdate(0, rs, data.TableMetadata);
ru.SetCell(1, "qqq"); ru.SetCell(1, "qqq");
// ... Then I update the cell to its original value // ... Then I update the cell to its original value
@@ -149,7 +148,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
var etm = Common.GetCustomEditTableMetadata(cols); var etm = Common.GetCustomEditTableMetadata(cols);
// ... Create the row update // ... Create the row update
RowUpdate ru = new RowUpdate(0, rs, etm); var ru = new RowUpdate(0, rs, etm);
// If: I set a cell in the newly created row to something that will be corrected // If: I set a cell in the newly created row to something that will be corrected
EditUpdateCellResult eucr = ru.SetCell(0, "1000"); EditUpdateCellResult eucr = ru.SetCell(0, "1000");
@@ -214,7 +213,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
ResultSet rs = await Common.GetResultSet(data.DbColumns, true); ResultSet rs = await Common.GetResultSet(data.DbColumns, true);
// If: I ask for a script to be generated for update // If: I ask for a script to be generated for update
RowUpdate ru = new RowUpdate(0, rs, data.TableMetadata); var ru = new RowUpdate(0, rs, data.TableMetadata);
Common.AddCells(ru, 1); Common.AddCells(ru, 1);
string script = ru.GetScript(); string script = ru.GetScript();
@@ -226,7 +225,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
string regexString = isMemoryOptimized string regexString = isMemoryOptimized
? @"UPDATE (.+) WITH \(SNAPSHOT\) SET (.*) WHERE .+" ? @"UPDATE (.+) WITH \(SNAPSHOT\) SET (.*) WHERE .+"
: @"UPDATE (.+) SET (.*) WHERE .+"; : @"UPDATE (.+) SET (.*) WHERE .+";
Regex r = new Regex(regexString); var r = new Regex(regexString);
var m = r.Match(script); var m = r.Match(script);
Assert.True(m.Success); Assert.True(m.Success);
@@ -248,7 +247,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
// ... Create a row update with cell updates // ... Create a row update with cell updates
var data = new Common.TestDbColumnsWithTableMetadata(isMemoryOptimized, includeIdentity, 0, 0); var data = new Common.TestDbColumnsWithTableMetadata(isMemoryOptimized, includeIdentity, 0, 0);
var rs = await Common.GetResultSet(data.DbColumns, includeIdentity); var rs = await Common.GetResultSet(data.DbColumns, includeIdentity);
RowUpdate ru = new RowUpdate(0, rs, data.TableMetadata); var ru = new RowUpdate(0, rs, data.TableMetadata);
Common.AddCells(ru, includeIdentity ? 1 : 0); Common.AddCells(ru, includeIdentity ? 1 : 0);
// ... Mock db connection for building the command // ... Mock db connection for building the command
@@ -267,8 +266,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
Assert.True(splitSql.Length >= 3); Assert.True(splitSql.Length >= 3);
// Check the declare statement first // Check the declare statement first
Regex declareRegex = new Regex(@"^DECLARE @(.+) TABLE \((.+)\)$"); Match declareMatch = GetDeclareTableRegex().Match(splitSql[0]);
Match declareMatch = declareRegex.Match(splitSql[0]);
Assert.True(declareMatch.Success); Assert.True(declareMatch.Success);
// Declared table name matches // Declared table name matches
@@ -283,7 +281,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
string regex = isMemoryOptimized string regex = isMemoryOptimized
? @"^UPDATE (.+) WITH \(SNAPSHOT\) SET (.+) OUTPUT (.+) INTO @(.+) WHERE .+$" ? @"^UPDATE (.+) WITH \(SNAPSHOT\) SET (.+) OUTPUT (.+) INTO @(.+) WHERE .+$"
: @"^UPDATE (.+) SET (.+) OUTPUT (.+) INTO @(.+) WHERE .+$"; : @"^UPDATE (.+) SET (.+) OUTPUT (.+) INTO @(.+) WHERE .+$";
Regex updateRegex = new Regex(regex); var updateRegex = new Regex(regex);
Match updateMatch = updateRegex.Match(splitSql[10]); Match updateMatch = updateRegex.Match(splitSql[10]);
Assert.True(updateMatch.Success); Assert.True(updateMatch.Success);
@@ -304,8 +302,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
Assert.That(updateMatch.Groups[4].Value, Does.EndWith("Output")); Assert.That(updateMatch.Groups[4].Value, Does.EndWith("Output"));
// Check the select statement last // Check the select statement last
Regex selectRegex = new Regex(@"^SELECT (.+) FROM @(.+)$"); Match selectMatch = GetSelectRegex().Match(splitSql[11]);
Match selectMatch = selectRegex.Match(splitSql[11]);
Assert.True(selectMatch.Success); Assert.True(selectMatch.Success);
// Correct number of columns in select statement // Correct number of columns in select statement
@@ -343,7 +340,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
// Setup: Create a row update with a cell set // Setup: Create a row update with a cell set
var data = new Common.TestDbColumnsWithTableMetadata(false, false, 0, 0); var data = new Common.TestDbColumnsWithTableMetadata(false, false, 0, 0);
var rs = await Common.GetResultSet(data.DbColumns, false); var rs = await Common.GetResultSet(data.DbColumns, false);
RowUpdate ru = new RowUpdate(0, rs, data.TableMetadata); var ru = new RowUpdate(0, rs, data.TableMetadata);
ru.SetCell(0, "foo"); ru.SetCell(0, "foo");
// If: I attempt to get an edit row // If: I attempt to get an edit row
@@ -399,7 +396,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
// ... Create a row update (no cell updates needed) // ... Create a row update (no cell updates needed)
var data = new Common.TestDbColumnsWithTableMetadata(false, includeIdentity, 0, 0); var data = new Common.TestDbColumnsWithTableMetadata(false, includeIdentity, 0, 0);
var rs = await Common.GetResultSet(data.DbColumns, includeIdentity); var rs = await Common.GetResultSet(data.DbColumns, includeIdentity);
RowUpdate ru = new RowUpdate(0, rs, data.TableMetadata); var ru = new RowUpdate(0, rs, data.TableMetadata);
long oldBytesWritten = rs.totalBytesWritten; long oldBytesWritten = rs.totalBytesWritten;
// ... Setup a db reader for the result of an update // ... Setup a db reader for the result of an update
@@ -421,7 +418,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
// ... Create a row update (no cell updates needed) // ... Create a row update (no cell updates needed)
var data = new Common.TestDbColumnsWithTableMetadata(false, true, 0, 0); var data = new Common.TestDbColumnsWithTableMetadata(false, true, 0, 0);
var rs = await Common.GetResultSet(data.DbColumns, true); var rs = await Common.GetResultSet(data.DbColumns, true);
RowUpdate ru = new RowUpdate(0, rs, data.TableMetadata); var ru = new RowUpdate(0, rs, data.TableMetadata);
// If: I ask for the changes to be applied with a null db reader // If: I ask for the changes to be applied with a null db reader
// Then: I should get an exception // Then: I should get an exception
@@ -439,7 +436,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
// ... Create a row update (no cell updates needed) // ... Create a row update (no cell updates needed)
var data = new Common.TestDbColumnsWithTableMetadata(false, false, 0, 0); var data = new Common.TestDbColumnsWithTableMetadata(false, false, 0, 0);
var rs = await Common.GetResultSet(data.DbColumns, false); var rs = await Common.GetResultSet(data.DbColumns, false);
RowUpdate ru = new RowUpdate(0, rs, data.TableMetadata); var ru = new RowUpdate(0, rs, data.TableMetadata);
// If: I attempt to revert a cell that is out of range // If: I attempt to revert a cell that is out of range
// Then: I should get an exception // Then: I should get an exception
@@ -453,7 +450,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
// ... Create a row update (no cell updates needed) // ... Create a row update (no cell updates needed)
var data = new Common.TestDbColumnsWithTableMetadata(false, true, 0, 0); var data = new Common.TestDbColumnsWithTableMetadata(false, true, 0, 0);
var rs = await Common.GetResultSet(data.DbColumns, true); var rs = await Common.GetResultSet(data.DbColumns, true);
RowUpdate ru = new RowUpdate(0, rs, data.TableMetadata); var ru = new RowUpdate(0, rs, data.TableMetadata);
// If: I attempt to revert a cell that has not been set // If: I attempt to revert a cell that has not been set
EditRevertCellResult result = ru.RevertCell(0); EditRevertCellResult result = ru.RevertCell(0);
@@ -480,7 +477,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
// ... Create a row update // ... Create a row update
var data = new Common.TestDbColumnsWithTableMetadata(false, false, 0, 0); var data = new Common.TestDbColumnsWithTableMetadata(false, false, 0, 0);
var rs = await Common.GetResultSet(data.DbColumns, false); var rs = await Common.GetResultSet(data.DbColumns, false);
RowUpdate ru = new RowUpdate(0, rs, data.TableMetadata); var ru = new RowUpdate(0, rs, data.TableMetadata);
ru.SetCell(0, "qqq"); ru.SetCell(0, "qqq");
ru.SetCell(1, "qqq"); ru.SetCell(1, "qqq");
@@ -509,7 +506,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
// ... Create a row update // ... Create a row update
var data = new Common.TestDbColumnsWithTableMetadata(false, false, 0, 0); var data = new Common.TestDbColumnsWithTableMetadata(false, false, 0, 0);
var rs = await Common.GetResultSet(data.DbColumns, false); var rs = await Common.GetResultSet(data.DbColumns, false);
RowUpdate ru = new RowUpdate(0, rs, data.TableMetadata); var ru = new RowUpdate(0, rs, data.TableMetadata);
ru.SetCell(0, "qqq"); ru.SetCell(0, "qqq");
// If: I attempt to revert a cell that was set // If: I attempt to revert a cell that was set
@@ -538,5 +535,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
var rs = await Common.GetResultSet(data.DbColumns, false); var rs = await Common.GetResultSet(data.DbColumns, false);
return new RowUpdate(0, rs, data.TableMetadata); return new RowUpdate(0, rs, data.TableMetadata);
} }
[GeneratedRegex("^DECLARE @(.+) TABLE \\((.+)\\)$")]
private static partial Regex GetDeclareTableRegex();
[GeneratedRegex("^SELECT (.+) FROM @(.+)$")]
private static partial Regex GetSelectRegex();
[GeneratedRegex("UPDATE .+ SET (.*) WHERE")]
private static partial Regex GetUpdateRegex();
} }
} }

View File

@@ -26,7 +26,7 @@ using NUnit.Framework;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
public class SessionTests public partial class SessionTests
{ {
#region Construction Tests #region Construction Tests
@@ -42,8 +42,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
public void SessionConstructionValid() public void SessionConstructionValid()
{ {
// If: I create a session object with a proper arguments // If: I create a session object with a proper arguments
Mock<IEditMetadataFactory> mockFactory = new Mock<IEditMetadataFactory>(); var mockFactory = new Mock<IEditMetadataFactory>();
EditSession s = new EditSession(mockFactory.Object); var s = new EditSession(mockFactory.Object);
// Then: // Then:
// ... The edit cache should not exist // ... The edit cache should not exist
@@ -87,7 +87,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
ConnectionService.Instance.OwnerToConnectionMap[ci.OwnerUri] = ci; ConnectionService.Instance.OwnerToConnectionMap[ci.OwnerUri] = ci;
var fsf = MemoryFileSystem.GetFileStreamFactory(); var fsf = MemoryFileSystem.GetFileStreamFactory();
Query query = new Query(Constants.StandardQuery, ci, new QueryExecutionSettings(), fsf); var query = new Query(Constants.StandardQuery, ci, new QueryExecutionSettings(), fsf);
query.Execute(); query.Execute();
query.ExecutionTask.Wait(); query.ExecutionTask.Wait();
@@ -116,8 +116,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: // Setup:
// ... Create a session without initializing // ... Create a session without initializing
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>(); var emf = new Mock<IEditMetadataFactory>();
EditSession s = new EditSession(emf.Object); var s = new EditSession(emf.Object);
// If: I ask to create a row without initializing // If: I ask to create a row without initializing
// Then: I should get an exception // Then: I should get an exception
@@ -292,8 +292,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: // Setup:
// ... Create a session and fake that it has been initialized // ... Create a session and fake that it has been initialized
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>(); var emf = new Mock<IEditMetadataFactory>();
EditSession s = new EditSession(emf.Object) {IsInitialized = true}; var s = new EditSession(emf.Object) {IsInitialized = true};
// If: I initialize it // If: I initialize it
// Then: I should get an exception // Then: I should get an exception
@@ -305,8 +305,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: // Setup:
// ... Create a session and fake that it is in progress of initializing // ... Create a session and fake that it is in progress of initializing
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>(); var emf = new Mock<IEditMetadataFactory>();
EditSession s = new EditSession(emf.Object) {InitializeTask = new Task(() => {})}; var s = new EditSession(emf.Object) {InitializeTask = new Task(() => {})};
// If: I initialize it // If: I initialize it
// Then: I should get an exception // Then: I should get an exception
@@ -320,8 +320,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: // Setup:
// ... Create a session that hasn't been initialized // ... Create a session that hasn't been initialized
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>(); var emf = new Mock<IEditMetadataFactory>();
EditSession s = new EditSession(emf.Object); var s = new EditSession(emf.Object);
Assert.Catch<ArgumentException>(() => s.Initialize(initParams, c, qr, sh, fh), "I initialize it with a missing parameter. It should throw an exception"); Assert.Catch<ArgumentException>(() => s.Initialize(initParams, c, qr, sh, fh), "I initialize it with a missing parameter. It should throw an exception");
} }
@@ -381,12 +381,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: // Setup:
// ... Create a metadata factory that throws // ... Create a metadata factory that throws
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>(); var emf = new Mock<IEditMetadataFactory>();
emf.Setup(f => f.GetObjectMetadata(It.IsAny<DbConnection>(), It.IsAny<string[]>(), It.IsAny<string>())) emf.Setup(f => f.GetObjectMetadata(It.IsAny<DbConnection>(), It.IsAny<string[]>(), It.IsAny<string>()))
.Throws<Exception>(); .Throws<Exception>();
// ... Create a session that hasn't been initialized // ... Create a session that hasn't been initialized
EditSession s = new EditSession(emf.Object); var s = new EditSession(emf.Object);
// ... Create a mock for verifying the failure handler will be called // ... Create a mock for verifying the failure handler will be called
var successHandler = DoNothingSuccessMock; var successHandler = DoNothingSuccessMock;
@@ -414,15 +414,15 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
// ... Create a metadata factory that will return some generic column information // ... Create a metadata factory that will return some generic column information
var b = QueryExecution.Common.GetBasicExecutedBatch(); var b = QueryExecution.Common.GetBasicExecutedBatch();
var etm = Common.GetCustomEditTableMetadata(b.ResultSets[0].Columns.Cast<DbColumn>().ToArray()); var etm = Common.GetCustomEditTableMetadata(b.ResultSets[0].Columns.Cast<DbColumn>().ToArray());
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>(); var emf = new Mock<IEditMetadataFactory>();
emf.Setup(f => f.GetObjectMetadata(It.IsAny<DbConnection>(), It.IsAny<string[]>(), It.IsAny<string>())) emf.Setup(f => f.GetObjectMetadata(It.IsAny<DbConnection>(), It.IsAny<string[]>(), It.IsAny<string>()))
.Returns(etm); .Returns(etm);
// ... Create a session that hasn't been initialized // ... Create a session that hasn't been initialized
EditSession s = new EditSession(emf.Object); var s = new EditSession(emf.Object);
// ... Create a query runner that will fail via exception // ... Create a query runner that will fail via exception
Mock<EditSession.QueryRunner> qr = new Mock<EditSession.QueryRunner>(); var qr = new Mock<EditSession.QueryRunner>();
qr.Setup(r => r(It.IsAny<string>())).Throws(new Exception("qqq")); qr.Setup(r => r(It.IsAny<string>())).Throws(new Exception("qqq"));
// ... Create a mock for verifying the failure handler will be called // ... Create a mock for verifying the failure handler will be called
@@ -451,15 +451,15 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
// ... Create a metadata factory that will return some generic column information // ... Create a metadata factory that will return some generic column information
var b = QueryExecution.Common.GetBasicExecutedBatch(); var b = QueryExecution.Common.GetBasicExecutedBatch();
var etm = Common.GetCustomEditTableMetadata(b.ResultSets[0].Columns.Cast<DbColumn>().ToArray()); var etm = Common.GetCustomEditTableMetadata(b.ResultSets[0].Columns.Cast<DbColumn>().ToArray());
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>(); var emf = new Mock<IEditMetadataFactory>();
emf.Setup(f => f.GetObjectMetadata(It.IsAny<DbConnection>(), It.IsAny<string[]>(), It.IsAny<string>())) emf.Setup(f => f.GetObjectMetadata(It.IsAny<DbConnection>(), It.IsAny<string[]>(), It.IsAny<string>()))
.Returns(etm); .Returns(etm);
// ... Create a session that hasn't been initialized // ... Create a session that hasn't been initialized
EditSession s = new EditSession(emf.Object); var s = new EditSession(emf.Object);
// ... Create a query runner that will fail via returning a null query // ... Create a query runner that will fail via returning a null query
Mock<EditSession.QueryRunner> qr = new Mock<EditSession.QueryRunner>(); var qr = new Mock<EditSession.QueryRunner>();
qr.Setup(r => r(It.IsAny<string>())) qr.Setup(r => r(It.IsAny<string>()))
.Returns(Task.FromResult(new EditSession.EditSessionQueryExecutionState(null, message))); .Returns(Task.FromResult(new EditSession.EditSessionQueryExecutionState(null, message)));
@@ -490,15 +490,15 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
var q = QueryExecution.Common.GetBasicExecutedQuery(); var q = QueryExecution.Common.GetBasicExecutedQuery();
var rs = q.Batches[0].ResultSets[0]; var rs = q.Batches[0].ResultSets[0];
var etm = Common.GetCustomEditTableMetadata(rs.Columns.Cast<DbColumn>().ToArray()); var etm = Common.GetCustomEditTableMetadata(rs.Columns.Cast<DbColumn>().ToArray());
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>(); var emf = new Mock<IEditMetadataFactory>();
emf.Setup(f => f.GetObjectMetadata(It.IsAny<DbConnection>(), It.IsAny<string[]>(), It.IsAny<string>())) emf.Setup(f => f.GetObjectMetadata(It.IsAny<DbConnection>(), It.IsAny<string[]>(), It.IsAny<string>()))
.Returns(etm); .Returns(etm);
// ... Create a session that hasn't been initialized // ... Create a session that hasn't been initialized
EditSession s = new EditSession(emf.Object); var s = new EditSession(emf.Object);
// ... Create a query runner that will return a successful query // ... Create a query runner that will return a successful query
Mock<EditSession.QueryRunner> qr = new Mock<EditSession.QueryRunner>(); var qr = new Mock<EditSession.QueryRunner>();
qr.Setup(r => r(It.IsAny<string>())) qr.Setup(r => r(It.IsAny<string>()))
.Returns(Task.FromResult(new EditSession.EditSessionQueryExecutionState(q))); .Returns(Task.FromResult(new EditSession.EditSessionQueryExecutionState(q)));
@@ -533,8 +533,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: // Setup:
// ... Create a session without initializing // ... Create a session without initializing
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>(); var emf = new Mock<IEditMetadataFactory>();
EditSession s = new EditSession(emf.Object); var s = new EditSession(emf.Object);
// If: I ask to delete a row without initializing // If: I ask to delete a row without initializing
// Then: I should get an exception // Then: I should get an exception
@@ -583,8 +583,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: // Setup:
// ... Create a session without initializing // ... Create a session without initializing
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>(); var emf = new Mock<IEditMetadataFactory>();
EditSession s = new EditSession(emf.Object); var s = new EditSession(emf.Object);
// If: I ask to revert a row without initializing // If: I ask to revert a row without initializing
// Then: I should get an exception // Then: I should get an exception
@@ -683,8 +683,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: // Setup:
// ... Create a session without initializing // ... Create a session without initializing
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>(); var emf = new Mock<IEditMetadataFactory>();
EditSession s = new EditSession(emf.Object); var s = new EditSession(emf.Object);
// If: I ask to revert a cell without initializing // If: I ask to revert a cell without initializing
// Then: I should get an exception // Then: I should get an exception
@@ -724,8 +724,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: // Setup:
// ... Create a session without initializing // ... Create a session without initializing
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>(); var emf = new Mock<IEditMetadataFactory>();
EditSession s = new EditSession(emf.Object); var s = new EditSession(emf.Object);
// If: I ask to update a cell without initializing // If: I ask to update a cell without initializing
// Then: I should get an exception // Then: I should get an exception
@@ -807,8 +807,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: // Setup:
// ... Create a session without initializing // ... Create a session without initializing
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>(); var emf = new Mock<IEditMetadataFactory>();
EditSession s = new EditSession(emf.Object); var s = new EditSession(emf.Object);
// If: I ask to update a cell without initializing // If: I ask to update a cell without initializing
// Then: I should get an exception // Then: I should get an exception
@@ -974,8 +974,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: // Setup:
// ... Create a session without initializing // ... Create a session without initializing
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>(); var emf = new Mock<IEditMetadataFactory>();
EditSession s = new EditSession(emf.Object); var s = new EditSession(emf.Object);
// If: I ask to script edits without initializing // If: I ask to script edits without initializing
// Then: I should get an exception // Then: I should get an exception
@@ -1001,12 +1001,12 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
EditSession s = await GetBasicSession(); EditSession s = await GetBasicSession();
// ... Add two mock edits that will generate a script // ... Add two mock edits that will generate a script
Mock<RowEditBase> edit = new Mock<RowEditBase>(); var edit = new Mock<RowEditBase>();
edit.Setup(e => e.GetScript()).Returns("test"); edit.Setup(e => e.GetScript()).Returns("test");
s.EditCache[0] = edit.Object; s.EditCache[0] = edit.Object;
s.EditCache[1] = edit.Object; s.EditCache[1] = edit.Object;
using (SelfCleaningTempFile file = new SelfCleaningTempFile()) using (var file = new SelfCleaningTempFile())
{ {
// If: I script the edit cache to a local output path // If: I script the edit cache to a local output path
string outputPath = s.ScriptEdits(file.FilePath); string outputPath = s.ScriptEdits(file.FilePath);
@@ -1029,8 +1029,8 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
// Setup: // Setup:
// ... Create a session without initializing // ... Create a session without initializing
Mock<IEditMetadataFactory> emf = new Mock<IEditMetadataFactory>(); var emf = new Mock<IEditMetadataFactory>();
EditSession s = new EditSession(emf.Object); var s = new EditSession(emf.Object);
// If: I ask to script edits without initializing // If: I ask to script edits without initializing
// Then: I should get an exception // Then: I should get an exception
@@ -1088,7 +1088,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
DbConnection conn = new TestSqlConnection(null); DbConnection conn = new TestSqlConnection(null);
// ... Mock a task that has not completed // ... Mock a task that has not completed
Task notCompleted = new Task(() => {}); var notCompleted = new Task(() => {});
s.CommitTask = notCompleted; s.CommitTask = notCompleted;
// If: I attempt to commit while a task is in progress // If: I attempt to commit while a task is in progress
@@ -1106,7 +1106,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
DbConnection conn = new TestSqlConnection(null); DbConnection conn = new TestSqlConnection(null);
// ... Add a mock commands for fun // ... Add a mock commands for fun
Mock<RowEditBase> edit = new Mock<RowEditBase>(); var edit = new Mock<RowEditBase>();
edit.Setup(e => e.GetCommand(It.IsAny<DbConnection>())).Returns<DbConnection>(dbc => dbc.CreateCommand()); edit.Setup(e => e.GetCommand(It.IsAny<DbConnection>())).Returns<DbConnection>(dbc => dbc.CreateCommand());
edit.Setup(e => e.ApplyChanges(It.IsAny<DbDataReader>())).Returns(Task.FromResult(0)); edit.Setup(e => e.ApplyChanges(It.IsAny<DbDataReader>())).Returns(Task.FromResult(0));
s.EditCache[0] = edit.Object; s.EditCache[0] = edit.Object;
@@ -1150,7 +1150,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
DbConnection conn = new TestSqlConnection(null); DbConnection conn = new TestSqlConnection(null);
// ... Add a mock edit that will explode on generating a command // ... Add a mock edit that will explode on generating a command
Mock<RowEditBase> edit = new Mock<RowEditBase>(); var edit = new Mock<RowEditBase>();
edit.Setup(e => e.GetCommand(It.IsAny<DbConnection>())).Throws<Exception>(); edit.Setup(e => e.GetCommand(It.IsAny<DbConnection>())).Throws<Exception>();
s.EditCache[0] = edit.Object; s.EditCache[0] = edit.Object;
@@ -1194,7 +1194,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
var data = new Common.TestDbColumnsWithTableMetadata(false, false, 0, 0); var data = new Common.TestDbColumnsWithTableMetadata(false, false, 0, 0);
// If: I generate a query for selecting rows without a limit // If: I generate a query for selecting rows without a limit
EditInitializeFiltering eif = new EditInitializeFiltering var eif = new EditInitializeFiltering
{ {
LimitResults = null LimitResults = null
}; };
@@ -1202,7 +1202,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
// Then: // Then:
// ... The query should look like a select statement // ... The query should look like a select statement
Regex selectRegex = new Regex("SELECT (.+) FROM (.+)", RegexOptions.IgnoreCase); Regex selectRegex = GetSelectRegex();
var match = selectRegex.Match(query); var match = selectRegex.Match(query);
Assert.True(match.Success); Assert.True(match.Success);
@@ -1223,7 +1223,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
// If: I generate a query for selecting rows with a negative limit // If: I generate a query for selecting rows with a negative limit
// Then: An exception should be thrown // Then: An exception should be thrown
EditInitializeFiltering eif = new EditInitializeFiltering var eif = new EditInitializeFiltering
{ {
LimitResults = -1 LimitResults = -1
}; };
@@ -1237,7 +1237,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
var data = new Common.TestDbColumnsWithTableMetadata(false, false, 0, 0); var data = new Common.TestDbColumnsWithTableMetadata(false, false, 0, 0);
// If: I generate a query for selecting rows without a limit // If: I generate a query for selecting rows without a limit
EditInitializeFiltering eif = new EditInitializeFiltering var eif = new EditInitializeFiltering
{ {
LimitResults = limit LimitResults = limit
}; };
@@ -1245,7 +1245,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
// Then: // Then:
// ... The query should look like a select statement // ... The query should look like a select statement
Regex selectRegex = new Regex(@"SELECT TOP (\d+) (.+) FROM (.+)", RegexOptions.IgnoreCase); var selectRegex = GetSelectTopRegex();
var match = selectRegex.Match(query); var match = selectRegex.Match(query);
Assert.True(match.Success); Assert.True(match.Success);
@@ -1286,7 +1286,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
private static Mock<Func<Task>> DoNothingSuccessMock private static Mock<Func<Task>> DoNothingSuccessMock
{ {
get { get {
Mock<Func<Task>> successHandler = new Mock<Func<Task>>(); var successHandler = new Mock<Func<Task>>();
successHandler.Setup(f => f()).Returns(Task.FromResult(0)); successHandler.Setup(f => f()).Returns(Task.FromResult(0));
return successHandler; return successHandler;
} }
@@ -1296,7 +1296,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
{ {
get get
{ {
Mock<Func<Exception, Task>> failureHandler = new Mock<Func<Exception, Task>>(); var failureHandler = new Mock<Func<Exception, Task>>();
failureHandler.Setup(f => f(It.IsAny<Exception>())).Returns(Task.FromResult(0)); failureHandler.Setup(f => f(It.IsAny<Exception>())).Returns(Task.FromResult(0));
return failureHandler; return failureHandler;
} }
@@ -1309,5 +1309,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.EditData
EditTableMetadata etm = Common.GetCustomEditTableMetadata(rs.Columns.Cast<DbColumn>().ToArray()); EditTableMetadata etm = Common.GetCustomEditTableMetadata(rs.Columns.Cast<DbColumn>().ToArray());
return await Common.GetCustomSession(q, etm); return await Common.GetCustomSession(q, etm);
} }
[GeneratedRegex("SELECT (.+) FROM (.+)", RegexOptions.IgnoreCase)]
private static partial Regex GetSelectRegex();
[GeneratedRegex("SELECT TOP (\\d+) (.+) FROM (.+)", RegexOptions.IgnoreCase)]
private static partial Regex GetSelectTopRegex();
} }
} }

View File

@@ -70,7 +70,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.LanguageServer
await langService.HandleDidChangeLanguageFlavorNotification(new LanguageFlavorChangeParams await langService.HandleDidChangeLanguageFlavorNotification(new LanguageFlavorChangeParams
{ {
Uri = textDocument.TextDocument.Uri, Uri = textDocument.TextDocument.Uri,
Language = LanguageService.SQL_LANG.ToLower(), Language = LanguageService.SQL_LANG.ToLower(System.Globalization.CultureInfo.InvariantCulture),
Flavor = "NotMSSQL" Flavor = "NotMSSQL"
}, null); }, null);
await langService.HandleSignatureHelpRequest(textDocument, signatureRequestContext.Object); await langService.HandleSignatureHelpRequest(textDocument, signatureRequestContext.Object);

View File

@@ -152,7 +152,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.LanguageServer
Assert.AreEqual(0, AutoCompleteHelper.EmptyCompletionList.Length); Assert.AreEqual(0, AutoCompleteHelper.EmptyCompletionList.Length);
} }
internal class TestScriptDocumentInfo : ScriptDocumentInfo internal sealed class TestScriptDocumentInfo : ScriptDocumentInfo
{ {
public TestScriptDocumentInfo(TextDocumentPosition textDocumentPosition, ScriptFile scriptFile, ScriptParseInfo scriptParseInfo, public TestScriptDocumentInfo(TextDocumentPosition textDocumentPosition, ScriptFile scriptFile, ScriptParseInfo scriptParseInfo,
string tokenText = null) string tokenText = null)

View File

@@ -95,7 +95,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Messaging
inputStream.Flush(); inputStream.Flush();
inputStream.Seek(0, SeekOrigin.Begin); inputStream.Seek(0, SeekOrigin.Begin);
Assert.ThrowsAsync<ArgumentException>(() => messageReader.ReadMessage(), "An exception should be thrown while reading"); Assert.ThrowsAsync<ArgumentException>(messageReader.ReadMessage, "An exception should be thrown while reading");
} }
} }
@@ -113,7 +113,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Messaging
inputStream.Flush(); inputStream.Flush();
inputStream.Seek(0, SeekOrigin.Begin); inputStream.Seek(0, SeekOrigin.Begin);
Assert.ThrowsAsync<MessageParseException>(() => messageReader.ReadMessage(), "An exception should be thrown while reading") ; Assert.ThrowsAsync<MessageParseException>(messageReader.ReadMessage, "An exception should be thrown while reading") ;
} }
} }
@@ -131,7 +131,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Messaging
inputStream.Flush(); inputStream.Flush();
inputStream.Seek(0, SeekOrigin.Begin); inputStream.Seek(0, SeekOrigin.Begin);
Assert.ThrowsAsync<MessageParseException>(() => messageReader.ReadMessage(), "An exception should be thrown while reading"); Assert.ThrowsAsync<MessageParseException>(messageReader.ReadMessage, "An exception should be thrown while reading");
} }
} }
@@ -153,9 +153,9 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Messaging
inputStream.Flush(); inputStream.Flush();
inputStream.Seek(0, SeekOrigin.Begin); inputStream.Seek(0, SeekOrigin.Begin);
Assert.ThrowsAsync<JsonReaderException>(() => messageReader.ReadMessage(), "The first read should fail with an exception while deserializing"); Assert.ThrowsAsync<JsonReaderException>(messageReader.ReadMessage, "The first read should fail with an exception while deserializing");
Assert.ThrowsAsync<MessageParseException>(() => messageReader.ReadMessage(), "The second read should fail with an exception while reading headers"); Assert.ThrowsAsync<MessageParseException>(messageReader.ReadMessage, "The second read should fail with an exception while reading headers");
} }
} }
@@ -176,7 +176,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Messaging
inputStream.Flush(); inputStream.Flush();
inputStream.Seek(0, SeekOrigin.Begin); inputStream.Seek(0, SeekOrigin.Begin);
Assert.ThrowsAsync<ArgumentException>(() => messageReader.ReadMessage(), "An exception should be thrown while reading the first one"); Assert.ThrowsAsync<ArgumentException>(messageReader.ReadMessage, "An exception should be thrown while reading the first one");
// ... A test event should be successfully read from the second one // ... A test event should be successfully read from the second one
Message messageResult = messageReader.ReadMessage().Result; Message messageResult = messageReader.ReadMessage().Result;

View File

@@ -12,7 +12,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Messaging
{ {
#region Request Types #region Request Types
internal class TestRequest internal sealed class TestRequest
{ {
public Task ProcessMessage(MessageWriter messageWriter) public Task ProcessMessage(MessageWriter messageWriter)
{ {
@@ -20,7 +20,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Messaging
} }
} }
internal class TestRequestArguments internal sealed class TestRequestArguments
{ {
public string SomeString { get; set; } public string SomeString { get; set; }
} }
@@ -29,11 +29,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Messaging
#region Response Types #region Response Types
internal class TestResponse internal sealed class TestResponse
{ {
} }
internal class TestResponseBody internal sealed class TestResponseBody
{ {
public string SomeString { get; set; } public string SomeString { get; set; }
} }
@@ -42,11 +42,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Messaging
#region Event Types #region Event Types
internal class TestEvent internal sealed class TestEvent
{ {
} }
internal class TestEventBody internal sealed class TestEventBody
{ {
public string SomeString { get; set; } public string SomeString { get; set; }
} }

View File

@@ -6,8 +6,8 @@
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<ApplicationIcon /> <ApplicationIcon />
<StartupObject /> <StartupObject />
<!-- TODO FIX THESE WARNINGS ASAP --> <!-- False alerts, disabled due to issue: https://github.com/dotnet/roslyn/issues/65850 -->
<NoWarn>$(NoWarn);SYSLIB1045;IDE0200;IDE0230;CA1311;CA1852;CA1854</NoWarn> <NoWarn>$(NoWarn);CS8795</NoWarn>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.Text.Encoding.CodePages" /> <PackageReference Include="System.Text.Encoding.CodePages" />

View File

@@ -15,7 +15,7 @@ using NUnit.Framework;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ObjectExplorer
{ {
class GroupBySchemaTests internal sealed class GroupBySchemaTests
{ {
Mock<DatabaseChildFactory> factory; Mock<DatabaseChildFactory> factory;
Mock<TreeNode> node; Mock<TreeNode> node;

View File

@@ -183,7 +183,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution
{ {
await service.HandleExecuteRequest(qeParams, requestContext); await service.HandleExecuteRequest(qeParams, requestContext);
await service.WorkTask; await service.WorkTask;
if (service.ActiveQueries.ContainsKey(qeParams.OwnerUri) && service.ActiveQueries[qeParams.OwnerUri].ExecutionTask != null) if (service.ActiveQueries.TryGetValue(qeParams.OwnerUri, out Query? query) && query.ExecutionTask != null)
{ {
await service.ActiveQueries[qeParams.OwnerUri].ExecutionTask; await service.ActiveQueries[qeParams.OwnerUri].ExecutionTask;
} }

View File

@@ -17,7 +17,7 @@ using NUnit.Framework;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
{ {
public class SaveAsCsvFileStreamWriterTests public partial class SaveAsCsvFileStreamWriterTests
{ {
[Test] [Test]
public void Constructor_NullStream() public void Constructor_NullStream()
@@ -148,7 +148,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
string output = writer.EncodeCsvField(field); string output = writer.EncodeCsvField(field);
// Then: It should wrap it in quotes // Then: It should wrap it in quotes
Assert.True(Regex.IsMatch(output, "^\".*\"$", RegexOptions.Singleline)); Assert.True(GetCsvRegexSingleLine().IsMatch(output));
} }
[TestCase("Something\rElse")] // Contains carriage return [TODO: Don't support this] [TestCase("Something\rElse")] // Contains carriage return [TODO: Don't support this]
@@ -165,7 +165,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
string output = writer.EncodeCsvField(field); string output = writer.EncodeCsvField(field);
// Then: It should wrap it in quotes // Then: It should wrap it in quotes
Assert.True(Regex.IsMatch(output, @"^\[.*\[$", RegexOptions.Singleline)); Assert.True(GetCsvBracketRegex().IsMatch(output));
} }
[TestCase("\tSomething")] // Starts with tab [TestCase("\tSomething")] // Starts with tab
@@ -186,7 +186,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
string output = writer.EncodeCsvField(field); string output = writer.EncodeCsvField(field);
// Then: It should wrap it in quotes // Then: It should wrap it in quotes
Assert.True(Regex.IsMatch(output, "^\".*\"$", RegexOptions.Singleline)); Assert.True(GetCsvRegexSingleLine().IsMatch(output));
} }
[TestCase("Something")] [TestCase("Something")]
@@ -201,7 +201,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
string output = writer.EncodeCsvField(field); string output = writer.EncodeCsvField(field);
// Then: It should not wrap it in quotes // Then: It should not wrap it in quotes
Assert.False(Regex.IsMatch(output, "^\".*\"$")); Assert.False(GetCsvRegex().IsMatch(output));
} }
[TestCase(null, "Some\"thing", "\"Some\"\"thing\"")] // Default identifier [TestCase(null, "Some\"thing", "\"Some\"\"thing\"")] // Default identifier
@@ -277,7 +277,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
byte[] output = new byte[8192]; byte[] output = new byte[8192];
// If: I write a row // If: I write a row
SaveAsCsvFileStreamWriter writer = new SaveAsCsvFileStreamWriter(new MemoryStream(output), requestParams, columns); var writer = new SaveAsCsvFileStreamWriter(new MemoryStream(output), requestParams, columns);
using (writer) using (writer)
{ {
writer.WriteRow(data, columns); writer.WriteRow(data, columns);
@@ -425,5 +425,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
Assert.IsEmpty(lines[lines.Length - 1]); Assert.IsEmpty(lines[lines.Length - 1]);
return lines.Take(lines.Length - 1).ToArray(); return lines.Take(lines.Length - 1).ToArray();
} }
[GeneratedRegex("^\\[.*\\[$", RegexOptions.Singleline)]
private static partial Regex GetCsvBracketRegex();
[GeneratedRegex("^\".*\"$")]
private static partial Regex GetCsvRegex();
[GeneratedRegex("^\".*\"$", RegexOptions.Singleline)]
private static partial Regex GetCsvRegexSingleLine();
} }
} }

View File

@@ -16,7 +16,7 @@ using NUnit.Framework;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
{ {
public class SaveAsExcelFileStreamWriterHelperTests : IDisposable public partial class SaveAsExcelFileStreamWriterHelperTests : IDisposable
{ {
private Stream _stream; private Stream _stream;
public SaveAsExcelFileStreamWriterHelperTests() public SaveAsExcelFileStreamWriterHelperTests()
@@ -25,7 +25,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
using (var helper = new SaveAsExcelFileStreamWriterHelper(_stream, true)) using (var helper = new SaveAsExcelFileStreamWriterHelper(_stream, true))
using (var sheet = helper.AddSheet()) using (var sheet = helper.AddSheet())
{ {
DbCellValue value = new DbCellValue(); var value = new DbCellValue();
sheet.AddRow(); sheet.AddRow();
value.IsNull = true; value.IsNull = true;
@@ -71,7 +71,10 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
sheet.AddCell(value); sheet.AddCell(value);
} }
} }
Regex contentRemoveLinebreakLeadingSpace = new Regex(@"\r?\n\s*");
[GeneratedRegex("\\r?\\n\\s*")]
private static partial Regex GetContentRemoveLinebreakLeadingSpaceRegex();
private void ContentMatch(string fileName) private void ContentMatch(string fileName)
{ {
string referencePath = Path.Combine(RunEnvironmentInfo.GetTestDataLocation(), string referencePath = Path.Combine(RunEnvironmentInfo.GetTestDataLocation(),
@@ -79,11 +82,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
"SaveAsExcelFileStreamWriterHelperTests", "SaveAsExcelFileStreamWriterHelperTests",
fileName); fileName);
string referenceContent = File.ReadAllText(referencePath); string referenceContent = File.ReadAllText(referencePath);
referenceContent = contentRemoveLinebreakLeadingSpace.Replace(referenceContent, ""); referenceContent = GetContentRemoveLinebreakLeadingSpaceRegex().Replace(referenceContent, "");
using (ZipArchive zip = new ZipArchive(_stream, ZipArchiveMode.Read, true)) using (var zip = new ZipArchive(_stream, ZipArchiveMode.Read, true))
{ {
using (var reader = new StreamReader(zip.GetEntry(fileName).Open())) using (var reader = new StreamReader(zip?.GetEntry(fileName)?.Open()!))
{ {
string realContent = reader.ReadToEnd(); string realContent = reader.ReadToEnd();
Assert.AreEqual(referenceContent, realContent); Assert.AreEqual(referenceContent, realContent);
@@ -130,7 +133,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
public class SaveAsExcelFileStreamWriterHelperReferenceManagerTests public class SaveAsExcelFileStreamWriterHelperReferenceManagerTests
{ {
private Mock<XmlWriter> _xmlWriterMock; private Mock<XmlWriter> _xmlWriterMock;
private string LastWrittenReference { get; set; } private string? LastWrittenReference { get; set; }
private int LastWrittenRow { get; set; } private int LastWrittenRow { get; set; }
public SaveAsExcelFileStreamWriterHelperReferenceManagerTests() public SaveAsExcelFileStreamWriterHelperReferenceManagerTests()
@@ -145,7 +148,6 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
_xmlWriterMock.Setup(a => a.WriteEndAttribute()); _xmlWriterMock.Setup(a => a.WriteEndAttribute());
_xmlWriterMock.Setup(a => a.WriteValue(It.IsAny<int>())) _xmlWriterMock.Setup(a => a.WriteValue(It.IsAny<int>()))
.Callback<int>(row => LastWrittenRow = row); .Callback<int>(row => LastWrittenRow = row);
} }
[Test] [Test]
@@ -203,8 +205,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
manager.AssureColumnReference(); manager.AssureColumnReference();
manager.WriteAndIncreaseColumnReference(); manager.WriteAndIncreaseColumnReference();
Assert.AreEqual("XFD1", LastWrittenReference); Assert.AreEqual("XFD1", LastWrittenReference);
var ex = Assert.Throws<InvalidOperationException>( var ex = Assert.Throws<InvalidOperationException>(manager.AssureColumnReference);
() => manager.AssureColumnReference());
Assert.That(ex.Message, Does.Contain("max column number is 16384")); Assert.That(ex.Message, Does.Contain("max column number is 16384"));
} }
[Test] [Test]
@@ -232,8 +233,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
var xmlWriter = _xmlWriterMock.Object; var xmlWriter = _xmlWriterMock.Object;
var manager = new SaveAsExcelFileStreamWriterHelper.ReferenceManager(xmlWriter); var manager = new SaveAsExcelFileStreamWriterHelper.ReferenceManager(xmlWriter);
var ex = Assert.Throws<InvalidOperationException>( var ex = Assert.Throws<InvalidOperationException>(manager.AssureColumnReference);
() => manager.AssureColumnReference());
Assert.That(ex.Message, Does.Contain("AddRow must be called before AddCell")); Assert.That(ex.Message, Does.Contain("AddRow must be called before AddCell"));
} }

View File

@@ -18,10 +18,11 @@ using NUnit.Framework;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
{ {
public class SaveAsMarkdownFileStreamWriterTests public partial class SaveAsMarkdownFileStreamWriterTests
{ {
// Regex: Matches '|' not preceded by a '\' // Regex: Matches '|' not preceded by a '\'
private static readonly Regex UnescapedPipe = new Regex(@"(?<!\\)\|", RegexOptions.Compiled); [GeneratedRegex("(?<!\\\\)\\|", RegexOptions.Compiled)]
private static partial Regex GetUnescapedPipeRegex();
[Test] [Test]
public void Constructor_NullStream() public void Constructor_NullStream()
@@ -362,7 +363,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
private static void ValidateLine(string line, IEnumerable<string> expectedCells) private static void ValidateLine(string line, IEnumerable<string> expectedCells)
{ {
string[] cells = UnescapedPipe.Split(line); string[] cells = GetUnescapedPipeRegex().Split(line);
string[] expectedCellsArray = expectedCells as string[] ?? expectedCells.ToArray(); string[] expectedCellsArray = expectedCells as string[] ?? expectedCells.ToArray();
Assert.That(cells.Length - 2, Is.EqualTo(expectedCellsArray.Length), "Wrong number of cells in output"); Assert.That(cells.Length - 2, Is.EqualTo(expectedCellsArray.Length), "Wrong number of cells in output");

View File

@@ -21,7 +21,7 @@ using NUnit.Framework;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
{ {
public class ServiceBufferReaderWriterTests public partial class ServiceBufferReaderWriterTests
{ {
[Test] [Test]
public void ReaderStreamNull() public void ReaderStreamNull()
@@ -49,7 +49,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
invalidStream.SetupGet(s => s.CanSeek).Returns(true); invalidStream.SetupGet(s => s.CanSeek).Returns(true);
Assert.Throws<InvalidOperationException>(() => Assert.Throws<InvalidOperationException>(() =>
{ {
ServiceBufferFileStreamReader obj = new ServiceBufferFileStreamReader(invalidStream.Object, new QueryExecutionSettings()); var obj = new ServiceBufferFileStreamReader(invalidStream.Object, new QueryExecutionSettings());
obj.Dispose(); obj.Dispose();
}); });
} }
@@ -64,7 +64,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
invalidStream.SetupGet(s => s.CanSeek).Returns(false); invalidStream.SetupGet(s => s.CanSeek).Returns(false);
Assert.Throws<InvalidOperationException>(() => Assert.Throws<InvalidOperationException>(() =>
{ {
ServiceBufferFileStreamReader obj = new ServiceBufferFileStreamReader(invalidStream.Object, new QueryExecutionSettings()); var obj = new ServiceBufferFileStreamReader(invalidStream.Object, new QueryExecutionSettings());
obj.Dispose(); obj.Dispose();
}); });
} }
@@ -95,7 +95,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
invalidStream.SetupGet(s => s.CanSeek).Returns(true); invalidStream.SetupGet(s => s.CanSeek).Returns(true);
Assert.Throws<InvalidOperationException>(() => Assert.Throws<InvalidOperationException>(() =>
{ {
ServiceBufferFileStreamWriter obj = new ServiceBufferFileStreamWriter(invalidStream.Object, new QueryExecutionSettings()); var obj = new ServiceBufferFileStreamWriter(invalidStream.Object, new QueryExecutionSettings());
obj.Dispose(); obj.Dispose();
}); });
} }
@@ -110,7 +110,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
invalidStream.SetupGet(s => s.CanSeek).Returns(false); invalidStream.SetupGet(s => s.CanSeek).Returns(false);
Assert.Throws<InvalidOperationException>(() => Assert.Throws<InvalidOperationException>(() =>
{ {
ServiceBufferFileStreamWriter obj = new ServiceBufferFileStreamWriter(invalidStream.Object, new QueryExecutionSettings()); var obj = new ServiceBufferFileStreamWriter(invalidStream.Object, new QueryExecutionSettings());
obj.Dispose(); obj.Dispose();
}); });
} }
@@ -128,7 +128,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
// If: // If:
// ... I write a type T to the writer // ... I write a type T to the writer
using (ServiceBufferFileStreamWriter writer = new ServiceBufferFileStreamWriter(new MemoryStream(storage), overrideSettings)) using (var writer = new ServiceBufferFileStreamWriter(new MemoryStream(storage), overrideSettings))
{ {
int writtenBytes = writeFunc(writer, value); int writtenBytes = writeFunc(writer, value);
Assert.AreEqual(valueLength, writtenBytes); Assert.AreEqual(valueLength, writtenBytes);
@@ -136,7 +136,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
// ... And read the type T back // ... And read the type T back
FileStreamReadResult outValue; FileStreamReadResult outValue;
using (ServiceBufferFileStreamReader reader = new ServiceBufferFileStreamReader(new MemoryStream(storage), overrideSettings)) using (var reader = new ServiceBufferFileStreamReader(new MemoryStream(storage), overrideSettings))
{ {
outValue = readFunc(reader, rowId); outValue = readFunc(reader, rowId);
} }
@@ -312,7 +312,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
}; };
// Setup: Create a DATE column // Setup: Create a DATE column
DbColumnWrapper col = new DbColumnWrapper(new TestDbColumn {DataTypeName = "DaTe"}); var col = new DbColumnWrapper(new TestDbColumn {DataTypeName = "DaTe"});
foreach (DateTime value in testValues) foreach (DateTime value in testValues)
{ {
@@ -320,7 +320,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
(reader, rowId) => reader.ReadDateTime(0, rowId, col)); (reader, rowId) => reader.ReadDateTime(0, rowId, col));
// Make sure the display value does not have a time string // Make sure the display value does not have a time string
Assert.True(Regex.IsMatch(displayValue, @"^[\d]{4}-[\d]{2}-[\d]{2}$")); Assert.True(GetDateRegex().IsMatch(displayValue));
} }
} }
@@ -335,7 +335,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
}; };
// Setup: Create a DATETIME column // Setup: Create a DATETIME column
DbColumnWrapper col = new DbColumnWrapper(new TestDbColumn {DataTypeName = "DaTeTiMe"}); var col = new DbColumnWrapper(new TestDbColumn {DataTypeName = "DaTeTiMe"});
foreach (DateTime value in testValues) foreach (DateTime value in testValues)
{ {
@@ -343,7 +343,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
(reader, rowId) => reader.ReadDateTime(0, rowId, col)); (reader, rowId) => reader.ReadDateTime(0, rowId, col));
// Make sure the display value has a time string with 3 milliseconds // Make sure the display value has a time string with 3 milliseconds
Assert.True(Regex.IsMatch(displayValue, @"^[\d]{4}-[\d]{2}-[\d]{2} [\d]{2}:[\d]{2}:[\d]{2}\.[\d]{3}$")); Assert.True(GetDateTimeRegex().IsMatch(displayValue));
} }
} }
@@ -358,7 +358,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
}; };
// Setup: Create a DATETIME column // Setup: Create a DATETIME column
DbColumnWrapper col = new DbColumnWrapper(new TestDbColumn var col = new DbColumnWrapper(new TestDbColumn
{ {
DataTypeName = "DaTeTiMe2", DataTypeName = "DaTeTiMe2",
NumericScale = precision NumericScale = precision
@@ -370,7 +370,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
(reader, rowId) => reader.ReadDateTime(0, rowId, col)); (reader, rowId) => reader.ReadDateTime(0, rowId, col));
// Make sure the display value has a time string with variable number of milliseconds // Make sure the display value has a time string with variable number of milliseconds
Assert.True(Regex.IsMatch(displayValue, @"^[\d]{4}-[\d]{2}-[\d]{2} [\d]{2}:[\d]{2}:[\d]{2}")); Assert.True(GetTimeRegex().IsMatch(displayValue));
if (precision > 0) if (precision > 0)
{ {
Assert.True(Regex.IsMatch(displayValue, $@"\.[\d]{{{precision}}}$")); Assert.True(Regex.IsMatch(displayValue, $@"\.[\d]{{{precision}}}$"));
@@ -389,7 +389,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
}; };
// Setup: Create a DATETIME2 column // Setup: Create a DATETIME2 column
DbColumnWrapper col = new DbColumnWrapper(new TestDbColumn {DataTypeName = "DaTeTiMe2", NumericScale = 0}); var col = new DbColumnWrapper(new TestDbColumn {DataTypeName = "DaTeTiMe2", NumericScale = 0});
foreach (DateTime value in testValues) foreach (DateTime value in testValues)
{ {
@@ -397,7 +397,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
(reader, rowId) => reader.ReadDateTime(0, rowId, col)); (reader, rowId) => reader.ReadDateTime(0, rowId, col));
// Make sure the display value has a time string with 0 milliseconds // Make sure the display value has a time string with 0 milliseconds
Assert.True(Regex.IsMatch(displayValue, @"^[\d]{4}-[\d]{2}-[\d]{2} [\d]{2}:[\d]{2}:[\d]{2}$")); Assert.True(GetTimeRegex().IsMatch(displayValue));
} }
} }
@@ -412,7 +412,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
}; };
// Setup: Create a DATETIME2 column // Setup: Create a DATETIME2 column
DbColumnWrapper col = new DbColumnWrapper(new TestDbColumn {DataTypeName = "DaTeTiMe2", NumericScale = 255}); var col = new DbColumnWrapper(new TestDbColumn {DataTypeName = "DaTeTiMe2", NumericScale = 255});
foreach (DateTime value in testValues) foreach (DateTime value in testValues)
{ {
@@ -420,7 +420,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
(reader, rowId) => reader.ReadDateTime(0, rowId, col)); (reader, rowId) => reader.ReadDateTime(0, rowId, col));
// Make sure the display value has a time string with 7 milliseconds // Make sure the display value has a time string with 7 milliseconds
Assert.True(Regex.IsMatch(displayValue, @"^[\d]{4}-[\d]{2}-[\d]{2} [\d]{2}:[\d]{2}:[\d]{2}\.[\d]{7}$")); Assert.True(GetDateTime2Regex().IsMatch(displayValue));
} }
} }
@@ -436,7 +436,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
}; };
// Setup: Create a DATETIMEOFFSET column // Setup: Create a DATETIMEOFFSET column
DbColumnWrapper col = new DbColumnWrapper(new TestDbColumn { DataTypeName = "datetimeoffset", NumericScale = 6 }); var col = new DbColumnWrapper(new TestDbColumn { DataTypeName = "datetimeoffset", NumericScale = 6 });
foreach (DateTimeOffset value in testValues) foreach (DateTimeOffset value in testValues)
{ {
@@ -444,7 +444,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
(reader, rowId) => reader.ReadDateTimeOffset(0, rowId, col)); (reader, rowId) => reader.ReadDateTimeOffset(0, rowId, col));
// Make sure the display value has a time string with 6 milliseconds and a time zone // Make sure the display value has a time string with 6 milliseconds and a time zone
Assert.True(Regex.IsMatch(displayValue, @"^[\d]{4}-[\d]{2}-[\d]{2} [\d]{2}:[\d]{2}:[\d]{2}\.[\d]{6} [+-][01][\d]:[\d]{2}$")); Assert.True(GetDateTimeOffset6Regex().IsMatch(displayValue));
} }
} }
@@ -458,7 +458,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
}; };
// Setup: Create a DATETIMEOFFSET column // Setup: Create a DATETIMEOFFSET column
DbColumnWrapper col = new DbColumnWrapper(new TestDbColumn { DataTypeName = "datetimeoffset", NumericScale = 0 }); var col = new DbColumnWrapper(new TestDbColumn { DataTypeName = "datetimeoffset", NumericScale = 0 });
foreach (DateTimeOffset value in testValues) foreach (DateTimeOffset value in testValues)
{ {
@@ -466,7 +466,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
(reader, rowId) => reader.ReadDateTimeOffset(0, rowId, col)); (reader, rowId) => reader.ReadDateTimeOffset(0, rowId, col));
// Make sure the display value has a time string with no millisecond and a time zone // Make sure the display value has a time string with no millisecond and a time zone
Assert.True(Regex.IsMatch(displayValue, @"^[\d]{4}-[\d]{2}-[\d]{2} [\d]{2}:[\d]{2}:[\d]{2} [+-][01][\d]:[\d]{2}$")); Assert.True(GetDateTimeOffset0Regex().IsMatch(displayValue));
} }
} }
@@ -490,11 +490,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
public void StringNullTest() public void StringNullTest()
{ {
// Setup: Create a mock file stream // Setup: Create a mock file stream
using (MemoryStream stream = new MemoryStream(new byte[8192])) using (var stream = new MemoryStream(new byte[8192]))
{ {
// If: // If:
// ... I write null as a string to the writer // ... I write null as a string to the writer
using (ServiceBufferFileStreamWriter writer = new ServiceBufferFileStreamWriter(stream, new QueryExecutionSettings())) using (var writer = new ServiceBufferFileStreamWriter(stream, new QueryExecutionSettings()))
{ {
// Then: // Then:
// ... I should get an argument null exception // ... I should get an argument null exception
@@ -514,7 +514,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
{ {
// Setup: // Setup:
// ... Generate the test value // ... Generate the test value
StringBuilder sb = new StringBuilder(); var sb = new StringBuilder();
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
{ {
sb.Append(values[i%values.Length]); sb.Append(values[i%values.Length]);
@@ -529,11 +529,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
public void BytesNullTest() public void BytesNullTest()
{ {
// Setup: Create a mock file stream wrapper // Setup: Create a mock file stream wrapper
using (MemoryStream stream = new MemoryStream(new byte[8192])) using (var stream = new MemoryStream(new byte[8192]))
{ {
// If: // If:
// ... I write null as a string to the writer // ... I write null as a string to the writer
using (ServiceBufferFileStreamWriter writer = new ServiceBufferFileStreamWriter(stream, new QueryExecutionSettings())) using (var writer = new ServiceBufferFileStreamWriter(stream, new QueryExecutionSettings()))
{ {
// Then: // Then:
// ... I should get an argument null exception // ... I should get an argument null exception
@@ -554,7 +554,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
{ {
// Setup: // Setup:
// ... Generate the test value // ... Generate the test value
List<byte> sb = new List<byte>(); var sb = new List<byte>();
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
{ {
sb.Add(values[i % values.Length]); sb.Add(values[i % values.Length]);
@@ -602,5 +602,22 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.DataStorage
(reader, rowId) => reader.ReadMoney(0, rowId)); (reader, rowId) => reader.ReadMoney(0, rowId));
} }
} }
[GeneratedRegex("^[\\d]{4}-[\\d]{2}-[\\d]{2}$")]
private static partial Regex GetDateRegex();
[GeneratedRegex("^[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}")]
private static partial Regex GetTimeRegex();
[GeneratedRegex("^[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}\\.[\\d]{3}$")]
private static partial Regex GetDateTimeRegex();
[GeneratedRegex("^[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}\\.[\\d]{7}$")]
private static partial Regex GetDateTime2Regex();
[GeneratedRegex("^[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2}\\.[\\d]{6} [+-][01][\\d]:[\\d]{2}$")]
private static partial Regex GetDateTimeOffset6Regex();
[GeneratedRegex("^[\\d]{4}-[\\d]{2}-[\\d]{2} [\\d]{2}:[\\d]{2}:[\\d]{2} [+-][01][\\d]:[\\d]{2}$")]
private static partial Regex GetDateTimeOffset0Regex();
} }
} }

View File

@@ -72,7 +72,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
BatchCallbackHelper(batch, BatchCallbackHelper(batch,
b => batchStartCalls++, b => batchStartCalls++,
b => batchEndCalls++, b => batchEndCalls++,
m => messages.Add(m), messages.Add,
r => resultSetCalls++); r => resultSetCalls++);
await batch.Execute(GetConnection(Common.CreateTestConnectionInfo(null, false, false)), CancellationToken.None); await batch.Execute(GetConnection(Common.CreateTestConnectionInfo(null, false, false)), CancellationToken.None);
@@ -108,7 +108,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
BatchCallbackHelper(batch, BatchCallbackHelper(batch,
b => batchStartCalls++, b => batchStartCalls++,
b => batchEndCalls++, b => batchEndCalls++,
m => messages.Add(m), messages.Add,
r => resultSetCalls++); r => resultSetCalls++);
await batch.Execute(GetConnection(ci), CancellationToken.None); await batch.Execute(GetConnection(ci), CancellationToken.None);
@@ -144,7 +144,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
BatchCallbackHelper(batch, BatchCallbackHelper(batch,
b => batchStartCalls++, b => batchStartCalls++,
b => batchEndCalls++, b => batchEndCalls++,
m => messages.Add(m), messages.Add,
r => resultSetCalls++); r => resultSetCalls++);
await batch.Execute(GetConnection(ci), CancellationToken.None); await batch.Execute(GetConnection(ci), CancellationToken.None);
@@ -180,7 +180,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
BatchCallbackHelper(batch, BatchCallbackHelper(batch,
b => batchStartCalls++, b => batchStartCalls++,
b => batchEndCalls++, b => batchEndCalls++,
m => messages.Add(m), messages.Add,
r => resultSetCalls++); r => resultSetCalls++);
await batch.Execute(GetConnection(ci), CancellationToken.None); await batch.Execute(GetConnection(ci), CancellationToken.None);
@@ -213,7 +213,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
BatchCallbackHelper(batch, BatchCallbackHelper(batch,
b => batchStartCalls++, b => batchStartCalls++,
b => batchEndCalls++, b => batchEndCalls++,
m => messages.Add(m), messages.Add,
r => { throw new Exception("ResultSet callback was called when it should not have been."); }); r => { throw new Exception("ResultSet callback was called when it should not have been."); });
await batch.Execute(GetConnection(ci), CancellationToken.None); await batch.Execute(GetConnection(ci), CancellationToken.None);
@@ -245,7 +245,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
BatchCallbackHelper(batch, BatchCallbackHelper(batch,
b => batchStartCalls++, b => batchStartCalls++,
b => batchEndCalls++, b => batchEndCalls++,
m => messages.Add(m), messages.Add,
r => { throw new Exception("ResultSet callback was called when it should not have been."); }); r => { throw new Exception("ResultSet callback was called when it should not have been."); });
await batch.Execute(GetConnection(ci), CancellationToken.None); await batch.Execute(GetConnection(ci), CancellationToken.None);

View File

@@ -19,7 +19,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
/// <summary> /// <summary>
/// Test DbColumn derived class /// Test DbColumn derived class
/// </summary> /// </summary>
private class TestColumn : DbColumn private sealed class TestColumn : DbColumn
{ {
public TestColumn( public TestColumn(
string dataTypeName = null, string dataTypeName = null,

View File

@@ -122,7 +122,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
BatchCallbackHelper(query, BatchCallbackHelper(query,
b => { throw new Exception("Batch startup callback should not have been called."); }, b => { throw new Exception("Batch startup callback should not have been called."); },
b => { throw new Exception("Batch completion callback was called"); }, b => { throw new Exception("Batch completion callback was called"); },
m => messages.Add(m)); messages.Add);
// If: // If:
// ... I Then execute the query // ... I Then execute the query
@@ -235,7 +235,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
BatchCallbackHelper(query, BatchCallbackHelper(query,
b => { throw new Exception("Batch start handler was called"); }, b => { throw new Exception("Batch start handler was called"); },
b => { throw new Exception("Batch completed handler was called"); }, b => { throw new Exception("Batch completed handler was called"); },
m => messages.Add(m)); messages.Add);
// .. I then execute the query // .. I then execute the query
query.Execute(); query.Execute();
@@ -271,7 +271,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.Execution
BatchCallbackHelper(query, BatchCallbackHelper(query,
b => batchStartCallbacksReceived++, b => batchStartCallbacksReceived++,
b => batchCompletionCallbacksReceived++, b => batchCompletionCallbacksReceived++,
m => messages.Add(m)); messages.Add);
// ... I then execute the query // ... I then execute the query
query.Execute(); query.Execute();

View File

@@ -50,7 +50,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution
// Then: // Then:
// ... It should throw an exception // ... It should throw an exception
Assert.ThrowsAsync<Exception>(() => planResultSet.GetExecutionPlan()); Assert.ThrowsAsync<Exception>(planResultSet.GetExecutionPlan);
} }
#endregion #endregion

View File

@@ -375,11 +375,11 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.QueryExecution.SaveResults
} }
else if (column.DataTypeName == "Int") else if (column.DataTypeName == "Int")
{ {
return Int64.Parse(value.DisplayValue.ToLower()); return Int64.Parse(value.DisplayValue.ToLower(System.Globalization.CultureInfo.InvariantCulture));
} }
else if (column.DataTypeName == "Bit") else if (column.DataTypeName == "Bit")
{ {
return Boolean.Parse(value.DisplayValue.ToLower()); return Boolean.Parse(value.DisplayValue.ToLower(System.Globalization.CultureInfo.InvariantCulture));
} }
return value.DisplayValue; return value.DisplayValue;
} }

View File

@@ -53,7 +53,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ResourceProvider.Azure
var currentUserAccount = CreateAccount(); var currentUserAccount = CreateAccount();
currentUserAccount.Account.IsStale = true; currentUserAccount.Account.IsStale = true;
IAzureAuthenticationManager accountManager = await CreateAccountManager(currentUserAccount, null); IAzureAuthenticationManager accountManager = await CreateAccountManager(currentUserAccount, null);
Assert.ThrowsAsync<ExpiredTokenException>(() => accountManager.GetSelectedSubscriptionsAsync()); Assert.ThrowsAsync<ExpiredTokenException>(accountManager.GetSelectedSubscriptionsAsync);
} }
[Test] [Test]
@@ -61,7 +61,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ResourceProvider.Azure
{ {
var currentUserAccount = CreateAccount(); var currentUserAccount = CreateAccount();
IAzureAuthenticationManager accountManager = await CreateAccountManager(currentUserAccount, null, true); IAzureAuthenticationManager accountManager = await CreateAccountManager(currentUserAccount, null, true);
Assert.ThrowsAsync<ServiceFailedException>(() => accountManager.GetSelectedSubscriptionsAsync()); Assert.ThrowsAsync<ServiceFailedException>(accountManager.GetSelectedSubscriptionsAsync);
} }
[Test] [Test]

View File

@@ -21,7 +21,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ResourceProvider.Azure
/// <summary> /// <summary>
/// A container to create test data and mock classes to test azure services and providers /// A container to create test data and mock classes to test azure services and providers
/// </summary> /// </summary>
internal class AzureTestContext internal sealed class AzureTestContext
{ {
public AzureTestContext(Dictionary<string, List<string>> subscriptionToDatabaseMap) public AzureTestContext(Dictionary<string, List<string>> subscriptionToDatabaseMap)
{ {

View File

@@ -406,7 +406,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.ResourceProvider
} }
} }
internal class ServiceTestContext internal sealed class ServiceTestContext
{ {
private string _validServerName = "validServerName.database.windows.net"; private string _validServerName = "validServerName.database.windows.net";
private string _startIpAddressValue = "1.2.3.6"; private string _startIpAddressValue = "1.2.3.6";

View File

@@ -21,7 +21,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.SqlProjects
DatabaseVariable = "$(DatabaseVariable)" DatabaseVariable = "$(DatabaseVariable)"
}; };
Assert.Throws<ArgumentException>(() => reference.Validate(), $"Validate() for a reference with both {nameof(reference.DatabaseLiteral)} and {nameof(reference.DatabaseVariable)} should have failed"); Assert.Throws<ArgumentException>(reference.Validate, $"Validate() for a reference with both {nameof(reference.DatabaseLiteral)} and {nameof(reference.DatabaseVariable)} should have failed");
// Verify that Validate() passes any other time // Verify that Validate() passes any other time
reference = new AddDacpacReferenceParams() { DatabaseLiteral = "DatabaseName" }; reference = new AddDacpacReferenceParams() { DatabaseLiteral = "DatabaseName" };

View File

@@ -15,7 +15,7 @@ using NUnit.Framework;
namespace Microsoft.SqlTools.ServiceLayer.UnitTests.UtilityTests namespace Microsoft.SqlTools.ServiceLayer.UnitTests.UtilityTests
{ {
public class ToSqlScriptTests public partial class ToSqlScriptTests
{ {
#region FormatValue Tests #region FormatValue Tests
@@ -60,7 +60,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.UtilityTests
{ {
// Setup: Build a column and cell for the integer type column // Setup: Build a column and cell for the integer type column
DbColumn column = new FormatterTestDbColumn(dataType); DbColumn column = new FormatterTestDbColumn(dataType);
DbCellValue cell = new DbCellValue { RawObject = (long)123 }; var cell = new DbCellValue { RawObject = (long)123 };
// If: I attempt to format an integer type column // If: I attempt to format an integer type column
string output = ToSqlScript.FormatValue(cell, column); string output = ToSqlScript.FormatValue(cell, column);
@@ -82,13 +82,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.UtilityTests
{ {
// Setup: Build a column and cell for the decimal type column // Setup: Build a column and cell for the decimal type column
DbColumn column = new FormatterTestDbColumn(dataType, precision, scale); DbColumn column = new FormatterTestDbColumn(dataType, precision, scale);
DbCellValue cell = new DbCellValue { RawObject = 123.45m }; var cell = new DbCellValue { RawObject = 123.45m };
// If: I attempt to format a decimal type column // If: I attempt to format a decimal type column
string output = ToSqlScript.FormatValue(cell, column); string output = ToSqlScript.FormatValue(cell, column);
// Then: It should match a something like CAST(123.45 AS MONEY) // Then: It should match a something like CAST(123.45 AS MONEY)
Regex castRegex = new Regex($@"CAST\([\d\.]+ AS {regex}", RegexOptions.IgnoreCase); var castRegex = new Regex($@"CAST\([\d\.]+ AS {regex}", RegexOptions.IgnoreCase);
Assert.True(castRegex.IsMatch(output)); Assert.True(castRegex.IsMatch(output));
} }
@@ -97,7 +97,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.UtilityTests
{ {
// Setup: Build a column and cell for the approx numeric type column // Setup: Build a column and cell for the approx numeric type column
DbColumn column = new FormatterTestDbColumn("FLOAT"); DbColumn column = new FormatterTestDbColumn("FLOAT");
DbCellValue cell = new DbCellValue { RawObject = 3.14159d }; var cell = new DbCellValue { RawObject = 3.14159d };
// If: I attempt to format a approx numeric type column // If: I attempt to format a approx numeric type column
string output = ToSqlScript.FormatValue(cell, column); string output = ToSqlScript.FormatValue(cell, column);
@@ -111,7 +111,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.UtilityTests
{ {
// Setup: Build a column and cell for the approx numeric type column // Setup: Build a column and cell for the approx numeric type column
DbColumn column = new FormatterTestDbColumn("REAL"); DbColumn column = new FormatterTestDbColumn("REAL");
DbCellValue cell = new DbCellValue { RawObject = (float)3.14159 }; var cell = new DbCellValue { RawObject = (float)3.14159 };
// If: I attempt to format a approx numeric type column // If: I attempt to format a approx numeric type column
string output = ToSqlScript.FormatValue(cell, column); string output = ToSqlScript.FormatValue(cell, column);
@@ -129,15 +129,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.UtilityTests
{ {
// Setup: Build a column and cell for the datetime type column // Setup: Build a column and cell for the datetime type column
DbColumn column = new FormatterTestDbColumn(dataType); DbColumn column = new FormatterTestDbColumn(dataType);
DbCellValue cell = new DbCellValue { RawObject = DateTime.Now }; var cell = new DbCellValue { RawObject = DateTime.Now };
// If: I attempt to format a datetime type column // If: I attempt to format a datetime type column
string output = ToSqlScript.FormatValue(cell, column); string output = ToSqlScript.FormatValue(cell, column);
// Then: The output string should be able to be converted back into a datetime // Then: The output string should be able to be converted back into a datetime
Regex dateTimeRegex = new Regex("N'(.*)'");
DateTime outputDateTime; DateTime outputDateTime;
Assert.True(DateTime.TryParse(dateTimeRegex.Match(output).Groups[1].Value, out outputDateTime)); Assert.True(DateTime.TryParse(GetDateTimeRegex().Match(output).Groups[1].Value, out outputDateTime));
} }
[Test] [Test]
@@ -145,15 +144,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.UtilityTests
{ {
// Setup: Build a column and cell for the datetime offset type column // Setup: Build a column and cell for the datetime offset type column
DbColumn column = new FormatterTestDbColumn("DATETIMEOFFSET"); DbColumn column = new FormatterTestDbColumn("DATETIMEOFFSET");
DbCellValue cell = new DbCellValue { RawObject = DateTimeOffset.Now }; var cell = new DbCellValue { RawObject = DateTimeOffset.Now };
// If: I attempt to format a datetime offset type column // If: I attempt to format a datetime offset type column
string output = ToSqlScript.FormatValue(cell, column); string output = ToSqlScript.FormatValue(cell, column);
// Then: The output string should be able to be converted back into a datetime offset // Then: The output string should be able to be converted back into a datetime offset
Regex dateTimeRegex = new Regex("N'(.*)'");
DateTimeOffset outputDateTime; DateTimeOffset outputDateTime;
Assert.True(DateTimeOffset.TryParse(dateTimeRegex.Match(output).Groups[1].Value, out outputDateTime)); Assert.True(DateTimeOffset.TryParse(GetDateTimeRegex().Match(output).Groups[1].Value, out outputDateTime));
} }
[Test] [Test]
@@ -161,15 +159,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.UtilityTests
{ {
// Setup: Build a column and cell for the time type column // Setup: Build a column and cell for the time type column
DbColumn column = new FormatterTestDbColumn("TIME"); DbColumn column = new FormatterTestDbColumn("TIME");
DbCellValue cell = new DbCellValue { RawObject = TimeSpan.FromHours(12) }; var cell = new DbCellValue { RawObject = TimeSpan.FromHours(12) };
// If: I attempt to format a time type column // If: I attempt to format a time type column
string output = ToSqlScript.FormatValue(cell, column); string output = ToSqlScript.FormatValue(cell, column);
// Then: The output string should be able to be converted back into a timespan // Then: The output string should be able to be converted back into a timespan
Regex dateTimeRegex = new Regex("N'(.*)'");
TimeSpan outputDateTime; TimeSpan outputDateTime;
Assert.True(TimeSpan.TryParse(dateTimeRegex.Match(output).Groups[1].Value, out outputDateTime)); Assert.True(TimeSpan.TryParse(GetDateTimeRegex().Match(output).Groups[1].Value, out outputDateTime));
} }
private static readonly object[] stringFormats = private static readonly object[] stringFormats =
@@ -186,7 +183,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.UtilityTests
// Setup: Build a column and cell for the string type column // Setup: Build a column and cell for the string type column
// NOTE: We're using VARCHAR because it's very general purpose. // NOTE: We're using VARCHAR because it's very general purpose.
DbColumn column = new FormatterTestDbColumn("VARCHAR"); DbColumn column = new FormatterTestDbColumn("VARCHAR");
DbCellValue cell = new DbCellValue { RawObject = input }; var cell = new DbCellValue { RawObject = input };
// If: I attempt to format a string type column // If: I attempt to format a string type column
string output = ToSqlScript.FormatValue(cell, column); string output = ToSqlScript.FormatValue(cell, column);
@@ -208,7 +205,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.UtilityTests
{ {
// Setup: Build a column and cell for the string type column // Setup: Build a column and cell for the string type column
DbColumn column = new FormatterTestDbColumn(datatype); DbColumn column = new FormatterTestDbColumn(datatype);
DbCellValue cell = new DbCellValue { RawObject = "test string" }; var cell = new DbCellValue { RawObject = "test string" };
// If: I attempt to format a string type column // If: I attempt to format a string type column
string output = ToSqlScript.FormatValue(cell, column); string output = ToSqlScript.FormatValue(cell, column);
@@ -222,17 +219,16 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.UtilityTests
{ {
// Setup: Build a column and cell for the string type column // Setup: Build a column and cell for the string type column
DbColumn column = new FormatterTestDbColumn(datatype); DbColumn column = new FormatterTestDbColumn(datatype);
DbCellValue cell = new DbCellValue var cell = new DbCellValue
{ {
RawObject = new byte[] { 0x42, 0x45, 0x4e, 0x49, 0x53, 0x43, 0x4f, 0x4f, 0x4c } RawObject = "BENISCOOL"u8.ToArray()
}; };
// If: I attempt to format a string type column // If: I attempt to format a string type column
string output = ToSqlScript.FormatValue(cell, column); string output = ToSqlScript.FormatValue(cell, column);
// Then: The output string should match the output string // Then: The output string should match the output string
Regex regex = new Regex("0x[0-9A-F]+", RegexOptions.IgnoreCase); Assert.True(GetOuputRegex().IsMatch(output));
Assert.True(regex.IsMatch(output));
} }
[Test] [Test]
@@ -240,13 +236,13 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.UtilityTests
{ {
// Setup: Build a column and cell for the string type column // Setup: Build a column and cell for the string type column
DbColumn column = new FormatterTestDbColumn("UNIQUEIDENTIFIER"); DbColumn column = new FormatterTestDbColumn("UNIQUEIDENTIFIER");
DbCellValue cell = new DbCellValue { RawObject = Guid.NewGuid() }; var cell = new DbCellValue { RawObject = Guid.NewGuid() };
// If: I attempt to format a string type column // If: I attempt to format a string type column
string output = ToSqlScript.FormatValue(cell, column); string output = ToSqlScript.FormatValue(cell, column);
// Then: The output string should match the output string // Then: The output string should match the output string
Regex regex = new Regex(@"N'[0-9A-F]{8}(-[0-9A-F]{4}){3}-[0-9A-F]{12}'", RegexOptions.IgnoreCase); var regex = GetGuidRegex();
Assert.True(regex.IsMatch(output)); Assert.True(regex.IsMatch(output));
} }
@@ -391,7 +387,7 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.UtilityTests
#endregion #endregion
private class FormatterTestDbColumn : DbColumn private sealed class FormatterTestDbColumn : DbColumn
{ {
public FormatterTestDbColumn(string dataType, int? precision = null, int? scale = null, int? size = null) public FormatterTestDbColumn(string dataType, int? precision = null, int? scale = null, int? size = null)
{ {
@@ -401,5 +397,14 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.UtilityTests
ColumnSize = size; ColumnSize = size;
} }
} }
[GeneratedRegex("0x[0-9A-F]+", RegexOptions.IgnoreCase, "en-CA")]
private static partial Regex GetOuputRegex();
[GeneratedRegex("N'[0-9A-F]{8}(-[0-9A-F]{4}){3}-[0-9A-F]{12}'", RegexOptions.IgnoreCase, "en-CA")]
private static partial Regex GetGuidRegex();
[GeneratedRegex("N'(.*)'")]
private static partial Regex GetDateTimeRegex();
} }
} }