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: Malisa Ncube
@@ -23,7 +23,9 @@ internal class Compiler : SqlCompiler
2323 private static readonly int StartOffsetIndex = DateTimeOffsetExampleString . IndexOf ( '+' ) ;
2424
2525 private const long NanosecondsPerMillisecond = 1000000L ;
26- private const string DateFormat = "%Y-%m-%d 00:00:00.000" ;
26+ private const string DateWithZeroTimeFormat = "%Y-%m-%d 00:00:00.000" ;
27+ private const string DateFormat = "%Y-%m-%d" ;
28+ private const string TimeFormat = "%H:%M:%f" ;
2729 private const string DateTimeFormat = "%Y-%m-%d %H:%M:%f" ;
2830 private const string DateTimeIsoFormat = "%Y-%m-%dT%H:%M:%S" ;
2931 private const string DateTimeOffsetExampleString = "2001-02-03 04:05:06.789+02.45" ;
@@ -131,15 +133,16 @@ public override void Visit(SqlExtract node)
131133 /// <inheritdoc/>
132134 public override void Visit ( SqlFunctionCall node )
133135 {
136+ var arguments = node . Arguments ;
134137 switch ( node . FunctionType ) {
135138 case SqlFunctionType . CharLength :
136- ( SqlDml . FunctionCall ( "LENGTH" , node . Arguments ) / 2 ) . AcceptVisitor ( this ) ;
139+ ( SqlDml . FunctionCall ( "LENGTH" , arguments ) / 2 ) . AcceptVisitor ( this ) ;
137140 return ;
138141 case SqlFunctionType . PadLeft :
139142 case SqlFunctionType . PadRight :
140143 return ;
141144 case SqlFunctionType . Concat :
142- var nod = node . Arguments [ 0 ] ;
145+ var nod = arguments [ 0 ] ;
143146 return ;
144147 case SqlFunctionType . Round :
145148 // Round should always be called with 2 arguments
@@ -149,40 +152,54 @@ public override void Visit(SqlFunctionCall node)
149152 }
150153 break ;
151154 case SqlFunctionType . Truncate :
152- Visit ( CastToLong ( node . Arguments [ 0 ] ) ) ;
155+ Visit ( CastToLong ( arguments [ 0 ] ) ) ;
153156 return ;
154157 case SqlFunctionType . IntervalConstruct :
155- Visit ( CastToLong ( node . Arguments [ 0 ] ) ) ;
158+ Visit ( CastToLong ( arguments [ 0 ] ) ) ;
156159 return ;
157160 case SqlFunctionType . IntervalToNanoseconds :
158- Visit ( CastToLong ( node . Arguments [ 0 ] ) ) ;
161+ Visit ( CastToLong ( arguments [ 0 ] ) ) ;
159162 return ;
160163 case SqlFunctionType . IntervalToMilliseconds :
161- Visit ( CastToLong ( node . Arguments [ 0 ] / NanosecondsPerMillisecond ) ) ;
164+ Visit ( CastToLong ( arguments [ 0 ] / NanosecondsPerMillisecond ) ) ;
162165 return ;
163166 case SqlFunctionType . DateTimeAddMonths :
164- DateAddMonth ( node . Arguments [ 0 ] , node . Arguments [ 1 ] ) . AcceptVisitor ( this ) ;
167+ DateTimeAddMonth ( arguments [ 0 ] , arguments [ 1 ] ) . AcceptVisitor ( this ) ;
165168 return ;
166169 case SqlFunctionType . DateTimeAddYears :
167- DateAddYear ( node . Arguments [ 0 ] , node . Arguments [ 1 ] ) . AcceptVisitor ( this ) ;
170+ DateTimeAddYear ( arguments [ 0 ] , arguments [ 1 ] ) . AcceptVisitor ( this ) ;
168171 return ;
169172 case SqlFunctionType . DateTimeTruncate :
170- DateTimeTruncate ( node . Arguments [ 0 ] ) . AcceptVisitor ( this ) ;
173+ DateTimeTruncate ( arguments [ 0 ] ) . AcceptVisitor ( this ) ;
171174 return ;
172175 case SqlFunctionType . DateTimeConstruct :
173- DateAddDay ( DateAddMonth ( DateAddYear ( SqlDml . Literal ( new DateTime ( 2001 , 1 , 1 ) ) ,
174- node . Arguments [ 0 ] - 2001 ) ,
175- node . Arguments [ 1 ] - 1 ) ,
176- node . Arguments [ 2 ] - 1 ) . AcceptVisitor ( this ) ;
177- return ;
176+ DateTimeAddDay ( DateTimeAddMonth ( DateTimeAddYear ( SqlDml . Literal ( new DateTime ( 2001 , 1 , 1 ) ) ,
177+ arguments [ 0 ] - 2001 ) ,
178+ arguments [ 1 ] - 1 ) ,
179+ arguments [ 2 ] - 1 ) . AcceptVisitor ( this ) ;
180+ return ;
181+ #if NET6_0_OR_GREATER //DO_DATEONLY
182+ case SqlFunctionType . DateConstruct:
183+ DateAddDay( DateAddMonth ( DateAddYear ( SqlDml . Literal ( new DateOnly ( 2001 , 1 , 1 ) ) ,
184+ arguments [ 0 ] - 2001 ) ,
185+ arguments[ 1 ] - 1 ) ,
186+ arguments[ 2 ] - 1 ) . AcceptVisitor ( this ) ;
187+ return ;
188+ case SqlFunctionType . TimeConstruct:
189+ TimeAddSeconds( TimeAddMinutes ( TimeAddHours ( SqlDml . Literal ( new TimeOnly ( 0 , 0 , 0 , 0 ) ) ,
190+ arguments [ 0 ] ) ,
191+ arguments [ 1 ] ) ,
192+ arguments [ 2 ] , arguments [ 3 ] ) . AcceptVisitor( this ) ;
193+ return ;
194+ #endif
178195 case SqlFunctionType . DateTimeToStringIso :
179196 DateTimeToStringIso ( node . Arguments [ 0 ] ) . AcceptVisitor ( this ) ;
180197 return ;
181198 case SqlFunctionType . DateTimeOffsetAddMonths :
182- SqlDml . Concat ( DateAddMonth ( DateTimeOffsetExtractDateTimeAsString ( node . Arguments [ 0 ] ) , node . Arguments [ 1 ] ) , DateTimeOffsetExtractOffsetAsString ( node . Arguments [ 0 ] ) ) . AcceptVisitor ( this ) ;
199+ SqlDml . Concat ( DateTimeAddMonth ( DateTimeOffsetExtractDateTimeAsString ( node . Arguments [ 0 ] ) , node . Arguments [ 1 ] ) , DateTimeOffsetExtractOffsetAsString ( node . Arguments [ 0 ] ) ) . AcceptVisitor ( this ) ;
183200 return ;
184201 case SqlFunctionType . DateTimeOffsetAddYears :
185- SqlDml . Concat ( DateAddYear ( DateTimeOffsetExtractDateTimeAsString ( node . Arguments [ 0 ] ) , node . Arguments [ 1 ] ) , DateTimeOffsetExtractOffsetAsString ( node . Arguments [ 0 ] ) ) . AcceptVisitor ( this ) ;
202+ SqlDml . Concat ( DateTimeAddYear ( DateTimeOffsetExtractDateTimeAsString ( node . Arguments [ 0 ] ) , node . Arguments [ 1 ] ) , DateTimeOffsetExtractOffsetAsString ( node . Arguments [ 0 ] ) ) . AcceptVisitor ( this ) ;
186203 return ;
187204 case SqlFunctionType . DateTimeOffsetConstruct :
188205 SqlDml . Concat ( node . Arguments [ 0 ] , OffsetToOffsetAsString ( node . Arguments [ 1 ] ) ) . AcceptVisitor ( this ) ;
@@ -351,10 +368,10 @@ private void VisitDateTimeOffset(SqlExtract node)
351368 }
352369
353370 private static SqlExpression DateTimeAddInterval ( SqlExpression date , SqlExpression interval ) =>
354- DateAddSeconds ( date , interval / Convert . ToDouble ( NanosecondsPerSecond ) ) ;
371+ DateTimeAddSeconds ( date , interval / Convert . ToDouble ( NanosecondsPerSecond ) ) ;
355372
356373 private static SqlExpression DateTimeTruncate ( SqlExpression date ) =>
357- DateTime ( SqlDml . FunctionCall ( "STRFTIME" , DateFormat , date ) ) ;
374+ DateTime ( SqlDml . FunctionCall ( "STRFTIME" , DateWithZeroTimeFormat , date ) ) ;
358375
359376 private static SqlExpression DateTime ( SqlExpression date ) => SqlDml . FunctionCall ( "STRFTIME" , DateTimeFormat , date ) ;
360377
@@ -405,20 +422,38 @@ private static SqlExpression DateTimeOffsetToLocalDateTime(SqlExpression dateTim
405422 private static SqlExpression DateTimeToStringIso ( SqlExpression dateTime ) =>
406423 SqlDml . FunctionCall ( "STRFTIME" , DateTimeIsoFormat , dateTime ) ;
407424
408- private static SqlExpression DateAddYear ( SqlExpression date , SqlExpression years ) =>
425+ private static SqlExpression DateTimeAddYear ( SqlExpression date , SqlExpression years ) =>
409426 SqlDml . FunctionCall ( "STRFTIME" , DateTimeFormat , date , SqlDml . Concat ( years , " " , "YEARS" ) ) ;
410-
411427
412- private static SqlExpression DateAddMonth ( SqlExpression date , SqlExpression months ) =>
428+ private static SqlExpression DateTimeAddMonth ( SqlExpression date , SqlExpression months ) =>
413429 SqlDml . FunctionCall ( "STRFTIME" , DateTimeFormat , date , SqlDml . Concat ( months , " " , "MONTHS" ) ) ;
414430
415- private static SqlExpression DateAddDay ( SqlExpression date , SqlExpression days ) =>
431+ private static SqlExpression DateTimeAddDay ( SqlExpression date , SqlExpression days ) =>
416432 SqlDml . FunctionCall ( "STRFTIME" , DateTimeFormat , date , SqlDml . Concat ( days , " " , "DAYS" ) ) ;
417433
418-
419- private static SqlExpression DateAddSeconds ( SqlExpression date , SqlExpression seconds ) =>
434+ private static SqlExpression DateTimeAddSeconds ( SqlExpression date , SqlExpression seconds ) =>
420435 SqlDml . FunctionCall ( "STRFTIME" , DateTimeFormat , date , SqlDml . Concat ( seconds , " " , "SECONDS" ) ) ;
421436
437+ #if NET6_0_OR_GREATER // DO_DATEONLY
438+ private static SqlExpression DateAddYear ( SqlExpression date , SqlExpression years ) =>
439+ SqlDml . FunctionCall ( "STRFTIME" , DateFormat , date , SqlDml . Concat ( years , " " , "YEARS" ) ) ;
440+
441+ private static SqlExpression DateAddMonth ( SqlExpression date , SqlExpression months ) =>
442+ SqlDml . FunctionCall ( "STRFTIME" , DateFormat , date , SqlDml . Concat ( months , " " , "MONTHS" ) ) ;
443+
444+ private static SqlExpression DateAddDay ( SqlExpression date , SqlExpression days ) =>
445+ SqlDml . FunctionCall ( "STRFTIME" , DateFormat , date , SqlDml . Concat ( days , " " , "DAYS" ) ) ;
446+
447+ private static SqlExpression TimeAddHours ( SqlExpression date , SqlExpression seconds ) =>
448+ SqlDml . FunctionCall ( "STRFTIME" , TimeFormat , date , SqlDml . Concat ( seconds , " " , "HOURS" ) ) ;
449+
450+ private static SqlExpression TimeAddMinutes ( SqlExpression date , SqlExpression seconds ) =>
451+ SqlDml . FunctionCall ( "STRFTIME" , TimeFormat , date , SqlDml . Concat ( seconds , " " , "MINUTES" ) ) ;
452+
453+ private static SqlExpression TimeAddSeconds ( SqlExpression date , SqlExpression seconds , SqlExpression milliseconds ) =>
454+ SqlDml . FunctionCall ( "STRFTIME" , TimeFormat , date , SqlDml . Concat ( seconds , "." , milliseconds , " " , "SECONDS" ) ) ;
455+ #endif
456+
422457 private static SqlExpression DateGetMilliseconds ( SqlExpression date ) =>
423458 CastToLong ( SqlDml . FunctionCall ( "STRFTIME" , "%f" , date ) * MillisecondsPerSecond ) -
424459 CastToLong ( SqlDml . FunctionCall ( "STRFTIME" , "%S" , date ) * MillisecondsPerSecond ) ;
0 commit comments