You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pc...@apache.org on 2025/09/23 02:50:02 UTC

(openjpa) 02/03: [WIP][OPENJPA-2940] Fixing Criteria typecast support when target type is a number

This is an automated email from the ASF dual-hosted git repository.

pcristof pushed a commit to branch OPENJPA-2940
in repository https://gitbox.apache.org/repos/asf/openjpa.git

commit f06c2231fe8095d7cdf0440f785217dfcd62379e
Author: Paulo Cristovão de Araújo Silva Filho <pc...@gmail.com>
AuthorDate: Mon Sep 22 11:34:09 2025 -0300

    [WIP][OPENJPA-2940] Fixing Criteria typecast support when target type is a number
---
 .../criteria/TestTypecastAsCriteria.java           | 11 +++++------
 .../persistence/criteria/ExpressionImpl.java       |  8 ++++----
 .../openjpa/persistence/criteria/Expressions.java  | 22 ++++++++++++++++++++--
 .../openjpa/persistence/criteria/PathImpl.java     |  8 ++++----
 4 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestTypecastAsCriteria.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestTypecastAsCriteria.java
index 716107259..b342fecbf 100644
--- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestTypecastAsCriteria.java
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestTypecastAsCriteria.java
@@ -52,11 +52,11 @@ public class TestTypecastAsCriteria extends CriteriaTest {
     }
 
     public void testTypecastAsInteger() {
-    	String jpql = "SELECT c FROM Customer c JOIN c.orders o WHERE CAST(o.quantity AS INTEGER) = 0";
+    	String jpql = "SELECT c FROM Customer c JOIN c.orders o WHERE CAST(CAST(o.quantity AS STRING) AS INTEGER) = 0";
     	CriteriaQuery<Customer> q = cb.createQuery(Customer.class);
     	Root<Customer> c = q.from(Customer.class);
     	SetJoin<Customer, Order> o = c.joinSet("orders");
-    	q.where(cb.equal(o.get("quantity").cast(Integer.class), 0));
+    	q.where(cb.equal(o.get("quantity").cast(String.class).cast(Integer.class), 0));
     	q.select(c);
     	
     	assertEquivalence(q, jpql);
@@ -67,7 +67,7 @@ public class TestTypecastAsCriteria extends CriteriaTest {
     	CriteriaQuery<Customer> q = cb.createQuery(Customer.class);
     	Root<Customer> c = q.from(Customer.class);
     	SetJoin<Customer, Order> o = c.joinSet("orders");
-    	q.where(cb.equal(o.get("quantity").cast(Long.class), 0l));
+    	q.where(cb.equal(o.get("quantity").cast(String.class).cast(Long.class), 0l));
     	q.select(c);
     	
     	assertEquivalence(q, jpql);
@@ -78,7 +78,7 @@ public class TestTypecastAsCriteria extends CriteriaTest {
     	CriteriaQuery<Customer> q = cb.createQuery(Customer.class);
     	Root<Customer> c = q.from(Customer.class);
     	SetJoin<Customer, Order> o = c.joinSet("orders");
-    	q.where(cb.equal(o.get("quantity").cast(Float.class), 0f));
+    	q.where(cb.equal(o.get("quantity").cast(String.class).cast(Float.class), 0f));
     	q.select(c);
     	
     	assertEquivalence(q, jpql);
@@ -89,14 +89,13 @@ public class TestTypecastAsCriteria extends CriteriaTest {
     	CriteriaQuery<Customer> q = cb.createQuery(Customer.class);
     	Root<Customer> c = q.from(Customer.class);
     	SetJoin<Customer, Order> o = c.joinSet("orders");
-    	q.where(cb.equal(o.get("quantity").cast(Float.class), 0d));
+    	q.where(cb.equal(o.get("quantity").cast(String.class).cast(Double.class), 0d));
     	q.select(c);
     	
     	assertEquivalence(q, jpql);
     }
     
     public void testTypecastAsInvalid() {
-    	String jpql = "SELECT c FROM Customer c JOIN c.orders o WHERE CAST(o.quantity AS double) = 0";
     	CriteriaQuery<Customer> q = cb.createQuery(Customer.class);
     	Root<Customer> c = q.from(Customer.class);
     	SetJoin<Customer, Order> o = c.joinSet("orders");
diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ExpressionImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ExpressionImpl.java
index 32dcc2917..2c413cf2e 100644
--- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ExpressionImpl.java
+++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ExpressionImpl.java
@@ -129,13 +129,13 @@ public Predicate in(Object... values) {
     public <X> Expression<X> cast(Class<X> type) {
     	if (type == String.class) {
     		return new Expressions.TypecastAs(this, "STRING");
-    	} else if (type == Integer.class) {
+    	} else if (type == Integer.class || type == int.class) {
     		return new Expressions.TypecastAs(this, "INTEGER");
-    	} else if (type == Long.class) {
+    	} else if (type == Long.class || type == long.class) {
     		return new Expressions.TypecastAs(this, "LONG");
-    	} else if (type == Float.class) {
+    	} else if (type == Float.class || type == float.class) {
     		return new Expressions.TypecastAs(this, "FLOAT");
-    	} else if (type == Double.class) {
+    	} else if (type == Double.class || type == double.class) {
     		return new Expressions.TypecastAs(this, "DOUBLE");
     	}
 		throw new IllegalArgumentException("Target cast not supported");
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 7d30dc146..1e82c64f1 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
@@ -623,12 +623,30 @@ class Expressions {
     	
     	@Override
     	public Value toValue(ExpressionFactory factory, CriteriaQueryImpl q) {
-    		return factory.newTypecastAsString(Expressions.toValue(e, factory, q));
+    		return switch (target) {
+				case "STRING": {
+					yield factory.newTypecastAsString(Expressions.toValue(e, factory, q));
+				}
+				case "INTEGER":{
+					yield factory.newTypecastAsNumber(Expressions.toValue(e, factory, q), Integer.class);
+				}
+				case "LONG":{
+					yield factory.newTypecastAsNumber(Expressions.toValue(e, factory, q), Long.class);
+				}
+				case "FLOAT":{
+					yield factory.newTypecastAsNumber(Expressions.toValue(e, factory, q), Float.class);
+				}
+				case "DOUBLE":{
+					yield factory.newTypecastAsNumber(Expressions.toValue(e, factory, q), Double.class);
+				}
+				default:
+					throw new IllegalArgumentException("Unexpected value: " + target);
+			};
     	}
     	
     	@Override
     	public StringBuilder asValue(AliasContext q) {
-    		return Expressions.asValue(q, "CAST", OPEN_BRACE, e, "AS", target, CLOSE_BRACE);
+    		return Expressions.asValue(q, "CAST", OPEN_BRACE, e, " AS ", target, CLOSE_BRACE);
     	}
     }
 
diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PathImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PathImpl.java
index 6f5ee0ed8..8dc92213e 100644
--- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PathImpl.java
+++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PathImpl.java
@@ -356,13 +356,13 @@ class PathImpl<Z,X> extends ExpressionImpl<X> implements Path<X> {
 	public <X> Expression<X> cast(Class<X> type) {
     	if (type == String.class) {
     		return new Expressions.TypecastAs(this, "STRING");
-    	} else if (type == Integer.class) {
+    	} else if (type == Integer.class || type == int.class) {
     		return new Expressions.TypecastAs(this, "INTEGER");
-    	} else if (type == Long.class) {
+    	} else if (type == Long.class || type == long.class) {
     		return new Expressions.TypecastAs(this, "LONG");
-    	} else if (type == Float.class) {
+    	} else if (type == Float.class || type == float.class) {
     		return new Expressions.TypecastAs(this, "FLOAT");
-    	} else if (type == Double.class) {
+    	} else if (type == Double.class || type == double.class) {
     		return new Expressions.TypecastAs(this, "DOUBLE");
     	}
 		throw new IllegalArgumentException("Target cast not supported");