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