Skip to content

Commit 6c9ba6f

Browse files
authored
Merge branch 'master' into upstream/covariantReturnTypes
2 parents 0e7900c + 65b45a2 commit 6c9ba6f

81 files changed

Lines changed: 2227 additions & 899 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ChangeLog/7.1.0-RC2-dev.txt

Lines changed: 0 additions & 1 deletion
This file was deleted.

ChangeLog/7.1.0-Z_Final.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[main] Added support for DefaultExpression within Linq queries
2+
[main] Support for TimeOnly ctors (time parts and ticks) in Linq, except for SQLite and MySQL providers
3+
[main] No Session.Activate() in ToTransactional extension, it affects EntitySet<T> enumeration.

ChangeLog/7.2.0-Beta-1-dev.txt

Whitespace-only changes.

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Collections.Generic;
12
using System.Linq.Expressions;
23
using Xtensive.Linq;
34
using Xtensive.Orm.Model;
@@ -14,9 +15,9 @@ internal class AddValueContext
1415
public LambdaExpression Lambda { get; set; }
1516
public SetStatement Statement { get; set; }
1617

17-
public FieldInfo Field { get; set; }
18+
public FieldInfo Field => Descriptor.Field;
1819

19-
public bool SubqueryExists { get; set; }
20+
public Dictionary<SqlColumn, SqlExpression> Values { get; set; }
2021

2122
public object EvalLambdaBody() =>
2223
Lambda.Body is ConstantExpression ce

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

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Collections.Generic;
1+
using System.Collections.Generic;
2+
using System.Linq;
23
using Xtensive.Sql;
34
using Xtensive.Sql.Ddl;
45
using Xtensive.Sql.Dml;
@@ -247,6 +248,10 @@ public virtual void Visit(SqlDropView node)
247248
{
248249
}
249250

251+
public virtual void Visit(SqlTruncateTable node)
252+
{
253+
}
254+
250255
public virtual void Visit(SqlDynamicFilter node)
251256
{
252257
foreach (SqlExpression expression in node.Expressions)
@@ -314,9 +319,12 @@ public virtual void Visit(SqlInsert node)
314319
{
315320
VisitInternal(node.From);
316321
VisitInternal(node.Into);
317-
foreach (var pair in node.Values) {
318-
VisitInternal(pair.Key);
319-
VisitInternal(pair.Value);
322+
323+
foreach(var row in node.ValueRows) {
324+
foreach(var columnvalue in row.Zip(node.ValueRows.Columns)) {
325+
VisitInternal(columnvalue.Second);
326+
VisitInternal(columnvalue.First);
327+
}
320328
}
321329
}
322330

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

Lines changed: 163 additions & 152 deletions
Large diffs are not rendered by default.

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

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System;
1+
using System;
2+
using System.Collections.Generic;
23
using Xtensive.Sql;
34
using Xtensive.Sql.Dml;
45

@@ -20,9 +21,9 @@ public override SqlTable Table
2021
get { return insert.Into; }
2122
}
2223

23-
public override void AddValue(SqlTableColumn column, SqlExpression value)
24+
public override void AddValues(Dictionary<SqlColumn, SqlExpression> values)
2425
{
25-
insert.Values.Add(column, value);
26+
insert.ValueRows.Add(values);
2627
}
2728
}
2829

@@ -42,30 +43,33 @@ public override SqlTable Table
4243
get { return update.Update; }
4344
}
4445

45-
public override void AddValue(SqlTableColumn column, SqlExpression value)
46+
public override void AddValues(Dictionary<SqlColumn, SqlExpression> values)
4647
{
47-
update.Values.Add(column, value);
48+
if (update.Values.Count!=0) {
49+
throw new InvalidOperationException("Update values have already been initialized");
50+
}
51+
foreach (var keyValue in values) {
52+
update.Values.Add((SqlTableColumn)keyValue.Key, keyValue.Value);
53+
}
4854
}
4955
}
5056

5157
#endregion
5258

5359
private SqlQueryStatement statement;
5460

55-
public static SetStatement Create(SqlQueryStatement statement)
61+
public static SetStatement Create(SqlUpdate updateStatement)
5662
{
57-
SetStatement result;
58-
if (statement is SqlUpdate)
59-
result = new Update();
60-
else if (statement is SqlInsert)
61-
result = new Insert();
62-
else
63-
throw new InvalidOperationException("Statement must be SqlUpdate or SqlInsert");
64-
result.statement = statement;
65-
return result;
63+
return new Update() { statement = updateStatement };
64+
}
65+
66+
public static SetStatement Create(SqlInsert insertStatement)
67+
{
68+
return new Insert() { statement = insertStatement };
6669
}
6770

6871
public abstract SqlTable Table { get; }
69-
public abstract void AddValue(SqlTableColumn column, SqlExpression value);
72+
73+
public abstract void AddValues(Dictionary<SqlColumn, SqlExpression> values);
7074
}
7175
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2020 Xtensive LLC.
1+
// Copyright (C) 2020-2023 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

@@ -16,7 +16,9 @@ internal static class WellKnownMembers
1616
public static readonly Type FuncOfTArgTResultType = typeof(Func<,>);
1717

1818
public static readonly Type IncludeAlgorithmType = typeof(IncludeAlgorithm);
19+
public static readonly Type QueryableType = typeof(Queryable);
1920
public static readonly Type QueryableExtensionsType = typeof(QueryableExtensions);
21+
2022
public const string InMethodName = nameof(QueryableExtensions.In);
2123

2224
public static readonly MethodInfo TranslateQueryMethod =

Orm/Xtensive.Orm.Firebird/Sql.Drivers.Firebird/v2_5/Compiler.cs

Lines changed: 82 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,20 @@
1010
using Xtensive.Sql.Ddl;
1111
using Xtensive.Sql.Dml;
1212
using Xtensive.Core;
13+
using System.Collections.Generic;
1314

1415
namespace Xtensive.Sql.Drivers.Firebird.v2_5
1516
{
1617
internal class Compiler : SqlCompiler
1718
{
18-
protected static readonly long NanosecondsPerDay = TimeSpan.FromDays(1).Ticks * 100;
19-
protected static readonly long NanosecondsPerSecond = 1000000000;
20-
protected static readonly long NanosecondsPerMillisecond = 1000000;
21-
protected static readonly long MillisecondsPerDay = (long) TimeSpan.FromDays(1).TotalMilliseconds;
22-
protected static readonly long MillisecondsPerSecond = 1000L;
19+
protected const long NanosecondsPerDay = 86400000000000;
20+
protected const long NanosecondsPerHour = 3600000000000;
21+
protected const long NanosecondsPerMinute = 60000000000;
22+
protected const long NanosecondsPerSecond = 1000000000;
23+
protected const long NanosecondsPerMillisecond = 1000000;
24+
protected const long MillisecondsPerDay = 86400000;
25+
protected const long MillisecondsPerSecond = 1000L;
26+
2327
private bool case_SqlDateTimePart_DayOfYear;
2428
private bool case_SqlDateTimePart_Second;
2529

@@ -228,10 +232,7 @@ public override void Visit(SqlFunctionCall node)
228232
Visit(DateAddYear(arguments[0], arguments[1]));
229233
return;
230234
case SqlFunctionType.DateTimeConstruct:
231-
Visit(DateAddDay(DateAddMonth(DateAddYear(SqlDml.Cast(SqlDml.Literal(new DateTime(2001, 1, 1)), SqlType.DateTime),
232-
arguments[0] - 2001),
233-
arguments[1] - 1),
234-
arguments[2] - 1));
235+
ConstructDateTime(arguments).AcceptVisitor(this);
235236
return;
236237
#if NET6_0_OR_GREATER
237238
case SqlFunctionType.DateAddYears:
@@ -244,10 +245,7 @@ public override void Visit(SqlFunctionCall node)
244245
Visit(DateAddDay(arguments[0], arguments[1]));
245246
return;
246247
case SqlFunctionType.DateConstruct:
247-
Visit(DateAddDay(DateAddMonth(DateAddYear(SqlDml.Cast(SqlDml.Literal(new DateOnly(2001, 1, 1)), SqlType.Date),
248-
arguments[0] - 2001),
249-
arguments[1] - 1),
250-
arguments[2] - 1));
248+
ConstructDate(arguments).AcceptVisitor(this);
251249
return;
252250
case SqlFunctionType.TimeAddHours:
253251
Visit(DateAddHour(node.Arguments[0], node.Arguments[1]));
@@ -256,11 +254,10 @@ public override void Visit(SqlFunctionCall node)
256254
Visit(DateAddMinute(node.Arguments[0], node.Arguments[1]));
257255
return;
258256
case SqlFunctionType.TimeConstruct:
259-
Visit(DateAddMillisecond(DateAddSecond(DateAddMinute(DateAddHour(SqlDml.Cast(SqlDml.Literal(new TimeOnly(0, 0, 0)), SqlType.Time),
260-
arguments[0]),
261-
arguments[1]),
262-
arguments[2]),
263-
arguments[3]));
257+
ConstructTime(arguments).AcceptVisitor(this);
258+
return;
259+
case SqlFunctionType.TimeToNanoseconds:
260+
TimeToNanoseconds(arguments[0]).AcceptVisitor(this);
264261
return;
265262
case SqlFunctionType.DateToString:
266263
Visit(DateToString(arguments[0]));
@@ -299,6 +296,73 @@ public override void Visit(SqlAlterSequence node)
299296
translator.Translate(context, node, NodeSection.Exit);
300297
}
301298

299+
protected virtual SqlExpression ConstructDateTime(IReadOnlyList<SqlExpression> arguments)
300+
{
301+
return DateAddDay(
302+
DateAddMonth(
303+
DateAddYear(
304+
SqlDml.Cast(SqlDml.Literal(new DateTime(2001, 1, 1)), SqlType.DateTime),
305+
arguments[0] - 2001),
306+
arguments[1] - 1),
307+
arguments[2] - 1);
308+
}
309+
#if NET6_0_OR_GREATER
310+
311+
protected virtual SqlExpression ConstructDate(IReadOnlyList<SqlExpression> arguments)
312+
{
313+
return DateAddDay(
314+
DateAddMonth(
315+
DateAddYear(
316+
SqlDml.Cast(SqlDml.Literal(new DateOnly(2001, 1, 1)), SqlType.Date),
317+
arguments[0] - 2001),
318+
arguments[1] - 1),
319+
arguments[2] - 1);
320+
}
321+
322+
protected virtual SqlExpression ConstructTime(IReadOnlyList<SqlExpression> arguments)
323+
{
324+
SqlExpression hour, minute, second, millisecond;
325+
if (arguments.Count == 4) {
326+
hour = arguments[0];
327+
minute = arguments[1];
328+
second = arguments[2];
329+
millisecond = arguments[3] * 10;
330+
}
331+
else if (arguments.Count == 1) {
332+
var ticks = arguments[0];
333+
// try to optimize and reduce calculations when TimeSpan.Ticks where used for TimeOnly(ticks) ctor
334+
ticks = SqlHelper.IsTimeSpanTicks(ticks, out var sourceInterval) ? sourceInterval / 100 : ticks;
335+
hour = SqlDml.Cast(ticks / 36000000000, SqlType.Int32);
336+
minute = SqlDml.Cast((ticks / 600000000) % 60, SqlType.Int32);
337+
second = SqlDml.Cast((ticks / 10000000) % 60, SqlType.Int32);
338+
millisecond = SqlDml.Cast((ticks % 10000000) / 1000, SqlType.Int32);
339+
}
340+
else {
341+
throw new InvalidOperationException("Unsupported count of parameters");
342+
}
343+
344+
// using string version of time allows to control hours overflow
345+
// we cannot add hours, minutes and other parts to 00:00:00.0000 time
346+
// because hours might step over 24 hours and start counting from 0.
347+
var hourString = SqlDml.Cast(hour, new SqlValueType(SqlType.VarChar, 3));
348+
var minuteString = SqlDml.Cast(minute, new SqlValueType(SqlType.VarChar, 2));
349+
var secondString = SqlDml.Cast(second, new SqlValueType(SqlType.VarChar, 2));
350+
var millisecondString = SqlDml.Cast(millisecond, new SqlValueType(SqlType.VarChar, 4));
351+
var composedTimeString = SqlDml.Concat(hourString, SqlDml.Literal(":"), minuteString, SqlDml.Literal(":"), secondString, SqlDml.Literal("."), millisecondString);
352+
return SqlDml.Cast(composedTimeString, SqlType.Time);
353+
}
354+
355+
protected virtual SqlExpression TimeToNanoseconds(SqlExpression time)
356+
{
357+
var nPerHour = SqlDml.Extract(SqlTimePart.Hour, time) * NanosecondsPerHour;
358+
var nPerMinute = SqlDml.Extract(SqlTimePart.Minute, time) * NanosecondsPerMinute;
359+
var nPerSecond = SqlDml.Extract(SqlTimePart.Second, time) * NanosecondsPerSecond;
360+
var nPerMillisecond = SqlDml.Extract(SqlTimePart.Millisecond, time) * NanosecondsPerMillisecond;
361+
362+
return nPerHour + nPerMinute + nPerSecond + nPerMillisecond;
363+
}
364+
#endif
365+
302366
#region Static helpers
303367

304368
protected static SqlExpression DateTimeSubtractDateTime(SqlExpression date1, SqlExpression date2)

Orm/Xtensive.Orm.MySql/Sql.Drivers.MySql/v5_0/Compiler.cs

Lines changed: 44 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,19 @@
1010
using Xtensive.Sql.Dml;
1111
using Xtensive.Sql.Model;
1212
using Xtensive.Core;
13+
using System.Collections.Generic;
1314

1415
namespace Xtensive.Sql.Drivers.MySql.v5_0
1516
{
1617
internal class Compiler : SqlCompiler
1718
{
18-
protected static readonly long NanosecondsPerDay = TimeSpan.FromDays(1).Ticks * 100;
19-
protected static readonly long NanosecondsPerSecond = 1000000000;
20-
protected static readonly long NanosecondsPerMillisecond = 1000000;
21-
protected static readonly long NanosecondsPerMicrosecond = 1000;
22-
protected static readonly long MillisecondsPerDay = (long) TimeSpan.FromDays(1).TotalMilliseconds;
23-
protected static readonly long MillisecondsPerSecond = 1000L;
19+
protected const long NanosecondsPerDay = 86400000000000;
20+
protected const long NanosecondsPerHour = 3600000000000;
21+
protected const long NanosecondsPerMinute = 60000000000;
22+
protected const long NanosecondsPerSecond = 1000000000;
23+
protected const long NanosecondsPerMillisecond = 1000000;
24+
protected const long NanosecondsPerMicrosecond = 1000;
25+
protected const long MillisecondsPerDay = 86400000;
2426

2527
/// <inheritdoc/>
2628
public override void Visit(SqlSelect node)
@@ -182,10 +184,7 @@ public override void Visit(SqlFunctionCall node)
182184
Visit(DateTimeAddYear(arguments[0], arguments[1]));
183185
return;
184186
case SqlFunctionType.DateTimeConstruct:
185-
Visit(DateTimeAddDay(DateTimeAddMonth(DateTimeAddYear(SqlDml.Literal(new DateTime(2001, 1, 1)),
186-
arguments[0] - 2001),
187-
arguments[1] - 1),
188-
arguments[2] - 1));
187+
ConstructDateTime(arguments).AcceptVisitor(this);
189188
return;
190189
#if NET6_0_OR_GREATER
191190
case SqlFunctionType.DateAddYears:
@@ -198,10 +197,7 @@ public override void Visit(SqlFunctionCall node)
198197
Visit(DateAddDay(arguments[0], arguments[1]));
199198
return;
200199
case SqlFunctionType.DateConstruct:
201-
Visit(DateAddDay(DateAddMonth(DateAddYear(SqlDml.Literal(new DateOnly(2001, 1, 1)),
202-
arguments[0] - 2001),
203-
arguments[1] - 1),
204-
arguments[2] - 1));
200+
ConstructDate(arguments).AcceptVisitor(this);
205201
return;
206202
case SqlFunctionType.TimeAddHours:
207203
Visit(SqlDml.FunctionCall("TIME", SqlDml.FunctionCall(
@@ -219,12 +215,8 @@ public override void Visit(SqlFunctionCall node)
219215
SqlDml.RawConcat(SqlDml.Native("INTERVAL "), SqlDml.FunctionCall("TIME_TO_SEC", arguments[0]) + arguments[1] * 60),
220216
SqlDml.Native("SECOND")))));
221217
return;
222-
case SqlFunctionType.TimeConstruct:
223-
Visit(SqlDml.FunctionCall("TIME", TimeAddMillisecond(TimeAddSecond(TimeAddMinute(TimeAddHour(SqlDml.Literal(new DateTime(2001, 1, 1)),
224-
arguments[0]),
225-
arguments[1]),
226-
arguments[2]),
227-
arguments[3])));
218+
case SqlFunctionType.TimeToNanoseconds:
219+
TimeToNanoseconds(arguments[0]).AcceptVisitor(this);
228220
return;
229221
case SqlFunctionType.DateToString:
230222
Visit(DateToString(arguments[0]));
@@ -302,6 +294,17 @@ public override void Visit(SqlExtract node)
302294
base.Visit(node);
303295
}
304296

297+
protected virtual SqlExpression ConstructDateTime(IReadOnlyList<SqlExpression> arguments)
298+
{
299+
return DateTimeAddDay(
300+
DateTimeAddMonth(
301+
DateTimeAddYear(
302+
SqlDml.Literal(new DateTime(2001, 1, 1)),
303+
arguments[0] - 2001),
304+
arguments[1] - 1),
305+
arguments[2] - 1);
306+
}
307+
305308
protected virtual SqlExpression DateTimeSubtractDateTime(SqlExpression date1, SqlExpression date2)
306309
{
307310
return (CastToDecimal(DateDiffDay(date1, date2), 18, 0) * NanosecondsPerDay)
@@ -317,6 +320,27 @@ protected virtual SqlExpression DateTimeAddInterval(SqlExpression date, SqlExpre
317320
}
318321
#if NET6_0_OR_GREATER
319322

323+
protected virtual SqlExpression ConstructDate(IReadOnlyList<SqlExpression> arguments)
324+
{
325+
return DateAddDay(
326+
DateAddMonth(
327+
DateAddYear(
328+
SqlDml.Literal(new DateOnly(2001, 1, 1)),
329+
arguments[0] - 2001),
330+
arguments[1] - 1),
331+
arguments[2] - 1);
332+
}
333+
334+
protected virtual SqlExpression TimeToNanoseconds(SqlExpression time)
335+
{
336+
var nPerHour = SqlDml.Extract(SqlTimePart.Hour, time) * NanosecondsPerHour;
337+
var nPerMinute = SqlDml.Extract(SqlTimePart.Minute, time) * NanosecondsPerMinute;
338+
var nPerSecond = SqlDml.Extract(SqlTimePart.Second, time) * NanosecondsPerSecond;
339+
var nPerMillisecond = SqlDml.Extract(SqlTimePart.Millisecond, time) * NanosecondsPerMillisecond;
340+
341+
return nPerHour + nPerMinute + nPerSecond + nPerMillisecond;
342+
}
343+
320344
protected virtual SqlExpression TimeSubtractTime(SqlExpression time1, SqlExpression time2) =>
321345
SqlDml.Modulo(
322346
NanosecondsPerDay + CastToDecimal(SqlDml.FunctionCall("TIME_TO_SEC", time1) - SqlDml.FunctionCall("TIME_TO_SEC", time2), 18, 0) * NanosecondsPerSecond,

0 commit comments

Comments
 (0)