HHH-15516 add two-arg form of log() to HQL
This commit is contained in:
parent
1b5935e66d
commit
3ddfa3f47c
|
@ -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
|
||||
| `log()` | Arbitrary-base logarithm | `log(b,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
|
||||
|
|
|
@ -127,8 +127,8 @@ public abstract class AbstractTransactSQLDialect extends Dialect {
|
|||
|
||||
CommonFunctionFactory functionFactory = new CommonFunctionFactory(queryEngine);
|
||||
functionFactory.cot();
|
||||
functionFactory.log();
|
||||
functionFactory.ln_log();
|
||||
functionFactory.log_loglog();
|
||||
functionFactory.log10();
|
||||
functionFactory.atan2_atn2();
|
||||
functionFactory.mod_operator();
|
||||
|
|
|
@ -207,7 +207,6 @@ public class DB2Dialect extends Dialect {
|
|||
|
||||
functionFactory.cot();
|
||||
functionFactory.degrees();
|
||||
functionFactory.log();
|
||||
functionFactory.log10();
|
||||
functionFactory.radians();
|
||||
functionFactory.rand();
|
||||
|
|
|
@ -735,6 +735,7 @@ public abstract class Dialect implements ConversionContext {
|
|||
* <ul>
|
||||
* <li> <code>pi</code>
|
||||
* <li> <code>log10(arg)</code>
|
||||
* <li> <code>log(base, arg)</code>
|
||||
* <li> <code>sign(arg)</code>
|
||||
* <li> <code>sin(arg)</code>
|
||||
* <li> <code>cos(arg)</code>
|
||||
|
@ -817,6 +818,10 @@ public abstract class Dialect implements ConversionContext {
|
|||
|
||||
functionFactory.pi_acos();
|
||||
|
||||
//log(base, arg) supported on most databases, but emulate it here
|
||||
|
||||
functionFactory.log_ln();
|
||||
|
||||
//coalesce() function, supported by most databases, must be emulated
|
||||
//in terms of nvl() for platforms which don't support it natively
|
||||
|
||||
|
|
|
@ -444,7 +444,6 @@ public class MySQLDialect extends Dialect {
|
|||
functionFactory.log();
|
||||
functionFactory.log2();
|
||||
functionFactory.log10();
|
||||
functionFactory.pi();
|
||||
functionFactory.trim2();
|
||||
functionFactory.octetLength();
|
||||
functionFactory.reverse();
|
||||
|
@ -498,6 +497,12 @@ public class MySQLDialect extends Dialect {
|
|||
.setUseParenthesesWhenNoArgs( false )
|
||||
.register();
|
||||
|
||||
queryEngine.getSqmFunctionRegistry().patternDescriptorBuilder( "pi", "cast(pi() as double)" )
|
||||
.setInvariantType(basicTypeRegistry.resolve( StandardBasicTypes.DOUBLE ))
|
||||
.setExactArgumentCount(0)
|
||||
.setArgumentListSignature("")
|
||||
.register();
|
||||
|
||||
// MySQL timestamp type defaults to precision 0 (seconds) but
|
||||
// we want the standard default precision of 6 (microseconds)
|
||||
functionFactory.sysdateExplicitMicros();
|
||||
|
|
|
@ -265,6 +265,8 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
|
|||
// AVG by default uses the input type, so we possibly need to cast the argument type, hence a special function
|
||||
functionFactory.avg_castingNonDoubleArguments( this, SqlAstNodeRenderingMode.DEFAULT );
|
||||
|
||||
functionFactory.log_log();
|
||||
|
||||
functionFactory.truncate_round();
|
||||
functionFactory.everyAny_minMaxIif();
|
||||
functionFactory.octetLength_pattern( "datalength(?1)" );
|
||||
|
|
|
@ -88,6 +88,9 @@ public class CommonFunctionFactory {
|
|||
.register();
|
||||
}
|
||||
|
||||
/**
|
||||
* For databases where the first parameter is the base
|
||||
*/
|
||||
public void log() {
|
||||
functionRegistry.namedDescriptorBuilder( "log" )
|
||||
.setArgumentCountBetween( 1, 2 )
|
||||
|
@ -96,6 +99,42 @@ public class CommonFunctionFactory {
|
|||
.register();
|
||||
}
|
||||
|
||||
public void log_ln() {
|
||||
functionRegistry.patternDescriptorBuilder( "log", "ln(?2)/ln(?1)" )
|
||||
.setExactArgumentCount( 2 )
|
||||
.setParameterTypes(NUMERIC, NUMERIC)
|
||||
.setInvariantType(doubleType)
|
||||
.setArgumentListSignature("(NUMERIC base, NUMERIC arg)")
|
||||
.register();
|
||||
}
|
||||
|
||||
/**
|
||||
* SQL Server defines parameters in reverse order
|
||||
*/
|
||||
public void log_log() {
|
||||
functionRegistry.patternDescriptorBuilder( "log", "log(?2,?1)" )
|
||||
.setExactArgumentCount( 2 )
|
||||
.setParameterTypes(NUMERIC, NUMERIC)
|
||||
.setInvariantType(doubleType)
|
||||
.setArgumentListSignature("(NUMERIC base, NUMERIC arg)")
|
||||
.register();
|
||||
}
|
||||
|
||||
/**
|
||||
* For Sybase
|
||||
*/
|
||||
public void log_loglog() {
|
||||
functionRegistry.patternDescriptorBuilder( "log", "log(?2)/log(?1)" )
|
||||
.setExactArgumentCount( 2 )
|
||||
.setParameterTypes(NUMERIC, NUMERIC)
|
||||
.setInvariantType(doubleType)
|
||||
.setArgumentListSignature("(NUMERIC base, NUMERIC arg)")
|
||||
.register();
|
||||
}
|
||||
|
||||
/**
|
||||
* For SQL Server and Sybase
|
||||
*/
|
||||
public void ln_log() {
|
||||
functionRegistry.namedDescriptorBuilder( "ln", "log" )
|
||||
.setInvariantType(doubleType)
|
||||
|
@ -385,6 +424,7 @@ public class CommonFunctionFactory {
|
|||
functionRegistry.noArgsBuilder( "pi" )
|
||||
.setInvariantType(doubleType)
|
||||
.setUseParenthesesWhenNoArgs( true )
|
||||
.setArgumentListSignature("")
|
||||
.register();
|
||||
}
|
||||
|
||||
|
@ -392,6 +432,7 @@ public class CommonFunctionFactory {
|
|||
functionRegistry.patternDescriptorBuilder( "pi", "acos(-1)" )
|
||||
.setInvariantType(doubleType)
|
||||
.setExactArgumentCount(0)
|
||||
.setArgumentListSignature("")
|
||||
.register();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.sql.Timestamp;
|
|||
import java.time.LocalDate;
|
||||
import java.time.LocalTime;
|
||||
|
||||
import org.hamcrest.number.IsCloseTo;
|
||||
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
||||
import org.hibernate.testing.orm.domain.gambit.EntityOfBasics;
|
||||
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
||||
|
@ -913,8 +914,24 @@ public class StandardFunctionTests {
|
|||
scope.inTransaction(
|
||||
session -> {
|
||||
assertThat(
|
||||
session.createQuery("select pi").getSingleResult(),
|
||||
is( Math.PI )
|
||||
session.createQuery("select pi", Double.class).getSingleResult(),
|
||||
IsCloseTo.closeTo( Math.PI, 1e-9 )
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLog(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
assertThat(
|
||||
session.createQuery("select log(3,9)", Double.class).getSingleResult(),
|
||||
IsCloseTo.closeTo( 2d, 1e-9 )
|
||||
);
|
||||
assertThat(
|
||||
session.createQuery("select log(10,1e12)", Double.class).getSingleResult(),
|
||||
IsCloseTo.closeTo( 12d, 1e-9 )
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue