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
@@ -94,6 +94,14 @@ public override void Visit(SqlBinary node)
9494 case SqlNodeType . DateTimeMinusInterval :
9595 DateTimeAddInterval ( node . Left , - node . Right ) . AcceptVisitor ( this ) ;
9696 return ;
97+ #if NET6_0_OR_GREATER //DO_DATEONLY
98+ case SqlNodeType . TimePlusInterval:
99+ TimeAddInterval( node . Left , node . Right ) . AcceptVisitor ( this ) ;
100+ return ;
101+ case SqlNodeType . TimeMinusTime:
102+ TimeSubtractTime( node . Left , node . Right ) . AcceptVisitor ( this ) ;
103+ return ;
104+ #endif
97105 default :
98106 base . Visit ( node ) ;
99107 return ;
@@ -137,13 +145,14 @@ public override void Visit(SqlQueryExpression node)
137145 /// <inheritdoc/>
138146 public override void Visit ( SqlFunctionCall node )
139147 {
148+ var arguments = node . Arguments ;
149+
140150 switch ( node . FunctionType ) {
141151 case SqlFunctionType . Truncate :
142- var argument = node . Arguments [ 0 ] ;
143- SqlDml . FunctionCall ( "TRUNCATE" , argument , SqlDml . Literal ( 0 ) ) . AcceptVisitor ( this ) ;
152+ SqlDml . FunctionCall ( "TRUNCATE" , arguments [ 0 ] , SqlDml . Literal ( 0 ) ) . AcceptVisitor ( this ) ;
144153 return ;
145154 case SqlFunctionType . Concat :
146- Visit ( SqlDml . Concat ( node . Arguments . ToArray ( node . Arguments . Count ) ) ) ;
155+ Visit ( SqlDml . Concat ( arguments . ToArray ( node . Arguments . Count ) ) ) ;
147156 return ;
148157 case SqlFunctionType . CharLength :
149158 SqlDml . FunctionCall ( translator . TranslateToString ( SqlFunctionType . CharLength ) , node . Arguments [ 0 ] ) . AcceptVisitor ( this ) ;
@@ -157,44 +166,75 @@ public override void Visit(SqlFunctionCall node)
157166 SqlDml . FunctionCall ( translator . TranslateToString ( SqlFunctionType . Rand ) ) . AcceptVisitor ( this ) ;
158167 return ;
159168 case SqlFunctionType . Square :
160- SqlDml . Power ( node . Arguments [ 0 ] , 2 ) . AcceptVisitor ( this ) ;
169+ SqlDml . Power ( arguments [ 0 ] , 2 ) . AcceptVisitor ( this ) ;
161170 return ;
162171 case SqlFunctionType . IntervalToMilliseconds :
163- Visit ( CastToLong ( node . Arguments [ 0 ] ) / NanosecondsPerMillisecond ) ;
172+ Visit ( CastToLong ( arguments [ 0 ] ) / NanosecondsPerMillisecond ) ;
164173 return ;
165174 case SqlFunctionType . IntervalConstruct :
166175 case SqlFunctionType . IntervalToNanoseconds :
167- Visit ( CastToLong ( node . Arguments [ 0 ] ) ) ;
176+ Visit ( CastToLong ( arguments [ 0 ] ) ) ;
168177 return ;
169178 case SqlFunctionType . DateTimeAddMonths :
170- Visit ( DateTimeAddMonth ( node . Arguments [ 0 ] , node . Arguments [ 1 ] ) ) ;
179+ Visit ( DateTimeAddMonth ( arguments [ 0 ] , arguments [ 1 ] ) ) ;
171180 return ;
172181 case SqlFunctionType . DateTimeAddYears :
173- Visit ( DateTimeAddYear ( node . Arguments [ 0 ] , node . Arguments [ 1 ] ) ) ;
182+ Visit ( DateTimeAddYear ( arguments [ 0 ] , arguments [ 1 ] ) ) ;
174183 return ;
175184 case SqlFunctionType . DateTimeConstruct :
176185 Visit ( DateTimeAddDay ( DateTimeAddMonth ( DateTimeAddYear ( SqlDml . Literal ( new DateTime ( 2001 , 1 , 1 ) ) ,
177- node . Arguments [ 0 ] - 2001 ) ,
178- node . Arguments [ 1 ] - 1 ) ,
179- node . Arguments [ 2 ] - 1 ) ) ;
186+ arguments [ 0 ] - 2001 ) ,
187+ arguments [ 1 ] - 1 ) ,
188+ arguments [ 2 ] - 1 ) ) ;
180189 return ;
181190#if NET6_0_OR_GREATER //DO_DATEONLY
191+ case SqlFunctionType . DateAddYears:
192+ Visit( DateAddYear ( arguments [ 0 ] , arguments [ 1 ] ) ) ;
193+ return ;
194+ case SqlFunctionType . DateAddMonths:
195+ Visit( DateAddMonth ( arguments [ 0 ] , arguments [ 1 ] ) ) ;
196+ return ;
197+ case SqlFunctionType . DateAddDays:
198+ Visit( DateAddDay ( arguments [ 0 ] , arguments [ 1 ] ) ) ;
199+ return ;
182200 case SqlFunctionType . DateConstruct:
183201 Visit( DateAddDay ( DateAddMonth ( DateAddYear ( SqlDml . Literal ( new DateOnly ( 2001 , 1 , 1 ) ) ,
184- node . Arguments[ 0 ] - 2001 ) ,
185- node. Arguments [ 1 ] - 1 ) ,
186- node. Arguments [ 2 ] - 1 ) ) ;
202+ arguments [ 0 ] - 2001 ) ,
203+ arguments[ 1 ] - 1 ) ,
204+ arguments[ 2 ] - 1 ) ) ;
205+ return ;
206+ case SqlFunctionType . TimeAddHours:
207+ Visit( SqlDml . FunctionCall ( "TIME" , SqlDml . FunctionCall (
208+ "DATE_ADD" ,
209+ SqlDml . Literal ( new DateTime ( 2001 , 1 , 1 ) ) ,
210+ SqlDml . RawConcat (
211+ SqlDml . RawConcat ( SqlDml . Native ( "INTERVAL " ) , SqlDml . FunctionCall ( "TIME_TO_SEC" , arguments [ 0 ] ) + arguments [ 1 ] * 3600 ) ,
212+ SqlDml . Native ( "SECOND" ) ) ) ) ) ;
213+ return ;
214+ case SqlFunctionType . TimeAddMinutes:
215+ Visit( SqlDml . FunctionCall ( "TIME ",
216+ SqlDml . FunctionCall ( "DATE_ADD ",
217+ SqlDml . Literal ( new DateTime ( 2001 , 1 , 1 ) ) ,
218+ SqlDml . RawConcat (
219+ SqlDml . RawConcat ( SqlDml . Native ( "INTERVAL "), SqlDml.FunctionCall(" TIME_TO_SEC", arguments [ 0 ] ) + arguments [ 1 ] * 60 ) ,
220+ SqlDml. Native ( "SECOND" ) ) ) ) ) ;
187221 return ;
188222 case SqlFunctionType . TimeConstruct:
189223 Visit( SqlDml . FunctionCall ( "TIME" , TimeAddMillisecond ( TimeAddSecond ( TimeAddMinute ( TimeAddHour ( SqlDml . Literal ( new DateTime ( 2001 , 1 , 1 ) ) ,
190- node . Arguments [ 0 ] ) ,
191- node . Arguments [ 1 ] ) ,
192- node . Arguments [ 2 ] ) ,
193- node . Arguments [ 3 ] ) ) ) ;
224+ arguments [ 0 ] ) ,
225+ arguments [ 1 ] ) ,
226+ arguments [ 2 ] ) ,
227+ arguments [ 3 ] ) ) ) ;
228+ return ;
229+ case SqlFunctionType . DateToString:
230+ Visit( DateToString ( arguments [ 0 ] ) ) ;
231+ return ;
232+ case SqlFunctionType . TimeToString:
233+ Visit( TimeToString ( arguments [ 0 ] ) ) ;
194234 return ;
195235#endif
196236 case SqlFunctionType . DateTimeToStringIso :
197- Visit ( DateTimeToStringIso ( node . Arguments [ 0 ] ) ) ;
237+ Visit ( DateTimeToStringIso ( arguments [ 0 ] ) ) ;
198238 return ;
199239 }
200240
@@ -204,7 +244,7 @@ public override void Visit(SqlFunctionCall node)
204244#if NET6_0_OR_GREATER //DO_DATEONLY
205245 public override void Visit ( SqlPlaceholder node )
206246 {
207- if ( node . Id is Xtensive . Orm . Providers . QueryParameterBinding qpb && qpb . TypeMapping . Type == typeof ( TimeOnly ) ) {
247+ if ( node . Id is Xtensive . Orm . Providers . QueryParameterBinding qpb && qpb . TypeMapping . Type == typeof ( TimeOnly ) ) {
208248 _ = context . Output . Append ( "TIME(" ) ;
209249 base . Visit ( node ) ;
210250 _ = context . Output . Append ( ")" ) ;
@@ -263,51 +303,81 @@ protected virtual SqlExpression DateTimeAddInterval(SqlExpression date, SqlExpre
263303 ( interval / NanosecondsPerMillisecond * NanosecondsPerMicrosecond ) % ( MillisecondsPerDay * NanosecondsPerMicrosecond ) ) ;
264304 }
265305
306+ #if NET6_0_OR_GREATER //DO_DATEONLY
307+ protected virtual SqlExpression TimeSubtractTime ( SqlExpression time1 , SqlExpression time2 ) =>
308+ SqlDml . Modulo (
309+ NanosecondsPerDay + CastToDecimal ( SqlDml . FunctionCall ( "TIME_TO_SEC" , time1 ) - SqlDml . FunctionCall ( "TIME_TO_SEC" , time2 ) , 18 , 0 ) * NanosecondsPerSecond ,
310+ NanosecondsPerDay ) ;
311+
312+ protected virtual SqlExpression TimeAddInterval ( SqlExpression time , SqlExpression interval ) =>
313+
314+ SqlDml . FunctionCall ( "TIME" ,
315+ SqlDml . FunctionCall (
316+ "DATE_ADD" ,
317+ SqlDml . Literal ( new DateTime ( 2001 , 1 , 1 ) ) ,
318+ SqlDml . RawConcat (
319+ SqlDml . RawConcat ( SqlDml . Native ( "INTERVAL " ) ,
320+ SqlDml . FunctionCall ( "TIME_TO_SEC" , time ) + interval / NanosecondsPerSecond ) ,
321+ SqlDml . Native ( "SECOND" ) ) ) ) ;
322+ #endif
323+
266324 #region Static helpers
267325
268- private static SqlCast CastToLong ( SqlExpression arg ) => SqlDml . Cast ( arg , SqlType . Int64 ) ;
326+ protected static SqlCast CastToLong ( SqlExpression arg ) => SqlDml . Cast ( arg , SqlType . Int64 ) ;
269327
270- private static SqlCast CastToDecimal ( SqlExpression arg , short precision , short scale ) =>
328+ protected static SqlCast CastToDecimal ( SqlExpression arg , short precision , short scale ) =>
271329 SqlDml . Cast ( arg , SqlType . Decimal , precision , scale ) ;
272330
273- private static SqlUserFunctionCall DateDiffDay ( SqlExpression date1 , SqlExpression date2 ) =>
331+ protected static SqlUserFunctionCall DateDiffDay ( SqlExpression date1 , SqlExpression date2 ) =>
274332 SqlDml . FunctionCall ( "DATEDIFF" , date1 , date2 ) ;
275333
276- private static SqlUserFunctionCall DateTimeDiffMicrosecond ( SqlExpression datetime1 , SqlExpression datetime2 ) =>
334+ protected static SqlUserFunctionCall DateTimeDiffMicrosecond ( SqlExpression datetime1 , SqlExpression datetime2 ) =>
277335 SqlDml . FunctionCall ( "TIMESTAMPDIFF" , SqlDml . Native ( "MICROSECOND" ) , datetime1 , datetime2 ) ;
278336
279- private static SqlUserFunctionCall DateTimeAddYear ( SqlExpression datetime , SqlExpression years ) =>
337+ protected static SqlUserFunctionCall DateTimeDiffSecond ( SqlExpression datetime1 , SqlExpression datetime2 ) =>
338+ SqlDml . FunctionCall ( "TIMESTAMPDIFF" , SqlDml . Native ( "SECOND" ) , datetime1 , datetime2 ) ;
339+
340+ protected static SqlUserFunctionCall DateTimeAddYear ( SqlExpression datetime , SqlExpression years ) =>
280341 SqlDml . FunctionCall ( "TIMESTAMPADD" , SqlDml . Native ( "YEAR" ) , years , datetime ) ;
281342
282- private static SqlUserFunctionCall DateTimeAddMonth ( SqlExpression datetime , SqlExpression months ) =>
343+ protected static SqlUserFunctionCall DateTimeAddMonth ( SqlExpression datetime , SqlExpression months ) =>
283344 SqlDml . FunctionCall ( "TIMESTAMPADD" , SqlDml . Native ( "MONTH" ) , months , datetime ) ;
284345
285- private static SqlUserFunctionCall DateTimeAddDay ( SqlExpression datetime , SqlExpression days ) =>
346+ protected static SqlUserFunctionCall DateTimeAddDay ( SqlExpression datetime , SqlExpression days ) =>
286347 SqlDml . FunctionCall ( "TIMESTAMPADD" , SqlDml . Native ( "DAY" ) , days , datetime ) ;
287348
288- private static SqlUserFunctionCall DateTimeAddMicrosecond ( SqlExpression datetime , SqlExpression microseconds ) =>
349+ protected static SqlUserFunctionCall DateTimeAddHour ( SqlExpression datetime , SqlExpression days ) =>
350+ SqlDml . FunctionCall ( "TIMESTAMPADD" , SqlDml . Native ( "HOUR" ) , days , datetime ) ;
351+
352+ protected static SqlUserFunctionCall DateTimeAddMicrosecond ( SqlExpression datetime , SqlExpression microseconds ) =>
289353 SqlDml . FunctionCall ( "TIMESTAMPADD" , SqlDml . Native ( "MICROSECOND" ) , microseconds , datetime ) ;
290354
291355#if NET6_0_OR_GREATER //DO_DATEONLY
292- private static SqlUserFunctionCall DateAddYear ( SqlExpression date , SqlExpression years ) =>
356+ protected static SqlUserFunctionCall DateAddYear ( SqlExpression date , SqlExpression years ) =>
293357 SqlDml . FunctionCall ( "DATE_ADD" , date , SqlDml . RawConcat ( SqlDml . Native ( "INTERVAL " ) , SqlDml . RawConcat ( years , SqlDml . Native ( "YEAR" ) ) ) ) ;
294358
295- private static SqlUserFunctionCall DateAddMonth ( SqlExpression date , SqlExpression months ) =>
359+ protected static SqlUserFunctionCall DateAddMonth ( SqlExpression date , SqlExpression months ) =>
296360 SqlDml . FunctionCall ( "DATE_ADD" , date , SqlDml . RawConcat ( SqlDml . Native ( "INTERVAL " ) , SqlDml . RawConcat ( months , SqlDml . Native ( "MONTH" ) ) ) ) ;
297- private static SqlUserFunctionCall DateAddDay ( SqlExpression date , SqlExpression days ) =>
361+ protected static SqlUserFunctionCall DateAddDay ( SqlExpression date , SqlExpression days ) =>
298362 SqlDml . FunctionCall ( "DATE_ADD" , date , SqlDml . RawConcat ( SqlDml . Native ( "INTERVAL " ) , SqlDml . RawConcat ( days , SqlDml . Native ( "DAY" ) ) ) ) ;
299363
300- private static SqlUserFunctionCall TimeAddHour ( SqlExpression time , SqlExpression hours ) =>
364+ protected static SqlUserFunctionCall TimeAddHour ( SqlExpression time , SqlExpression hours ) =>
301365 SqlDml . FunctionCall ( "DATE_ADD" , time , SqlDml . RawConcat ( SqlDml . Native ( "INTERVAL " ) , SqlDml . RawConcat ( hours , SqlDml . Native ( "HOUR" ) ) ) ) ;
302366
303- private static SqlUserFunctionCall TimeAddMinute ( SqlExpression time , SqlExpression minutes ) =>
367+ protected static SqlUserFunctionCall TimeAddMinute ( SqlExpression time , SqlExpression minutes ) =>
304368 SqlDml . FunctionCall ( "DATE_ADD" , time , SqlDml . RawConcat ( SqlDml . Native ( "INTERVAL " ) , SqlDml . RawConcat ( minutes , SqlDml . Native ( "MINUTE" ) ) ) ) ;
305369
306- private static SqlUserFunctionCall TimeAddSecond ( SqlExpression time , SqlExpression seconds ) =>
370+ protected static SqlUserFunctionCall TimeAddSecond ( SqlExpression time , SqlExpression seconds ) =>
307371 SqlDml . FunctionCall ( "DATE_ADD" , time , SqlDml . RawConcat ( SqlDml . Native ( "INTERVAL " ) , SqlDml . RawConcat ( seconds , SqlDml . Native ( "SECOND" ) ) ) ) ;
308372
309- private static SqlUserFunctionCall TimeAddMillisecond ( SqlExpression time , SqlExpression millisecond ) =>
373+ protected static SqlUserFunctionCall TimeAddMillisecond ( SqlExpression time , SqlExpression millisecond ) =>
310374 SqlDml . FunctionCall ( "DATE_ADD" , time , SqlDml . RawConcat ( SqlDml . Native ( "INTERVAL " ) , SqlDml . RawConcat ( millisecond * 1000 , SqlDml . Native ( "MICROSECOND" ) ) ) ) ;
375+
376+ protected static SqlUserFunctionCall DateToString ( SqlExpression dateTime ) =>
377+ SqlDml . FunctionCall ( "DATE_FORMAT" , dateTime , "%Y-%m-%d" ) ;
378+
379+ protected static SqlUserFunctionCall TimeToString ( SqlExpression dateTime ) =>
380+ SqlDml . FunctionCall ( "DATE_FORMAT" , dateTime , "%H:%i:%s.%f0" ) ;
311381#endif
312382
313383 protected static SqlUserFunctionCall DateTimeToStringIso ( SqlExpression dateTime ) =>
0 commit comments