1010import org .hibernate .boot .model .FunctionContributions ;
1111import org .hibernate .boot .model .TypeContributions ;
1212import org .hibernate .community .dialect .sequence .LegacyDB2SequenceSupport ;
13- import org .hibernate .dialect .DB2Dialect ;
1413import org .hibernate .dialect .DB2GetObjectExtractor ;
1514import org .hibernate .dialect .DatabaseVersion ;
1615import org .hibernate .dialect .Dialect ;
@@ -484,6 +483,12 @@ public void initializeFunctionRegistry(FunctionContributions functionContributio
484483 if ( supportsRecursiveCTE () ) {
485484 functionFactory .generateSeries_recursive ( getMaximumSeriesSize (), false , true );
486485 }
486+
487+ functionFactory .hex ( "hex(?1)" );
488+ if ( getDB2Version ().isSameOrAfter ( 11 ) ) {
489+ functionFactory .sha ( "hash(?1, 2)" );
490+ functionFactory .md5 ( "hash(?1, 0)" );
491+ }
487492 }
488493
489494 /**
@@ -522,7 +527,7 @@ public long getFractionalSecondPrecisionInNanos() {
522527 @ Override
523528 public String timestampdiffPattern (TemporalUnit unit , TemporalType fromTemporalType , TemporalType toTemporalType ) {
524529 if ( getDB2Version ().isBefore ( 11 ) ) {
525- return DB2Dialect . timestampdiffPatternV10 ( unit , fromTemporalType , toTemporalType );
530+ return timestampdiffPatternV10 ( unit , fromTemporalType , toTemporalType );
526531 }
527532 final StringBuilder pattern = new StringBuilder ();
528533 final String fromExpression ;
@@ -558,22 +563,30 @@ public String timestampdiffPattern(TemporalUnit unit, TemporalType fromTemporalT
558563 switch ( unit ) {
559564 case NATIVE :
560565 case NANOSECOND :
561- pattern .append ( "(seconds_between(" );
566+ pattern .append ( "(seconds_between(date_trunc('second'," );
567+ pattern .append ( toExpression );
568+ pattern .append ( "),date_trunc('second'," );
569+ pattern .append ( fromExpression );
570+ pattern .append ( "))" );
562571 break ;
563572 //note: DB2 does have weeks_between()
564573 case MONTH :
565574 case QUARTER :
566575 // the months_between() function results
567576 // in a non-integral value, so trunc() it
568577 pattern .append ( "trunc(months_between(" );
578+ pattern .append ( toExpression );
579+ pattern .append ( ',' );
580+ pattern .append ( fromExpression );
581+ pattern .append ( ')' );
569582 break ;
570583 default :
571584 pattern .append ( "?1s_between(" );
585+ pattern .append ( toExpression );
586+ pattern .append ( ',' );
587+ pattern .append ( fromExpression );
588+ pattern .append ( ')' );
572589 }
573- pattern .append ( toExpression );
574- pattern .append ( ',' );
575- pattern .append ( fromExpression );
576- pattern .append ( ')' );
577590 switch ( unit ) {
578591 case NATIVE :
579592 pattern .append ( "+(microsecond(" );
@@ -599,6 +612,97 @@ public String timestampdiffPattern(TemporalUnit unit, TemporalType fromTemporalT
599612 return pattern .toString ();
600613 }
601614
615+ @ SuppressWarnings ("deprecation" )
616+ public static String timestampdiffPatternV10 (TemporalUnit unit , TemporalType fromTemporalType , TemporalType toTemporalType ) {
617+ final boolean isTime = fromTemporalType == TemporalType .TIME || toTemporalType == TemporalType .TIME ;
618+ final String fromExpression ;
619+ final String toExpression ;
620+ if ( unit .isDateUnit () ) {
621+ if ( fromTemporalType == TemporalType .TIME ) {
622+ fromExpression = "timestamp('1970-01-01',?2)" ;
623+ }
624+ else {
625+ fromExpression = "?2" ;
626+ }
627+ if ( toTemporalType == TemporalType .TIME ) {
628+ toExpression = "timestamp('1970-01-01',?3)" ;
629+ }
630+ else {
631+ toExpression = "?3" ;
632+ }
633+ }
634+ else {
635+ if ( fromTemporalType == TemporalType .DATE ) {
636+ fromExpression = "cast(?2 as timestamp)" ;
637+ }
638+ else {
639+ fromExpression = "?2" ;
640+ }
641+ if ( toTemporalType == TemporalType .DATE ) {
642+ toExpression = "cast(?3 as timestamp)" ;
643+ }
644+ else {
645+ toExpression = "?3" ;
646+ }
647+ }
648+ switch ( unit ) {
649+ case NATIVE :
650+ if ( isTime ) {
651+ return "(midnight_seconds(" + toExpression + ")-midnight_seconds(" + fromExpression + "))" ;
652+ }
653+ else {
654+ return "(select (days(t2)-days(t1))*86400+(midnight_seconds(t2)-midnight_seconds(t1))+(microsecond(t2)-microsecond(t1))/1e6 " +
655+ "from lateral(values(" + fromExpression + ',' + toExpression + ")) as temp(t1,t2))" ;
656+ }
657+ case NANOSECOND :
658+ if ( isTime ) {
659+ return "(midnight_seconds(" + toExpression + ")-midnight_seconds(" + fromExpression + "))*1e9" ;
660+ }
661+ else {
662+ return "(select (days(t2)-days(t1))*86400+(midnight_seconds(t2)-midnight_seconds(t1))*1e9+(microsecond(t2)-microsecond(t1))*1e3 " +
663+ "from lateral(values(" + fromExpression + ',' + toExpression + ")) as temp(t1,t2))" ;
664+ }
665+ case SECOND :
666+ if ( isTime ) {
667+ return "(midnight_seconds(" + toExpression + ")-midnight_seconds(" + fromExpression + "))" ;
668+ }
669+ else {
670+ return "(select (days(t2)-days(t1))*86400+(midnight_seconds(t2)-midnight_seconds(t1)) " +
671+ "from lateral(values(" + fromExpression + ',' + toExpression + ")) as temp(t1,t2))" ;
672+ }
673+ case MINUTE :
674+ if ( isTime ) {
675+ return "(midnight_seconds(" + toExpression + ")-midnight_seconds(" + fromExpression + "))/60" ;
676+ }
677+ else {
678+ return "(select (days(t2)-days(t1))*1440+(midnight_seconds(t2)-midnight_seconds(t1))/60 from " +
679+ "lateral(values(" + fromExpression + ',' + toExpression + ")) as temp(t1,t2))" ;
680+ }
681+ case HOUR :
682+ if ( isTime ) {
683+ return "(midnight_seconds(" + toExpression + ")-midnight_seconds(" + fromExpression + "))/3600" ;
684+ }
685+ else {
686+ return "(select (days(t2)-days(t1))*24+(midnight_seconds(t2)-midnight_seconds(t1))/3600 " +
687+ "from lateral(values(" + fromExpression + ',' + toExpression + ")) as temp(t1,t2))" ;
688+ }
689+ case YEAR :
690+ return "(year(" + toExpression + ")-year(" + fromExpression + "))" ;
691+ // the months_between() function results
692+ // in a non-integral value, so trunc() it
693+ case MONTH :
694+ return "trunc(months_between(" + toExpression + ',' + fromExpression + "))" ;
695+ case QUARTER :
696+ return "trunc(months_between(" + toExpression + ',' + fromExpression + ")/3)" ;
697+ case WEEK :
698+ return "int((days" + toExpression + ")-days(" + fromExpression + "))/7)" ;
699+ case DAY :
700+ return "(days(" + toExpression + ")-days(" + fromExpression + "))" ;
701+ default :
702+ throw new UnsupportedOperationException ( "Unsupported unit: " + unit );
703+ }
704+ }
705+
602706 @ Override
603707 public String timestampaddPattern (TemporalUnit unit , TemporalType temporalType , IntervalType intervalType ) {
604708 final StringBuilder pattern = new StringBuilder ();
@@ -902,13 +1006,34 @@ public boolean supportsCommentOn() {
9021006 return true ;
9031007 }
9041008
1009+ @ Override
1010+ public String getAlterColumnTypeString (String columnName , String columnType , String columnDefinition ) {
1011+ // would need multiple statements to 'set not null'/'drop not null', 'set default'/'drop default', 'set generated', etc
1012+ return "alter column " + columnName + " set data type " + columnType ;
1013+ }
1014+
1015+ @ Override
1016+ public boolean supportsAlterColumnType () {
1017+ return getVersion ().isSameOrAfter ( 10 , 5 );
1018+ }
1019+
1020+ @ Override
1021+ public boolean supportsIfExistsBeforeTableName () {
1022+ return getVersion ().isSameOrAfter ( 11 , 5 );
1023+ }
1024+
9051025 @ Override
9061026 public SqmMultiTableMutationStrategy getFallbackSqmMutationStrategy (
9071027 EntityMappingType rootEntityDescriptor ,
9081028 RuntimeModelCreationContext runtimeModelCreationContext ) {
9091029 return new CteMutationStrategy ( rootEntityDescriptor , runtimeModelCreationContext );
9101030 }
9111031
1032+ @ Override
1033+ public boolean supportsIsTrue () {
1034+ return getDB2Version ().isSameOrAfter ( 11 );
1035+ }
1036+
9121037 @ Override
9131038 public SqmMultiTableInsertStrategy getFallbackSqmInsertStrategy (
9141039 EntityMappingType rootEntityDescriptor ,
@@ -950,6 +1075,11 @@ public boolean supportsLobValueChangePropagation() {
9501075 return false ;
9511076 }
9521077
1078+ @ Override
1079+ public boolean useInputStreamToInsertBlob () {
1080+ return false ;
1081+ }
1082+
9531083 @ Override
9541084 public boolean doesReadCommittedCauseWritersToBlockReaders () {
9551085 return true ;
0 commit comments