Skip to content

Commit 4e8dfa7

Browse files
authored
Merge pull request #307 from DataObjects-NET/master-date-and-time-support
DateOnly/TimeOnly support
2 parents bb43189 + e19c329 commit 4e8dfa7

File tree

150 files changed

+8084
-2273
lines changed

Some content is hidden

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

150 files changed

+8084
-2273
lines changed

ChangeLog/7.1.0-RC-dev.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
[main] Add support for new .NET 6 DateOnly and TimeOnly types
12
[main] Updated BitFaster.Caching package reference to v2.0.0
23
[sqlserver] Updated Microsoft.Data.SqlClient package reference to v5.0.0

Extensions/TestCommon/TestCommon.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" />
1313
</ItemGroup>
1414
<ItemGroup Condition="'$(TargetFramework)'=='net6.0'">
15-
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
15+
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" />
1616
</ItemGroup>
1717
<ItemGroup>
1818
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.0.0" />

Extensions/Xtensive.Orm.Reprocessing/Xtensive.Orm.Reprocessing.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" />
1717
</ItemGroup>
1818
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0'">
19-
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
19+
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" />
2020
</ItemGroup>
2121
<ItemGroup>
2222
<None Include="Readme.txt" />

Extensions/Xtensive.Orm.Security/Xtensive.Orm.Security.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" />
1818
</ItemGroup>
1919
<ItemGroup Condition="'$(TargetFramework)'=='net6.0'">
20-
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
20+
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" />
2121
</ItemGroup>
2222
<ItemGroup>
2323
<ProjectReference Include="..\..\Orm\Xtensive.Orm\Xtensive.Orm.csproj" />

Extensions/Xtensive.Orm.Tracking/Xtensive.Orm.Tracking.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" />
1717
</ItemGroup>
1818
<ItemGroup Condition="'$(TargetFramework)'=='net6.0'">
19-
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
19+
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" />
2020
</ItemGroup>
2121
<ItemGroup>
2222
<ProjectReference Include="..\..\Orm\Xtensive.Orm\Xtensive.Orm.csproj" />

Extensions/Xtensive.Orm.Web/Xtensive.Orm.Web.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" />
2020
</ItemGroup>
2121
<ItemGroup Condition="'$(TargetFramework)'=='net6.0'">
22-
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
22+
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" />
2323
</ItemGroup>
2424
<ItemGroup>
2525
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />

Orm/Xtensive.Orm.Firebird/Sql.Drivers.Firebird/Constants.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,9 @@ internal static class Constants
1414

1515
// cannot use "FFF" cause it may lead to empty string for fractions part.
1616
public const string DateTimeFormatString = @"''\'yyyy\.MM\.dd HH\:mm\:ss\.fff\'''";
17+
#if NET6_0_OR_GREATER
18+
public const string DateFormatString = @"''\'yyyy\.MM\.dd\'''";
19+
public const string TimeFormatString = @"''\'HH\:mm\:ss\.ffff\'''";
20+
#endif
1721
}
1822
}

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

Lines changed: 130 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2011-2022 Xtensive LLC.
1+
// Copyright (C) 2011-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
// Created by: Csaba Beer
@@ -101,6 +101,31 @@ public override void Visit(SqlExtract node)
101101
Visit(CastToLong(node.Operand));
102102
return;
103103
}
104+
#if NET6_0_OR_GREATER
105+
if (((node.IsDatePart && node.DatePart == SqlDatePart.DayOfYear)
106+
|| (node.IsDateTimePart && node.DateTimePart == SqlDateTimePart.DayOfYear))) {
107+
if (!case_SqlDateTimePart_DayOfYear) {
108+
case_SqlDateTimePart_DayOfYear = true;
109+
Visit(SqlDml.Add(node, SqlDml.Literal(1)));
110+
case_SqlDateTimePart_DayOfYear = false;
111+
}
112+
else {
113+
base.Visit(node);
114+
}
115+
return;
116+
}
117+
else if (node.IsSecondExtraction) {
118+
if (!case_SqlDateTimePart_Second) {
119+
case_SqlDateTimePart_Second = true;
120+
Visit(SqlDml.Truncate(node));
121+
case_SqlDateTimePart_Second = false;
122+
}
123+
else {
124+
base.Visit(node);
125+
}
126+
return;
127+
}
128+
#else
104129
switch (node.DateTimePart) {
105130
case SqlDateTimePart.DayOfYear:
106131
if (!case_SqlDateTimePart_DayOfYear) {
@@ -123,6 +148,8 @@ public override void Visit(SqlExtract node)
123148
}
124149
return;
125150
}
151+
#endif
152+
126153
base.Visit(node);
127154
}
128155

@@ -149,6 +176,14 @@ public override void Visit(SqlBinary node)
149176
case SqlNodeType.DateTimeMinusDateTime:
150177
DateTimeSubtractDateTime(node.Left, node.Right).AcceptVisitor(this);
151178
return;
179+
#if NET6_0_OR_GREATER
180+
case SqlNodeType.TimePlusInterval:
181+
TimeAddInterval(node.Left, node.Right).AcceptVisitor(this);
182+
return;
183+
case SqlNodeType.TimeMinusTime:
184+
TimeSubtractTime(node.Left, node.Right).AcceptVisitor(this);
185+
return;
186+
#endif
152187
case SqlNodeType.Modulo:
153188
Visit(SqlDml.FunctionCall(translator.TranslateToString(SqlNodeType.Modulo), node.Left, node.Right));
154189
return;
@@ -170,34 +205,84 @@ public override void Visit(SqlBinary node)
170205
/// <inheritdoc/>
171206
public override void Visit(SqlFunctionCall node)
172207
{
208+
var arguments = node.Arguments;
209+
173210
switch (node.FunctionType) {
174211
case SqlFunctionType.Concat:
175-
Visit(SqlDml.Concat(node.Arguments.ToArray(node.Arguments.Count)));
212+
Visit(SqlDml.Concat(arguments.ToArray(node.Arguments.Count)));
176213
return;
177214
case SqlFunctionType.DateTimeTruncate:
178-
Visit(SqlDml.Cast(node.Arguments[0], new SqlValueType("Date")));
215+
Visit(SqlDml.Cast(arguments[0], new SqlValueType("Date")));
179216
return;
180217
case SqlFunctionType.IntervalToMilliseconds:
181-
Visit(CastToLong(node.Arguments[0]) / NanosecondsPerMillisecond);
218+
Visit(CastToLong(arguments[0]) / NanosecondsPerMillisecond);
182219
return;
183220
case SqlFunctionType.IntervalConstruct:
184221
case SqlFunctionType.IntervalToNanoseconds:
185-
Visit(CastToLong(node.Arguments[0]));
222+
Visit(CastToLong(arguments[0]));
186223
return;
187224
case SqlFunctionType.DateTimeAddMonths:
188-
Visit(DateAddMonth(node.Arguments[0], node.Arguments[1]));
225+
Visit(DateAddMonth(arguments[0], arguments[1]));
189226
return;
190227
case SqlFunctionType.DateTimeAddYears:
191-
Visit(DateAddYear(node.Arguments[0], node.Arguments[1]));
228+
Visit(DateAddYear(arguments[0], arguments[1]));
192229
return;
193230
case SqlFunctionType.DateTimeConstruct:
194231
Visit(DateAddDay(DateAddMonth(DateAddYear(SqlDml.Cast(SqlDml.Literal(new DateTime(2001, 1, 1)), SqlType.DateTime),
195-
node.Arguments[0] - 2001),
196-
node.Arguments[1] - 1),
197-
node.Arguments[2] - 1));
232+
arguments[0] - 2001),
233+
arguments[1] - 1),
234+
arguments[2] - 1));
235+
return;
236+
#if NET6_0_OR_GREATER
237+
case SqlFunctionType.DateAddYears:
238+
Visit(DateAddYear(arguments[0], arguments[1]));
239+
return;
240+
case SqlFunctionType.DateAddMonths:
241+
Visit(DateAddMonth(arguments[0], arguments[1]));
242+
return;
243+
case SqlFunctionType.DateAddDays:
244+
Visit(DateAddDay(arguments[0], arguments[1]));
245+
return;
246+
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));
251+
return;
252+
case SqlFunctionType.TimeAddHours:
253+
Visit(DateAddHour(node.Arguments[0], node.Arguments[1]));
254+
return;
255+
case SqlFunctionType.TimeAddMinutes:
256+
Visit(DateAddMinute(node.Arguments[0], node.Arguments[1]));
257+
return;
258+
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]));
198264
return;
265+
case SqlFunctionType.DateToString:
266+
Visit(DateToString(arguments[0]));
267+
return;
268+
case SqlFunctionType.TimeToString:
269+
Visit(TimeToString(arguments[0]));
270+
return;
271+
case SqlFunctionType.DateToDateTime:
272+
DateToDateTime(arguments[0]).AcceptVisitor(this);
273+
return;
274+
case SqlFunctionType.DateTimeToDate:
275+
DateTimeToDate(arguments[0]).AcceptVisitor(this);
276+
return;
277+
case SqlFunctionType.DateTimeToTime:
278+
DateTimeToTime(arguments[0]).AcceptVisitor(this);
279+
return;
280+
case SqlFunctionType.TimeToDateTime:
281+
TimeToDateTime(arguments[0]).AcceptVisitor(this);
282+
return;
283+
#endif
199284
case SqlFunctionType.DateTimeToStringIso:
200-
Visit(DateTimeToStringIso(node.Arguments[0]));
285+
Visit(DateTimeToStringIso(arguments[0]));
201286
return;
202287
}
203288

@@ -223,6 +308,15 @@ protected static SqlExpression DateTimeSubtractDateTime(SqlExpression date1, Sql
223308
(CastToLong(DateDiffMillisecond(DateAddDay(date2, DateDiffDay(date2, date1)), date1)) *
224309
NanosecondsPerMillisecond);
225310
}
311+
#if NET6_0_OR_GREATER
312+
313+
protected static SqlExpression TimeSubtractTime(SqlExpression time1, SqlExpression time2)
314+
{
315+
return SqlDml.Modulo(
316+
NanosecondsPerDay + CastToLong(DateDiffMillisecond(time2, time1)) * NanosecondsPerMillisecond,
317+
NanosecondsPerDay);
318+
}
319+
#endif
226320

227321
protected static SqlExpression DateTimeAddInterval(SqlExpression date, SqlExpression interval)
228322
{
@@ -231,6 +325,9 @@ protected static SqlExpression DateTimeAddInterval(SqlExpression date, SqlExpres
231325
(interval / NanosecondsPerMillisecond) % (MillisecondsPerDay));
232326
}
233327

328+
protected static SqlExpression TimeAddInterval(SqlExpression time, SqlExpression interval) =>
329+
DateAddMillisecond(time, (interval / NanosecondsPerMillisecond) % (MillisecondsPerDay));
330+
234331
protected static SqlCast CastToLong(SqlExpression arg) => SqlDml.Cast(arg, SqlType.Int64);
235332

236333
protected static SqlUserFunctionCall DateDiffDay(SqlExpression date1, SqlExpression date2) =>
@@ -271,6 +368,26 @@ protected static SqlUserFunctionCall BitXor(SqlExpression left, SqlExpression ri
271368

272369
protected static SqlUserFunctionCall BitNot(SqlExpression operand) =>
273370
SqlDml.FunctionCall("BIN_NOT", operand);
371+
#if NET6_0_OR_GREATER
372+
373+
protected static SqlExpression TimeToDateTime(SqlExpression time) =>
374+
SqlDml.Cast(time, SqlType.DateTime);
375+
376+
protected static SqlExpression DateTimeToTime(SqlExpression dateTime) =>
377+
SqlDml.Cast(dateTime, SqlType.Time);
378+
379+
protected static SqlExpression DateToDateTime(SqlExpression date) =>
380+
SqlDml.Cast(date, SqlType.DateTime);
381+
382+
protected static SqlExpression DateTimeToDate(SqlExpression dateTime) =>
383+
SqlDml.Cast(dateTime, SqlType.Date);
384+
385+
protected static SqlFunctionCall DateToString(SqlExpression date) =>
386+
SqlDml.Substring(date, 0, 10);
387+
388+
protected static SqlConcat TimeToString(SqlExpression time) =>
389+
SqlDml.Concat(SqlDml.Substring(time, 0, 12), SqlDml.Literal("0000"));
390+
#endif
274391

275392
protected static SqlConcat DateTimeToStringIso(SqlExpression dateTime)
276393
{
@@ -279,8 +396,8 @@ protected static SqlConcat DateTimeToStringIso(SqlExpression dateTime)
279396

280397
return SqlDml.Concat(date, SqlDml.Literal("T"), time);
281398
}
282-
283-
#endregion
399+
400+
#endregion
284401

285402
protected internal Compiler(SqlDriver driver)
286403
: base(driver)

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

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,7 @@ private static void ReadForeignKeyColumnData(DbDataReader reader, ref ForeignKey
490490
state.ReferencingTable = state.ReferencingSchema.Tables[reader.GetString(1).Trim()];
491491
state.ForeignKey = state.ReferencingTable.CreateForeignKey(reader.GetString(2).Trim());
492492
ReadConstraintProperties(state.ForeignKey, reader, 3, 4);
493-
ReadCascadeAction(state.ForeignKey, reader, 5);
493+
ReadCascadeAction(state.ForeignKey, reader, 5, 12);
494494
state.ReferencedTable = state.ReferencedSchema.Tables[reader.GetString(9).Trim()];
495495
state.ForeignKey.ReferencedTable = state.ReferencedTable;
496496
}
@@ -618,25 +618,25 @@ private static void ReadConstraintProperties(Constraint constraint,
618618
constraint.IsInitiallyDeferred = ReadStringOrNull(row, isInitiallyDeferredIndex) == "YES";
619619
}
620620

621-
private static void ReadCascadeAction(ForeignKey foreignKey, IDataRecord row, int deleteRuleIndex)
621+
private static void ReadCascadeAction(ForeignKey foreignKey, IDataRecord row, int deleteRuleIndex, int updateRuleIndex)
622622
{
623623
var deleteRule = ReadStringOrNull(row, deleteRuleIndex);
624-
switch (deleteRule) {
625-
case "CASCADE":
626-
foreignKey.OnDelete = ReferentialAction.Cascade;
627-
return;
628-
case "SET NULL":
629-
foreignKey.OnDelete = ReferentialAction.SetNull;
630-
return;
631-
case "NO ACTION":
632-
foreignKey.OnDelete = ReferentialAction.NoAction;
633-
return;
634-
case "RESTRICT": // behaves like NO ACTION
635-
foreignKey.OnDelete = ReferentialAction.NoAction;
636-
return;
637-
case "SET DEFAULT":
638-
foreignKey.OnDelete = ReferentialAction.SetDefault;
639-
return;
624+
foreignKey.OnDelete = GetRefAction(deleteRule);
625+
626+
var updateRule = ReadStringOrNull(row, updateRuleIndex);
627+
foreignKey.OnUpdate = GetRefAction(updateRule);
628+
629+
630+
static ReferentialAction GetRefAction(in string rawActionName)
631+
{
632+
return rawActionName switch {
633+
"CASCADE" => ReferentialAction.Cascade,
634+
"SET NULL" => ReferentialAction.SetNull,
635+
"NO ACTION" => ReferentialAction.NoAction,
636+
"RESTRICT" => ReferentialAction.NoAction,
637+
"SET DEFAULT" => ReferentialAction.SetDefault,
638+
_ => throw new ArgumentOutOfRangeException()
639+
};
640640
}
641641
}
642642

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,11 @@ public override DataTypeCollection GetDataTypesInfo()
237237

238238
dtc.DateTime = DataTypeInfo.Range(SqlType.DateTime, commonFeatures,
239239
ValueRange.DateTime, "timestamp");
240+
#if NET6_0_OR_GREATER
241+
242+
dtc.DateOnly = DataTypeInfo.Range(SqlType.Date, commonFeatures, ValueRange.DateOnly, "date");
243+
dtc.TimeOnly = DataTypeInfo.Range(SqlType.Time, commonFeatures, ValueRange.TimeOnly, "time");
244+
#endif
240245

241246
dtc.Char = DataTypeInfo.Stream(SqlType.Char, commonFeatures, MaxCharLength, "char");
242247
dtc.VarChar = DataTypeInfo.Stream(SqlType.VarChar, commonFeatures, MaxCharLength, "varchar");

0 commit comments

Comments
 (0)