Skip to content

Commit 9b5cff6

Browse files
committed
Merge branch '7.0' into master
# Conflicts: # Version.props
2 parents c878c64 + 617e90e commit 9b5cff6

File tree

10 files changed

+188
-12
lines changed

10 files changed

+188
-12
lines changed

ChangeLog/7.0.3_Z_Final.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[main] NodeCollection supports different equality comparers for internal name index
2+
[sqlserver] Fixed TimeSpan.Ticks extraction problem
3+
[oracle] Fixed scheme extraction for case-sensitive schema names

Orm/Xtensive.Orm.Oracle/Sql.Drivers.Oracle/v09/Extractor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,9 @@ protected virtual string ToUpperInvariantIfNeeded(string schemaName)
142142

143143
private ExtractionContext CreateContext(string catalogName, string[] schemaNames)
144144
{
145-
var catalog = new Catalog(catalogName);
145+
var catalog = new Catalog(catalogName, true);
146146
for(var i = 0; i < schemaNames.Length; i++) {
147-
schemaNames[i] = schemaNames[i].ToUpperInvariant();
147+
schemaNames[i] = ToUpperInvariantIfNeeded(schemaNames[i]);
148148
}
149149

150150
var replacements = new Dictionary<string, string>();

Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v13/Compiler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public override void Visit(SqlFunctionCall node)
3636
// we have to use time consuming algorithm here because
3737
// DATEDIFF_BIG can throw arithmetic overflow on nanoseconds
3838
// so we should handle it by this big formula
39-
Visit(CastToLong(DateTimeSubtractDateTimeExpensive(binary.Right, binary.Left)));
39+
Visit(CastToLong(DateTimeSubtractDateTimeExpensive(binary.Left, binary.Right)));
4040
}
4141
else {
4242
base.Visit(node);

Orm/Xtensive.Orm.Tests.Framework/StorageTestHelper.cs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// Copyright (C) 2003-2010 Xtensive LLC.
2-
// All rights reserved.
3-
// For conditions of distribution and use, see license.
1+
// Copyright (C) 2009-2022 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
44
// Created by: Denis Krjuchkov
55
// Created: 2009.12.17
66

@@ -51,13 +51,16 @@ public static void DemandSchemas(ConnectionInfo connectionInfo, params string[]
5151
var extractionResult = driver.Extract(connection, new[] {extractionTask});
5252
var catalog = extractionResult.Catalogs.Single();
5353
var existingSchemas = catalog.Schemas.Select(s => s.Name);
54-
var schemasToCreate = schemas.Except(existingSchemas, StringComparer.OrdinalIgnoreCase);
5554

5655
// Oracle does not support creating schemas, user should be created instead.
57-
if (connectionInfo.Provider==WellKnown.Provider.Oracle)
56+
if (connectionInfo.Provider == WellKnown.Provider.Oracle) {
57+
var schemasToCreate = schemas.Except(existingSchemas, StringComparer.Ordinal);
5858
CreateUsers(connection, schemasToCreate);
59-
else
59+
}
60+
else {
61+
var schemasToCreate = schemas.Except(existingSchemas, StringComparer.OrdinalIgnoreCase);
6062
CreateSchemas(connection, catalog, schemasToCreate);
63+
}
6164

6265
connection.Close();
6366
}

Orm/Xtensive.Orm.Tests/Linq/DateTimeAndDateTimeOffset/DateTime/PartsExtractionTest.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2016-2021 Xtensive LLC.
1+
// Copyright (C) 2016-2022 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44
// Created by: Alex Groznov
@@ -188,5 +188,16 @@ public void ExtractDayOfWeekTest()
188188
RunWrongTest<SingleDateTimeEntity>(c => c.NullableDateTime.Value.DayOfWeek == WrongDateTime.DayOfWeek);
189189
});
190190
}
191+
192+
[Test]
193+
public void ExtractTimeOfDayTicksTest()
194+
{
195+
Require.ProviderIsNot(StorageProvider.PostgreSql | StorageProvider.Oracle);
196+
197+
ExecuteInsideSession(() => {
198+
RunTest<SingleDateTimeEntity>(c => c.DateTime.TimeOfDay.Ticks == FirstDateTime.TimeOfDay.Ticks);
199+
RunWrongTest<SingleDateTimeEntity>(c => c.DateTime.TimeOfDay.Ticks < FirstDateTime.TimeOfDay.Ticks);
200+
});
201+
}
191202
}
192203
}

Orm/Xtensive.Orm.Tests/Linq/DateTimeAndDateTimeOffset/DateTimeOffset/PartsExtractionTest.cs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2016-2021 Xtensive LLC.
1+
// Copyright (C) 2016-2022 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44
// Created by: Alex Groznov
@@ -189,6 +189,20 @@ public void ExtractTimeOfDayWithMillisecondsTest()
189189
});
190190
}
191191

192+
[Test]
193+
public void ExtractTimeOfDayTicksTest()
194+
{
195+
Require.ProviderIsNot(StorageProvider.PostgreSql | StorageProvider.Oracle);
196+
197+
ExecuteInsideSession(() => {
198+
var firstDateTimeOffset = TryMoveToLocalTimeZone(FirstDateTimeOffset);
199+
RunTest<SingleDateTimeOffsetEntity>(c => c.DateTimeOffset.TimeOfDay.Ticks == firstDateTimeOffset.TimeOfDay.Ticks);
200+
201+
var wrongDateTimeOffset = TryMoveToLocalTimeZone(WrongDateTimeOffset);
202+
RunWrongTest<SingleDateTimeOffsetEntity>(c => c.DateTimeOffset.TimeOfDay.Ticks == wrongDateTimeOffset.TimeOfDay.Ticks);
203+
});
204+
}
205+
192206
[Test]
193207
public void ExtractTimeOfDayOfNullableValueTest()
194208
{
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// Copyright (C) 2022 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
4+
5+
using System.Linq;
6+
using NUnit.Framework;
7+
using Xtensive.Orm.Configuration;
8+
using M = Xtensive.Orm.Tests.Storage.Multimapping.CaseSensitiveSchemasTestModel;
9+
10+
namespace Xtensive.Orm.Tests.Storage.Multimapping.CaseSensitiveSchemasTestModel
11+
{
12+
namespace Schema1
13+
{
14+
[HierarchyRoot]
15+
public class Entity1 : Entity
16+
{
17+
[Field, Key]
18+
public int Id { get; private set; }
19+
20+
[Field]
21+
public string OriginalSchemaName { get; set; }
22+
}
23+
}
24+
25+
namespace Schema2
26+
{
27+
[HierarchyRoot]
28+
public class Entity2 : Entity
29+
{
30+
[Field, Key]
31+
public int Id { get; private set; }
32+
33+
[Field]
34+
public string OriginalSchemaName { get; set; }
35+
}
36+
}
37+
}
38+
39+
namespace Xtensive.Orm.Tests.Storage.Multimapping
40+
{
41+
public sealed class CaseSensitiveSchemasTest : MultimappingTest
42+
{
43+
private const string Schema1Name = WellKnownSchemas.Schema1;
44+
45+
private readonly string schema1UpperCaseName = Schema1Name.ToUpperInvariant();
46+
47+
protected override void CheckRequirements() => Require.ProviderIs(StorageProvider.Oracle);
48+
49+
protected override DomainConfiguration BuildConfiguration()
50+
{
51+
var configuration = base.BuildConfiguration();
52+
configuration.DefaultSchema = Schema1Name;
53+
configuration.Types.Register(typeof(M.Schema1.Entity1));
54+
configuration.Types.Register(typeof(M.Schema2.Entity2));
55+
var rules = configuration.MappingRules;
56+
rules.Map(typeof(M.Schema1.Entity1).Namespace).ToSchema(Schema1Name);
57+
rules.Map(typeof(M.Schema2.Entity2).Namespace).ToSchema(schema1UpperCaseName);
58+
return configuration;
59+
}
60+
61+
[Test]
62+
public void MainTest()
63+
{
64+
BuildInitialDomain();
65+
BuildUpgradedDomain();
66+
}
67+
68+
private void BuildInitialDomain()
69+
{
70+
var config = BuildConfiguration();
71+
PrepareSchema(config.ConnectionInfo);
72+
var domain = Domain.Build(config);
73+
using (domain) {
74+
using (var session = domain.OpenSession())
75+
using (var tx = session.OpenTransaction()) {
76+
_ = new M.Schema1.Entity1 { OriginalSchemaName = Schema1Name };
77+
_ = new M.Schema2.Entity2 { OriginalSchemaName = schema1UpperCaseName };
78+
tx.Complete();
79+
}
80+
}
81+
}
82+
83+
private void BuildUpgradedDomain()
84+
{
85+
var config = BuildConfiguration();
86+
config.UpgradeMode = DomainUpgradeMode.PerformSafely;
87+
var domain = Domain.Build(config);
88+
using (domain) {
89+
using (var session = domain.OpenSession())
90+
using (var tx = session.OpenTransaction()) {
91+
var e1 = session.Query.All<M.Schema1.Entity1>().Single();
92+
var e2 = session.Query.All<M.Schema2.Entity2>().Single();
93+
Assert.That(e1.OriginalSchemaName, Is.EqualTo(Schema1Name));
94+
Assert.That(e2.OriginalSchemaName, Is.EqualTo(schema1UpperCaseName));
95+
tx.Complete();
96+
}
97+
}
98+
}
99+
100+
private void PrepareSchema(ConnectionInfo connectionInfo)
101+
{
102+
StorageTestHelper.DemandSchemas(
103+
connectionInfo, Schema1Name, schema1UpperCaseName);
104+
}
105+
}
106+
}

Orm/Xtensive.Orm/Sql/Model/Catalog.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,20 @@ internal string GetActualDbName(IReadOnlyDictionary<string, string> catalogNameM
198198

199199
// Constructors
200200

201-
public Catalog(string name) : base(name)
201+
public Catalog(string name)
202+
: base(name)
202203
{
203204
schemas =
204205
new PairedNodeCollection<Catalog, Schema>(this, "Schemas", 1);
205206
}
207+
208+
public Catalog(string name, bool caseSensitiveNames = false)
209+
: base(name)
210+
{
211+
schemas = caseSensitiveNames
212+
? new PairedNodeCollection<Catalog, Schema>(this, "Schemas", 1, StringComparer.Ordinal)
213+
: new PairedNodeCollection<Catalog, Schema>(this, "Schemas", 1, StringComparer.OrdinalIgnoreCase);
214+
}
215+
206216
}
207217
}

Orm/Xtensive.Orm/Sql/Model/NodeCollection.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,5 +96,16 @@ public NodeCollection(int capacity)
9696
{
9797
nameIndex = new Dictionary<string, TNode>(capacity, Comparer);
9898
}
99+
100+
/// <summary>
101+
/// Initializes new instance of this type.
102+
/// </summary>
103+
/// <param name="capacity">The initial collection capacity.</param>
104+
/// <param name="comparer">Comparer for inner name index.</param>
105+
public NodeCollection(int capacity, IEqualityComparer<string> comparer)
106+
: base(capacity)
107+
{
108+
nameIndex = new Dictionary<string, TNode>(capacity, comparer);
109+
}
99110
}
100111
}

Orm/Xtensive.Orm/Sql/Model/PairedNodeCollection.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,24 @@ public PairedNodeCollection(TOwner owner, string property, int capacity)
9292
this.property = property;
9393
}
9494

95+
/// <summary>
96+
/// Initializes a new instance of the <see cref="PairedNodeCollection{TOwner,TNode}"/> class.
97+
/// </summary>
98+
/// <param name="owner">The collection owner.</param>
99+
/// <param name="property">Owner collection property.</param>
100+
/// <param name="capacity">The initial collection capacity.</param>
101+
/// <param name="equalityComparer">Comparer for inner name index.</param>
102+
public PairedNodeCollection(TOwner owner, string property, int capacity, IEqualityComparer<string> equalityComparer)
103+
: base(capacity, equalityComparer)
104+
{
105+
ArgumentValidator.EnsureArgumentNotNull(owner, nameof(owner));
106+
ArgumentValidator.EnsureArgumentNotNullOrEmpty(property, nameof(property));
107+
ArgumentValidator.EnsureArgumentNotNull(equalityComparer, nameof(equalityComparer));
108+
109+
this.owner = owner;
110+
this.property = property;
111+
}
112+
95113
#endregion
96114
}
97115
}

0 commit comments

Comments
 (0)