Skip to content

Commit 9b68340

Browse files
committed
Merge remote-tracking branch 'origin/master' into ref-to-identify-bug
2 parents 4c663a3 + 9b77304 commit 9b68340

39 files changed

Lines changed: 531 additions & 221 deletions

Directory.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
</PropertyGroup>
2323

2424
<PropertyGroup>
25+
<LangVersion>8.0</LangVersion>
2526
<SolutionDir Condition="$(SolutionDir) == ''">$(MSBuildThisFileDirectory.TrimEnd('\').TrimEnd('/'))\</SolutionDir>
2627
<Configuration Condition="$(Configuration) == ''">Debug</Configuration>
2728
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>

Orm/Xtensive.Orm.SqlServer/Xtensive.Orm.SqlServer.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<WarningLevel>2</WarningLevel>
1818
</PropertyGroup>
1919
<ItemGroup>
20-
<PackageReference Include="System.Data.SqlClient" Version="4.8.0" />
20+
<PackageReference Include="System.Data.SqlClient" Version="4.8.1" />
2121
</ItemGroup>
2222

2323
<ItemGroup>
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
// Copyright (C) 2020 Xtensive LLC.
2+
// All rights reserved.
3+
// For conditions of distribution and use, see license.
4+
// Created by: Alexey Kulakov
5+
// Created: 2020.04.23
6+
7+
using System;
8+
using System.Collections.Generic;
9+
using System.Text;
10+
using NUnit.Framework;
11+
using Xtensive.Sql;
12+
13+
namespace Xtensive.Orm.Tests.Sql
14+
{
15+
[TestFixture]
16+
public sealed class SqlHelperQuotationTest
17+
{
18+
public static IEnumerable<(string[] testNames, string expectedResult)> QuotesRegularNames()
19+
{
20+
yield return (new string[] { "name1" }, "\"name1\"");
21+
yield return (new string[] { "n\"\"\"1" }, "\"n\"\"\"\"\"\"1\"");
22+
yield return (new string[] { "name1", "name2" }, "\"name1\".\"name2\"");
23+
yield return (new string[] { "n\"\"\"1", "n\"\"\"2" }, "\"n\"\"\"\"\"\"1\".\"n\"\"\"\"\"\"2\"");
24+
yield return (new string[] { "name1", "name2", "name3" }, "\"name1\".\"name2\".\"name3\"");
25+
yield return (new string[] { "n\"\"\"1", "n\"\"\"2", "n\"\"\"3" }, "\"n\"\"\"\"\"\"1\".\"n\"\"\"\"\"\"2\".\"n\"\"\"\"\"\"3\"");
26+
}
27+
28+
public static IEnumerable<(string[] testNames, string expectedResult)> QuotesEmptyNames()
29+
{
30+
yield return (new string[] {"name1", "name2", ""}, "\"name1\".\"name2\"");
31+
yield return (new string[] { "name1", "", "name3" }, "\"name1\".\"name3\"");
32+
yield return (new string[] { "", "name2", "name3" }, "\"name2\".\"name3\"");
33+
yield return (new string[] { "name1", "", "" } , "\"name1\"");
34+
yield return (new string[] { "", "", "name3" }, "\"name3\"");
35+
yield return (new string[] { "", "name2", "" }, "\"name2\"");
36+
yield return (new string[] { "", "", "" }, string.Empty);
37+
}
38+
39+
public static IEnumerable<(string[] testNames, string expectedResult)> QuotesNullNames()
40+
{
41+
yield return (new string[] { "name1", "name2", null }, "\"name1\".\"name2\"");
42+
yield return (new string[] { "name1", null, "name3" }, "\"name1\".\"name3\"");
43+
yield return (new string[] { null, "name2", "name3" }, "\"name2\".\"name3\"");
44+
yield return (new string[] { "name1", null, null }, "\"name1\"");
45+
yield return (new string[] { null, null, "name3" }, "\"name3\"");
46+
yield return (new string[] { null, "name2", null }, "\"name2\"");
47+
yield return (new string[] { null, null, null }, string.Empty);
48+
}
49+
50+
public static IEnumerable<(string[] testNames, string expectedResult)> BracketsRegularNames()
51+
{
52+
yield return (new string[] { "name1" }, "[name1]");
53+
yield return (new string[] { "n[[[1" }, "[n[[[1]");
54+
yield return (new string[] { "n]]]1" }, "[n]]]]]]1]");
55+
yield return (new string[] { "name1", "name2" }, "[name1].[name2]");
56+
yield return (new string[] { "n[[[1", "n[[[2" }, "[n[[[1].[n[[[2]");
57+
yield return (new string[] { "n]]]1", "n]]]2" }, "[n]]]]]]1].[n]]]]]]2]");
58+
yield return (new string[] { "name1", "name2", "name3" }, "[name1].[name2].[name3]");
59+
yield return (new string[] { "n[[[1", "n[[[2", "n[[[3" }, "[n[[[1].[n[[[2].[n[[[3]");
60+
yield return (new string[] { "n]]]1", "n]]]2", "n]]]3" }, "[n]]]]]]1].[n]]]]]]2].[n]]]]]]3]");
61+
}
62+
63+
public static IEnumerable<(string[] testNames, string expectedResult)> BracketsEmptyNames()
64+
{
65+
yield return (new string[] { "name1", "name2", "" }, "[name1].[name2]");
66+
yield return (new string[] { "name1", "", "name3" }, "[name1].[name3]");
67+
yield return (new string[] { "", "name2", "name3" }, "[name2].[name3]");
68+
yield return (new string[] { "name1", "", "" }, "[name1]");
69+
yield return (new string[] { "", "", "name3" }, "[name3]");
70+
yield return (new string[] { "", "name2", "" }, "[name2]");
71+
yield return (new string[] { "", "", "" }, string.Empty);
72+
}
73+
74+
public static IEnumerable<(string[] testNames, string expectedResult)> BracketsNullNames()
75+
{
76+
yield return (new string[] { "name1", "name2", null }, "[name1].[name2]");
77+
yield return (new string[] { "name1", null, "name3" }, "[name1].[name3]");
78+
yield return (new string[] { null, "name2", "name3" }, "[name2].[name3]");
79+
yield return (new string[] { "name1", null, null }, "[name1]");
80+
yield return (new string[] { null, null, "name3" }, "[name3]");
81+
yield return (new string[] { null, "name2", null }, "[name2]");
82+
yield return (new string[] { null, null, null }, string.Empty);
83+
}
84+
85+
public static IEnumerable<(string[] testNames, string expectedResult)> BackTickRegularNames()
86+
{
87+
yield return (new string[] { "name1" }, "`name1`");
88+
yield return (new string[] { "n```1" }, "`n``````1`");
89+
yield return (new string[] { "name1", "name2" }, "`name1`.`name2`");
90+
yield return (new string[] { "n```1", "n```2" }, "`n``````1`.`n``````2`");
91+
yield return (new string[] { "name1", "name2", "name3" }, "`name1`.`name2`.`name3`");
92+
yield return (new string[] { "n```1", "n```2", "n```3" }, "`n``````1`.`n``````2`.`n``````3`");
93+
}
94+
95+
public static IEnumerable<(string[] testNames, string expectedResult)> BackTickEmptyNames()
96+
{
97+
yield return (new string[] { "name1", "name2", "" }, "`name1`.`name2`");
98+
yield return (new string[] { "name1", "", "name3" }, "`name1`.`name3`");
99+
yield return (new string[] { "", "name2", "name3" }, "`name2`.`name3`");
100+
yield return (new string[] { "name1", "", "" }, "`name1`");
101+
yield return (new string[] { "", "", "name3" }, "`name3`");
102+
yield return (new string[] { "", "name2", "" }, "`name2`");
103+
yield return (new string[] { "", "", "" }, string.Empty);
104+
}
105+
106+
public static IEnumerable<(string[] testNames, string expectedResult)> BackTickNullNames()
107+
{
108+
yield return (new string[] { "name1", "name2", null }, "`name1`.`name2`");
109+
yield return (new string[] { "name1", null, "name3" }, "`name1`.`name3`");
110+
yield return (new string[] { null, "name2", "name3" }, "`name2`.`name3`");
111+
yield return (new string[] { "name1", null, null }, "`name1`");
112+
yield return (new string[] { null, null, "name3" }, "`name3`");
113+
yield return (new string[] { null, "name2", null }, "`name2`");
114+
yield return (new string[] { null, null, null }, string.Empty);
115+
}
116+
117+
[Test]
118+
[TestCaseSource(nameof(SqlHelperQuotationTest.QuotesRegularNames))]
119+
public void QuoteIndentifierWithQuotesWithRegularNames((string[] testNames, string expectedResult) testData)
120+
=> Assert.That(SqlHelper.QuoteIdentifierWithQuotes(testData.testNames),
121+
Is.EqualTo(testData.expectedResult));
122+
123+
[Test]
124+
[TestCaseSource(nameof(SqlHelperQuotationTest.QuotesEmptyNames))]
125+
public void QuoteIndentifierWithQuotesWithEmptyNames((string[] testNames, string expectedResult) testData)
126+
=> Assert.That(SqlHelper.QuoteIdentifierWithQuotes(testData.testNames),
127+
Is.EqualTo(testData.expectedResult));
128+
129+
[Test]
130+
[TestCaseSource(nameof(SqlHelperQuotationTest.QuotesNullNames))]
131+
public void QuoteIndentifierWithQuotesWithNullNames((string[] testNames, string expectedResult) testData)
132+
=> Assert.That(SqlHelper.QuoteIdentifierWithQuotes(testData.testNames),
133+
Is.EqualTo(testData.expectedResult));
134+
135+
[Test]
136+
[TestCaseSource(nameof(SqlHelperQuotationTest.BracketsRegularNames))]
137+
public void QuoteIdentifierWithBracketsWithRegularNames((string[] testNames, string expectedResult) testData)
138+
=> Assert.That(SqlHelper.QuoteIdentifierWithBrackets(testData.testNames),
139+
Is.EqualTo(testData.expectedResult));
140+
141+
[Test]
142+
[TestCaseSource(nameof(SqlHelperQuotationTest.BracketsEmptyNames))]
143+
public void QuoteIdentifierWithBracketsWithEmptyNames((string[] testNames, string expectedResult) testData)
144+
=> Assert.That(SqlHelper.QuoteIdentifierWithBrackets(testData.testNames),
145+
Is.EqualTo(testData.expectedResult));
146+
147+
[Test]
148+
[TestCaseSource(nameof(SqlHelperQuotationTest.BracketsNullNames))]
149+
public void QuoteIdentifierWithBracketsWithNullNames((string[] testNames, string expectedResult) testData)
150+
=> Assert.That(SqlHelper.QuoteIdentifierWithBrackets(testData.testNames),
151+
Is.EqualTo(testData.expectedResult));
152+
153+
[Test]
154+
[TestCaseSource(nameof(SqlHelperQuotationTest.BackTickRegularNames))]
155+
public void QuoteIdentifierWithBackTicksWithRegularNames((string[] testNames, string expectedResult) testData)
156+
=> Assert.That(SqlHelper.QuoteIdentifierWithBackTick(testData.testNames),
157+
Is.EqualTo(testData.expectedResult));
158+
159+
[Test]
160+
[TestCaseSource(nameof(SqlHelperQuotationTest.BackTickEmptyNames))]
161+
public void QuoteIdentifierWithBackTicksWithEmptyNames((string[] testNames, string expectedResult) testData)
162+
=> Assert.That(SqlHelper.QuoteIdentifierWithBackTick(testData.testNames),
163+
Is.EqualTo(testData.expectedResult));
164+
165+
[Test]
166+
[TestCaseSource(nameof(SqlHelperQuotationTest.BackTickNullNames))]
167+
public void QuoteIdentifierWithBackTicksWithNullNames((string[] testNames, string expectedResult) testData)
168+
=> Assert.That(SqlHelper.QuoteIdentifierWithBackTick(testData.testNames),
169+
Is.EqualTo(testData.expectedResult));
170+
}
171+
}

Orm/Xtensive.Orm/Core/ArgumentValidator.cs

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using System;
88
using System.Runtime.CompilerServices;
99
using JetBrains.Annotations;
10-
using Xtensive.Core;
1110
using Xtensive.Comparison;
1211

1312

@@ -28,7 +27,6 @@ public static class ArgumentValidator
2827
public static void EnsureArgumentNotNull(object value, [InvokerParameterName] string parameterName)
2928
{
3029
if (value==null) {
31-
EnsureArgumentNotNullOrEmpty(parameterName, "parameterName");
3230
throw new ArgumentNullException(parameterName);
3331
}
3432
}
@@ -45,13 +43,11 @@ public static void EnsureArgumentIsNotDefault<T>(T value, [InvokerParameterName]
4543
{
4644
if (default(T)==null) {
4745
if (value==null) {
48-
EnsureArgumentNotNullOrEmpty(parameterName, "parameterName");
49-
throw Exceptions.InvalidArgument(value, "parameterName");
46+
throw Exceptions.InvalidArgument(value, parameterName);
5047
}
5148
}
52-
else if (AdvancedComparerStruct<T>.System.Equals(value, default(T))) {
53-
EnsureArgumentNotNullOrEmpty(parameterName, "parameterName");
54-
throw Exceptions.InvalidArgument(value, "parameterName");
49+
else if (AdvancedComparerStruct<T>.System.Equals(value, default)) {
50+
throw Exceptions.InvalidArgument(value, parameterName);
5551
}
5652
}
5753

@@ -65,11 +61,9 @@ public static void EnsureArgumentIsNotDefault<T>(T value, [InvokerParameterName]
6561
public static void EnsureArgumentNotNullOrEmpty(string value, [InvokerParameterName] string parameterName)
6662
{
6763
if (value == null) {
68-
EnsureArgumentNotNullOrEmpty(parameterName, "parameterName");
6964
throw new ArgumentNullException(parameterName);
7065
}
7166
if (value.Length == 0) {
72-
EnsureArgumentNotNullOrEmpty(parameterName, "parameterName");
7367
throw new ArgumentException(Strings.ExArgumentCannotBeEmptyString, parameterName);
7468
}
7569
}
@@ -78,15 +72,14 @@ public static void EnsureArgumentNotNullOrEmpty(string value, [InvokerParameterN
7872
public static void EnsureArgumentNotNullOrEmptyOrWhiteSpace(string value, [InvokerParameterName] string parameterName)
7973
{
8074
if (value==null) {
81-
EnsureArgumentNotNullOrEmpty(parameterName, "parameterName");
8275
throw new ArgumentNullException(parameterName);
8376
}
77+
8478
if (value.Length==0) {
85-
EnsureArgumentNotNullOrEmpty(parameterName, "parameterName");
8679
throw new ArgumentException(Strings.ExArgumentCannotBeEmptyString, parameterName);
8780
}
81+
8882
if (value.Trim().Length==0) {
89-
EnsureArgumentNotNullOrEmpty(parameterName, "parameterName");
9083
throw new ArgumentException(Strings.ExArgumentCannotBeWhiteSpacesOnlyString, parameterName);
9184
}
9285
}
@@ -103,7 +96,6 @@ public static void EnsureArgumentIs<T>(object value, [InvokerParameterName] stri
10396
{
10497
EnsureArgumentNotNull(value, parameterName);
10598
if (!(value is T)) {
106-
EnsureArgumentNotNullOrEmpty(parameterName, "parameterName");
10799
throw new ArgumentException(string.Format(Strings.ExInvalidArgumentType, typeof(T)), parameterName);
108100
}
109101
}
@@ -119,8 +111,7 @@ public static void EnsureArgumentIs<T>(object value, [InvokerParameterName] stri
119111
public static void EnsureArgumentIs(object value, Type type, [InvokerParameterName] string parameterName)
120112
{
121113
EnsureArgumentNotNull(value, parameterName);
122-
if (!type.IsAssignableFrom(value.GetType())) {
123-
EnsureArgumentNotNullOrEmpty(parameterName, "parameterName");
114+
if (!type.IsInstanceOfType(value)) {
124115
throw new ArgumentException(string.Format(Strings.ExInvalidArgumentType, type), parameterName);
125116
}
126117
}
@@ -138,7 +129,6 @@ public static void EnsureArgumentIsNullOr<T>(object value, [InvokerParameterName
138129
if (value==null)
139130
return;
140131
if (!(value is T)) {
141-
EnsureArgumentNotNullOrEmpty(parameterName, "parameterName");
142132
throw new ArgumentException(string.Format(Strings.ExInvalidArgumentType, typeof(T)), parameterName);
143133
}
144134
}
@@ -157,7 +147,6 @@ public static void EnsureArgumentIsInRange<T>(T value, T lowerBoundary, T upperB
157147
where T: struct, IComparable<T>
158148
{
159149
if (value.CompareTo(lowerBoundary)<0 || value.CompareTo(upperBoundary)>0) {
160-
EnsureArgumentNotNullOrEmpty(parameterName, "parameterName");
161150
throw new ArgumentOutOfRangeException(parameterName, value,
162151
string.Format(Strings.ExArgumentShouldBeInRange, lowerBoundary, upperBoundary));
163152
}
@@ -176,7 +165,6 @@ public static void EnsureArgumentIsGreaterThan<T>(T value, T boundary, [InvokerP
176165
{
177166
if (value.CompareTo(boundary) > 0)
178167
return;
179-
EnsureArgumentNotNullOrEmpty(parameterName, "parameterName");
180168
throw new ArgumentOutOfRangeException(parameterName, value,
181169
string.Format(Strings.ExArgumentMustBeGreaterThanX, boundary));
182170
}
@@ -195,7 +183,6 @@ public static void EnsureArgumentIsGreaterThanOrEqual<T>(T value, T boundary, [I
195183
{
196184
if (value.CompareTo(boundary) >= 0)
197185
return;
198-
EnsureArgumentNotNullOrEmpty(parameterName, "parameterName");
199186
throw new ArgumentOutOfRangeException(parameterName, value,
200187
string.Format(Strings.ExArgumentMustBeGreaterThatOrEqualX, boundary));
201188
}
@@ -214,7 +201,6 @@ public static void EnsureArgumentIsLessThan<T>(T value, T boundary, [InvokerPara
214201
{
215202
if (value.CompareTo(boundary) < 0)
216203
return;
217-
EnsureArgumentNotNullOrEmpty(parameterName, "parameterName");
218204
throw new ArgumentOutOfRangeException(parameterName, value,
219205
string.Format(Strings.ExArgumentMustBeLessThanX, boundary));
220206
}
@@ -233,7 +219,6 @@ public static void EnsureArgumentIsLessThanOrEqual<T>(T value, T boundary, [Invo
233219
{
234220
if (value.CompareTo(boundary) <= 0)
235221
return;
236-
EnsureArgumentNotNullOrEmpty(parameterName, "parameterName");
237222
throw new ArgumentOutOfRangeException(parameterName, value,
238223
string.Format(Strings.ExArgumentMustBeLessThanOrEqualX, boundary));
239224
}

Orm/Xtensive.Orm/Core/Extensions/EnumerableExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ public static T[] ToArray<T>(this IEnumerable<T> sequence, int length)
312312
/// Gets the items from the segment.
313313
/// </summary>
314314
/// <param name="segment">The segment.</param>
315-
public static IEnumerable<int> GetItems(this Segment<int> segment)
315+
public static IEnumerable<int> GetItems(this in Segment<int> segment)
316316
{
317317
return Enumerable.Range(segment.Offset, segment.Length);
318318
}

Orm/Xtensive.Orm/Core/Segment.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ namespace Xtensive.Core
1919
/// <typeparam name="T">The type of segment boundaries.</typeparam>
2020
[Serializable]
2121
[DebuggerDisplay("Offset = {Offset}, Length = {Length}")]
22-
public struct Segment<T>
22+
public readonly struct Segment<T>
2323
{
2424
private static ArithmeticStruct<T> arithmetic = ArithmeticStruct<T>.Default;
2525

@@ -87,7 +87,7 @@ public override int GetHashCode()
8787
/// <param name="segment">The segment.</param>
8888
/// <param name="offsetShift">The offset shift.</param>
8989
/// <returns>The result of the operator.</returns>
90-
public static Segment<T> operator +(Segment<T> segment, T offsetShift)
90+
public static Segment<T> operator +(in Segment<T> segment, T offsetShift)
9191
{
9292
var newOffset = arithmetic.Add(segment.Offset, offsetShift);
9393
return new Segment<T>(newOffset, segment.Length);
@@ -99,7 +99,7 @@ public override int GetHashCode()
9999
/// <param name="segment">The segment.</param>
100100
/// <param name="offsetShift">The offset shift.</param>
101101
/// <returns>The result of the operator.</returns>
102-
public static Segment<T> operator -(Segment<T> segment, T offsetShift)
102+
public static Segment<T> operator -(in Segment<T> segment, T offsetShift)
103103
{
104104
var newOffset = arithmetic.Subtract(segment.Offset, offsetShift);
105105
return new Segment<T>(newOffset, segment.Length);

0 commit comments

Comments
 (0)