Adding decoding of multipart identifiers, default schema workaround (#295)

This change adds a couple things

_Multipart Identifier Decoding_
The ability to decode a multipart identifier (with or without escaping) has been added to the SqlScriptFormatter utility class. This code is utilized to split a table name provided to the edit/initialize request into schema and table name.

_Default Schema Workaround_
The code that retrieves the SMO metadata objects originally used the `[]` operator to access the objects. Due to a bug(?) in SMO, this results in problems when loading tables without a default schema (in our case if you're logged in as SA). Using the metadata object constructors gets around this issue, we are explicitly using them.

* Adding decoding of multipart identifiers
Adding code fix for default schema issue

* Adding some more localizable strings for errors when loading metadata

* Adding localization files... again?

* Changes as per pull request comments
This commit is contained in:
Benjamin Russell
2017-03-27 17:14:21 -07:00
committed by GitHub
parent 1909310a92
commit f7036f3f73
11 changed files with 235 additions and 17 deletions

View File

@@ -7,6 +7,8 @@ using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Text.RegularExpressions;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.SqlParser.SqlCodeDom;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility;
using Xunit;
@@ -308,6 +310,56 @@ namespace Microsoft.SqlTools.ServiceLayer.UnitTests.Utility
#endregion
#region DecodeMultipartIdentifier Tests
[Theory]
[MemberData(nameof(DecodeMultipartIdentifierTestData))]
public void DecodeMultipartIdentifierTest(string input, string[] output)
{
// If: I decode the input
string[] decoded = SqlScriptFormatter.DecodeMultipartIdenfitier(input);
// Then: The output should match what was expected
Assert.Equal(output, decoded);
}
public static IEnumerable<object> DecodeMultipartIdentifierTestData
{
get
{
yield return new object[] {"identifier", new[] {"identifier"}};
yield return new object[] {"simple.split", new[] {"simple", "split"}};
yield return new object[] {"multi.simple.split", new[] {"multi", "simple", "split"}};
yield return new object[] {"[escaped]", new[] {"escaped"}};
yield return new object[] {"[escaped].[split]", new[] {"escaped", "split"}};
yield return new object[] {"[multi].[escaped].[split]", new[] {"multi", "escaped", "split"}};
yield return new object[] {"[escaped]]characters]", new[] {"escaped]characters"}};
yield return new object[] {"[multi]]escaped]]chars]", new[] {"multi]escaped]chars"}};
yield return new object[] {"[multi]]]]chars]", new[] {"multi]]chars"}};
yield return new object[] {"unescaped]chars", new[] {"unescaped]chars"}};
yield return new object[] {"multi]unescaped]chars", new[] {"multi]unescaped]chars"}};
yield return new object[] {"multi]]chars", new[] {"multi]]chars"}};
yield return new object[] {"[escaped.dot]", new[] {"escaped.dot"}};
yield return new object[] {"mixed.[escaped]", new[] {"mixed", "escaped"}};
yield return new object[] {"[escaped].mixed", new[] {"escaped", "mixed"}};
yield return new object[] {"dbo.[[].weird", new[] {"dbo", "[", "weird"}};
}
}
[Theory]
[InlineData("[bracket]closed")]
[InlineData("[bracket][closed")]
[InlineData(".stuff")]
[InlineData(".")]
public void DecodeMultipartIdentifierFailTest(string input)
{
// If: I decode an invalid input
// Then: It should throw an exception
Assert.Throws<FormatException>(() => SqlScriptFormatter.DecodeMultipartIdenfitier(input));
}
#endregion
[Theory]
[InlineData("(0)", "0")]
[InlineData("((0))", "0")]