Skip to content

Commit d3aba36

Browse files
committed
Merge branch '7.0'
# Conflicts: # Extensions/Xtensive.Orm.BulkOperations/Internals/BaseSqlVisitor.cs # Orm/Xtensive.Orm.Tests.Sql/SqlServer/ExtractorTest.cs # Version.props
2 parents 5c1df60 + 83abf4f commit d3aba36

38 files changed

+2261
-367
lines changed

ChangeLog/6.0.9_Z_Final.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
[main] Improved enum comparison in queries so result SQL queries won't break index seek if any exists
2+
[main] Improved enum comparison in partial indexes
3+
[main] Addressed certain issues with with async queries containing .Store() and .In() via temporary table
4+
[sqlserver] Fixed Full-text indexes extraction for Azure SQL provider
5+
[sqlserver] Correct extraction of custom sequences based on types other than BIGINT

ChangeLog/7.0.2.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[main] Addressed certain issues of enum equality expressions translation that appeared in v7.0.0
2+
[sqlserver] Replaced usage of DATEDIFF with DATEDIFF_BIG for v13 and newer
3+
[sqlserver] Improved certain operations based on DateTime/DateTimeOffset subtraction for v13 and newer

Extensions/Xtensive.Orm.BulkOperations/Internals/BaseSqlVisitor.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,6 @@ public virtual void Visit(SqlWhile node)
516516
VisitInternal(node.Statement);
517517
}
518518

519-
520519
public virtual void Visit(SqlFragment node)
521520
{
522521
VisitInternal(node.Expression);
@@ -526,6 +525,11 @@ public virtual void Visit(SqlComment node)
526525
{
527526
}
528527

528+
public virtual void Visit(SqlMetadata node)
529+
{
530+
VisitInternal(node.Expression);
531+
}
532+
529533
#region Non-public methods
530534

531535
private void VisitInternal(ISqlNode node)
@@ -539,4 +543,4 @@ private void VisitInternal(ISqlNode node)
539543

540544
#endregion
541545
}
542-
}
546+
}
Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,18 @@
1-
// Copyright (C) 2010-2020 Xtensive LLC.
1+
// Copyright (C) 2010-2021 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: Denis Krjuchkov
55
// Created: 2010.03.02
66

7-
using System.Threading;
8-
using System.Threading.Tasks;
9-
107
namespace Xtensive.Sql.Drivers.SqlServer.Azure
118
{
129
internal class Extractor : v12.Extractor
1310
{
14-
protected override void ExtractFulltextIndexes(ExtractionContext context)
15-
{
16-
}
17-
18-
protected override Task ExtractFulltextIndexesAsync(ExtractionContext context, CancellationToken token) => Task.CompletedTask;
19-
20-
2111
// Constructors
2212

2313
public Extractor(SqlDriver driver)
2414
: base(driver)
2515
{
2616
}
2717
}
28-
}
18+
}

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

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ namespace Xtensive.Sql.Drivers.SqlServer.v09
1818
{
1919
internal class Compiler : SqlCompiler
2020
{
21+
#region Date parts
22+
protected const string NanosecondPart = "NS";
23+
protected const string MillisecondPart = "MS";
24+
protected const string SecondPart = "SECOND";
25+
protected const string MinutePart = "MINUTE";
26+
protected const string HourPart = "HOUR";
27+
protected const string DayPart = "DAY";
28+
protected const string MonthPart = "MONTH";
29+
protected const string YearPart = "YEAR";
30+
protected const string WeekdayPart = "WEEKDAY";
31+
#endregion
32+
2133
protected static readonly long NanosecondsPerDay = TimeSpan.FromDays(1).Ticks*100;
2234
protected static readonly long NanosecondsPerSecond = 1000000000;
2335
protected static readonly long NanosecondsPerMillisecond = 1000000;
@@ -383,64 +395,64 @@ public override void Visit(SqlCreateIndex node, IndexColumn item)
383395

384396
#region Static helpers
385397

386-
private static SqlCast CastToLong(SqlExpression arg)
398+
protected static SqlCast CastToLong(SqlExpression arg)
387399
{
388400
return SqlDml.Cast(arg, SqlType.Int64);
389401
}
390402

391-
private static SqlCast CastToDecimal(SqlExpression arg, short precision, short scale)
403+
protected static SqlCast CastToDecimal(SqlExpression arg, short precision, short scale)
392404
{
393405
return SqlDml.Cast(arg, SqlType.Decimal, precision, scale);
394406
}
395407

396408
protected static SqlUserFunctionCall DatePartWeekDay(SqlExpression date)
397409
{
398-
return SqlDml.FunctionCall("DATEPART", SqlDml.Native("WEEKDAY"), date);
410+
return SqlDml.FunctionCall("DATEPART", SqlDml.Native(WeekdayPart), date);
399411
}
400412

401413
protected static SqlUserFunctionCall DateDiffDay(SqlExpression date1, SqlExpression date2)
402414
{
403-
return SqlDml.FunctionCall("DATEDIFF", SqlDml.Native("DAY"), date1, date2);
415+
return SqlDml.FunctionCall("DATEDIFF", SqlDml.Native(DayPart), date1, date2);
404416
}
405417

406418
protected static SqlUserFunctionCall DateDiffMillisecond(SqlExpression date1, SqlExpression date2)
407419
{
408-
return SqlDml.FunctionCall("DATEDIFF", SqlDml.Native("MS"), date1, date2);
420+
return SqlDml.FunctionCall("DATEDIFF", SqlDml.Native(MillisecondPart), date1, date2);
409421
}
410422

411423
protected static SqlUserFunctionCall DateAddYear(SqlExpression date, SqlExpression years)
412424
{
413-
return SqlDml.FunctionCall("DATEADD", SqlDml.Native("YEAR"),years, date);
425+
return SqlDml.FunctionCall("DATEADD", SqlDml.Native(YearPart),years, date);
414426
}
415427

416428
protected static SqlUserFunctionCall DateAddMonth(SqlExpression date, SqlExpression months)
417429
{
418-
return SqlDml.FunctionCall("DATEADD", SqlDml.Native("MONTH"), months, date);
430+
return SqlDml.FunctionCall("DATEADD", SqlDml.Native(MonthPart), months, date);
419431
}
420432

421433
protected static SqlUserFunctionCall DateAddDay(SqlExpression date, SqlExpression days)
422434
{
423-
return SqlDml.FunctionCall("DATEADD", SqlDml.Native("DAY"), days, date);
435+
return SqlDml.FunctionCall("DATEADD", SqlDml.Native(DayPart), days, date);
424436
}
425437

426438
protected static SqlUserFunctionCall DateAddHour(SqlExpression date, SqlExpression hours)
427439
{
428-
return SqlDml.FunctionCall("DATEADD", SqlDml.Native("HOUR"), hours, date);
440+
return SqlDml.FunctionCall("DATEADD", SqlDml.Native(HourPart), hours, date);
429441
}
430442

431443
protected static SqlUserFunctionCall DateAddMinute(SqlExpression date, SqlExpression minutes)
432444
{
433-
return SqlDml.FunctionCall("DATEADD", SqlDml.Native("MINUTE"), minutes, date);
445+
return SqlDml.FunctionCall("DATEADD", SqlDml.Native(MinutePart), minutes, date);
434446
}
435447

436448
protected static SqlUserFunctionCall DateAddSecond(SqlExpression date, SqlExpression seconds)
437449
{
438-
return SqlDml.FunctionCall("DATEADD", SqlDml.Native("SECOND"), seconds, date);
450+
return SqlDml.FunctionCall("DATEADD", SqlDml.Native(SecondPart), seconds, date);
439451
}
440452

441453
protected static SqlUserFunctionCall DateAddMillisecond(SqlExpression date, SqlExpression milliseconds)
442454
{
443-
return SqlDml.FunctionCall("DATEADD", SqlDml.Native("MS"), milliseconds, date);
455+
return SqlDml.FunctionCall("DATEADD", SqlDml.Native(MillisecondPart), milliseconds, date);
444456
}
445457

446458
protected static SqlUserFunctionCall DateTimeToStringIso(SqlExpression dateTime)

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

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,17 @@ namespace Xtensive.Sql.Drivers.SqlServer.v10
1111
{
1212
internal class Compiler : v09.Compiler
1313
{
14+
protected const string OffsetPart = "TZoffset";
1415
protected const string UtcTimeZone = "+00:00";
16+
protected const string ZeroTime = "'00:00:00.0000000'";
1517
protected const string SqlDateTypeName = "date";
1618
protected const string SqlDateTime2TypeName = "datetime2";
1719

1820
protected static SqlUserFunctionCall DateAddNanosecond(SqlExpression date, SqlExpression nanoseconds) =>
19-
SqlDml.FunctionCall("DATEADD", SqlDml.Native("NS"), nanoseconds, date);
21+
SqlDml.FunctionCall("DATEADD", SqlDml.Native(NanosecondPart), nanoseconds, date);
2022

2123
protected static SqlUserFunctionCall DateDiffNanosecond(SqlExpression date1, SqlExpression date2) =>
22-
SqlDml.FunctionCall("DATEDIFF", SqlDml.Native("NS"), date1, date2);
24+
SqlDml.FunctionCall("DATEDIFF", SqlDml.Native(NanosecondPart), date1, date2);
2325

2426
protected override SqlExpression DateTimeTruncate(SqlExpression date) =>
2527
SqlDml.Cast(
@@ -144,7 +146,7 @@ private static SqlExpression DateTimeOffsetPartOffset(SqlExpression dateTimeOffs
144146

145147
private static SqlExpression DateTimeOffsetTimeOfDay(SqlExpression dateTimeOffset) =>
146148
DateDiffMillisecond(
147-
SqlDml.Native("'00:00:00.0000000'"),
149+
SqlDml.Native(ZeroTime),
148150
SqlDml.Cast(dateTimeOffset, new SqlValueType("time")))
149151
* NanosecondsPerMillisecond;
150152

@@ -158,7 +160,7 @@ private static SqlExpression Switchoffset(SqlExpression dateTimeOffset, SqlExpre
158160
SqlDml.FunctionCall("SWITCHOFFSET", dateTimeOffset, offset);
159161

160162
private static SqlUserFunctionCall DateTimeOffsetTimeZoneInMinutes(SqlExpression date) =>
161-
SqlDml.FunctionCall("DATEPART", SqlDml.Native("TZoffset"), date);
163+
SqlDml.FunctionCall("DATEPART", SqlDml.Native(OffsetPart), date);
162164

163165
private static SqlExpression DateTimeOffsetToLocalTime(SqlExpression dateTimeOffset) =>
164166
Switchoffset(dateTimeOffset, DateTimeOffsetTimeZoneInMinutes(SqlDml.Native("SYSDATETIMEOFFSET()")));
@@ -170,7 +172,7 @@ private static SqlExpression DateTimeToDateTimeOffset(SqlExpression dateTime) =>
170172
SqlDml.FunctionCall("TODATETIMEOFFSET",
171173
dateTime,
172174
SqlDml.FunctionCall("DATEPART",
173-
SqlDml.Native("TZoffset"),
175+
SqlDml.Native(OffsetPart),
174176
SqlDml.Native("SYSDATETIMEOFFSET()")));
175177

176178
#endregion

Orm/Xtensive.Orm.SqlServer/Sql.Drivers.SqlServer/v11/Extractor.cs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// Created by: Denis Krjuchkov
55
// Created: 2012.04.05
66

7+
using System;
78
using System.Collections.Generic;
89
using System.Data.Common;
910
using System.Threading;
@@ -13,6 +14,8 @@ namespace Xtensive.Sql.Drivers.SqlServer.v11
1314
{
1415
internal class Extractor : v10.Extractor
1516
{
17+
private readonly Dictionary<int, Func<DbDataReader, int, long>> valueReaders;
18+
1619
protected override void ExtractCatalogContents(ExtractionContext context)
1720
{
1821
base.ExtractCatalogContents(context);
@@ -57,6 +60,7 @@ private string BuildExtractSequencesQuery(ExtractionContext context)
5760
SELECT
5861
schema_id,
5962
name,
63+
user_type_id,
6064
start_value,
6165
increment,
6266
minimum_value,
@@ -74,15 +78,22 @@ ORDER BY
7478

7579
private void ReadSequenceData(DbDataReader reader, ExtractionContext context)
7680
{
81+
7782
var currentSchema = context.SchemaIndex[reader.GetInt32(0)];
78-
var sequence = currentSchema.CreateSequence(reader.GetString(1));
83+
var sequenceName = reader.GetString(1);
84+
var sequence = currentSchema.CreateSequence(sequenceName);
7985
var descriptor = sequence.SequenceDescriptor;
80-
descriptor.StartValue = reader.GetInt64(2);
81-
descriptor.Increment = reader.GetInt64(3);
82-
descriptor.MinValue = reader.GetInt64(4);
83-
descriptor.MaxValue = reader.GetInt64(5);
84-
descriptor.IsCyclic = reader.GetBoolean(6);
85-
descriptor.LastValue = reader.GetInt64(7);
86+
87+
if (!valueReaders.TryGetValue(reader.GetInt32(2), out var valueReader)) {
88+
throw new ArgumentOutOfRangeException($"Type of sequence '{sequenceName}' is not supported.");
89+
}
90+
91+
descriptor.StartValue = valueReader(reader, 3);
92+
descriptor.Increment = valueReader(reader, 4);
93+
descriptor.MinValue = valueReader(reader, 5);
94+
descriptor.MaxValue = valueReader(reader, 6);
95+
descriptor.IsCyclic = reader.GetBoolean(7);
96+
descriptor.LastValue = valueReader(reader, 8);
8697
}
8798

8899

@@ -95,6 +106,11 @@ protected override void RegisterReplacements(ExtractionContext context)
95106
public Extractor(SqlDriver driver)
96107
: base(driver)
97108
{
109+
valueReaders = new Dictionary<int, Func<DbDataReader, int, long>>(4);
110+
valueReaders[48] = (DbDataReader reader, int index) => reader.GetByte(index);
111+
valueReaders[52] = (DbDataReader reader, int index) => reader.GetInt16(index);
112+
valueReaders[56] = (DbDataReader reader, int index) => reader.GetInt32(index);
113+
valueReaders[127] = (DbDataReader reader, int index) => reader.GetInt64(index);
98114
}
99115
}
100-
}
116+
}

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

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,85 @@
1-
// Copyright (C) 2018 Xtensive LLC.
2-
// All rights reserved.
3-
// For conditions of distribution and use, see license.
1+
// Copyright (C) 2018-2021 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: Alexey Kulakov
55
// Created: 2018.09.21
66

7+
using Xtensive.Sql.Dml;
8+
79
namespace Xtensive.Sql.Drivers.SqlServer.v13
810
{
911
internal class Compiler : v12.Compiler
1012
{
13+
protected const string MicrosecondPart = "MCS";
14+
protected const long NanosecondsPerMicrosecond = 1000;
15+
16+
/// <inheritdoc/>
17+
public override void Visit(SqlFunctionCall node)
18+
{
19+
switch (node.FunctionType) {
20+
case SqlFunctionType.DateTimeOffsetTimeOfDay:
21+
DateTimeOffsetTimeOfDay(node.Arguments[0]).AcceptVisitor(this);
22+
break;
23+
case SqlFunctionType.IntervalToMilliseconds: {
24+
if (node.Arguments[0] is SqlBinary binary
25+
&& (binary.NodeType == SqlNodeType.DateTimeMinusDateTime || binary.NodeType == SqlNodeType.DateTimeOffsetMinusDateTimeOffset)) {
26+
Visit(DateDiffBigMicrosecond(binary.Right, binary.Left) / CastToLong(1000));
27+
}
28+
else {
29+
base.Visit(node);
30+
}
31+
break;
32+
}
33+
case SqlFunctionType.IntervalToNanoseconds: {
34+
if (node.Arguments[0] is SqlBinary binary
35+
&& (binary.NodeType == SqlNodeType.DateTimeMinusDateTime || binary.NodeType == SqlNodeType.DateTimeOffsetMinusDateTimeOffset)) {
36+
// we have to use time consuming algorithm here because
37+
// DATEDIFF_BIG can throw arithmetic overflow on nanoseconds
38+
// so we should handle it by this big formula
39+
Visit(CastToLong(DateTimeSubtractDateTimeExpensive(binary.Right, binary.Left)));
40+
}
41+
else {
42+
base.Visit(node);
43+
}
44+
break;
45+
}
46+
default:
47+
base.Visit(node); break;
48+
}
49+
}
50+
51+
protected override SqlExpression DateTimeSubtractDateTime(SqlExpression date1, SqlExpression date2)
52+
{
53+
return CastToDecimal(DateDiffBigMicrosecond(date2, date1), 18, 0) * CastToLong(1000);
54+
}
55+
56+
private SqlExpression DateTimeSubtractDateTimeExpensive(SqlExpression date1, SqlExpression date2)
57+
{
58+
return CastToDecimal(DateDiffBigDay(date2, date1), 18, 0) * NanosecondsPerDay
59+
+ CastToDecimal(DateDiffBigMillisecond(DateAddDay(date2, DateDiffBigDay(date2, date1)), date1), 18, 0) * NanosecondsPerMillisecond;
60+
}
61+
62+
#region Static Helpers
63+
64+
protected static SqlExpression DateTimeOffsetTimeOfDay(SqlExpression dateTimeOffset) =>
65+
DateDiffBigNanosecond(
66+
SqlDml.Native(ZeroTime),
67+
SqlDml.Cast(dateTimeOffset, new SqlValueType("time")));
68+
69+
protected static SqlUserFunctionCall DateDiffBigNanosecond(SqlExpression date1, SqlExpression date2) =>
70+
SqlDml.FunctionCall("DATEDIFF_BIG", SqlDml.Native(NanosecondPart), date1, date2);
71+
72+
protected static SqlUserFunctionCall DateDiffBigMicrosecond(SqlExpression date1, SqlExpression date2) =>
73+
SqlDml.FunctionCall("DATEDIFF_BIG", SqlDml.Native(MicrosecondPart), date1, date2);
74+
75+
protected static SqlUserFunctionCall DateDiffBigMillisecond(SqlExpression date1, SqlExpression date2) =>
76+
SqlDml.FunctionCall("DATEDIFF_BIG", SqlDml.Native(MillisecondPart), date1, date2);
77+
78+
protected static SqlUserFunctionCall DateDiffBigDay(SqlExpression date1, SqlExpression date2) =>
79+
SqlDml.FunctionCall("DATEDIFF_BIG", SqlDml.Native(DayPart), date1, date2);
80+
81+
#endregion
82+
1183
public Compiler(SqlDriver driver)
1284
: base(driver)
1385
{

0 commit comments

Comments
 (0)