Skip to content

Commit e331fb6

Browse files
committed
PgSQL: Support for new TimeOnly(ticks)
1 parent 0adc93e commit e331fb6

3 files changed

Lines changed: 75 additions & 30 deletions

File tree

Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/v10_0/Compiler.cs

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,29 @@
44
// Created by: Alexey Kulakov
55
// Created: 2019.09.25
66

7+
using System;
8+
using System.Collections.Generic;
79
using Xtensive.Sql.Dml;
810

911
namespace Xtensive.Sql.Drivers.PostgreSql.v10_0
1012
{
1113
internal class Compiler : v9_1.Compiler
1214
{
13-
public override void Visit(SqlFunctionCall node)
14-
{
15-
var arguments = node.Arguments;
16-
switch (node.FunctionType) {
17-
case SqlFunctionType.DateTimeConstruct:
18-
Visit(MakeDateTime(arguments[0], arguments[1], arguments[2]));
19-
return;
15+
protected override SqlUserFunctionCall ConstructDateTime(IReadOnlyList<SqlExpression> arguments) => MakeDateTime(arguments[0], arguments[1], arguments[2]);
2016
#if NET6_0_OR_GREATER
21-
case SqlFunctionType.DateConstruct:
22-
Visit(MakeDate(arguments[0], arguments[1], arguments[2]));
23-
return;
24-
case SqlFunctionType.TimeConstruct:
25-
Visit(MakeTime(arguments[0], arguments[1], arguments[2], arguments[3]));
26-
return;
27-
#endif
28-
default:
29-
base.Visit(node);
30-
return;
17+
18+
protected override SqlUserFunctionCall ConstructDate(IReadOnlyList<SqlExpression> arguments) => MakeDate(arguments[0], arguments[1], arguments[2]);
19+
20+
protected override SqlExpression ConstructTime(IReadOnlyList<SqlExpression> arguments)
21+
{
22+
if (arguments.Count == 4) {
23+
return MakeTime(arguments[0], arguments[1], arguments[2], arguments[3]);
24+
}
25+
else {
26+
return base.ConstructTime(arguments);
3127
}
3228
}
29+
#endif
3330

3431
protected static SqlUserFunctionCall MakeDateTime(SqlExpression year, SqlExpression month, SqlExpression day) =>
3532
SqlDml.FunctionCall("MAKE_TIMESTAMP", year, month, day, SqlDml.Literal(0), SqlDml.Literal(0), SqlDml.Literal(0.0));

Orm/Xtensive.Orm.PostgreSql/Sql.Drivers.PostgreSql/v8_0/Compiler.cs

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the License.txt file in the project root for more information.
44

55
using System;
6+
using System.Collections.Generic;
67
using System.Linq;
78
using Xtensive.Orm.Providers.PostgreSql;
89
using Xtensive.Sql.Compiler;
@@ -125,24 +126,14 @@ public override void Visit(SqlFunctionCall node)
125126
SqlHelper.IntervalAbs(node.Arguments[0]).AcceptVisitor(this);
126127
return;
127128
case SqlFunctionType.DateTimeConstruct:
128-
var newNode = ReferenceDateTimeLiteral
129-
+ (OneYearInterval * (node.Arguments[0] - 2001))
130-
+ (OneMonthInterval * (node.Arguments[1] - 1))
131-
+ (OneDayInterval * (node.Arguments[2] - 1));
132-
newNode.AcceptVisitor(this);
129+
ConstructDateTime(node.Arguments).AcceptVisitor(this);
133130
return;
134131
#if NET6_0_OR_GREATER
135132
case SqlFunctionType.DateConstruct:
136-
(ReferenceDateLiteral
137-
+ (OneYearInterval * (node.Arguments[0] - 2001))
138-
+ (OneMonthInterval * (node.Arguments[1] - 1))
139-
+ (OneDayInterval * (node.Arguments[2] - 1))).AcceptVisitor(this);
133+
ConstructDate(node.Arguments).AcceptVisitor(this);
140134
return;
141135
case SqlFunctionType.TimeConstruct:
142-
((ZeroTimeLiteral
143-
+ (OneHourInterval * (node.Arguments[0]))
144-
+ (OneMinuteInterval * (node.Arguments[1]))
145-
+ (OneSecondInterval * (node.Arguments[2] + (SqlDml.Cast(node.Arguments[3], SqlType.Double) / 1000))))).AcceptVisitor(this);
136+
ConstructTime(node.Arguments).AcceptVisitor(this);
146137
return;
147138
#endif
148139
case SqlFunctionType.DateTimeTruncate:
@@ -397,6 +388,45 @@ public override void Visit(SqlExtract node)
397388
base.Visit(node);
398389
}
399390

391+
protected virtual SqlExpression ConstructDateTime(IReadOnlyList<SqlExpression> arguments)
392+
{
393+
return ReferenceDateTimeLiteral
394+
+ (OneYearInterval * (arguments[0] - 2001))
395+
+ (OneMonthInterval * (arguments[1] - 1))
396+
+ (OneDayInterval * (arguments[2] - 1));
397+
}
398+
#if NET6_0_OR_GREATER
399+
400+
protected virtual SqlExpression ConstructDate(IReadOnlyList<SqlExpression> arguments)
401+
{
402+
return ReferenceDateLiteral
403+
+ (OneYearInterval * (arguments[0] - 2001))
404+
+ (OneMonthInterval * (arguments[1] - 1))
405+
+ (OneDayInterval * (arguments[2] - 1));
406+
}
407+
408+
protected virtual SqlExpression ConstructTime(IReadOnlyList<SqlExpression> arguments)
409+
{
410+
if (arguments.Count == 4) {
411+
return ZeroTimeLiteral
412+
+ (OneHourInterval * (arguments[0]))
413+
+ (OneMinuteInterval * (arguments[1]))
414+
+ (OneSecondInterval * (arguments[2] + (SqlDml.Cast(arguments[3], SqlType.Double) / 1000)));
415+
}
416+
else if (arguments.Count == 1) {
417+
var ticks = arguments[0];
418+
if (SqlHelper.IsTimeSpanTicks(ticks, out var intervalExpr)) {
419+
return ZeroTimeLiteral + intervalExpr;
420+
}
421+
return ZeroTimeLiteral + (ticks / SqlDml.Literal(10000000.0) * OneSecondInterval);
422+
}
423+
else {
424+
throw new InvalidOperationException("Unsupported count of parameters");
425+
}
426+
427+
}
428+
#endif
429+
400430
protected SqlExpression DateTimeOffsetExtractDate(SqlExpression timestamp) =>
401431
SqlDml.FunctionCall("DATE", timestamp);
402432

@@ -518,6 +548,23 @@ private bool TryDivideOffsetIntoParts(SqlExpression offsetInMinutes, ref int hou
518548
return false;
519549
}
520550

551+
private bool IsTimeSpanTicks(SqlExpression expressionToCheck, out SqlExpression source)
552+
{
553+
source = null;
554+
555+
if (expressionToCheck is SqlCast sqlCast && sqlCast.Type.Type==SqlType.Int64) {
556+
var operand = sqlCast.Operand;
557+
if (operand is SqlBinary sqlBinary && sqlBinary.NodeType == SqlNodeType.Divide) {
558+
var left = sqlBinary.Left;
559+
if (left is SqlFunctionCall functionCall && functionCall.FunctionType == SqlFunctionType.IntervalToNanoseconds) {
560+
source = functionCall.Arguments[0];
561+
return true;
562+
}
563+
}
564+
}
565+
return false;
566+
}
567+
521568
// Constructors
522569

523570
protected internal Compiler(SqlDriver driver)

Orm/Xtensive.Orm/Orm/Providers/Expressions/MemberCompilers/TimeSpanCompilers.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ public static SqlExpression TimeSpanDays(SqlExpression _this)
163163
[Compiler(typeof(TimeSpan), "Ticks", TargetKind.PropertyGet)]
164164
public static SqlExpression TimeSpanTicks(SqlExpression _this)
165165
{
166+
// there are some operations that rely on this structure.
166167
return ExpressionTranslationHelpers.ToLong(SqlDml.IntervalToNanoseconds(_this) / NanosecondsPerTick);
167168
}
168169

0 commit comments

Comments
 (0)