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
|
| `power()` | Exponentiation | `power(x,y)` | Universal in SQL dialects
|
||||||
| `ln()` | Natural logarithm | `ln(x)` | Very common in SQL dialects
|
| `ln()` | Natural logarithm | `ln(x)` | Very common in SQL dialects
|
||||||
| `log10()` | Base-10 logarithm | `log10(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
|
| `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
|
| `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
|
| `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);
|
CommonFunctionFactory functionFactory = new CommonFunctionFactory(queryEngine);
|
||||||
functionFactory.cot();
|
functionFactory.cot();
|
||||||
functionFactory.log();
|
|
||||||
functionFactory.ln_log();
|
functionFactory.ln_log();
|
||||||
|
functionFactory.log_loglog();
|
||||||
functionFactory.log10();
|
functionFactory.log10();
|
||||||
functionFactory.atan2_atn2();
|
functionFactory.atan2_atn2();
|
||||||
functionFactory.mod_operator();
|
functionFactory.mod_operator();
|
||||||
|
|
|
@ -207,7 +207,6 @@ public class DB2Dialect extends Dialect {
|
||||||
|
|
||||||
functionFactory.cot();
|
functionFactory.cot();
|
||||||
functionFactory.degrees();
|
functionFactory.degrees();
|
||||||
functionFactory.log();
|
|
||||||
functionFactory.log10();
|
functionFactory.log10();
|
||||||
functionFactory.radians();
|
functionFactory.radians();
|
||||||
functionFactory.rand();
|
functionFactory.rand();
|
||||||
|
|
|
@ -735,6 +735,7 @@ public abstract class Dialect implements ConversionContext {
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li> <code>pi</code>
|
* <li> <code>pi</code>
|
||||||
* <li> <code>log10(arg)</code>
|
* <li> <code>log10(arg)</code>
|
||||||
|
* <li> <code>log(base, arg)</code>
|
||||||
* <li> <code>sign(arg)</code>
|
* <li> <code>sign(arg)</code>
|
||||||
* <li> <code>sin(arg)</code>
|
* <li> <code>sin(arg)</code>
|
||||||
* <li> <code>cos(arg)</code>
|
* <li> <code>cos(arg)</code>
|
||||||
|
@ -817,6 +818,10 @@ public abstract class Dialect implements ConversionContext {
|
||||||
|
|
||||||
functionFactory.pi_acos();
|
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
|
//coalesce() function, supported by most databases, must be emulated
|
||||||
//in terms of nvl() for platforms which don't support it natively
|
//in terms of nvl() for platforms which don't support it natively
|
||||||
|
|
||||||
|
|
|
@ -444,7 +444,6 @@ public class MySQLDialect extends Dialect {
|
||||||
functionFactory.log();
|
functionFactory.log();
|
||||||
functionFactory.log2();
|
functionFactory.log2();
|
||||||
functionFactory.log10();
|
functionFactory.log10();
|
||||||
functionFactory.pi();
|
|
||||||
functionFactory.trim2();
|
functionFactory.trim2();
|
||||||
functionFactory.octetLength();
|
functionFactory.octetLength();
|
||||||
functionFactory.reverse();
|
functionFactory.reverse();
|
||||||
|
@ -498,6 +497,12 @@ public class MySQLDialect extends Dialect {
|
||||||
.setUseParenthesesWhenNoArgs( false )
|
.setUseParenthesesWhenNoArgs( false )
|
||||||
.register();
|
.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
|
// MySQL timestamp type defaults to precision 0 (seconds) but
|
||||||
// we want the standard default precision of 6 (microseconds)
|
// we want the standard default precision of 6 (microseconds)
|
||||||
functionFactory.sysdateExplicitMicros();
|
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
|
// 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.avg_castingNonDoubleArguments( this, SqlAstNodeRenderingMode.DEFAULT );
|
||||||
|
|
||||||
|
functionFactory.log_log();
|
||||||
|
|
||||||
functionFactory.truncate_round();
|
functionFactory.truncate_round();
|
||||||
functionFactory.everyAny_minMaxIif();
|
functionFactory.everyAny_minMaxIif();
|
||||||
functionFactory.octetLength_pattern( "datalength(?1)" );
|
functionFactory.octetLength_pattern( "datalength(?1)" );
|
||||||
|
|
|
@ -88,6 +88,9 @@ public class CommonFunctionFactory {
|
||||||
.register();
|
.register();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For databases where the first parameter is the base
|
||||||
|
*/
|
||||||
public void log() {
|
public void log() {
|
||||||
functionRegistry.namedDescriptorBuilder( "log" )
|
functionRegistry.namedDescriptorBuilder( "log" )
|
||||||
.setArgumentCountBetween( 1, 2 )
|
.setArgumentCountBetween( 1, 2 )
|
||||||
|
@ -96,6 +99,42 @@ public class CommonFunctionFactory {
|
||||||
.register();
|
.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() {
|
public void ln_log() {
|
||||||
functionRegistry.namedDescriptorBuilder( "ln", "log" )
|
functionRegistry.namedDescriptorBuilder( "ln", "log" )
|
||||||
.setInvariantType(doubleType)
|
.setInvariantType(doubleType)
|
||||||
|
@ -385,6 +424,7 @@ public class CommonFunctionFactory {
|
||||||
functionRegistry.noArgsBuilder( "pi" )
|
functionRegistry.noArgsBuilder( "pi" )
|
||||||
.setInvariantType(doubleType)
|
.setInvariantType(doubleType)
|
||||||
.setUseParenthesesWhenNoArgs( true )
|
.setUseParenthesesWhenNoArgs( true )
|
||||||
|
.setArgumentListSignature("")
|
||||||
.register();
|
.register();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,6 +432,7 @@ public class CommonFunctionFactory {
|
||||||
functionRegistry.patternDescriptorBuilder( "pi", "acos(-1)" )
|
functionRegistry.patternDescriptorBuilder( "pi", "acos(-1)" )
|
||||||
.setInvariantType(doubleType)
|
.setInvariantType(doubleType)
|
||||||
.setExactArgumentCount(0)
|
.setExactArgumentCount(0)
|
||||||
|
.setArgumentListSignature("")
|
||||||
.register();
|
.register();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import java.sql.Timestamp;
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.LocalTime;
|
import java.time.LocalTime;
|
||||||
|
|
||||||
|
import org.hamcrest.number.IsCloseTo;
|
||||||
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
import org.hibernate.testing.orm.domain.StandardDomainModel;
|
||||||
import org.hibernate.testing.orm.domain.gambit.EntityOfBasics;
|
import org.hibernate.testing.orm.domain.gambit.EntityOfBasics;
|
||||||
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
|
||||||
|
@ -913,8 +914,24 @@ public class StandardFunctionTests {
|
||||||
scope.inTransaction(
|
scope.inTransaction(
|
||||||
session -> {
|
session -> {
|
||||||
assertThat(
|
assertThat(
|
||||||
session.createQuery("select pi").getSingleResult(),
|
session.createQuery("select pi", Double.class).getSingleResult(),
|
||||||
is( Math.PI )
|
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