66
77using System ;
88using System . Linq ;
9- using System . Text ;
9+ using System . Collections . Generic ;
1010using Xtensive . Sql . Compiler ;
1111using Xtensive . Sql . Info ;
1212using Xtensive . Sql . Model ;
@@ -220,24 +220,14 @@ public override void Visit(SqlFunctionCall node)
220220 DateTimeTruncate ( arguments [ 0 ] ) . AcceptVisitor ( this ) ;
221221 return ;
222222 case SqlFunctionType . DateTimeConstruct :
223- Visit ( DateAddDay ( DateAddMonth ( DateAddYear ( SqlDml . Literal ( new DateTime ( 2001 , 1 , 1 ) ) ,
224- arguments [ 0 ] - 2001 ) ,
225- arguments [ 1 ] - 1 ) ,
226- arguments [ 2 ] - 1 ) ) ;
223+ ConstructDateTime ( arguments ) . AcceptVisitor ( this ) ;
227224 return ;
228225#if NET6_0_OR_GREATER
229226 case SqlFunctionType . DateConstruct:
230- Visit( SqlDml . Cast ( DateAddDay ( DateAddMonth ( DateAddYear ( SqlDml . Literal ( new DateOnly ( 2001 , 1 , 1 ) ) ,
231- arguments [ 0 ] - 2001 ) ,
232- arguments[ 1 ] - 1 ) ,
233- arguments[ 2 ] - 1 ) , SqlType. Date ) ) ;
227+ ConstructDate( arguments ) . AcceptVisitor( this ) ;
234228 return ;
235229 case SqlFunctionType . TimeConstruct:
236- Visit( SqlDml . Cast ( DateAddMillisecond ( DateAddSecond ( DateAddMinute ( DateAddHour ( SqlDml . Literal ( new TimeOnly ( 0 , 0 , 0 ) ) ,
237- arguments [ 0 ] ) ,
238- arguments [ 1 ] ) ,
239- arguments [ 2 ] ) ,
240- arguments [ 3 ] ) , SqlType . Time) ) ;
230+ ConstructTime( arguments ) . AcceptVisitor( this ) ;
241231 return ;
242232 case SqlFunctionType . DateToString:
243233 Visit( DateToString ( arguments [ 0 ] ) ) ;
@@ -481,14 +471,83 @@ protected virtual SqlExpression DateTimeAddInterval(SqlExpression date, SqlExpre
481471 DateAddDay ( date , interval / NanosecondsPerDay ) ,
482472 ( interval / NanosecondsPerMillisecond ) % ( MillisecondsPerDay ) ) ;
483473 }
474+
475+ /// <summary>
476+ /// Creates expression that represents construction of datetime value
477+ /// from arguments (year, month, day).
478+ /// </summary>
479+ /// <param name="arguments">Expressions representing year, month, and day.</param>
480+ /// <returns>Result expression.</returns>
481+ protected virtual SqlExpression ConstructDateTime ( IReadOnlyList < SqlExpression > arguments )
482+ {
483+ return DateAddDay ( DateAddMonth ( DateAddYear ( SqlDml . Literal ( new DateTime ( 2001 , 1 , 1 ) ) ,
484+ arguments [ 0 ] - 2001 ) ,
485+ arguments [ 1 ] - 1 ) ,
486+ arguments [ 2 ] - 1 ) ;
487+ }
488+
484489#if NET6_0_OR_GREATER
485490
491+ /// <summary>
492+ /// Creates expression that represents construction of date value
493+ /// from arguments (year, month, day).
494+ /// </summary>
495+ /// <param name="arguments">Expressions representing year, month, and day.</param>
496+ /// <returns>Result expression.</returns>
497+ protected virtual SqlExpression ConstructDate ( IReadOnlyList < SqlExpression > arguments )
498+ {
499+ return SqlDml . Cast ( DateAddDay ( DateAddMonth ( DateAddYear ( SqlDml . Literal ( new DateOnly ( 2001 , 1 , 1 ) ) ,
500+ arguments [ 0 ] - 2001 ) ,
501+ arguments [ 1 ] - 1 ) ,
502+ arguments [ 2 ] - 1 ) , SqlType . Date ) ;
503+ }
504+
505+ /// <summary>
506+ /// Creates expression that represents construction of time value from arguments.
507+ /// </summary>
508+ /// <param name="arguments">Expressions to construct time from.</param>
509+ /// <returns>Result expression.</returns>
510+ /// <exception cref="NotSupportedException"></exception>
511+ /// <exception cref="InvalidOperationException"></exception>
512+ protected virtual SqlExpression ConstructTime ( IReadOnlyList < SqlExpression > arguments )
513+ {
514+ SqlExpression hour , minute , second , millisecond ;
515+ if ( arguments . Count == 4 ) {
516+ hour = arguments [ 0 ] ;
517+ minute = arguments [ 1 ] ;
518+ second = arguments [ 2 ] ;
519+ millisecond = arguments [ 3 ] ;
520+ }
521+ else if ( arguments . Count == 1 ) {
522+ var ticks = arguments [ 0 ] ;
523+ hour = SqlDml . Cast ( ticks / 36000000000 , SqlType . Int32 ) ;
524+ minute = SqlDml . Cast ( ( ticks / 600000000 ) % 60 , SqlType . Int32 ) ;
525+ second = SqlDml . Cast ( ( ticks / 10000000 ) % 60 , SqlType . Int32 ) ;
526+ millisecond = SqlDml . Cast ( ticks % 10000000 , SqlType . Int32 ) ;
527+ }
528+ else {
529+ throw new InvalidOperationException ( "Unsupported count of parameters" ) ;
530+ }
531+
532+ return SqlDml . Cast (
533+ DateAddMillisecond (
534+ DateAddSecond (
535+ DateAddMinute (
536+ DateAddHour (
537+ SqlDml . Literal ( new TimeOnly ( 0 , 0 , 0 ) ) ,
538+ hour ) ,
539+ minute ) ,
540+ second ) ,
541+ millisecond ) ,
542+ SqlType . Time ) ;
543+ }
544+
486545 /// <summary>
487546 /// Creates expression that represents addition <paramref name="interval"/> to the given <paramref name="time"/>.
488547 /// </summary>
489548 /// <param name="time">Time expression.</param>
490549 /// <param name="interval">Interval expression to add.</param>
491- /// <returns></returns>
550+ /// <returns>Result expression. </returns>
492551 protected virtual SqlExpression TimeAddInterval ( SqlExpression time , SqlExpression interval ) =>
493552 DateAddMillisecond ( time , ( interval / NanosecondsPerMillisecond ) % ( MillisecondsPerDay ) ) ;
494553
@@ -498,7 +557,6 @@ protected virtual SqlExpression TimeAddInterval(SqlExpression time, SqlExpressio
498557 /// <param name="time1">First <see cref="TimeOnly"/> expression.</param>
499558 /// <param name="time2">Second <see cref="TimeOnly"/> expression.</param>
500559 /// <returns>Result expression.</returns>
501- /// <returns></returns>
502560 protected virtual SqlExpression TimeSubtractTime ( SqlExpression time1 , SqlExpression time2 ) =>
503561 SqlDml . Modulo (
504562 NanosecondsPerDay + CastToDecimal ( DateDiffMillisecond ( time2 , time1 ) , 18 , 0 ) * NanosecondsPerMillisecond ,
0 commit comments