HHH-15588 promote sinh(), cosh(), and tanh()

This commit is contained in:
Gavin King 2022-10-08 14:10:43 +02:00
parent 6ea6359638
commit 477f1e7af6
8 changed files with 83 additions and 17 deletions

View File

@ -1000,8 +1000,10 @@ Of course, we also have a number of functions for working with numeric values.
| `log10()` | Base-10 logarithm | `log10(x)` | ✗
| `log()` | Arbitrary-base logarithm | `log(b,x)` | ✗
| `pi` | π | `pi` | ✗
| `sin()`, `cos()`, `tan()`, `asin()`, `acos()`, `atan()`, `atan2()`
| Basic trigonometric functions | `sin(theta)`, `cos(theta)`, `atan2(opposite, adjacent)` | ✗
| `sin()`, `cos()`, `tan()`, `asin()`, `acos()`, `atan()`
| Basic trigonometric functions | `sin(theta)`, `cos(theta)` | ✗
| `atan2()` | Two-argument arctangent (range `(-π,π]`) | `atan2(y, x)` | ✗
| `sinh()`, `cosh()`, `tanh()` | Hyperbolic functions | `sinh(x)`, `cosh(x)`, `tanh(x)` | ✗
| `degrees()` | Convert radians to degrees | `degrees(x)` | ✗
| `radians()` | Convert degrees to radians | `radians(x)` | ✗
| `least()` | Return the smallest of the given arguments | `least(x, y, z)` |✗

View File

@ -527,11 +527,16 @@ public class PostgreSQLLegacyDialect extends Dialect {
functionFactory.log();
if ( getVersion().isSameOrAfter(12) ) {
functionFactory.log10();
functionFactory.tanh();
functionFactory.sinh();
functionFactory.cosh();
functionFactory.moreHyperbolic();
}
else {
queryEngine.getSqmFunctionRegistry().registerAlternateKey( "log10", "log" );
}
functionFactory.cbrt();
functionFactory.pi();
functionFactory.trim2();
functionFactory.repeat();
functionFactory.md5();

View File

@ -207,6 +207,9 @@ public class DB2Dialect extends Dialect {
functionFactory.avg_castingNonDoubleArguments( this, SqlAstNodeRenderingMode.DEFAULT );
functionFactory.cot();
functionFactory.sinh();
functionFactory.cosh();
functionFactory.tanh();
functionFactory.degrees();
functionFactory.log10();
functionFactory.radians();

View File

@ -785,6 +785,9 @@ public abstract class Dialect implements ConversionContext {
* <li> <code>atan(arg)</code>
* <li> <code>atan2(arg0, arg1)</code>
* <li> <code>round(arg0, arg1)</code>
* <li> <code>sinh(arg)</code>
* <li> <code>tanh(arg)</code>
* <li> <code>cosh(arg)</code>
* <li> <code>least(arg0, arg1, ...)</code>
* <li> <code>greatest(arg0, arg1, ...)</code>
* <li> <code>degrees(arg)</code>
@ -860,6 +863,13 @@ public abstract class Dialect implements ConversionContext {
functionFactory.trigonometry();
//hyperbolic sinh and tanh are very useful but not supported on most
//databases, so emulate them here (cosh along for the ride)
functionFactory.sinh_exp();
functionFactory.cosh_exp();
functionFactory.tanh_exp();
//pi supported on most databases, but emulate it here
functionFactory.pi_acos();

View File

@ -511,11 +511,16 @@ public class PostgreSQLDialect extends Dialect {
functionFactory.log();
if ( getVersion().isSameOrAfter(12) ) {
functionFactory.log10();
functionFactory.tanh();
functionFactory.sinh();
functionFactory.cosh();
functionFactory.moreHyperbolic();
}
else {
queryEngine.getSqmFunctionRegistry().registerAlternateKey( "log10", "log" );
}
functionFactory.cbrt();
functionFactory.pi();
functionFactory.trim2();
functionFactory.repeat();
functionFactory.md5();

View File

@ -64,14 +64,6 @@ public class CommonFunctionFactory {
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// trigonometric/geometric functions
public void cosh() {
functionRegistry.namedDescriptorBuilder( "cosh" )
.setInvariantType(doubleType)
.setExactArgumentCount( 1 )
.setParameterTypes(NUMERIC)
.register();
}
public void cot() {
functionRegistry.namedDescriptorBuilder( "cot" )
.setExactArgumentCount( 1 )
@ -208,6 +200,30 @@ public class CommonFunctionFactory {
.register();
}
public void sinh_exp() {
functionRegistry.patternDescriptorBuilder( "sinh", "((exp(?1)-exp(-?1))/2)" )
.setExactArgumentCount( 1 )
.setParameterTypes(NUMERIC)
.setInvariantType(doubleType)
.register();
}
public void cosh() {
functionRegistry.namedDescriptorBuilder( "cosh" )
.setExactArgumentCount( 1 )
.setParameterTypes(NUMERIC)
.setInvariantType(doubleType)
.register();
}
public void cosh_exp() {
functionRegistry.patternDescriptorBuilder( "cosh", "((exp(?1)+exp(-?1))/2)" )
.setExactArgumentCount( 1 )
.setParameterTypes(NUMERIC)
.setInvariantType(doubleType)
.register();
}
public void tanh() {
functionRegistry.namedDescriptorBuilder( "tanh" )
.setExactArgumentCount( 1 )
@ -216,6 +232,14 @@ public class CommonFunctionFactory {
.register();
}
public void tanh_exp() {
functionRegistry.patternDescriptorBuilder( "tanh", "((exp(2*?1)-1)/(exp(2*?1)+1))" )
.setExactArgumentCount( 1 )
.setParameterTypes(NUMERIC)
.setInvariantType(doubleType)
.register();
}
public void moreHyperbolic() {
functionRegistry.namedDescriptorBuilder( "acosh" )
.setInvariantType(doubleType)
@ -302,9 +326,10 @@ public class CommonFunctionFactory {
/**
* Warning: the semantics of this function are inconsistent between DBs.
*
* - On Postgres it means stdev_samp()
* - On Oracle, DB2, MySQL it means stdev_pop()
* <ul>
* <li>On Postgres it means {@code stdev_samp()}
* <li>On Oracle, DB2, MySQL it means {@code stdev_pop()}
* </ul>
*/
public void stddev() {
functionRegistry.namedAggregateDescriptorBuilder( "stddev" )
@ -316,9 +341,10 @@ public class CommonFunctionFactory {
/**
* Warning: the semantics of this function are inconsistent between DBs.
*
* - On Postgres it means var_samp()
* - On Oracle, DB2, MySQL it means var_pop()
* <ul>
* <li>On Postgres it means {@code var_samp()}
* <li>On Oracle, DB2, MySQL it means {@code var_pop()}
* </ul>
*/
public void variance() {
functionRegistry.namedAggregateDescriptorBuilder( "variance" )

View File

@ -27,7 +27,7 @@ import org.hibernate.internal.CoreMessageLogger;
public class Expectations {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( Expectations.class );
private static SqlExceptionHelper sqlExceptionHelper = new SqlExceptionHelper( false );
private static final SqlExceptionHelper sqlExceptionHelper = new SqlExceptionHelper( false );
public static final int USUAL_EXPECTED_COUNT = 1;
public static final int USUAL_PARAM_POSITION = 1;

View File

@ -1429,6 +1429,21 @@ public class FunctionTests {
);
}
@Test
public void testHyperbolic(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
assertEquals( Math.sinh(1), (Double) session.createQuery("select sinh(e.theDouble) from EntityOfBasics e")
.getSingleResult(), 1e-6 );
assertEquals( Math.cosh(1), (Double) session.createQuery("select cosh(e.theDouble) from EntityOfBasics e")
.getSingleResult(), 1e-6 );
assertEquals( Math.tanh(1), (Double) session.createQuery("select tanh(e.theDouble) from EntityOfBasics e")
.getSingleResult(), 1e-6 );
}
);
}
@Test
public void testGrouping(SessionFactoryScope scope) {
scope.inTransaction(