@@ -484,6 +484,12 @@ public void initializeFunctionRegistry(FunctionContributions functionContributio
484484		if  ( supportsRecursiveCTE () ) {
485485			functionFactory .generateSeries_recursive ( getMaximumSeriesSize (), false , true  );
486486		}
487+ 
488+ 		functionFactory .hex ( "hex(?1)"  );
489+ 		if  ( getDB2Version ().isSameOrAfter ( 11  ) ) {
490+ 			functionFactory .sha ( "hash(?1, 2)"  );
491+ 			functionFactory .md5 ( "hash(?1, 0)"  );
492+ 		}
487493	}
488494
489495	/** 
@@ -522,7 +528,7 @@ public long getFractionalSecondPrecisionInNanos() {
522528	@ Override 
523529	public  String  timestampdiffPattern (TemporalUnit  unit , TemporalType  fromTemporalType , TemporalType  toTemporalType ) {
524530		if  ( getDB2Version ().isBefore ( 11  ) ) {
525- 			return  DB2Dialect . timestampdiffPatternV10 ( unit , fromTemporalType , toTemporalType  );
531+ 			return  timestampdiffPatternV10 ( unit , fromTemporalType , toTemporalType  );
526532		}
527533		final  StringBuilder  pattern  = new  StringBuilder ();
528534		final  String  fromExpression ;
@@ -558,22 +564,30 @@ public String timestampdiffPattern(TemporalUnit unit, TemporalType fromTemporalT
558564		switch  ( unit  ) {
559565			case  NATIVE :
560566			case  NANOSECOND :
561- 				pattern .append ( "(seconds_between("  );
567+ 				pattern .append ( "(seconds_between(date_trunc('second',"  );
568+ 				pattern .append ( toExpression  );
569+ 				pattern .append ( "),date_trunc('second',"  );
570+ 				pattern .append ( fromExpression  );
571+ 				pattern .append ( "))"  );
562572				break ;
563573			//note: DB2 does have weeks_between() 
564574			case  MONTH :
565575			case  QUARTER :
566576				// the months_between() function results 
567577				// in a non-integral value, so trunc() it 
568578				pattern .append ( "trunc(months_between("  );
579+ 				pattern .append ( toExpression  );
580+ 				pattern .append ( ','  );
581+ 				pattern .append ( fromExpression  );
582+ 				pattern .append ( ')'  );
569583				break ;
570584			default :
571585				pattern .append ( "?1s_between("  );
586+ 				pattern .append ( toExpression  );
587+ 				pattern .append ( ','  );
588+ 				pattern .append ( fromExpression  );
589+ 				pattern .append ( ')'  );
572590		}
573- 		pattern .append ( toExpression  );
574- 		pattern .append ( ','  );
575- 		pattern .append ( fromExpression  );
576- 		pattern .append ( ')'  );
577591		switch  ( unit  ) {
578592			case  NATIVE :
579593				pattern .append ( "+(microsecond(" );
@@ -599,6 +613,97 @@ public String timestampdiffPattern(TemporalUnit unit, TemporalType fromTemporalT
599613		return  pattern .toString ();
600614	}
601615
616+ 	@ SuppressWarnings ("deprecation" )
617+ 	public  static  String  timestampdiffPatternV10 (TemporalUnit  unit , TemporalType  fromTemporalType , TemporalType  toTemporalType ) {
618+ 		final  boolean  isTime  = fromTemporalType  == TemporalType .TIME  || toTemporalType  == TemporalType .TIME ;
619+ 		final  String  fromExpression ;
620+ 		final  String  toExpression ;
621+ 		if  ( unit .isDateUnit () ) {
622+ 			if  ( fromTemporalType  == TemporalType .TIME  ) {
623+ 				fromExpression  = "timestamp('1970-01-01',?2)" ;
624+ 			}
625+ 			else  {
626+ 				fromExpression  = "?2" ;
627+ 			}
628+ 			if  ( toTemporalType  == TemporalType .TIME  ) {
629+ 				toExpression  = "timestamp('1970-01-01',?3)" ;
630+ 			}
631+ 			else  {
632+ 				toExpression  = "?3" ;
633+ 			}
634+ 		}
635+ 		else  {
636+ 			if  ( fromTemporalType  == TemporalType .DATE  ) {
637+ 				fromExpression  = "cast(?2 as timestamp)" ;
638+ 			}
639+ 			else  {
640+ 				fromExpression  = "?2" ;
641+ 			}
642+ 			if  ( toTemporalType  == TemporalType .DATE  ) {
643+ 				toExpression  = "cast(?3 as timestamp)" ;
644+ 			}
645+ 			else  {
646+ 				toExpression  = "?3" ;
647+ 			}
648+ 		}
649+ 		switch  ( unit  ) {
650+ 			case  NATIVE :
651+ 				if  ( isTime  ) {
652+ 					return  "(midnight_seconds("  + toExpression  + ")-midnight_seconds("  + fromExpression  + "))" ;
653+ 				}
654+ 				else  {
655+ 					return  "(select (days(t2)-days(t1))*86400+(midnight_seconds(t2)-midnight_seconds(t1))+(microsecond(t2)-microsecond(t1))/1e6 "  +
656+ 						   "from lateral(values("  + fromExpression  + ','  + toExpression  + ")) as temp(t1,t2))" ;
657+ 				}
658+ 			case  NANOSECOND :
659+ 				if  ( isTime  ) {
660+ 					return  "(midnight_seconds("  + toExpression  + ")-midnight_seconds("  + fromExpression  + "))*1e9" ;
661+ 				}
662+ 				else  {
663+ 					return  "(select (days(t2)-days(t1))*86400+(midnight_seconds(t2)-midnight_seconds(t1))*1e9+(microsecond(t2)-microsecond(t1))*1e3 "  +
664+ 						   "from lateral(values("  + fromExpression  + ','  + toExpression  + ")) as temp(t1,t2))" ;
665+ 				}
666+ 			case  SECOND :
667+ 				if  ( isTime  ) {
668+ 					return  "(midnight_seconds("  + toExpression  + ")-midnight_seconds("  + fromExpression  + "))" ;
669+ 				}
670+ 				else  {
671+ 					return  "(select (days(t2)-days(t1))*86400+(midnight_seconds(t2)-midnight_seconds(t1)) "  +
672+ 						   "from lateral(values("  + fromExpression  + ','  + toExpression  + ")) as temp(t1,t2))" ;
673+ 				}
674+ 			case  MINUTE :
675+ 				if  ( isTime  ) {
676+ 					return  "(midnight_seconds("  + toExpression  + ")-midnight_seconds("  + fromExpression  + "))/60" ;
677+ 				}
678+ 				else  {
679+ 					return  "(select (days(t2)-days(t1))*1440+(midnight_seconds(t2)-midnight_seconds(t1))/60 from "  +
680+ 						   "lateral(values("  + fromExpression  + ','  + toExpression  + ")) as temp(t1,t2))" ;
681+ 				}
682+ 			case  HOUR :
683+ 				if  ( isTime  ) {
684+ 					return  "(midnight_seconds("  + toExpression  + ")-midnight_seconds("  + fromExpression  + "))/3600" ;
685+ 				}
686+ 				else  {
687+ 					return  "(select (days(t2)-days(t1))*24+(midnight_seconds(t2)-midnight_seconds(t1))/3600 "  +
688+ 						   "from lateral(values("  + fromExpression  + ','  + toExpression  + ")) as temp(t1,t2))" ;
689+ 				}
690+ 			case  YEAR :
691+ 				return  "(year("  + toExpression  + ")-year("  + fromExpression  + "))" ;
692+ 			// the months_between() function results 
693+ 			// in a non-integral value, so trunc() it 
694+ 			case  MONTH :
695+ 				return  "trunc(months_between("  + toExpression  + ','  + fromExpression  + "))" ;
696+ 			case  QUARTER :
697+ 				return  "trunc(months_between("  + toExpression  + ','  + fromExpression  + ")/3)" ;
698+ 			case  WEEK :
699+ 				return  "int((days"  + toExpression  + ")-days("  + fromExpression  + "))/7)" ;
700+ 			case  DAY :
701+ 				return  "(days("  + toExpression  + ")-days("  + fromExpression  + "))" ;
702+ 			default :
703+ 				throw  new  UnsupportedOperationException ( "Unsupported unit: "  + unit  );
704+ 		}
705+ 	}
706+ 
602707	@ Override 
603708	public  String  timestampaddPattern (TemporalUnit  unit , TemporalType  temporalType , IntervalType  intervalType ) {
604709		final  StringBuilder  pattern  = new  StringBuilder ();
@@ -902,13 +1007,34 @@ public boolean supportsCommentOn() {
9021007		return  true ;
9031008	}
9041009
1010+ 	@ Override 
1011+ 	public  String  getAlterColumnTypeString (String  columnName , String  columnType , String  columnDefinition ) {
1012+ 		// would need multiple statements to 'set not null'/'drop not null', 'set default'/'drop default', 'set generated', etc 
1013+ 		return  "alter column "  + columnName  + " set data type "  + columnType ;
1014+ 	}
1015+ 
1016+ 	@ Override 
1017+ 	public  boolean  supportsAlterColumnType () {
1018+ 		return  getVersion ().isSameOrAfter ( 10 , 5  );
1019+ 	}
1020+ 
1021+ 	@ Override 
1022+ 	public  boolean  supportsIfExistsBeforeTableName () {
1023+ 		return  getVersion ().isSameOrAfter ( 11 , 5  );
1024+ 	}
1025+ 
9051026	@ Override 
9061027	public  SqmMultiTableMutationStrategy  getFallbackSqmMutationStrategy (
9071028			EntityMappingType  rootEntityDescriptor ,
9081029			RuntimeModelCreationContext  runtimeModelCreationContext ) {
9091030		return  new  CteMutationStrategy ( rootEntityDescriptor , runtimeModelCreationContext  );
9101031	}
9111032
1033+ 	@ Override 
1034+ 	public  boolean  supportsIsTrue () {
1035+ 		return  getDB2Version ().isSameOrAfter ( 11  );
1036+ 	}
1037+ 
9121038	@ Override 
9131039	public  SqmMultiTableInsertStrategy  getFallbackSqmInsertStrategy (
9141040			EntityMappingType  rootEntityDescriptor ,
@@ -950,6 +1076,11 @@ public boolean supportsLobValueChangePropagation() {
9501076		return  false ;
9511077	}
9521078
1079+ 	@ Override 
1080+ 	public  boolean  useInputStreamToInsertBlob () {
1081+ 		return  false ;
1082+ 	}
1083+ 
9531084	@ Override 
9541085	public  boolean  doesReadCommittedCauseWritersToBlockReaders () {
9551086		return  true ;
0 commit comments