This is an automated email from the ASF dual-hosted git repository.
solomax pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/openjpa.git
The following commit(s) were added to refs/heads/master by this push:
new 4cc305099 [OPENJPA-2932] Implements numeric JPA 3.1 JPQL functions and
equivalent Criteria API (#122)
4cc305099 is described below
commit 4cc3050998afbdf8d59d5e96ccc9ff0580ee07ff
Author: Paulo Cristovão de Araújo Silva Filho <[email protected]>
AuthorDate: Sun Feb 2 11:34:55 2025 -0300
[OPENJPA-2932] Implements numeric JPA 3.1 JPQL functions and equivalent
Criteria API (#122)
* [OPENJPA-2932] Implements numeric JPA 3.1 JPQL functions and equivalent
Criteria API
* Implements CEILING, EXP, FLOOR, SIGN, LN, POWER and ROUND JPQL functions
* Ajusts JPQL.jjt
* Added kernel and jdbc equivalent expressions
* Added one test for each new expression in JPQL and Criteria API
* Updates manual page referring new FUNCTIONS
* Added DatabaseHelper to add necessary functions on DerbyDb (it does not
natively support POWER and ROUND functions)
---
.../apache/openjpa/jdbc/kernel/JDBCStoreQuery.java | 3 +
.../apache/openjpa/jdbc/kernel/exps/Ceiling.java | 66 +++++++++
.../openjpa/jdbc/kernel/exps/Exponential.java | 52 +++++++
.../org/apache/openjpa/jdbc/kernel/exps/Floor.java | 66 +++++++++
.../jdbc/kernel/exps/JDBCExpressionFactory.java | 35 +++++
.../org/apache/openjpa/jdbc/kernel/exps/Math.java | 2 +
.../openjpa/jdbc/kernel/exps/NaturalLogarithm.java | 52 +++++++
.../org/apache/openjpa/jdbc/kernel/exps/Sign.java | 57 ++++++++
.../org/apache/openjpa/jdbc/kernel/exps/Val.java | 5 +
.../org/apache/openjpa/jdbc/sql/DBDictionary.java | 9 +-
.../java/org/apache/openjpa/kernel/Filters.java | 43 +++++-
.../org/apache/openjpa/kernel/exps/Ceiling.java | 76 ++++++++++
.../apache/openjpa/kernel/exps/Exponential.java | 47 +++++++
.../openjpa/kernel/exps/ExpressionFactory.java | 35 +++++
.../java/org/apache/openjpa/kernel/exps/Floor.java | 76 ++++++++++
.../kernel/exps/InMemoryExpressionFactory.java | 35 +++++
.../openjpa/kernel/exps/NaturalLogarithm.java | 47 +++++++
.../java/org/apache/openjpa/kernel/exps/Power.java | 46 ++++++
.../java/org/apache/openjpa/kernel/exps/Round.java | 45 ++++++
.../java/org/apache/openjpa/kernel/exps/Sign.java | 59 ++++++++
.../openjpa/kernel/jpql/JPQLExpressionBuilder.java | 21 +++
.../jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt | 57 +++++++-
.../persistence/common/utils/DatabaseHelper.java | 156 +++++++++++++++++++++
.../persistence/criteria/TestTypesafeCriteria.java | 76 ++++++++++
.../jpql/functions/TestEJBQLFunction.java | 143 +++++++++++++++++++
.../persistence/criteria/CriteriaBuilderImpl.java | 87 ++++++------
.../openjpa/persistence/criteria/Expressions.java | 133 ++++++++++++++++++
.../src/doc/manual/jpa_overview_query.xml | 149 ++++++++++++++++++--
28 files changed, 1613 insertions(+), 65 deletions(-)
diff --git
a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
index ce69d3634..ebd107f2d 100644
---
a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
+++
b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreQuery.java
@@ -841,6 +841,9 @@ public class JDBCStoreQuery
return Filters.divide(val1, c1, val2, c2);
else if (op.equals(org.apache.openjpa.jdbc.kernel.exps.Math.MOD))
return Filters.mod(val1, c1, val2, c2);
+ else if (op.equals(org.apache.openjpa.jdbc.kernel.exps.Math.POWER)) {
+ return Filters.power(val1, c1, val2, c2);
+ }
throw new UnsupportedException();
}
diff --git
a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Ceiling.java
b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Ceiling.java
new file mode 100644
index 000000000..4cd583234
--- /dev/null
+++
b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Ceiling.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.jdbc.kernel.exps;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import org.apache.openjpa.kernel.Filters;
+
+/**
+ * Ceiling value.
+ */
+public class Ceiling
+ extends UnaryOp {
+
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor. Provide the value to operate on.
+ */
+ public Ceiling(Val val) {
+ super(val);
+ }
+
+ @Override
+ protected Class getType(Class c) {
+ Class wrap = Filters.wrap(c);
+ if (wrap == Integer.class
+ || wrap == Float.class
+ || wrap == Double.class
+ || wrap == Long.class
+ || wrap == BigDecimal.class
+ || wrap == BigInteger.class) {
+ return Filters.unwrap(c);
+ }
+ return int.class;
+ }
+
+ @Override
+ protected String getOperator() {
+ return "CEILING";
+ }
+
+ @Override
+ public int getId() {
+ return Val.CEILING_VAL;
+ }
+}
+
diff --git
a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Exponential.java
b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Exponential.java
new file mode 100644
index 000000000..c6fdc867e
--- /dev/null
+++
b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Exponential.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.jdbc.kernel.exps;
+
+/**
+ * Exponential value.
+ */
+public class Exponential
+ extends UnaryOp {
+
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor. Provide the value to which the Euler's constant should be
powered.
+ */
+ public Exponential(Val val) {
+ super(val);
+ }
+
+ @Override
+ protected Class getType(Class c) {
+ return double.class;
+ }
+
+ @Override
+ protected String getOperator() {
+ return "EXP";
+ }
+
+ @Override
+ public int getId() {
+ return Val.EXP_VAL;
+ }
+}
+
diff --git
a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Floor.java
b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Floor.java
new file mode 100644
index 000000000..e8f7740aa
--- /dev/null
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Floor.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.jdbc.kernel.exps;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import org.apache.openjpa.kernel.Filters;
+
+/**
+ * Floor value.
+ */
+public class Floor
+ extends UnaryOp {
+
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor. Provide the value to operate on.
+ */
+ public Floor(Val val) {
+ super(val);
+ }
+
+ @Override
+ protected Class getType(Class c) {
+ Class wrap = Filters.wrap(c);
+ if (wrap == Integer.class
+ || wrap == Float.class
+ || wrap == Double.class
+ || wrap == Long.class
+ || wrap == BigDecimal.class
+ || wrap == BigInteger.class) {
+ return Filters.unwrap(c);
+ }
+ return int.class;
+ }
+
+ @Override
+ protected String getOperator() {
+ return "FLOOR";
+ }
+
+ @Override
+ public int getId() {
+ return Val.FLOOR_VAL;
+ }
+}
+
diff --git
a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java
b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java
index fbb273270..41e6f5b30 100644
---
a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java
+++
b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/JDBCExpressionFactory.java
@@ -448,6 +448,41 @@ public class JDBCExpressionFactory
public Value abs(Value val) {
return new Abs((Val) val);
}
+
+ @Override
+ public Value ceiling(Value val) {
+ return new Ceiling((Val) val);
+ }
+
+ @Override
+ public Value exp(Value val) {
+ return new Exponential((Val) val);
+ }
+
+ @Override
+ public Value floor(Value val) {
+ return new Floor((Val) val);
+ }
+
+ @Override
+ public Value ln(Value val) {
+ return new NaturalLogarithm((Val) val);
+ }
+
+ @Override
+ public Value sign(Value val) {
+ return new Sign((Val) val);
+ }
+
+ @Override
+ public Value power(Value base, Value exponent) {
+ return new Math((Val) base, (Val) exponent, Math.POWER);
+ }
+
+ @Override
+ public Value round(Value num, Value precision) {
+ return new Math((Val) num, (Val) precision, Math.ROUND);
+ }
@Override
public Value indexOf(Value v1, Value v2) {
diff --git
a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Math.java
b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Math.java
index 744130d3d..dfbab290d 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Math.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Math.java
@@ -43,6 +43,8 @@ public class Math
public static final String MULTIPLY = "*";
public static final String DIVIDE = "/";
public static final String MOD = "MOD";
+ public static final String POWER = "POWER";
+ public static final String ROUND = "ROUND";
private final Val _val1;
private final Val _val2;
diff --git
a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NaturalLogarithm.java
b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NaturalLogarithm.java
new file mode 100644
index 000000000..9c940a3f8
--- /dev/null
+++
b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/NaturalLogarithm.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.jdbc.kernel.exps;
+
+/**
+ * Natural logarithm (base e) value.
+ */
+public class NaturalLogarithm
+ extends UnaryOp {
+
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor. Provide the value from which the natural logarithm should
be calculated.
+ */
+ public NaturalLogarithm(Val val) {
+ super(val);
+ }
+
+ @Override
+ protected Class getType(Class c) {
+ return double.class;
+ }
+
+ @Override
+ protected String getOperator() {
+ return "LN";
+ }
+
+ @Override
+ public int getId() {
+ return Val.LN_VAL;
+ }
+}
+
diff --git
a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Sign.java
b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Sign.java
new file mode 100644
index 000000000..1079a3557
--- /dev/null
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Sign.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.jdbc.kernel.exps;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import org.apache.openjpa.kernel.Filters;
+
+/**
+ * Sign value.
+ */
+public class Sign
+ extends UnaryOp {
+
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor. Provide the value whose sign will be found.
+ */
+ public Sign(Val val) {
+ super(val);
+ }
+
+ @Override
+ protected Class getType(Class c) {
+ return int.class;
+ }
+
+ @Override
+ protected String getOperator() {
+ return "SIGN";
+ }
+
+ @Override
+ public int getId() {
+ return Val.SIGN_VAL;
+ }
+}
+
diff --git
a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Val.java
b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Val.java
index 049cec503..958bb024d 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Val.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Val.java
@@ -75,6 +75,11 @@ public interface Val
int WHENSCALAR_VAL = 16;
int COALESCE_VAL = 17;
int NULLIF_VAL = 18;
+ int CEILING_VAL = 19;
+ int EXP_VAL = 20;
+ int FLOOR_VAL = 21;
+ int LN_VAL = 22;
+ int SIGN_VAL = 23;
/**
* Initialize the value. This method should recursively initialize any
diff --git
a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
index 025306b5a..9dbba34c9 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
@@ -3181,12 +3181,15 @@ public class DBDictionary
}
boolean mod = "MOD".equals(op);
- if (mod) {
- if (supportsModOperator)
+ boolean power = "POWER".equals(op);
+ boolean round = "ROUND".equals(op);
+ if (mod || power || round) {
+ if (supportsModOperator && mod)
op = "%";
else
buf.append(op);
}
+
buf.append("(");
if (castlhs)
@@ -3194,7 +3197,7 @@ public class DBDictionary
else
lhs.appendTo(buf);
- if (mod && !supportsModOperator)
+ if ((mod && !supportsModOperator) || power || round)
buf.append(", ");
else
buf.append(" ").append(op).append(" ");
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
index 5cc92f006..36df09254 100644
--- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Filters.java
@@ -21,6 +21,7 @@ package org.apache.openjpa.kernel;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
+import java.math.RoundingMode;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.sql.Time;
@@ -65,6 +66,8 @@ public class Filters {
private static final int OP_MULTIPLY = 2;
private static final int OP_DIVIDE = 3;
private static final int OP_MOD = 4;
+ private static final int OP_POWER = 5;
+ private static final int OP_ROUND = 6;
private static final Localizer _loc = Localizer.forPackage(Filters.class);
@@ -480,6 +483,17 @@ public class Filters {
return op(o1, c1, o2, c2, OP_MOD);
}
+ /**
+ * Power the base to the exponent
+ */
+ public static Object power(Object o1, Class<?> c1, Object o2, Class<?> c2)
{
+ return op(o1, c1, o2, c2, OP_POWER);
+ }
+
+ public static Object round(Object o1, Class<?> c1, Object o2, Class<?> c2)
{
+ return op(o1, c1, o2, c2, OP_ROUND);
+ }
+
/**
* Perform the given operation on two numbers.
*/
@@ -546,6 +560,10 @@ public class Filters {
case OP_MOD:
tot = n1 % n2;
break;
+ case OP_POWER:
+ return Math.pow(n1, n2);
+ case OP_ROUND:
+ tot = n1;
default:
throw new InternalException();
}
@@ -573,7 +591,12 @@ public class Filters {
case OP_MOD:
tot = n1 % n2;
break;
- default:
+ case OP_POWER:
+ return Math.pow(n1, n2);
+ case OP_ROUND:
+ BigDecimal bg = new BigDecimal(Float.toString(n1));
+ return bg.setScale(Math.toIntExact(Math.round(n2)),
RoundingMode.HALF_EVEN).floatValue();
+ default:
throw new InternalException();
}
return tot;
@@ -600,6 +623,12 @@ public class Filters {
case OP_MOD:
tot = n1 % n2;
break;
+ case OP_POWER:
+ tot = Math.pow(n1, n2);
+ break;
+ case OP_ROUND:
+ BigDecimal bg = new BigDecimal(Double.toString(n1));
+ return bg.setScale(Math.toIntExact(Math.round(n2)),
RoundingMode.HALF_EVEN).doubleValue();
default:
throw new InternalException();
}
@@ -627,6 +656,10 @@ public class Filters {
case OP_MOD:
tot = n1 % n2;
break;
+ case OP_POWER:
+ return Math.pow(n1, n2);
+ case OP_ROUND:
+ return n1;
default:
throw new InternalException();
}
@@ -649,6 +682,10 @@ public class Filters {
return n1.divide(n2, scale, BigDecimal.ROUND_HALF_UP);
case OP_MOD:
throw new UserException(_loc.get("mod-bigdecimal"));
+ case OP_POWER:
+ return n1.pow(n2.intValue());
+ case OP_ROUND:
+ return n1.setScale(n2.intValue(), RoundingMode.HALF_EVEN);
default:
throw new InternalException();
}
@@ -667,6 +704,10 @@ public class Filters {
return n1.multiply(n2);
case OP_DIVIDE:
return n1.divide(n2);
+ case OP_POWER:
+ return n1.pow(n2.intValue());
+ case OP_ROUND:
+ return n1;
default:
throw new InternalException();
}
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Ceiling.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Ceiling.java
new file mode 100644
index 000000000..19123b661
--- /dev/null
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Ceiling.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.kernel.exps;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.RoundingMode;
+
+import org.apache.openjpa.kernel.Filters;
+
+/**
+ * Take the ceiling value of a number.
+ */
+class Ceiling
+ extends UnaryMathVal {
+
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor. Provide the number whose ceiling value to calculate.
+ */
+ public Ceiling(Val val) {
+ super(val);
+ }
+
+ @Override
+ protected Class getType(Class c) {
+ Class wrap = Filters.wrap(c);
+ if (wrap == Integer.class
+ || wrap == Float.class
+ || wrap == Double.class
+ || wrap == Long.class
+ || wrap == BigDecimal.class
+ || wrap == BigInteger.class) {
+ return Filters.unwrap(c);
+ }
+ return int.class;
+ }
+
+ @Override
+ protected Object operate(Object o, Class c) {
+ c = Filters.wrap(c);
+ if (c == Integer.class)
+ return Math.ceil(((Number) o).intValue());
+ if (c == Float.class)
+ return Math.ceil(((Number) o).floatValue());
+ if (c == Double.class)
+ return Math.ceil(((Number) o).doubleValue());
+ if (c == Long.class)
+ return Math.ceil(((Number) o).longValue());
+ if (c == BigDecimal.class)
+ return ((BigDecimal) o).setScale(0, RoundingMode.CEILING);
+ if (c == BigInteger.class)
+ return ((BigInteger) o);
+
+ // default to int
+ return Math.ceil(((Number) o).intValue());
+ }
+}
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Exponential.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Exponential.java
new file mode 100644
index 000000000..ef34c7a78
--- /dev/null
+++
b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Exponential.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.kernel.exps;
+
+/**
+ * Exponential value.
+ *
+ */
+class Exponential
+ extends UnaryMathVal {
+
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor. Provide the value to which the Euler's constant should be
powered.
+ */
+ public Exponential(Val val) {
+ super(val);
+ }
+
+ @Override
+ protected Class getType(Class c) {
+ return double.class;
+ }
+
+ @Override
+ protected Object operate(Object o, Class c) {
+ return Math.exp(((Number) o).doubleValue());
+ }
+}
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java
index 8c6b86cfd..38f433935 100644
---
a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java
+++
b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/ExpressionFactory.java
@@ -327,6 +327,41 @@ public interface ExpressionFactory {
* Return a value representing the absolute value of the given one.
*/
Value abs(Value num);
+
+ /**
+ * Returns a value representing the ceiling value of the given one.
+ */
+ Value ceiling(Value num);
+
+ /**
+ * Returns a value representing the Euler's e constant powered to the
given value.
+ */
+ Value exp(Value num);
+
+ /**
+ * Returns a value representing the floor of the given value.
+ */
+ Value floor(Value num);
+
+ /**
+ * Returns the natural logarithm of the given value
+ */
+ Value ln(Value num);
+
+ /**
+ * Returns the sign of the given value as a number (-1 for negative, 0 for
zeroes and 1 for positive)
+ */
+ Value sign(Value num);
+
+ /**
+ * Returns a value representing base powered by the exponent
+ */
+ Value power(Value base, Value exponent);
+
+ /*
+ * Returns the number rounded to the given precision.
+ */
+ Value round(Value num, Value precision);
/**
* Return a value representing the indexOf (LOCATE in JPQL) function on
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Floor.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Floor.java
new file mode 100644
index 000000000..95b1ffdf3
--- /dev/null
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Floor.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.kernel.exps;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.RoundingMode;
+
+import org.apache.openjpa.kernel.Filters;
+
+/**
+ * Take the floor value of a number.
+ */
+class Floor
+ extends UnaryMathVal {
+
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor. Provide the number whose floor value will be calculated.
+ */
+ public Floor(Val val) {
+ super(val);
+ }
+
+ @Override
+ protected Class getType(Class c) {
+ Class wrap = Filters.wrap(c);
+ if (wrap == Integer.class
+ || wrap == Float.class
+ || wrap == Double.class
+ || wrap == Long.class
+ || wrap == BigDecimal.class
+ || wrap == BigInteger.class) {
+ return Filters.unwrap(c);
+ }
+ return int.class;
+ }
+
+ @Override
+ protected Object operate(Object o, Class c) {
+ c = Filters.wrap(c);
+ if (c == Integer.class)
+ return Math.floor(((Number) o).intValue());
+ if (c == Float.class)
+ return Math.floor(((Number) o).floatValue());
+ if (c == Double.class)
+ return Math.floor(((Number) o).doubleValue());
+ if (c == Long.class)
+ return Math.floor(((Number) o).longValue());
+ if (c == BigDecimal.class)
+ return ((BigDecimal) o).setScale(0, RoundingMode.FLOOR);
+ if (c == BigInteger.class)
+ return ((BigInteger) o);
+
+ // default to int
+ return Math.floor(((Number) o).intValue());
+ }
+}
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java
index 8e83bbe5f..00a399d8c 100644
---
a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java
+++
b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/InMemoryExpressionFactory.java
@@ -624,6 +624,41 @@ public class InMemoryExpressionFactory
public Value abs(Value val) {
return new Abs((Val) val);
}
+
+ @Override
+ public Value ceiling(Value val) {
+ return new Ceiling((Val) val);
+ }
+
+ @Override
+ public Value exp(Value val) {
+ return new Exponential((Val) val);
+ }
+
+ @Override
+ public Value floor(Value val) {
+ return new Floor((Val) val);
+ }
+
+ @Override
+ public Value ln(Value val) {
+ return new NaturalLogarithm(((Val) val));
+ }
+
+ @Override
+ public Value sign(Value val) {
+ return new Sign((Val) val);
+ }
+
+ @Override
+ public Value power(Value base, Value exponent) {
+ return new Power((Val) base, (Val) exponent);
+ }
+
+ @Override
+ public Value round(Value num, Value precision) {
+ return new Round((Val) num, (Val) precision);
+ }
@Override
public Value indexOf(Value val1, Value val2) {
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/NaturalLogarithm.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/NaturalLogarithm.java
new file mode 100644
index 000000000..38bb1e805
--- /dev/null
+++
b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/NaturalLogarithm.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.kernel.exps;
+
+/**
+ * Natural logarithm (base e) value.
+ *
+ */
+class NaturalLogarithm
+ extends UnaryMathVal {
+
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor. Provide the value from which the natural logarithm should
be calculated.
+ */
+ public NaturalLogarithm(Val val) {
+ super(val);
+ }
+
+ @Override
+ protected Class getType(Class c) {
+ return double.class;
+ }
+
+ @Override
+ protected Object operate(Object o, Class c) {
+ return Math.log(((Number) o).doubleValue());
+ }
+}
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Power.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Power.java
new file mode 100644
index 000000000..70c7a539f
--- /dev/null
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Power.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.kernel.exps;
+
+import org.apache.openjpa.kernel.Filters;
+
+/**
+ * Value produced by one value being powered by another.
+ *
+ * @author Abe White
+ */
+class Power
+ extends MathVal {
+
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor. Provide the values to divide.
+ */
+ public Power(Val val1, Val val2) {
+ super(val1, val2);
+ }
+
+ @Override
+ protected Object operate(Object o1, Class c1, Object o2, Class c2) {
+ return Filters.power(o1, c1, o2, c2);
+ }
+}
+
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Round.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Round.java
new file mode 100644
index 000000000..ccb6fbaf2
--- /dev/null
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Round.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.kernel.exps;
+
+import org.apache.openjpa.kernel.Filters;
+
+/**
+ * Value produced by one value being rounded to the another precision.
+ *
+ */
+class Round
+ extends MathVal {
+
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor. Rounds the value to a given precision.
+ */
+ public Round(Val val1, Val val2) {
+ super(val1, val2);
+ }
+
+ @Override
+ protected Object operate(Object o1, Class c1, Object o2, Class c2) {
+ return Filters.round(o1, c1, o2, c2);
+ }
+}
+
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Sign.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Sign.java
new file mode 100644
index 000000000..0816bfc57
--- /dev/null
+++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Sign.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.kernel.exps;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import org.apache.openjpa.kernel.Filters;
+
+/**
+ * Take the sign of a number.
+ */
+class Sign
+ extends UnaryMathVal {
+
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructor. Provide the value whose sign will be found.
+ */
+ public Sign(Val val) {
+ super(val);
+ }
+
+ @Override
+ protected Class getType(Class c) {
+ return int.class;
+ }
+
+ @Override
+ protected Object operate(Object o, Class c) {
+ c = Filters.wrap(c);
+ float value = 0;
+ if (c == Integer.class || c == Float.class || c == Double.class || c
== Long.class)
+ value = ((Number) o).floatValue();
+ else if (c == BigDecimal.class)
+ value = ((BigDecimal) o).floatValue();
+ else if (c == BigInteger.class)
+ value = ((BigInteger) o).floatValue();
+ return Math.round(Math.signum(value));
+ }
+}
diff --git
a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
index fb7af4277..68c71456e 100644
---
a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
+++
b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
@@ -1273,6 +1273,27 @@ public class JPQLExpressionBuilder
case JJTABS:
return factory.abs(getNumberValue(onlyChild(node)));
+
+ case JJTCEILING:
+ return factory.ceiling(getNumberValue(onlyChild(node)));
+
+ case JJTEXP:
+ return factory.exp(getNumberValue(onlyChild(node)));
+
+ case JJTFLOOR:
+ return factory.floor(getNumberValue(onlyChild(node)));
+
+ case JJTLN:
+ return factory.ln(getNumberValue(onlyChild(node)));
+
+ case JJTSIGN:
+ return factory.sign(getNumberValue(onlyChild(node)));
+
+ case JJTPOWER:
+ return factory.power(getNumberValue(firstChild(node)),
getNumberValue(secondChild(node)));
+
+ case JJTROUND:
+ return factory.round(getNumberValue(firstChild(node)),
getNumberValue(secondChild(node)));
case JJTSQRT:
return factory.sqrt(getNumberValue(onlyChild(node)));
diff --git
a/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt
b/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt
index 8ee0aa099..a14aec2ea 100644
--- a/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt
+++ b/openjpa-kernel/src/main/jjtree/org/apache/openjpa/kernel/jpql/JPQL.jjt
@@ -208,6 +208,13 @@ TOKEN [ IGNORE_CASE ]: /* functions returning numerics */
< LENGTH: "LENGTH" >
| < LOCATE: "LOCATE" >
| < ABS: "ABS" >
+ | < CEILING: "CEILING" >
+ | < EXP: "EXP" >
+ | < FLOOR: "FLOOR" >
+ | < LN: "LN" >
+ | < SIGN: "SIGN" >
+ | < POWER: "POWER" >
+ | < ROUND: "ROUND" >
| < SQRT: "SQRT" >
| < MOD: "MOD" >
| < SIZE: "SIZE" >
@@ -1233,7 +1240,7 @@ void trim_specification() : { }
void functions_returning_numerics() : { }
{
- length() | locate() | abs() | sqrt() | mod() | size() | index()
+ length() | locate() | abs() | ceiling() | exp() | floor() | ln() |
sign() | power() | round() | sqrt() | mod() | size() | index()
}
@@ -1258,6 +1265,47 @@ void abs() #ABS : { }
}
+void ceiling() #CEILING : { }
+{
+ <CEILING> "(" arithmetic_expression() ")"
+
+}
+
+void exp() #EXP : { }
+{
+ <EXP> "(" arithmetic_expression() ")"
+
+}
+
+void floor() #FLOOR : { }
+{
+ <FLOOR> "(" arithmetic_expression() ")"
+
+}
+
+void ln() #LN : { }
+{
+ <LN> "(" arithmetic_expression() ")"
+
+}
+
+void sign() #SIGN : { }
+{
+ <SIGN> "(" arithmetic_expression() ")"
+
+}
+
+void power() #POWER : { }
+{
+ <POWER> "(" arithmetic_expression() <COMMA> arithmetic_expression() ")"
+
+}
+
+void round() #ROUND : { }
+{
+ <ROUND> "(" arithmetic_expression() <COMMA> arithmetic_expression() ")"
+
+}
void sqrt() #SQRT : { }
{
@@ -1376,6 +1424,13 @@ void path_component() #IDENTIFICATIONVARIABLE :
| t = <LENGTH>
| t = <LOCATE>
| t = <ABS>
+ | t = <CEILING>
+ | t = <EXP>
+ | t = <FLOOR>
+ | t = <LN>
+ | t = <SIGN>
+ | t = <POWER>
+ | t = <ROUND>
| t = <SQRT>
| t = <MOD>
| t = <SIZE>
diff --git
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/common/utils/DatabaseHelper.java
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/common/utils/DatabaseHelper.java
new file mode 100644
index 000000000..b61ce71ca
--- /dev/null
+++
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/common/utils/DatabaseHelper.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.common.utils;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.jdbc.sql.DerbyDictionary;
+import org.apache.openjpa.kernel.Broker;
+import org.apache.openjpa.persistence.JPAFacadeHelper;
+
+import jakarta.persistence.EntityManager;
+
+/**
+ * Allows augmentation of databases, if they don't have support to some
+ * necessary functions, such as DerbyDb's lack of POWER and ROUND
+ */
+public class DatabaseHelper {
+
+ private static final String CREATE_DERBYDB_POWER_FUNCTION_SQL = "CREATE
FUNCTION POWER(a DOUBLE, b DOUBLE) " +
+ "RETURNS DOUBLE PARAMETER STYLE JAVA NO SQL LANGUAGE JAVA EXTERNAL
NAME 'java.lang.Math.pow'";
+
+ private static final String DROP_DERBYDB_POWER_FUNCTION_SQL = "DROP
FUNCTION POWER";
+
+ private static final String CREATE_DERBYDB_ROUND_FUNCTION_SQL = "CREATE
FUNCTION ROUND(a DOUBLE, b INTEGER) " +
+ "RETURNS DOUBLE PARAMETER STYLE JAVA NO SQL LANGUAGE JAVA " +
+ "EXTERNAL NAME
'org.apache.openjpa.persistence.common.utils.DatabaseHelper.roundFunction'";
+
+ private static final String DROP_DERBYDB_ROUND_FUNCTION_SQL = "DROP
FUNCTION ROUND";
+
+ /**
+ * Creates the POWER function on DerbyDB, ignoring exceptions if it
already exists.
+ *
+ */
+ public static void createPowerFunctionIfNecessary(EntityManager em,
DBDictionary dict) {
+ if (dict instanceof DerbyDictionary) {
+ try {
+ exec(em, true, 10, CREATE_DERBYDB_POWER_FUNCTION_SQL);
+ } catch (Exception ex) {
+ // swallowing because the function probably already exists and
any exceptions
+ // should have been ignored on exec.
+ }
+ }
+ }
+
+ /**
+ * Drops the POWER function on DerbyDB.
+ *
+ */
+ public static void dropPowerFunction(EntityManager em, DBDictionary dict) {
+ if (dict instanceof DerbyDictionary) {
+ try {
+ exec(em, true, 10, DROP_DERBYDB_POWER_FUNCTION_SQL);
+ } catch (Exception ex) {
+ // swallowing because this is just a clean-up
+ }
+ }
+ }
+
+ /**
+ * Creates the ROUND function on DerbyDB, ignoring exceptions if it
already exists.
+ *
+ */
+ public static void createRoundFunctionIfNecessary(EntityManager em,
DBDictionary dict) {
+ if (dict instanceof DerbyDictionary) {
+ try {
+ exec(em, true, 10, CREATE_DERBYDB_ROUND_FUNCTION_SQL);
+ } catch (Exception ex) {
+ // swallowing because the function probably already exists and
any exceptions
+ // should have been ignored on exec.
+ }
+ }
+ }
+
+ public static void dropRoundFunction(EntityManager em, DBDictionary dict) {
+ if (dict instanceof DerbyDictionary) {
+ try {
+ exec(em, true, 10, DROP_DERBYDB_ROUND_FUNCTION_SQL);
+ } catch (Exception ex) {
+ // swallowing because this is just a clean-up
+ }
+ }
+
+ }
+
+ /**
+ * Rounds the number to given precision.
+ */
+ public static double roundFunction(Double num, int precision) {
+ BigDecimal db = new BigDecimal(Double.toString(num));
+ return db.setScale(precision, RoundingMode.HALF_EVEN).doubleValue();
+ }
+
+ /**
+ * Convenience method to execute SQL statements. Does not close
EntityManager
+ * after executing.
+ *
+ * @param em EntityManager whose connection will be extracted
+ * @param ignoreExceptions indicate if exceptions should be ignored during
executions
+ * @param timeoutSecs timeout, in seconds, of execution
+ * @param sql SQL to be executed
+ * @throws SQLException
+ */
+ static void exec(EntityManager em, boolean ignoreExceptions, int
timeoutSecs, String sql)
+ throws SQLException {
+ Statement s = null;
+ try {
+ assertNotNull(em);
+ Broker broker = JPAFacadeHelper.toBroker(em);
+ Connection conn = (Connection) broker.getConnection();
+ s = conn.createStatement();
+ if (timeoutSecs > 0) {
+ s.setQueryTimeout(timeoutSecs);
+ }
+ s.execute(sql);
+ } catch (SQLException sqe) {
+ if (!ignoreExceptions) {
+ // fail(sqe.toString());
+ throw sqe;
+ }
+ } finally {
+ if (s != null) {
+ try {
+ s.close();
+ } catch (Exception e) {
+ // ignore
+ }
+ }
+ }
+ }
+
+
+}
diff --git
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestTypesafeCriteria.java
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestTypesafeCriteria.java
index 09b313327..80ddda975 100644
---
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestTypesafeCriteria.java
+++
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestTypesafeCriteria.java
@@ -49,6 +49,7 @@ import jakarta.persistence.metamodel.Metamodel;
import org.apache.openjpa.jdbc.sql.AbstractSQLServerDictionary;
import org.apache.openjpa.jdbc.sql.OracleDictionary;
+import org.apache.openjpa.persistence.common.utils.DatabaseHelper;
import org.apache.openjpa.persistence.test.AllowFailure;
/**
@@ -185,6 +186,80 @@ public class TestTypesafeCriteria extends CriteriaTest {
assertEquivalence(c, jpql);
}
+ public void testCeilingExpression() {
+ String jpql = "select a from Account a where ceiling(a.balance)=100";
+
+ CriteriaQuery<Account> c = cb.createQuery(Account.class);
+ Root<Account> account = c.from(Account.class);
+
+
c.select(account).where(cb.equal(cb.ceiling(account.get(Account_.balance)),
100));
+ assertEquivalence(c, jpql);
+ }
+
+ public void testExponentialExpression() {
+ String jpql = "select a from Account a where exp(a.balance)=100";
+
+ CriteriaQuery<Account> c = cb.createQuery(Account.class);
+ Root<Account> account = c.from(Account.class);
+
+
c.select(account).where(cb.equal(cb.exp(account.get(Account_.balance)), 100));
+ assertEquivalence(c, jpql);
+ }
+
+ public void testFloorExpression() {
+ String jpql = "select a from Account a where floor(a.balance)=100";
+
+ CriteriaQuery<Account> c = cb.createQuery(Account.class);
+ Root<Account> account = c.from(Account.class);
+
+
c.select(account).where(cb.equal(cb.floor(account.get(Account_.balance)), 100));
+ assertEquivalence(c, jpql);
+ }
+
+ public void testLnExpression() {
+ String jpql = "select a from Account a where ln(a.balance)=100";
+
+ CriteriaQuery<Account> c = cb.createQuery(Account.class);
+ Root<Account> account = c.from(Account.class);
+
+ c.select(account).where(cb.equal(cb.ln(account.get(Account_.balance)),
100));
+ assertEquivalence(c, jpql);
+ }
+
+ public void testSignExpression() {
+ String jpql = "select a from Account a where sign(a.balance)=1";
+
+ CriteriaQuery<Account> c = cb.createQuery(Account.class);
+ Root<Account> account = c.from(Account.class);
+
+
c.select(account).where(cb.equal(cb.sign(account.get(Account_.balance)), 1));
+ assertEquivalence(c, jpql);
+ }
+
+ public void testPowerExpression() {
+ DatabaseHelper.createPowerFunctionIfNecessary(getEntityManager(),
getDictionary());
+ String jpql = "select a from Account a where power(a.balance, 7)=1";
+
+ CriteriaQuery<Account> c = cb.createQuery(Account.class);
+ Root<Account> account = c.from(Account.class);
+
+
c.select(account).where(cb.equal(cb.power(account.get(Account_.balance), 7),
1));
+ assertEquivalence(c, jpql);
+ DatabaseHelper.dropPowerFunction(getEntityManager(), getDictionary());
+ }
+
+ public void testRoundExpression() {
+ DatabaseHelper.createRoundFunctionIfNecessary(getEntityManager(),
getDictionary());
+ String jpql = "select a from Account a where round(a.balance, 1)=1";
+
+ CriteriaQuery<Account> c = cb.createQuery(Account.class);
+ Root<Account> account = c.from(Account.class);
+
+
c.select(account).where(cb.equal(cb.round(account.get(Account_.balance), 1),
1));
+ assertEquivalence(c, jpql);
+ DatabaseHelper.dropRoundFunction(getEntityManager(), getDictionary());
+ }
+
public void testAvgExpression() {
String jpql = "select avg(a.balance) from Account a";
@@ -1645,4 +1720,5 @@ public class TestTypesafeCriteria extends CriteriaTest {
assertEquivalence(cq, jpql);
}
+
}
diff --git
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/functions/TestEJBQLFunction.java
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/functions/TestEJBQLFunction.java
index c337e0f8a..845f84276 100644
---
a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/functions/TestEJBQLFunction.java
+++
b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jpql/functions/TestEJBQLFunction.java
@@ -18,12 +18,14 @@
*/
package org.apache.openjpa.persistence.jpql.functions;
+import java.math.BigDecimal;
import java.util.List;
import jakarta.persistence.EntityManager;
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.jdbc.sql.DerbyDictionary;
import org.apache.openjpa.jdbc.sql.OracleDictionary;
import org.apache.openjpa.jdbc.sql.SybaseDictionary;
import org.apache.openjpa.persistence.OpenJPAEntityManagerSPI;
@@ -32,6 +34,7 @@ import org.apache.openjpa.persistence.common.apps.CompUser;
import org.apache.openjpa.persistence.common.apps.FemaleUser;
import org.apache.openjpa.persistence.common.apps.MaleUser;
import org.apache.openjpa.persistence.common.utils.AbstractTestCase;
+import org.apache.openjpa.persistence.common.utils.DatabaseHelper;
public class TestEJBQLFunction extends AbstractTestCase {
@@ -85,11 +88,25 @@ public class TestEJBQLFunction extends AbstractTestCase {
if(dict instanceof SybaseDictionary) {
expectedShannonName="Shannon";
}
+ DatabaseHelper.createPowerFunctionIfNecessary(em, dict);
+ DatabaseHelper.createRoundFunctionIfNecessary(em, dict);
endTx(em);
endEm(em);
}
+ @Override
+ public void tearDown() throws Exception {
+ OpenJPAEntityManagerSPI em = (OpenJPAEntityManagerSPI)
currentEntityManager();
+
+ DBDictionary dict = ((JDBCConfiguration)
em.getConfiguration()).getDBDictionaryInstance();
+ DatabaseHelper.dropPowerFunction(em, dict);
+ DatabaseHelper.dropRoundFunction(em, dict);
+
+ endEm(em);
+ super.tearDown();
+ }
+
public void testConcatSubStringFunc() {
EntityManager em = currentEntityManager();
startTx(em);
@@ -491,6 +508,132 @@ public class TestEJBQLFunction extends AbstractTestCase {
endEm(em);
}
+
+ public void testCEILINGFunc() {
+ EntityManager em = currentEntityManager();
+
+ String query = "SELECT CEILING(SUM(c.age) + 0.4) FROM CompUser c";
+
+ List result = em.createQuery(query).getResultList();
+
+ assertNotNull(result);
+ assertEquals(1, result.size());
+ assertEquals(154L, ((BigDecimal) result.get(0)).longValue());
+
+ endEm(em);
+ }
+
+ public void testCEILINGFuncNegative() {
+ EntityManager em = currentEntityManager();
+
+ String query = "SELECT CEILING(0.4 - SUM(c.age)) FROM CompUser c";
+
+ List result = em.createQuery(query).getResultList();
+
+ assertNotNull(result);
+ assertEquals(1, result.size());
+ assertEquals(-152L, ((BigDecimal) result.get(0)).longValue());
+
+ endEm(em);
+ }
+
+ public void testEXPFunc() {
+ EntityManager em = currentEntityManager();
+
+ String query = "SELECT EXP(MIN(c.age)) FROM CompUser c";
+
+ List result = em.createQuery(query).getResultList();
+
+ assertNotNull(result);
+ assertEquals(1, result.size());
+ assertEquals(Math.exp(10), (double) result.get(0));
+
+ endEm(em);
+ }
+
+ public void testFLOORFunc() {
+ EntityManager em = currentEntityManager();
+
+ String query = "SELECT FLOOR(SUM(c.age) - 0.4) FROM CompUser c";
+
+ List result = em.createQuery(query).getResultList();
+
+ assertNotNull(result);
+ assertEquals(1, result.size());
+ assertEquals(152L, ((BigDecimal) result.get(0)).longValue());
+
+ endEm(em);
+ }
+
+ public void testFLOORFuncNegative() {
+ EntityManager em = currentEntityManager();
+
+ String query = "SELECT FLOOR(10.4 - SUM(c.age)) FROM CompUser c";
+
+ List result = em.createQuery(query).getResultList();
+
+ assertNotNull(result);
+ assertEquals(1, result.size());
+ assertEquals(-143L, ((BigDecimal) result.get(0)).longValue());
+
+ endEm(em);
+ }
+
+ public void testPOWERFunc() {
+ EntityManager em = currentEntityManager();
+
+ String query = "SELECT POWER(MIN(c.age), 3) FROM CompUser c";
+
+ List result = em.createQuery(query).getResultList();
+
+ assertNotNull(result);
+ assertEquals(1, result.size());
+ assertEquals(1000L, result.get(0));
+
+ endEm(em);
+ }
+
+ public void testROUNDFunc() {
+ EntityManager em = currentEntityManager();
+
+ String query = "SELECT ROUND(SQRT(MIN(c.age)), 3) FROM CompUser c";
+
+ List result = em.createQuery(query).getResultList();
+
+ assertNotNull(result);
+ assertEquals(1, result.size());
+ assertEquals(3.162, (double) result.get(0));
+
+ endEm(em);
+ }
+
+ public void testSIGNFunc() {
+ EntityManager em = currentEntityManager();
+
+ String query = "SELECT SIGN(1 - SUM(c.age)) FROM CompUser c";
+
+ List result = em.createQuery(query).getResultList();
+
+ assertNotNull(result);
+ assertEquals(1, result.size());
+ assertEquals(-1, ((Integer) result.get(0)).intValue());
+
+ endEm(em);
+ }
+
+ public void testLNFunc() {
+ EntityManager em = currentEntityManager();
+
+ String query = "SELECT LN(MIN(c.age)) FROM CompUser c";
+
+ List result = em.createQuery(query).getResultList();
+
+ assertNotNull(result);
+ assertEquals(1, result.size());
+ assertEquals(Math.log(10), (double) result.get(0));
+
+ endEm(em);
+ }
public CompUser createUser(String name, String cName, Address add, int age,
boolean isMale) {
diff --git
a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilderImpl.java
b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilderImpl.java
index 7d109f25e..c9c0e2bf0 100644
---
a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilderImpl.java
+++
b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilderImpl.java
@@ -153,6 +153,46 @@ public class CriteriaBuilderImpl implements
OpenJPACriteriaBuilder, ExpressionPa
public <N extends Number> Expression<N> abs(Expression<N> x) {
return new Expressions.Abs<>(x);
}
+
+ @Override
+ public <N extends Number> Expression<N> ceiling(Expression<N> x) {
+ return new Expressions.Ceiling<>(x);
+ }
+
+ @Override
+ public Expression<Double> exp(Expression<? extends Number> x) {
+ return new Expressions.Exponential(x);
+ }
+
+ @Override
+ public <N extends Number> Expression<N> floor(Expression<N> x) {
+ return new Expressions.Floor<>(x);
+ }
+
+ @Override
+ public Expression<Double> ln(Expression<? extends Number> x) {
+ return new Expressions.NaturalLogarithm(x);
+ }
+
+ @Override
+ public Expression<Integer> sign(Expression<? extends Number> x) {
+ return new Expressions.Sign(x);
+ }
+
+ @Override
+ public Expression<Double> power(Expression<? extends Number> x, Number y) {
+ return new Expressions.Power<>(x, y);
+ }
+
+ @Override
+ public Expression<Double> power(Expression<? extends Number> x,
Expression<? extends Number> y) {
+ return new Expressions.Power<>(x, y);
+ }
+
+ @Override
+ public <T extends Number> Expression<T> round(Expression<T> x, Integer n) {
+ return new Expressions.Round<>(x, new Expressions.Constant<>(n));
+ }
@Override
public <Y> Expression<Y> all(Subquery<Y> subquery) {
@@ -988,30 +1028,6 @@ public class CriteriaBuilderImpl implements
OpenJPACriteriaBuilder, ExpressionPa
return new ComparisonStyle.Default();
}
- @Override
- public <N extends Number> Expression<N> ceiling(Expression<N> x) {
- // TODO Implement ceiling op
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Expression<Double> exp(Expression<? extends Number> x) {
- // TODO Implement exp op
- throw new UnsupportedAddressTypeException();
- }
-
- @Override
- public <N extends Number> Expression<N> floor(Expression<N> x) {
- // TODO Implement floor op
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Expression<Double> ln(Expression<? extends Number> x) {
- // TODO Implement ln op
- throw new UnsupportedOperationException();
- }
-
@Override
public Expression<LocalDate> localDate() {
// TODO Implement localDate
@@ -1030,27 +1046,4 @@ public class CriteriaBuilderImpl implements
OpenJPACriteriaBuilder, ExpressionPa
throw new UnsupportedOperationException();
}
- @Override
- public Expression<Double> power(Expression<? extends Number> x, Number y) {
- // TODO Implement power op
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Expression<Double> power(Expression<? extends Number> x,
Expression<? extends Number> y) {
- // TODO Implement power op
- throw new UnsupportedOperationException();
- }
-
- @Override
- public <T extends Number> Expression<T> round(Expression<T> x, Integer n) {
- // TODO Implement round op
- throw new UnsupportedOperationException();
- }
-
- @Override
- public Expression<Integer> sign(Expression<? extends Number> x) {
- // TODO Implement sign op
- throw new UnsupportedOperationException();
- }
}
diff --git
a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java
b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java
index f7ca4633b..e8502a5b0 100644
---
a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java
+++
b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Expressions.java
@@ -298,6 +298,139 @@ class Expressions {
}
}
+ public static class Ceiling<X> extends UnaryFunctionalExpression<X> {
+ public Ceiling(Expression<X> x) {
+ super(x);
+ }
+
+ @Override
+ public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?>
q) {
+ Value value = factory.ceiling(Expressions.toValue(e, factory, q));
+ value.setImplicitType(getJavaType());
+ return value;
+ }
+
+ @Override
+ public StringBuilder asValue(AliasContext q) {
+ return Expressions.asValue(q, "CEILING", OPEN_BRACE, e,
CLOSE_BRACE);
+ }
+ }
+
+ public static class Exponential extends UnaryFunctionalExpression<Double> {
+ public Exponential(Expression<? extends Number> x) {
+ super(Double.class, x);
+ }
+
+ @Override
+ public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?>
q) {
+ Value value = factory.exp(Expressions.toValue(e, factory, q));
+ value.setImplicitType(getJavaType());
+ return value;
+ }
+
+ @Override
+ public StringBuilder asValue(AliasContext q) {
+ return Expressions.asValue(q, "EXP", OPEN_BRACE, e, CLOSE_BRACE);
+ }
+ }
+
+ public static class Floor<X> extends UnaryFunctionalExpression<X> {
+ public Floor(Expression<X> x) {
+ super(x);
+ }
+
+ @Override
+ public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?>
q) {
+ Value value = factory.floor(Expressions.toValue(e, factory, q));
+ value.setImplicitType(getJavaType());
+ return value;
+ }
+
+ @Override
+ public StringBuilder asValue(AliasContext q) {
+ return Expressions.asValue(q, "FLOOR", OPEN_BRACE, e, CLOSE_BRACE);
+ }
+ }
+
+ public static class NaturalLogarithm extends
UnaryFunctionalExpression<Double> {
+ public NaturalLogarithm(Expression<? extends Number> x) {
+ super(Double.class, x);
+ }
+
+ @Override
+ public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?>
q) {
+ Value value = factory.ln(Expressions.toValue(e, factory, q));
+ value.setImplicitType(getJavaType());
+ return value;
+ }
+
+ @Override
+ public StringBuilder asValue(AliasContext q) {
+ return Expressions.asValue(q, "LN", OPEN_BRACE, e, CLOSE_BRACE);
+ }
+ }
+
+ public static class Sign extends UnaryFunctionalExpression<Integer> {
+ public Sign(Expression<? extends Number> x) {
+ super(Integer.class, x);
+ }
+
+ @Override
+ public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?>
q) {
+ Value value = factory.sign(Expressions.toValue(e, factory, q));
+ value.setImplicitType(getJavaType());
+ return value;
+ }
+
+ @Override
+ public StringBuilder asValue(AliasContext q) {
+ return Expressions.asValue(q, "SIGN", OPEN_BRACE, e, CLOSE_BRACE);
+ }
+ }
+
+ public static class Power<X, Y extends Number> extends
BinarayFunctionalExpression<Double> {
+ public Power(Expression<X> x, Expression<Y> y) {
+ super(double.class, x, y);
+ }
+ public Power(Expression<X> x, Y y) {
+ this(x,new Constant<>(y));
+ }
+
+ @Override
+ public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?>
q) {
+ Value value = factory.power(
+ Expressions.toValue(e1, factory, q),
+ Expressions.toValue(e2, factory, q));
+ value.setImplicitType(getJavaType());
+ return value;
+ }
+
+ @Override
+ public StringBuilder asValue(AliasContext q) {
+ return Expressions.asValue(q, "POWER", OPEN_BRACE, e1, COMMA, e2,
CLOSE_BRACE);
+ }
+ }
+
+ public static class Round<X> extends BinarayFunctionalExpression<X> {
+ public Round(Expression<?> x, Expression<?> y) {
+ super(((Class<X>) x.getJavaType()), x, y);
+ }
+
+ @Override
+ public Value toValue(ExpressionFactory factory, CriteriaQueryImpl<?>
q) {
+ Value value = factory.round(
+ Expressions.toValue(e1, factory, q),
+ Expressions.toValue(e2, factory, q));
+ value.setImplicitType(getJavaType());
+ return value;
+ }
+
+ @Override
+ public StringBuilder asValue(AliasContext q) {
+ return Expressions.asValue(q, "ROUND", OPEN_BRACE, e1, COMMA, e2,
CLOSE_BRACE);
+ }
+ }
+
public static class Count extends UnaryFunctionalExpression<Long> {
private boolean _distinct;
public Count(Expression<?> x) {
diff --git a/openjpa-project/src/doc/manual/jpa_overview_query.xml
b/openjpa-project/src/doc/manual/jpa_overview_query.xml
index c338634b6..f681f7374 100644
--- a/openjpa-project/src/doc/manual/jpa_overview_query.xml
+++ b/openjpa-project/src/doc/manual/jpa_overview_query.xml
@@ -565,6 +565,64 @@ SELECT x FROM Magazine x WHERE LOCATE('D', x.title) = 2
</para>
<programlisting>
SELECT x FROM Magazine x WHERE ABS(x.price) >= 5.00
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ <indexterm>
+ <primary>
+ CEILING function
+ </primary>
+ </indexterm>
+
+<literal>CEILING(number)</literal>: Returns the smallest (closest to negative
infinity)
+ value that is greater than or equal to the argument and is equal to a
mathematical integer.
+ </para>
+<programlisting>
+SELECT x FROM Magazine x WHERE CEILING(x.price) >= 10
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ <indexterm>
+ <primary>
+ EXP function
+ </primary>
+ </indexterm>
+
+<literal>EXP(number)</literal>: Returns the Euler's number
<literal>e</literal> raised to the power of a value.
+ </para>
+<programlisting>
+SELECT x FROM Magazine x WHERE EXP(x.price) >= 10
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ <indexterm>
+ <primary>
+ FLOOR function
+ </primary>
+ </indexterm>
+
+<literal>FLOOR(number)</literal>: Returns the largest (closest to positive
infinity)
+ value that is less than or equal to the argument and is equal to a
mathematical integer.
+ </para>
+<programlisting>
+SELECT x FROM Magazine x WHERE FLOOR(x.price) >= 10
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ <indexterm>
+ <primary>
+ LN function
+ </primary>
+ </indexterm>
+
+<literal>LN(number)</literal>: Returns the natural logarithm (base
<litera>e</literal>) of a value.
+ </para>
+<programlisting>
+SELECT x FROM Magazine x WHERE LN(x.price) >= 10
</programlisting>
</listitem>
<listitem>
@@ -574,6 +632,7 @@ SELECT x FROM Magazine x WHERE ABS(x.price) >= 5.00
SQRT function
</primary>
</indexterm>
+
<literal>SQRT(number)</literal>: Returns the square root of the argument.
</para>
<programlisting>
@@ -592,6 +651,48 @@ SELECT x FROM Magazine x WHERE SQRT(x.price) >= 1.00
</para>
<programlisting>
SELECT x FROM Magazine x WHERE MOD(x.price, 10) = 0
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ <indexterm>
+ <primary>
+ POWER function
+ </primary>
+ </indexterm>
+
+<literal>POWER(base, exponent)</literal>: Returns the value of the first
argument raised to the power of the second argument.
+ </para>
+<programlisting>
+SELECT x FROM Magazine x WHERE POWER(x.price, 2) >= 10
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ <indexterm>
+ <primary>
+ ROUND function
+ </primary>
+ </indexterm>
+
+<literal>ROUND(number, precision)</literal>: Rounds the number to given
precision.
+ </para>
+<programlisting>
+SELECT x FROM Magazine x WHERE ROUND(x.price, 2) >= 10
+</programlisting>
+ </listitem>
+ <listitem>
+ <para>
+ <indexterm>
+ <primary>
+ SIGN function
+ </primary>
+ </indexterm>
+
+<literal>SIGN(number)</literal>: Returns the sign (-1, 0, 1) of a number
+ </para>
+<programlisting>
+SELECT x FROM Magazine x WHERE SIGN(x.price) >= 0
</programlisting>
</listitem>
<listitem>
@@ -3365,6 +3466,13 @@ that represents the string position at which the search
is started (by default,
the beginning of the string to be searched). The first position in a string is
denoted by 1. If the string is not found, 0 is returned.
</para>
+ <para>
+Note that not all databases support the use of a trim character other than the
+space character; use of this argument may result in queries that are not
+portable. Note that not all databases support the use of the third argument to
+<literal>LOCATE</literal>; use of this argument may result in queries that are
+not portable.
+ </para>
<para>
The <literal>LENGTH
</literal> function returns the length of the string in characters as an
@@ -3378,33 +3486,48 @@ integer.
<para>
<itemizedlist><listitem><para>functions_returning_numerics ::=
ABS(simple_arithmetic_expression) |
+CEILING(arithmetic_expression) |
+EXP(arithmetic_expression) |
+FLOOR(arithmetic_expression) |
+LN(arithmetic_expression) |
+POWER(arithmetic_expression, arithmetic_expression) |
+ROUND(arithmetic_expression, arithmetic_expression) |
+SIGN(arithmetic_expression) |
SQRT(simple_arithmetic_expression) |
MOD(simple_arithmetic_expression, simple_arithmetic_expression) |
SIZE(collection_valued_path_expression) |
-INDEX(identification_variable)
+INDEX(identification_variable) |
+extract_datetime_field
</para>
</listitem>
</itemizedlist>
</para>
<para>
-The <literal>ABS</literal> function takes a numeric argument and returns a
-number (integer, float, or double) of the same type as the argument to the
-function.
+The <literal>ABS</literal>, <literal>CEILING</literal> and
<literal>FLOOR</literal> functions
+accept a numeric argument and return a number (integer, float, or double) of
the same type as
+the argument.
</para>
<para>
-The <literal>SQRT</literal> function takes a numeric argument and
-returns a double.
+The <literal>SIGN</literal> function accepts a numeric argument and
+returns an integer.
</para>
<para>
-Note that not all databases support the use of a trim character other than the
-space character; use of this argument may result in queries that are not
-portable. Note that not all databases support the use of the third argument to
-<literal>LOCATE</literal>; use of this argument may result in queries that are
-not portable.
+The <literal>SQRT</literal>, <literal>EXP</literal> and <literal>LN</literal>
functions accept
+a numeric argument and return a double.
</para>
<para>
-The <literal>MOD</literal> function takes two integer arguments and returns an
-integer.
+The <literal>MOD</literal> function takes two integer arguments and returns an
integer.
+ </para>
+ <para>
+The <literal>ROUND</literal> function accepts a numeric argument and an
integer argument and
+returns a number of the same type as the first argument.
+ </para>
+ <para>
+The <literal>POWER<literal> function accepts two numeric arguments and returns
a double.
+ </para>
+ <para>
+Numeric arguments to these functions may correspond to the numeric Java object
types as well
+as the primitive numeric types.
</para>
<para>
The <literal>SIZE</literal> function returns an integer value, the