diff --git a/hibernate-core/src/main/java/org/hibernate/query/criteria/HibernateCriteriaBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/criteria/HibernateCriteriaBuilder.java
index a9f47ddc0a..242927ef88 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/criteria/HibernateCriteriaBuilder.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/criteria/HibernateCriteriaBuilder.java
@@ -918,7 +918,7 @@ public interface HibernateCriteriaBuilder extends CriteriaBuilder {
* The pattern must be written in a subset of the pattern language defined by
* Java’s {@link java.time.format.DateTimeFormatter}.
*
- * See {@link org.hibernate.dialect.Dialect#appendDatetimeFormat Dialect#appendDatetimeFormat}
+ * See {@link org.hibernate.dialect.Dialect#appendDatetimeFormat}
* for a full list of pattern elements.
*
* @param datetime the datetime expression to format
diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java
index 950c73dc10..f88cef18c0 100644
--- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java
+++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SqmCriteriaNodeBuilder.java
@@ -104,6 +104,7 @@ import org.hibernate.query.sqm.tree.expression.SqmCollectionSize;
import org.hibernate.query.sqm.tree.expression.SqmDistinct;
import org.hibernate.query.sqm.tree.expression.SqmExpression;
import org.hibernate.query.sqm.tree.expression.SqmExtractUnit;
+import org.hibernate.query.sqm.tree.expression.SqmFormat;
import org.hibernate.query.sqm.tree.expression.SqmFunction;
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
import org.hibernate.query.sqm.tree.expression.SqmLiteralNull;
@@ -2588,11 +2589,11 @@ public class SqmCriteriaNodeBuilder implements NodeBuilder, SqmCreationContext,
@Override
public SqmFunction format(Expression extends TemporalAccessor> datetime, String pattern) {
- SqmExpression patternLiteral = value( pattern );
+ SqmFormat sqmFormat = new SqmFormat( pattern, null, this );
return getFunctionDescriptor( "format" ).generateSqmExpression(
- asList( (SqmExpression>) datetime, patternLiteral ),
+ asList( (SqmExpression>) datetime, sqmFormat ),
null,
- queryEngine,
+ getQueryEngine(),
getJpaMetamodel().getTypeConfiguration()
);
}
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/HibernateCriteriaBuilderFunctionsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/CriteriaBuilderNonStandardFunctionsTest.java
similarity index 91%
rename from hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/HibernateCriteriaBuilderFunctionsTest.java
rename to hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/CriteriaBuilderNonStandardFunctionsTest.java
index dbab586026..f929b69432 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/HibernateCriteriaBuilderFunctionsTest.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/CriteriaBuilderNonStandardFunctionsTest.java
@@ -15,15 +15,19 @@ import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
+import org.hibernate.dialect.DB2Dialect;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.query.criteria.HibernateCriteriaBuilder;
import org.hibernate.testing.orm.domain.StandardDomainModel;
import org.hibernate.testing.orm.domain.gambit.EntityOfBasics;
+import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialect;
+import org.hibernate.testing.orm.junit.RequiresDialectFeature;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
+import org.hibernate.testing.orm.junit.SkipForDialect;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -46,9 +50,9 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
*/
@DomainModel(standardModels = StandardDomainModel.GAMBIT)
@SessionFactory
-public class HibernateCriteriaBuilderFunctionsTest {
+public class CriteriaBuilderNonStandardFunctionsTest {
- private final static String DATETIME_PATTERN = "yyyy-MM-dd";
+ private final static String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
@BeforeEach
public void prepareData(SessionFactoryScope scope) {
@@ -150,6 +154,7 @@ public class HibernateCriteriaBuilderFunctionsTest {
}
@Test
+ @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsFormat.class)
public void testFormatWithJavaUtilDate(SessionFactoryScope scope) {
scope.inTransaction( session -> {
HibernateCriteriaBuilder cb = session.getCriteriaBuilder();
@@ -171,6 +176,7 @@ public class HibernateCriteriaBuilderFunctionsTest {
}
@Test
+ @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsFormat.class)
public void testFormatWithJavaTimeLocalDateTime(SessionFactoryScope scope) {
scope.inTransaction( session -> {
HibernateCriteriaBuilder cb = session.getCriteriaBuilder();
@@ -239,6 +245,7 @@ public class HibernateCriteriaBuilderFunctionsTest {
}
@Test
+ @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsPadWithChar.class)
public void testPad(SessionFactoryScope scope) {
scope.inTransaction( session -> {
HibernateCriteriaBuilder cb = session.getCriteriaBuilder();
@@ -279,6 +286,7 @@ public class HibernateCriteriaBuilderFunctionsTest {
}
@Test
+ @RequiresDialectFeature(feature = DialectFeatureChecks.SupportsReplace.class)
public void testReplace(SessionFactoryScope scope) {
scope.inTransaction( session -> {
HibernateCriteriaBuilder cb = session.getCriteriaBuilder();
@@ -361,9 +369,7 @@ public class HibernateCriteriaBuilderFunctionsTest {
cb.tan( theDouble ),
cb.asin( theDouble ),
cb.acos( theDouble ),
- cb.atan( theDouble ),
- cb.atan2( cb.sin( theDouble ), 0 ),
- cb.atan2( cb.sin( theDouble ), cb.cos( theDouble ) )
+ cb.atan( theDouble )
).where( cb.equal( from.get( "id" ), 1 ) );
Tuple result = session.createQuery( query ).getSingleResult();
@@ -373,8 +379,26 @@ public class HibernateCriteriaBuilderFunctionsTest {
assertEquals( Math.asin( 1.0 ), result.get( 3, Double.class ), 1e-6 );
assertEquals( Math.acos( 1.0 ), result.get( 4, Double.class ), 1e-6 );
assertEquals( Math.atan( 1.0 ), result.get( 5, Double.class ), 1e-6 );
- assertEquals( Math.atan2( Math.sin( 1.0 ), 0 ), result.get( 6, Double.class ), 1e-6 );
- assertEquals( Math.atan2( Math.sin( 1.0 ), Math.cos( 1.0 ) ), result.get( 7, Double.class ), 1e-6 );
+ } );
+ }
+
+ @Test
+ @SkipForDialect(dialectClass = DB2Dialect.class, reason = "DB2 atan2 function expects the arguments in inverted order")
+ public void testAtan2(SessionFactoryScope scope) {
+ scope.inTransaction( session -> {
+ HibernateCriteriaBuilder cb = session.getCriteriaBuilder();
+ CriteriaQuery query = cb.createTupleQuery();
+ Root from = query.from( EntityOfBasics.class );
+
+ Path theDouble = from.get( "theDouble" );
+ query.multiselect(
+ cb.atan2( cb.sin( theDouble ), 0 ),
+ cb.atan2( cb.sin( theDouble ), cb.cos( theDouble ) )
+ ).where( cb.equal( from.get( "id" ), 1 ) );
+
+ Tuple result = session.createQuery( query ).getSingleResult();
+ assertEquals( Math.atan2( Math.sin( 1.0 ), 0 ), result.get( 0, Double.class ), 1e-6 );
+ assertEquals( Math.atan2( Math.sin( 1.0 ), Math.cos( 1.0 ) ), result.get( 1, Double.class ), 1e-6 );
} );
}