diff --git a/documentation/src/main/asciidoc/userguide/chapters/query/hql/QueryLanguage.adoc b/documentation/src/main/asciidoc/userguide/chapters/query/hql/QueryLanguage.adoc index 697cc918e5..7b0ac71a82 100644 --- a/documentation/src/main/asciidoc/userguide/chapters/query/hql/QueryLanguage.adoc +++ b/documentation/src/main/asciidoc/userguide/chapters/query/hql/QueryLanguage.adoc @@ -1023,6 +1023,7 @@ Next, functions for working with numeric values: | `power()` | Exponentiation | `power(x,y)` | Universal in SQL dialects | `ln()` | Natural logarithm | `ln(x)` | Very common in SQL dialects | `log10()` | Base-10 logarithm | `log10(x)` | Very common in SQL dialects +| `pi` | π | `pi` | Very common in SQL dialects | `sin()`, `cos()`, `tan()`, `asin()`, `acos()`, `atan()`, `atan2()` | Basic trigonometric functions | `sin(theta)`, `cos(theta)`, `atan2(opposite, adjacent)` | Very common in SQL dialects | `round()` | Numeric rounding | As usual: `round(number, places)` | Very common in SQL dialects | `floor()` | Floor function | `floor(x)` | Universal in SQL dialects diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java index 23cbc7f081..25590d2851 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -652,124 +652,126 @@ public abstract class Dialect implements ConversionContext { * query language specification: * *
avg(arg)
- aggregate function
+ * count([distinct ]arg)
- aggregate function
+ * max(arg)
- aggregate function
+ * min(arg)
- aggregate function
+ * sum(arg)
- aggregate function
* coalesce(arg0, arg1, ...)
+ * nullif(arg0, arg1)
* lower(arg)
+ * upper(arg)
+ * length(arg)
+ * concat(arg0, arg1, ...)
+ * locate(pattern, string[, start])
+ * substring(string, start[, length])
+ * trim([[spec ][character ]from] string)
* abs(arg)
+ * mod(arg0, arg1)
+ * sqrt(arg)
* current date
+ * current time
+ * current timestamp
* any(arg)
- aggregate function
+ * every(arg)
- aggregate function
* cast(arg as Type)
+ * extract(field from arg)
* ln(arg)
+ * exp(arg)
+ * power(arg0, arg1)
+ * floor(arg)
+ * ceiling(arg)
* position(pattern in string)
+ * substring(string from start[ for length])
+ * overlay(string placing replacement from start[ for length])
* java.time
+ * types:
*
* local date
+ * local time
+ * local datetime
+ * offset datetime
+ * instant
* left(string, length)
+ * right(string, length)
+ * replace(string, pattern, replacement)
+ * pad(string with length spec[ character])
* pi
+ * log10(arg)
+ * sign(arg)
+ * sin(arg)
+ * cos(arg)
+ * tan(arg)
+ * asin(arg)
+ * acos(arg)
+ * atan(arg)
+ * atan2(arg0, arg1)
+ * round(arg0, arg1)
+ * least(arg0, arg1, ...)
+ * greatest(arg0, arg1, ...)
* format(datetime as pattern)
+ * collate(string as collation)
+ * str(arg)
- synonym of cast(a as String)
+ * ifnull(arg0, arg1)
- synonym of coalesce(a, b)
* extract()
, and desugared by the parser:
*
* second(arg)
- synonym of extract(second from a)
+ * minute(arg)
- synonym of extract(minute from a)
+ * hour(arg)
- synonym of extract(hour from a)
+ * day(arg)
- synonym of extract(day from a)
+ * month(arg)
- synonym of extract(month from a)
+ * year(arg)
- synonym of extract(year from a)
* second()
+ * function returns a floating point value, contrary to the integer
+ * type returned by the native function with this name on many databases.
+ * Thus, we don't just naively map these HQL functions to the native SQL
+ * functions with the same names.
*/
public void initializeFunctionRegistry(QueryEngine queryEngine) {
final TypeConfiguration typeConfiguration = queryEngine.getTypeConfiguration();
@@ -811,6 +813,10 @@ public abstract class Dialect implements ConversionContext {
functionFactory.trigonometry();
+ //pi supported on most databases, but emulate it here
+
+ functionFactory.pi_acos();
+
//coalesce() function, supported by most databases, must be emulated
//in terms of nvl() for platforms which don't support it natively
diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java b/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java
index 933aaf3c4e..ca3bd705ff 100644
--- a/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java
+++ b/hibernate-core/src/main/java/org/hibernate/dialect/function/CommonFunctionFactory.java
@@ -388,6 +388,13 @@ public class CommonFunctionFactory {
.register();
}
+ public void pi_acos() {
+ functionRegistry.patternDescriptorBuilder( "pi", "acos(-1)" )
+ .setInvariantType(doubleType)
+ .setExactArgumentCount(0)
+ .register();
+ }
+
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// character functions
diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/StandardFunctionTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/StandardFunctionTests.java
index 96040851d7..95b2f9fe80 100644
--- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/StandardFunctionTests.java
+++ b/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/StandardFunctionTests.java
@@ -907,4 +907,16 @@ public class StandardFunctionTests {
}
);
}
+
+ @Test
+ public void testPi(SessionFactoryScope scope) {
+ scope.inTransaction(
+ session -> {
+ assertThat(
+ session.createQuery("select pi").getSingleResult(),
+ is( Math.PI )
+ );
+ }
+ );
+ }
}