Skip to content

Commit 5845d50

Browse files
committed
MySQL: Support for TimeOnly(ticks) ctor
1 parent 036959d commit 5845d50

2 files changed

Lines changed: 90 additions & 19 deletions

File tree

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

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
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
{
@@ -182,10 +183,7 @@ public override void Visit(SqlFunctionCall node)
182183
Visit(DateTimeAddYear(arguments[0], arguments[1]));
183184
return;
184185
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));
186+
ConstructDateTime(arguments).AcceptVisitor(this);
189187
return;
190188
#if NET6_0_OR_GREATER
191189
case SqlFunctionType.DateAddYears:
@@ -198,10 +196,7 @@ public override void Visit(SqlFunctionCall node)
198196
Visit(DateAddDay(arguments[0], arguments[1]));
199197
return;
200198
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));
199+
ConstructDate(arguments).AcceptVisitor(this);
205200
return;
206201
case SqlFunctionType.TimeAddHours:
207202
Visit(SqlDml.FunctionCall("TIME", SqlDml.FunctionCall(
@@ -220,11 +215,7 @@ public override void Visit(SqlFunctionCall node)
220215
SqlDml.Native("SECOND")))));
221216
return;
222217
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+
ConstructTime(arguments).AcceptVisitor(this);
228219
return;
229220
case SqlFunctionType.DateToString:
230221
Visit(DateToString(arguments[0]));
@@ -302,6 +293,17 @@ public override void Visit(SqlExtract node)
302293
base.Visit(node);
303294
}
304295

296+
protected virtual SqlExpression ConstructDateTime(IReadOnlyList<SqlExpression> arguments)
297+
{
298+
return DateTimeAddDay(
299+
DateTimeAddMonth(
300+
DateTimeAddYear(
301+
SqlDml.Literal(new DateTime(2001, 1, 1)),
302+
arguments[0] - 2001),
303+
arguments[1] - 1),
304+
arguments[2] - 1);
305+
}
306+
305307
protected virtual SqlExpression DateTimeSubtractDateTime(SqlExpression date1, SqlExpression date2)
306308
{
307309
return (CastToDecimal(DateDiffDay(date1, date2), 18, 0) * NanosecondsPerDay)
@@ -317,6 +319,48 @@ protected virtual SqlExpression DateTimeAddInterval(SqlExpression date, SqlExpre
317319
}
318320
#if NET6_0_OR_GREATER
319321

322+
protected virtual SqlExpression ConstructDate(IReadOnlyList<SqlExpression> arguments)
323+
{
324+
return DateAddDay(
325+
DateAddMonth(
326+
DateAddYear(
327+
SqlDml.Literal(new DateOnly(2001, 1, 1)),
328+
arguments[0] - 2001),
329+
arguments[1] - 1),
330+
arguments[2] - 1);
331+
}
332+
333+
protected virtual SqlExpression ConstructTime(IReadOnlyList<SqlExpression> arguments)
334+
{
335+
SqlExpression hour, minute, second, millisecond;
336+
if (arguments.Count == 4) {
337+
hour = arguments[0];
338+
minute = arguments[1];
339+
second = arguments[2];
340+
millisecond = arguments[3];
341+
}
342+
else if (arguments.Count == 1) {
343+
var ticks = arguments[0];
344+
hour = SqlDml.Cast(ticks / 36000000000, SqlType.Int32);
345+
minute = SqlDml.Cast((ticks / 600000000) % 60, SqlType.Int32);
346+
second = SqlDml.Cast((ticks / 10000000) % 60, SqlType.Int32);
347+
millisecond = 0; //SqlDml.Cast((ticks % 10000000) / 10, SqlType.Int32);
348+
}
349+
else {
350+
throw new InvalidOperationException("Unsupported count of parameters");
351+
}
352+
353+
return SqlDml.FunctionCall("TIME",
354+
TimeAddMillisecond(
355+
TimeAddSecond(
356+
TimeAddMinute(
357+
TimeAddHour(
358+
SqlDml.Literal(new DateTime(2001, 1, 1)),
359+
hour),
360+
minute),
361+
second),
362+
millisecond));
363+
}
320364
protected virtual SqlExpression TimeSubtractTime(SqlExpression time1, SqlExpression time2) =>
321365
SqlDml.Modulo(
322366
NanosecondsPerDay + CastToDecimal(SqlDml.FunctionCall("TIME_TO_SEC", time1) - SqlDml.FunctionCall("TIME_TO_SEC", time2), 18, 0) * NanosecondsPerSecond,

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

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// Created: 2013.12.30
66

77
using System;
8+
using System.Collections.Generic;
89
using Xtensive.Sql.Dml;
910

1011
namespace Xtensive.Sql.Drivers.MySql.v5_6
@@ -40,10 +41,6 @@ public override void Visit(SqlFunctionCall node)
4041
SqlDml.Cast(arguments[0], SqlType.DateTime),
4142
arguments[1] * 100))); // 100 = 0:01:00
4243
return;
43-
case SqlFunctionType.TimeConstruct: {
44-
Visit(MakeTime(arguments[0], arguments[1], arguments[2], arguments[3]));
45-
return;
46-
}
4744
case SqlFunctionType.TimeToDateTime:
4845
Visit(SqlDml.Cast(arguments[0], SqlType.DateTime));
4946
return;
@@ -53,18 +50,48 @@ public override void Visit(SqlFunctionCall node)
5350
}
5451
}
5552

56-
protected override SqlExpression TimeAddInterval(SqlExpression time, SqlExpression interval)
53+
protected override SqlUserFunctionCall TimeAddInterval(SqlExpression time, SqlExpression interval)
5754
{
5855
var timeAsDate = SqlDml.Cast(time, SqlType.DateTime);
5956
return DateTimeAddMicrosecond(timeAsDate,
6057
(interval / NanosecondsPerMillisecond * NanosecondsPerMicrosecond) % (MillisecondsPerDay * NanosecondsPerMicrosecond));
6158
}
6259

63-
protected override SqlExpression TimeSubtractTime(SqlExpression time1, SqlExpression time2) =>
60+
protected override SqlBinary TimeSubtractTime(SqlExpression time1, SqlExpression time2) =>
6461
SqlDml.Modulo(
6562
NanosecondsPerDay + CastToDecimal(DateTimeDiffMicrosecond(time2, time1), 18, 0) * NanosecondsPerMicrosecond,
6663
NanosecondsPerDay);
6764

65+
protected override SqlUserFunctionCall ConstructTime(IReadOnlyList<SqlExpression> arguments)
66+
{
67+
SqlExpression hour, minute, second, millisecond;
68+
if (arguments.Count == 4) {
69+
hour = arguments[0];
70+
minute = arguments[1];
71+
second = arguments[2];
72+
millisecond = arguments[3];
73+
}
74+
else if (arguments.Count == 1) {
75+
var ticks = arguments[0];
76+
if (SqlHelper.IsTimeSpanTicks(ticks, out var sourceInterval)) {
77+
hour = SqlDml.Cast(ticks / 36000000000, SqlType.Int32);
78+
minute = SqlDml.Cast((ticks / 600000000) % 60, SqlType.Int32);
79+
second = SqlDml.Cast((ticks / 10000000) % 60, SqlType.Int32);
80+
millisecond = SqlDml.Cast((ticks % 10000000) / 10, SqlType.Int32) / 1000;
81+
}
82+
else {
83+
hour = SqlDml.Cast(ticks / 36000000000, SqlType.Int32);
84+
minute = SqlDml.Cast((ticks / 600000000) % 60, SqlType.Int32);
85+
second = SqlDml.Cast((ticks / 10000000) % 60, SqlType.Int32);
86+
millisecond = SqlDml.Cast((ticks % 10000000) / 10, SqlType.Int32) / 1000;
87+
}
88+
}
89+
else {
90+
throw new InvalidOperationException("Unsupported count of parameters");
91+
}
92+
return MakeTime(hour, minute, second, millisecond);
93+
}
94+
6895
protected SqlUserFunctionCall MakeTime(
6996
SqlExpression hours, SqlExpression minutes, SqlExpression seconds, SqlExpression milliseconds) =>
7097
SqlDml.FunctionCall("MAKETIME", hours, minutes, seconds + (milliseconds / 1000));

0 commit comments

Comments
 (0)