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 38b6df69d..76f9dace3 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 @@ -439,14 +439,16 @@ public class JDBCExpressionFactory if (val instanceof Lit) { Lit lit = (Lit) val; StringBuffer value = new StringBuffer(); - if (lit.getParseType() == Literal.TYPE_SQ_STRING) + int pType = lit.getParseType(); + if (pType == Literal.TYPE_SQ_STRING || + pType == Literal.TYPE_STRING) value.append("'").append(lit.getValue().toString()).append("'"); - else if (lit.getParseType() == Literal.TYPE_BOOLEAN) { + else if (pType == Literal.TYPE_BOOLEAN) { if ((Boolean) lit.getValue()) value.append("1"); else value.append("0"); - } else if (lit.getParseType() == Literal.TYPE_ENUM) { + } else if (pType == Literal.TYPE_ENUM) { lit.setRaw(true); return val; } else diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Address.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Address.java index 9d632c093..85a2d0694 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Address.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Address.java @@ -25,6 +25,7 @@ import javax.persistence.Id; import javax.persistence.OneToOne; import javax.persistence.Table; + /** * Used for testing Criteria API. * The fields are sometimes not declared as there is no validation yet during diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/CustomerDetails.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/CustomerDetails.java index 0dcf4fb40..38dab5cb1 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/CustomerDetails.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/CustomerDetails.java @@ -19,11 +19,24 @@ package org.apache.openjpa.persistence.criteria; public class CustomerDetails { - int id; + long id; int status; int quantity; + + public CustomerDetails() {} + + public CustomerDetails(long id, int status) { + this.id = id; + this.status = status; + } + + public CustomerDetails(long id, int status, int quantity) { + this.id = id; + this.status = status; + this.quantity = quantity; + } public int getStatus() { return status; @@ -33,11 +46,11 @@ public class CustomerDetails { this.status = status; } - public int getId() { + public long getId() { return id; } - public void setId(int id) { + public void setId(long id) { this.id = id; } diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/CustomerFullName.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/CustomerFullName.java new file mode 100644 index 000000000..4298a7bdb --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/CustomerFullName.java @@ -0,0 +1,49 @@ +/* + * 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.criteria; + +public class CustomerFullName { + public String firstName; + + public String lastName; + + public CustomerFullName() {} + + public CustomerFullName(String firstName, String lastName) { + this.firstName = firstName; + this.lastName = lastName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } +} + diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestTypeSafeCondExpression.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestTypeSafeCondExpression.java index 125c1af0b..496b60442 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestTypeSafeCondExpression.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestTypeSafeCondExpression.java @@ -266,7 +266,6 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure(message="JPQL generates two queries, Criteria only one") public void testNullExprUsingCriteria() { String query = "SELECT o.name FROM CompUser o WHERE o.age IS NOT NULL AND " + @@ -289,7 +288,6 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure(message="Invalid SQL for Criteria") public void testNullExpr2UsingCriteria() { String query = "SELECT o.name FROM CompUser o WHERE o.address.country IS NULL"; @@ -407,12 +405,10 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure(message="new() in projection is badly broken") public void testConstructorExprUsingCriteria() { String query = "SELECT NEW org.apache.openjpa.persistence.common.apps.MaleUser(" + - "c.name, " + - "c.computerName, c.address, c.age, c.userid)" + + "c.name, c.computerName, c.address, c.age, c.userid)" + " FROM CompUser c WHERE c.name = 'Seetha'"; CriteriaQuery q = cb.create(); q = cb.create(); @@ -433,11 +429,10 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure public void testConcatSubStringFunc1() { String query = "select " + "CONCAT('Ablahum', SUBSTRING(e.name, LOCATE('e', e.name), 4)) " + - "From CompUer e WHERE e.name='Seetha'"; + "From CompUser e WHERE e.name='Seetha'"; CriteriaQuery q = cb.create(); q = cb.create(); Root e = q.from(CompUser.class); @@ -455,30 +450,29 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure public void testConcatSubStringFunc2() { String query = "select e.address From CompUser e where " + - "e.computerName = " + + "e.name = 'Seetha' AND e.computerName = " + "CONCAT('Ablahum', SUBSTRING(e.name, LOCATE('e', e.name), 4)) "; CriteriaQuery q = cb.create(); q = cb.create(); Root e = q.from(CompUser.class); q.select(e.get(CompUser_.address)); - q.where(cb.equal( - e.get(CompUser_.computerName), - cb.concat("Ablahum", - cb.substring( - e.get(CompUser_.name), - cb.locate(e.get(CompUser_.name), "e"), - cb.literal(4) - ) - )) - ); + q.where(cb.and(cb.equal(e.get(CompUser_.name), "Seetha"), + cb.equal( + e.get(CompUser_.computerName), + cb.concat("Ablahum", + cb.substring( + e.get(CompUser_.name), + cb.locate(e.get(CompUser_.name), "e"), + cb.literal(4) + ) + ))) + ); assertEquivalence(q, query); em.clear(); } - @AllowFailure public void testConcatSubStringFunc3() { String query = "select " + "CONCAT('XYZ', SUBSTRING(e.name, LOCATE('e', e.name))) " + @@ -499,31 +493,31 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure public void testConcatSubStringFunc4() { - String query = "select e.nicknames from CompUser e where e.name = " + + String query = "select e.age from CompUser e where " + + "e.name = 'Seetha' AND e.computerName = " + "CONCAT('XYZ', SUBSTRING(e.name, LOCATE('e', e.name))) "; CriteriaQuery q = cb.create(); q = cb.create(); Root e = q.from(CompUser.class); - q.select(e.get(CompUser_.nicknames)); - q.where(cb.equal( - e.get(CompUser_.name), - cb.concat("XYZ", - cb.substring( - e.get(CompUser_.name), - cb.locate(e.get(CompUser_.name), "e") - ) - )) - ); + q.select(e.get(CompUser_.age)); + q.where(cb.and(cb.equal(e.get(CompUser_.name), "Seetha"), + cb.equal( + e.get(CompUser_.computerName), + cb.concat("XYZ", + cb.substring( + e.get(CompUser_.name), + cb.locate(e.get(CompUser_.name), "e") + ) + ))) + ); assertEquivalence(q, query); em.clear(); } - @AllowFailure public void testConcatFunc() { String query = "select " + - "CONCAT('', '') From CompUser WHERE e.name='Seetha'"; + "CONCAT('', '') From CompUser e WHERE e.name='Seetha'"; CriteriaQuery q = cb.create(); q = cb.create(); Root e = q.from(CompUser.class); @@ -533,7 +527,6 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure public void testTrimFunc1() { String query = "select Trim(e.computerName) From CompUser e " + "WHERE e.name='Shannon '"; @@ -546,20 +539,18 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure public void testTrimFunc2() { - String query = "select e.name From CompUser e where Trim(e.name) =" + - "'Shannon'"; + String query = "select e.computerName From CompUser e where " + + "Trim(e.name) = 'Shannon '"; CriteriaQuery q = cb.create(); q = cb.create(); Root e = q.from(CompUser.class); - q.where(cb.equal(cb.trim(e.get(CompUser_.computerName)), "Shannon")); - q.select(e.get(CompUser_.name)); + q.where(cb.equal(cb.trim(e.get(CompUser_.name)), "Shannon")); + q.select(e.get(CompUser_.computerName)); assertEquivalence(q, query); em.clear(); } - @AllowFailure public void testLowerFunc1() { String query = "select LOWER(e.name) From CompUser e WHERE " + "e.computerName='UNIX'"; @@ -572,7 +563,6 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure public void testLowerFunc2() { String query = "select e.age From CompUser e where LOWER(e.name)" + " ='ugo'"; @@ -585,7 +575,6 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure public void testUpperFunc1() { String query = "select UPPER(e.name) From CompUser e WHERE " + "e.computerName='PC'"; @@ -598,33 +587,31 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure public void testUpperFunc2() { - String query = "select e.nicknames from CompUser e where " + - "UPPER(e.name)='UGO'"; + String query = "select e.age from CompUser e where " + + "UPPER(e.name)='UGO'"; CriteriaQuery q = cb.create(); q = cb.create(); Root e = q.from(CompUser.class); q.where(cb.equal(cb.upper(e.get(CompUser_.name)), "UGO")); - q.select(e.get(CompUser_.nicknames)); + q.select(e.get(CompUser_.age)); assertEquivalence(q, query); em.clear(); } - @AllowFailure public void testLengthFunc() { String query = "SELECT o.name FROM CompUser o " + "WHERE LENGTH(o.address.country) = 3"; CriteriaQuery q = cb.create(); q = cb.create(); Root e = q.from(CompUser.class); - q.where(cb.equal(cb.length(e.get(CompUser_.name)), 3)); + q.where(cb.equal(cb.length(e.get(CompUser_.address). + get(Address_.country)), 3)); q.select(e.get(CompUser_.name)); assertEquivalence(q, query); em.clear(); } - @AllowFailure public void testArithmFunc1() { String query = "select ABS(e.age) From CompUser e WHERE e.name='Seetha'"; @@ -637,7 +624,6 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure public void testArithmFunc2() { String query = "select SQRT(e.age) From CompUser e WHERE e.name='Seetha'"; @@ -677,7 +663,6 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure public void testGroupByHavingClause() { String query = "SELECT c.name FROM CompUser c GROUP BY c.name HAVING c.name " + @@ -690,18 +675,9 @@ public class TestTypeSafeCondExpression extends CriteriaTest { q.having(cb.like(e.get(CompUser_.name), "S%")); q.select(e.get(CompUser_.name)); assertEquivalence(q, query); - List result = em.createQuery(q).getResultList(); - - assertNotNull(result); - assertEquals(3, result.size()); - assertTrue(result.contains("Shannon ")); - assertTrue(result.contains("Shade")); - assertTrue(result.contains("Seetha")); - em.clear(); } - @AllowFailure public void testOrderByClause() { String query = "SELECT c.name FROM CompUser c WHERE c.name LIKE 'S%' " + @@ -714,18 +690,9 @@ public class TestTypeSafeCondExpression extends CriteriaTest { q.select(e.get(CompUser_.name)); q.orderBy(cb.asc(e.get(CompUser_.name))); assertEquivalence(q, query); - List result = em.createQuery(q).getResultList(); - - assertNotNull(result); - assertEquals(3, result.size()); - assertTrue(result.contains("Shannon ")); - assertTrue(result.contains("Seetha")); - assertTrue(result.contains("Shade")); - em.clear(); } - @AllowFailure public void testAVGAggregFunc() { //To be Tested: AVG, COUNT, MAX, MIN, SUM String query = "SELECT AVG(e.age) FROM CompUser e"; @@ -734,16 +701,9 @@ public class TestTypeSafeCondExpression extends CriteriaTest { Root e = q.from(CompUser.class); q.select(cb.avg(e.get(CompUser_.age))); assertEquivalence(q, query); - List result = em.createQuery(q).getResultList(); - - assertNotNull(result); - assertEquals(1, result.size()); - assertTrue(result.contains(25)); - em.clear(); } - @AllowFailure public void testCOUNTAggregFunc() { String query = "SELECT COUNT(c.name) FROM CompUser c"; @@ -752,16 +712,9 @@ public class TestTypeSafeCondExpression extends CriteriaTest { Root e = q.from(CompUser.class); q.select(cb.count(e.get(CompUser_.name))); assertEquivalence(q, query); - List result = em.createQuery(q).getResultList(); - - assertNotNull(result); - assertEquals(1, result.size()); - assertTrue(result.contains(6l)); - em.clear(); } - @AllowFailure public void testMAXAggregFunc() { String query = "SELECT DISTINCT MAX(c.age) FROM CompUser c"; @@ -770,16 +723,10 @@ public class TestTypeSafeCondExpression extends CriteriaTest { Root e = q.from(CompUser.class); q.select(cb.max(e.get(CompUser_.age))).distinct(true); assertEquivalence(q, query); - List result = em.createQuery(q).getResultList(); - - assertNotNull(result); - assertEquals(1, result.size()); - assertTrue(result.contains(36)); - em.clear(); } - @AllowFailure + @AllowFailure(message="criteria does not generate Optimize for 1 row") public void testMINAggregFunc() { String query = "SELECT DISTINCT MIN(c.age) FROM CompUser c"; @@ -788,16 +735,9 @@ public class TestTypeSafeCondExpression extends CriteriaTest { Root e = q.from(CompUser.class); q.select(cb.min(e.get(CompUser_.age))).distinct(true); assertEquivalence(q, query); - List result = em.createQuery(q).getResultList(); - - assertNotNull(result); - assertEquals(1, result.size()); - assertTrue(result.contains(10)); - em.clear(); } - @AllowFailure public void testSUMAggregFunc() { String query = "SELECT SUM(c.age) FROM CompUser c"; @@ -806,12 +746,6 @@ public class TestTypeSafeCondExpression extends CriteriaTest { Root e = q.from(CompUser.class); q.select(cb.sum(e.get(CompUser_.age))); assertEquivalence(q, query); - List result = em.createQuery(q).getResultList(); - - assertNotNull(result); - assertEquals(1, result.size()); - assertTrue(result.contains(153l)); - em.clear(); } @@ -819,7 +753,7 @@ public class TestTypeSafeCondExpression extends CriteriaTest { @AllowFailure public void testTypeExpression1() { String query = "SELECT e FROM CompUser e where TYPE(e) in (?1, ?2) " + - "ORDER By e.name"; + "ORDER By e.name"; CriteriaQuery q = cb.create(); q = cb.create(); Root e = q.from(CompUser.class); @@ -861,7 +795,6 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure public void testTypeExpression4() { String query = "SELECT e FROM CompUser e where TYPE(e) = MaleUser"; CriteriaQuery q = cb.create(); @@ -873,7 +806,6 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure public void testTypeExpression5() { String query = "SELECT e FROM CompUser e where TYPE(e) in (MaleUser)"; CriteriaQuery q = cb.create(); @@ -885,10 +817,9 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure public void testTypeExpression6() { String query = "SELECT e FROM CompUser e where TYPE(e) not in " + - "(MaleUser, FemaleUser)"; + "(MaleUser, FemaleUser)"; CriteriaQuery q = cb.create(); q = cb.create(); Root e = q.from(CompUser.class); @@ -910,7 +841,6 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure public void testTypeExpression8() { String query = "SELECT MaleUser FROM Address a"; CriteriaQuery q = cb.create(); @@ -921,7 +851,6 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure public void testTypeExpression9() { String query = "SELECT " + " CASE TYPE(e) WHEN FemaleUser THEN 'Female' " @@ -935,10 +864,8 @@ public class TestTypeSafeCondExpression extends CriteriaTest { em.clear(); } - @AllowFailure public void testCoalesceExpressions() { - startTx(em); - String query = "SELECT e.name, " + String query = "SELECT e.name, " + "COALESCE (e.address.country, 'Unknown')" + " FROM CompUser e ORDER BY e.name DESC"; @@ -949,18 +876,10 @@ public class TestTypeSafeCondExpression extends CriteriaTest { .value("Unknown")); q.orderBy(cb.desc(e.get(CompUser_.name))); assertEquivalence(q, query); - List rs = em.createQuery(q).getResultList(); - Object[] result = (Object[]) rs.get(rs.size() - 1); - assertEquals("the name is not famzy", "Famzy", result[0]); - assertEquals("Unknown", result[1]); - - endTx(em); em.clear(); } - @AllowFailure public void testNullIfExpressions() { - startTx(em); String query = "SELECT e.name, NULLIF (e.address.country, 'USA')" + " FROM CompUser e ORDER BY e.name DESC"; CriteriaQuery q = cb.create(); @@ -969,22 +888,14 @@ public class TestTypeSafeCondExpression extends CriteriaTest { Address_.country), "USA")); q.orderBy(cb.desc(e.get(CompUser_.name))); assertEquivalence(q, query); - - List rs = em.createQuery(q).getResultList(); - Object[] result = (Object[]) rs.get(1); - assertEquals("the name is not shannon ", "Shannon ", result[0]); - assertNull("is not null", result[1]); - - endTx(em); em.clear(); } - @AllowFailure public void testSimpleCaseExpression1() { - String query = "SELECT e.name, e.age+1 as cage, " + String query = "SELECT e.name, e.age+1, " + "CASE e.address.country WHEN 'USA' THEN 'us' " - + " ELSE 'non-us' END as d2, e.address.country " - + " FROM CompUser e ORDER BY cage, d2 DESC"; + + " ELSE 'non-us' END, e.address.country " + + " FROM CompUser e"; CriteriaQuery q = cb.create(); Root e = q.from(CompUser.class); Expression cage = cb.sum(e.get(CompUser_.age), 1); @@ -993,21 +904,15 @@ public class TestTypeSafeCondExpression extends CriteriaTest { "us").otherwise("non-us"); q.select(e.get(CompUser_.name), cage, d2, e.get(CompUser_.address).get( Address_.country)); - q.orderBy(cb.asc(cage), cb.desc(d2)); assertEquivalence(q, query); - - List rs = em.createQuery(q).getResultList(); - Object[] result = (Object[]) rs.get(rs.size() - 1); - assertEquals("the name is not seetha", "Seetha", result[0]); } - @AllowFailure public void testSimpleCaseExpression2() { - String query = "SELECT e.name, e.age+1 as cage, " + String query = "SELECT e.name, e.age+1, " + "CASE e.address.country WHEN 'USA'" + " THEN 'United-States' " - + " ELSE e.address.country END as d2," + " e.address.country " - + " FROM CompUser e ORDER BY cage, d2 DESC"; + + " ELSE e.address.country END," + " e.address.country " + + " FROM CompUser e"; CriteriaQuery q = cb.create(); Root e = q.from(CompUser.class); Expression cage = cb.sum(e.get(CompUser_.age), 1); @@ -1017,42 +922,29 @@ public class TestTypeSafeCondExpression extends CriteriaTest { e.get(CompUser_.address).get(Address_.country)); q.select(e.get(CompUser_.name), cage, d2, e.get(CompUser_.address).get( Address_.country)); - q.orderBy(cb.asc(cage), cb.desc(d2)); assertEquivalence(q, query); - List rs = em.createQuery(q).getResultList(); - Object[] result = (Object[]) rs.get(rs.size() - 1); - assertEquals("the name is not seetha", "Seetha", result[0]); } - @AllowFailure public void testSimpleCaseExpression3() { String query = "SELECT e.name, " + " CASE TYPE(e) WHEN FemaleUser THEN 'Female' " - + " ELSE 'Male' END as result" + + " ELSE 'Male' END" + " FROM CompUser e WHERE e.name like 'S%' " + " ORDER BY e.name DESC"; CriteriaQuery q = cb.create(); Root e = q.from(CompUser.class); - q.select(cb.selectCase(e.type()).when(FemaleUser.class, "Female") - .otherwise("Male")); + q.select(e.get(CompUser_.name), + cb.selectCase(e.type()).when(FemaleUser.class, "Female") + .otherwise("Male")); q.where(cb.like(e.get(CompUser_.name), "S%")); - q.orderBy(cb.asc(e.get(CompUser_.name))); + q.orderBy(cb.desc(e.get(CompUser_.name))); assertEquivalence(q, query); - List rs = em.createQuery(q).getResultList(); - Object[] result = (Object[]) rs.get(0); - assertEquals("the result is not female", "Female", result[1]); - assertEquals("the name is not shannon", "Shannon ", result[0]); - result = (Object[]) rs.get(2); - assertEquals("the result is not male", "Male", result[1]); - assertEquals("the name is not seetha", "Seetha", result[0]); } - @AllowFailure public void testSimpleCaseExpression4() { - // boolean literal in case expression String query = "SELECT e.name, CASE e.address.country WHEN 'USA'" - + " THEN true ELSE false END as b," - + " e.address.country FROM CompUser e order by b"; + + " THEN true ELSE false END," + + " e.address.country FROM CompUser e"; CriteriaQuery q = cb.create(); Root e = q.from(CompUser.class); Expression b = cb.selectCase( @@ -1060,21 +952,14 @@ public class TestTypeSafeCondExpression extends CriteriaTest { true).otherwise(false); q.select(e.get(CompUser_.name), b, e.get(CompUser_.address).get( Address_.country)); - q.where(cb.like(e.get(CompUser_.name), "S%")); - q.orderBy(cb.asc(b)); assertEquivalence(q, query); - List rs = em.createQuery(q).getResultList(); - - Object[] result = (Object[]) rs.get(rs.size() - 1); - assertEquals(result[1], 1); } - @AllowFailure public void testGeneralCaseExpression1() { String query = "SELECT e.name, e.age, " + " CASE WHEN e.age > 30 THEN e.age - 1 " + " WHEN e.age < 15 THEN e.age + 1 ELSE e.age + 0 " - + " END AS cage FROM CompUser e ORDER BY cage"; + + " END FROM CompUser e"; CriteriaQuery q = cb.create(); Root e = q.from(CompUser.class); Expression cage = cb.selectCase().when(cb.gt(e.get(CompUser_.age), 30), @@ -1083,18 +968,16 @@ public class TestTypeSafeCondExpression extends CriteriaTest { cb.sum(e.get(CompUser_.age), 1)).otherwise( cb.sum(e.get(CompUser_.age), 0)); q.select(e.get(CompUser_.name), e.get(CompUser_.age), cage); - q.orderBy(cb.asc(cage)); assertEquivalence(q, query); } - @AllowFailure public void testGeneralCaseExpression2() { - String query = "SELECT e.name, e.age+1 as cage, " + String query = "SELECT e.name, e.age+1, " + "CASE WHEN e.address.country = 'USA' " + " THEN 'United-States' " - + " ELSE 'Non United-States' END as d2," + + " ELSE 'Non United-States' END," + " e.address.country " - + " FROM CompUser e ORDER BY cage, d2 DESC"; + + " FROM CompUser e"; CriteriaQuery q = cb.create(); Root e = q.from(CompUser.class); Expression d2 = cb.selectCase() @@ -1106,29 +989,21 @@ public class TestTypeSafeCondExpression extends CriteriaTest { Expression cage = cb.sum(e.get(CompUser_.age), 1); q.select(e.get(CompUser_.name), cage, d2, e.get(CompUser_.address).get( Address_.country)); - q.orderBy(cb.asc(cage), cb.desc(d2)); assertEquivalence(q, query); - - List rs = em.createQuery(q).getResultList(); - Object[] result = (Object[]) rs.get(rs.size() - 1); - assertEquals("the name is not seetha", "Seetha", result[0]); - assertEquals("the country is not 'Non United-States'", - "Non United-States", result[2]); } - @AllowFailure public void testGeneralCaseExpression3() { String query = " select e.name, " - + "CASE WHEN e.age = 11 THEN " - + "org.apache.openjpa.persistence.criteria.CompUser$" + - "CreditRating.POOR" - + " WHEN e.age = 35 THEN " - + "org.apache.openjpa.persistence.criteria.CompUser$" + - "CreditRating.GOOD" - + " ELSE " - + "org.apache.openjpa.persistence.criteria.CompUser$" + - "CreditRating.EXCELLENT" - + " END FROM CompUser e ORDER BY e.age"; + + "CASE WHEN e.age = 11 THEN " + + "org.apache.openjpa.persistence.criteria.CompUser$" + + "CreditRating.POOR" + + " WHEN e.age = 35 THEN " + + "org.apache.openjpa.persistence.criteria.CompUser$" + + "CreditRating.GOOD" + + " ELSE " + + "org.apache.openjpa.persistence.criteria.CompUser$" + + "CreditRating.EXCELLENT" + + " END FROM CompUser e ORDER BY e.age"; CriteriaQuery q = cb.create(); Root e = q.from(CompUser.class); q.select(e.get(CompUser_.name), cb.selectCase().when( @@ -1139,10 +1014,6 @@ public class TestTypeSafeCondExpression extends CriteriaTest { q.orderBy(cb.asc(e.get(CompUser_.age))); assertEquivalence(q, query); - List rs = em.createQuery(q).getResultList(); - Object[] result = (Object[]) rs.get(0); - assertEquals("the name is not Jacob", "Jacob", result[0]); - assertEquals("the credit rating is not 'POOR'", "POOR", result[1]); } // not sure how to write CriteriaQuery for @@ -1150,19 +1021,19 @@ public class TestTypeSafeCondExpression extends CriteriaTest { @AllowFailure public void testGeneralCaseExpression4() { String query = "select e.name, e.creditRating from CompUser e " - + "where e.creditRating = " - + "(select " - + "CASE WHEN e1.age = 11 THEN " - + "org.apache.openjpa.persistence.criteria.CompUser$" + - "CreditRating.POOR" - + " WHEN e1.age = 35 THEN " - + "org.apache.openjpa.persistence.criteria.CompUser$" + - "CreditRating.GOOD" - + " ELSE " - + "org.apache.openjpa.persistence.criteria.CompUser$" + - "CreditRating.EXCELLENT" - + " END from CompUser e1" - + " where e.userid = e1.userid) ORDER BY e.age"; + + "where e.creditRating = " + + "(select " + + "CASE WHEN e1.age = 11 THEN " + + "org.apache.openjpa.persistence.criteria.CompUser$" + + "CreditRating.POOR" + + " WHEN e1.age = 35 THEN " + + "org.apache.openjpa.persistence.criteria.CompUser$" + + "CreditRating.GOOD" + + " ELSE " + + "org.apache.openjpa.persistence.criteria.CompUser$" + + "CreditRating.EXCELLENT" + + " END from CompUser e1" + + " where e.userid = e1.userid) ORDER BY e.age"; CriteriaQuery q = cb.create(); Root e = q.from(CompUser.class); q.select(e.get(CompUser_.name), e.get(CompUser_.creditRating)); 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 7e2e18361..7a11f5104 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 @@ -116,7 +116,7 @@ public class TestTypesafeCriteria extends CriteriaTest { CriteriaQuery c = cb.create(); Root account = c.from(Account.class); c.where(cb.in(account.get(Account_.name)).value("X").value("Y").value( - "Z")); + "Z")); assertEquivalence(c, jpql); } @@ -186,26 +186,26 @@ public class TestTypesafeCriteria extends CriteriaTest { @AllowFailure(message = "Extra joins created in Criteria") public void testMultiLevelJoins() { String jpql = "SELECT c FROM Customer c JOIN c.orders o " - + "JOIN o.lineItems i WHERE i.product.productType = 'printer'"; + + "JOIN o.lineItems i WHERE i.product.productType = 'printer'"; CriteriaQuery c = cb.create(); Root cust = c.from(Customer.class); Join order = cust.join(Customer_.orders); Join item = order.join(Order_.lineItems); c.select(cust.get(Customer_.name)) - .where(cb.equal(item.get(LineItem_.product). - get(Product_.productType), "printer")); - + .where(cb.equal(item.get(LineItem_.product) + .get(Product_.productType), "printer")); + assertEquivalence(c, jpql); } public void testJoinsNotPresentInWhereClause() { String jpql = "SELECT c FROM Customer c LEFT JOIN c.orders o " - + "WHERE c.status = 1"; + + "WHERE c.status = 1"; CriteriaQuery c = cb.create(); Root cust = c.from(Customer.class); Join order = cust - .join(Customer_.orders, JoinType.LEFT); + .join(Customer_.orders, JoinType.LEFT); c.where(cb.equal(cust.get(Customer_.status), 1)).select(cust); assertEquivalence(c, jpql); @@ -214,7 +214,7 @@ public class TestTypesafeCriteria extends CriteriaTest { @AllowFailure(message = "Fetch joins not implemented") public void testFetchJoins() { String jpql = "SELECT d FROM Department LEFT JOIN FETCH d.employees " - + "WHERE d.deptNo = 1"; + + "WHERE d.deptNo = 1"; CriteriaQuery q = cb.create(); Root d = q.from(Department.class); d.fetch(Department_.employees, JoinType.LEFT); @@ -226,8 +226,8 @@ public class TestTypesafeCriteria extends CriteriaTest { @AllowFailure(message = "Invalid SQL is generated") public void testJoinedPathInProjection() { String jpql = "SELECT p.vendor FROM Employee e JOIN " - + "e.contactInfo.phones p " - + "WHERE e.contactInfo.address.zipCode = '95054'"; + + "e.contactInfo.phones p " + + "WHERE e.contactInfo.address.zipCode = '95054'"; CriteriaQuery q = cb.create(); Root emp = q.from(Employee.class); Join phone = emp.join(Employee_.contactInfo).join( @@ -243,7 +243,7 @@ public class TestTypesafeCriteria extends CriteriaTest { public void testKeyExpression() { String jpql = "SELECT i.name, p FROM Item i JOIN i.photos p WHERE KEY(p) " - + "LIKE '%egret%'"; + + "LIKE '%egret%'"; CriteriaQuery q = cb.create(); Root item = q.from(Item.class); MapJoin photo = item.join(Item_.photos); @@ -256,12 +256,12 @@ public class TestTypesafeCriteria extends CriteriaTest { @AllowFailure(message = "Index expression not implemented") public void testIndexExpression() { String jpql = "SELECT t FROM CreditCard c JOIN c.transactionHistory t " - + "WHERE c.customer.accountNum = 321987 AND INDEX(t) BETWEEN 0 " - + "AND 9"; + + "WHERE c.customer.accountNum = 321987 AND INDEX(t) BETWEEN 0 " + + "AND 9"; CriteriaQuery q = cb.create(); Root c = q.from(CreditCard.class); ListJoin t = c - .join(CreditCard_.transactionHistory); + .join(CreditCard_.transactionHistory); q.select(t).where( cb.equal(c.get(CreditCard_.customer).get(Customer_.accountNum), 321987), cb.between(t.index(), 0, 9)); @@ -278,65 +278,64 @@ public class TestTypesafeCriteria extends CriteriaTest { assertEquivalence(q, jpql); } -// @AllowFailure(message = "broken") -// public void testExpressionInProjection() { -// String jpql = "SELECT o.quantity, o.totalCost*1.08 AS taxedCost, " -// + "a.zipCode FROM Customer c JOIN c.orders o JOIN c.address a" -// + "WHERE a.state = 'CA' AND a.county = 'Santa Clara'"; -// CriteriaQuery q = cb.create(); -// Root cust = q.from(Customer.class); -// Join order = cust.join(Customer_.orders); -// Join address = cust.join(Customer_.address); -// q.where(cb.equal(address.get(Address_.state), "CA"), cb.equal(address -// .get(Address_.county), "Santa Clara")); -// q.select(order.get(Order_.quantity), cb.prod(order -// .get(Order_.totalCost), 1.08), address.get(Address_.zipCode)); -// -// assertEquivalence(q, jpql); -// } + @AllowFailure(message = "broken") + public void testExpressionInProjection() { + String jpql = "SELECT o.quantity, o.totalCost*1.08 AS taxedCost, " + + "a.zipCode FROM Customer c JOIN c.orders o JOIN c.address a" + + "WHERE a.state = 'CA' AND a.county = 'Santa Clara'"; + CriteriaQuery q = cb.create(); + Root cust = q.from(Customer.class); + Join order = cust.join(Customer_.orders); + Join address = cust.join(Customer_.address); + q.where(cb.equal(address.get(Address_.state), "CA"), cb.equal(address + .get(Address_.county), "Santa Clara")); + q.select(order.get(Order_.quantity), cb.prod(order + .get(Order_.totalCost), 1.08), address.get(Address_.zipCode)); - // @AllowFailure(message = - // "Type expression was working with Fay. Now refactored and broken") - // public void testTypeExpression() { - // String jpql = "SELECT TYPE(e) FROM Employee e WHERE TYPE(e) <> Exempt"; - // CriteriaQuery q = cb.create(); - // Root emp = q.from(Employee.class); - // q.select(emp.type()).where(cb.notEqual(emp.type(), Exempt.class)); - // - // assertEquivalence(q, jpql); - // } + assertEquivalence(q, jpql); + } - // @AllowFailure(message = "Index expression not implemented") - // public void testIndexExpressionAndLietral() { - // String jpql = "SELECT w.name FROM Course c JOIN c.studentWaitList w " - // + "WHERE c.name = 'Calculus' AND INDEX(w) = 0"; - // CriteriaQuery q = cb.create(); - // Root course = q.from(Course.class); - // ListJoin w = course.join(Course_.studentWaitList); - // q.where(cb.equal(course.get(Course_.name), "Calculus"), - // cb.equal(w.index(), 0)).select(w.get(Student_.name)); - // - // assertEquivalence(q, jpql); - // } + public void testTypeExpression() { + String jpql = "SELECT TYPE(e) FROM Employee e WHERE TYPE(e) <> Exempt"; + CriteriaQuery q = cb.create(); + Root emp = q.from(Employee.class); + q.select(emp.type()).where(cb.notEqual(emp.type(), Exempt.class)); - // @AllowFailure(message = "SQL for Criteria has extra join") - // public void testAggregateInProjection() { - // String jpql = "SELECT SUM(i.price) FROM Order o JOIN o.lineItems i JOIN " - // + "o.customer c WHERE c.lastName = 'Smith' AND c.firstName = 'John'"; - // CriteriaQuery q = cb.create(); - // Root o = q.from(Order.class); - // Join i = o.join(Order_.lineItems); - // Join c = o.join(Order_.customer); - // q.where(cb.equal(c.get(Customer_.lastName), "Smith"), cb.equal(c - // .get(Customer_.firstName), "John")); - // q.select(cb.sum(i.get(LineItem_.price))); - // - // assertEquivalence(q, jpql); - // } + assertEquivalence(q, jpql); + } + + @AllowFailure(message = "Index expression not implemented") + public void testIndexExpressionAndLietral() { + String jpql = "SELECT w.name FROM Course c JOIN c.studentWaitList w " + + "WHERE c.name = 'Calculus' AND INDEX(w) = 0"; + CriteriaQuery q = cb.create(); + Root course = q.from(Course.class); + ListJoin w = course.join(Course_.studentWaitList); + q.where(cb.equal(course.get(Course_.name), "Calculus"), + cb.equal(w.index(), 0)).select(w.get(Student_.name)); + + assertEquivalence(q, jpql); + } + + @AllowFailure(message = "SQL for Criteria has extra join") + public void testAggregateInProjection() { + String jpql = "SELECT SUM(i.price) FROM Order o JOIN o.lineItems i " + + "JOIN o.customer c WHERE c.lastName = 'Smith' AND " + + "c.firstName = 'John'"; + CriteriaQuery q = cb.create(); + Root o = q.from(Order.class); + Join i = o.join(Order_.lineItems); + Join c = o.join(Order_.customer); + q.where(cb.equal(c.get(Customer_.lastName), "Smith"), cb.equal(c + .get(Customer_.firstName), "John")); + q.select(cb.sum(i.get(LineItem_.price))); + + assertEquivalence(q, jpql); + } public void testSizeExpression() { String jpql = "SELECT SIZE(d.employees) FROM Department d " - + "WHERE d.name = 'Sales'"; + + "WHERE d.name = 'Sales'"; CriteriaQuery q = cb.create(); Root d = q.from(Department.class); q.where(cb.equal(d.get(Department_.name), "Sales")); @@ -348,134 +347,114 @@ public class TestTypesafeCriteria extends CriteriaTest { public void testCaseExpression() { String jpql = "SELECT e.name, CASE WHEN e.rating = 1 THEN e.salary * 1.1 " - + "WHEN e.rating = 2 THEN e.salary * 1.2 ELSE e.salary * " - + "1.01 END " - + "FROM Employee e WHERE e.department.name = 'Engineering'"; + + "WHEN e.rating = 2 THEN e.salary * 1.2 ELSE e.salary * " + + "1.01 END " + + "FROM Employee e WHERE e.department.name = 'Engineering'"; CriteriaQuery q = cb.create(); Root e = q.from(Employee.class); q.where(cb.equal(e.get(Employee_.department).get(Department_.name), - "Engineering")); + "Engineering")); q.select(e.get(Employee_.name), cb.selectCase().when( cb.equal(e.get(Employee_.rating), 1), cb.prod(e.get(Employee_.salary), 1.1)).when( - cb.equal(e.get(Employee_.rating), 2), - cb.prod(e.get(Employee_.salary), 1.2)).otherwise( - cb.prod(e.get(Employee_.salary), 1.01))); + cb.equal(e.get(Employee_.rating), 2), + cb.prod(e.get(Employee_.salary), 1.2)).otherwise( + cb.prod(e.get(Employee_.salary), 1.01))); assertEquivalence(q, jpql); } - // @AllowFailure(message = "Extra Joins created") - // public void testExpression1() { - // String jpql = "SELECT o.quantity, o.totalCost*1.08 AS taxedCost, " - // + "a.zipCode FROM Customer c JOIN c.orders o JOIN c.address a " - // + "WHERE a.state = 'CA' AND a.county = 'Santa Clara'"; - // CriteriaQuery q = cb.create(); - // Root cust = q.from(Customer.class); - // Join order = cust.join(Customer_.orders); - // Join address = cust.join(Customer_.address); - // q.where(cb.equal(address.get(Address_.state), "CA"), cb.equal(address - // .get(Address_.county), "Santa Clara")); - // q.select(order.get(Order_.quantity), cb.prod(order - // .get(Order_.totalCost), 1.08), address.get(Address_.zipCode)); - // - // assertEquivalence(q, jpql); - // } - // - // @AllowFailure(message = "Type expression in projection not implemented") - // public void testExpression2() { - // String jpql = "SELECT TYPE(e) FROM Employee e WHERE TYPE(e) <> Exempt"; - // CriteriaQuery q = cb.create(); - // Root emp = q.from(Employee.class); - // q.select(emp.type()).where(cb.notEqual(emp.type(), Exempt.class)); - // - // assertEquivalence(q, jpql); - // } - // - // @AllowFailure(message = "Index expression not implemented") - // public void testExpression3() { - // String jpql = "SELECT w.name FROM Course c JOIN c.studentWaitList w " - // + "WHERE c.name = 'Calculus' AND INDEX(w) = 0"; - // CriteriaQuery q = cb.create(); - // Root course = q.from(Course.class); - // ListJoin w = course.join(Course_.studentWaitList); - // q.where(cb.equal(course.get(Course_.name), "Calculus"), - // cb.equal(w.index(), 0)).select(w.get(Student_.name)); - // - // assertEquivalence(q, jpql); - // } - // - // @AllowFailure(message = "Generates extra Join") - // public void testExpression4() { - // String jpql = "SELECT SUM(i.price) FROM Order o JOIN o.lineItems i JOIN " - // + "o.customer c WHERE c.lastName = 'Smith' AND c.firstName = 'John'"; - // CriteriaQuery q = cb.create(); - // Root o = q.from(Order.class); - // Join i = o.join(Order_.lineItems); - // Join c = o.join(Order_.customer); - // q.where(cb.equal(c.get(Customer_.lastName), "Smith"), cb.equal(c - // .get(Customer_.firstName), "John")); - // q.select(cb.sum(i.get(LineItem_.price))); - // - // assertEquivalence(q, jpql); - // } - - public void testExpression5() { - String jpql = "SELECT SIZE(d.employees) FROM Department d " - + "WHERE d.name = 'Sales'"; + @AllowFailure(message = "Extra Joins created") + public void testExpression1() { + String jpql = "SELECT o.quantity, o.totalCost*1.08 AS taxedCost, " + + "a.zipCode FROM Customer c JOIN c.orders o JOIN c.address a " + + "WHERE a.state = 'CA' AND a.county = 'Santa Clara'"; CriteriaQuery q = cb.create(); - Root d = q.from(Department.class); - q.where(cb.equal(d.get(Department_.name), "Sales")); - q.select(cb.size(d.get(Department_.employees))); + Root cust = q.from(Customer.class); + Join order = cust.join(Customer_.orders); + Join address = cust.join(Customer_.address); + q.where(cb.equal(address.get(Address_.state), "CA"), cb.equal(address + .get(Address_.county), "Santa Clara")); + q.select(order.get(Order_.quantity), cb.prod(order + .get(Order_.totalCost), 1.08), address.get(Address_.zipCode)); + + assertEquivalence(q, jpql); + } + + @AllowFailure(message = "Index expression not implemented") + public void testExpression3() { + String jpql = "SELECT w.name FROM Course c JOIN c.studentWaitList w " + + "WHERE c.name = 'Calculus' AND INDEX(w) = 0"; + CriteriaQuery q = cb.create(); + Root course = q.from(Course.class); + ListJoin w = course.join(Course_.studentWaitList); + q.where(cb.equal(course.get(Course_.name), "Calculus"), + cb.equal(w.index(), 0)).select(w.get(Student_.name)); + + assertEquivalence(q, jpql); + } + + @AllowFailure(message = "Generates extra Join") + public void testExpression4() { + String jpql = "SELECT SUM(i.price) FROM Order o JOIN o.lineItems i " + + "JOIN o.customer c WHERE c.lastName = 'Smith' AND " + + "c.firstName = 'John'"; + CriteriaQuery q = cb.create(); + Root o = q.from(Order.class); + Join i = o.join(Order_.lineItems); + Join c = o.join(Order_.customer); + q.where(cb.equal(c.get(Customer_.lastName), "Smith"), cb.equal(c + .get(Customer_.firstName), "John")); + q.select(cb.sum(i.get(LineItem_.price))); assertEquivalence(q, jpql); } public void testGeneralCaseExpression() { String jpql = "SELECT e.name, CASE " - + "WHEN e.rating = 1 THEN e.salary * 1.1 " - + "WHEN e.rating = 2 THEN e.salary * 1.2 ELSE e.salary * " - + "1.01 END " - + "FROM Employee e WHERE e.department.name = 'Engineering'"; + + "WHEN e.rating = 1 THEN e.salary * 1.1 " + + "WHEN e.rating = 2 THEN e.salary * 1.2 ELSE e.salary * " + + "1.01 END " + + "FROM Employee e WHERE e.department.name = 'Engineering'"; CriteriaQuery q = cb.create(); Root e = q.from(Employee.class); q.where(cb.equal(e.get(Employee_.department).get(Department_.name), - "Engineering")); + "Engineering")); q.select(e.get(Employee_.name), cb.selectCase().when( cb.equal(e.get(Employee_.rating), 1), cb.prod(e.get(Employee_.salary), 1.1)).when( - cb.equal(e.get(Employee_.rating), 2), - cb.prod(e.get(Employee_.salary), 1.2)).otherwise( - cb.prod(e.get(Employee_.salary), 1.01))); + cb.equal(e.get(Employee_.rating), 2), + cb.prod(e.get(Employee_.salary), 1.2)).otherwise( + cb.prod(e.get(Employee_.salary), 1.01))); assertEquivalence(q, jpql); } public void testSimpleCaseExpression1() { String jpql = "SELECT e.name, CASE e.rating " - + "WHEN 1 THEN e.salary * 1.1 " - + "WHEN 2 THEN e.salary * 1.2 ELSE e.salary * 1.01 END " - + "FROM Employee e WHERE e.department.name = 'Engineering'"; + + "WHEN 1 THEN e.salary * 1.1 " + + "WHEN 2 THEN e.salary * 1.2 ELSE e.salary * 1.01 END " + + "FROM Employee e WHERE e.department.name = 'Engineering'"; CriteriaQuery q = cb.create(); Root e = q.from(Employee.class); q.where(cb.equal(e.get(Employee_.department).get(Department_.name), - "Engineering")); + "Engineering")); q.select(e.get(Employee_.name), cb.selectCase(e.get(Employee_.rating)) .when(1, cb.prod(e.get(Employee_.salary), 1.1)).when(2, cb.prod(e.get(Employee_.salary), 1.2)).otherwise( - cb.prod(e.get(Employee_.salary), 1.01))); + cb.prod(e.get(Employee_.salary), 1.01))); assertEquivalence(q, jpql); } public void testSimpleCaseExpression2() { String jpql = "SELECT e.name, CASE e.rating WHEN 1 THEN 10 " - + "WHEN 2 THEN 20 ELSE 30 END " - + "FROM Employee e WHERE e.department.name = 'Engineering'"; + + "WHEN 2 THEN 20 ELSE 30 END " + + "FROM Employee e WHERE e.department.name = 'Engineering'"; CriteriaQuery q = cb.create(); Root e = q.from(Employee.class); q.where(cb.equal(e.get(Employee_.department).get(Department_.name), - "Engineering")); + "Engineering")); q.select(e.get(Employee_.name), cb.selectCase(e.get(Employee_.rating)) .when(1, 10).when(2, 20).otherwise(30)); assertEquivalence(q, jpql); @@ -483,7 +462,7 @@ public class TestTypesafeCriteria extends CriteriaTest { public void testLiterals() { String jpql = "SELECT p FROM Person p where 'Joe' MEMBER OF " + - "p.nickNames"; + "p.nickNames"; CriteriaQuery q = cb.create(); Root p = q.from(Person.class); q.select(p).where( @@ -492,7 +471,6 @@ public class TestTypesafeCriteria extends CriteriaTest { assertEquivalence(q, jpql); } - // @AllowFailure(message = "Parameters not implemented") public void testParameters1() { String jpql = "SELECT c FROM Customer c Where c.status = :stat"; CriteriaQuery q = cb.create(); @@ -505,7 +483,7 @@ public class TestTypesafeCriteria extends CriteriaTest { public void testParameters2() { String jpql = "SELECT c FROM Customer c Where c.status = :stat AND " - + "c.name = :name"; + + "c.name = :name"; CriteriaQuery q = cb.create(); Root c = q.from(Customer.class); Parameter param1 = cb.parameter(Integer.class, "stat"); @@ -527,21 +505,22 @@ public class TestTypesafeCriteria extends CriteriaTest { assertEquivalence(q, jpql, new Object[] { 1 }); } - // @AllowFailure(message="add QuotedNumbersInQueries=true otherwise " + - // "AbstractExpressionBuilder.convertTypes() compliants") - // public void testParameters4() { - // String jpql = "SELECT c FROM Customer c Where c.status = ?1 AND " - // + "c.name = ?2"; - // CriteriaQuery q = cb.create(); - // Root c = q.from(Customer.class); - // Parameter param1 = cb.parameter(Integer.class); - // Parameter param2 = cb.parameter(Integer.class); - // q.select(c).where( - // cb.and(cb.equal(c.get(Customer_.status), param1), cb.equal(c - // .get(Customer_.name), param2))); - // assertEquivalence(q, jpql, new Object[] { 1, "test" }); - // } - + @AllowFailure(message="add QuotedNumbersInQueries=true otherwise " + + "AbstractExpressionBuilder.convertTypes() compliants") + public void testParameters4() { + String jpql = "SELECT c FROM Customer c Where c.status = ?1 AND " + + "c.name = ?2"; + CriteriaQuery q = cb.create(); + Root c = q.from(Customer.class); + Parameter param1 = cb.parameter(Integer.class); + Parameter param2 = cb.parameter(Integer.class); + q.select(c).where( + cb.and(cb.equal(c.get(Customer_.status), param1), cb.equal(c + .get(Customer_.name), param2))); + assertEquivalence(q, jpql, new Object[] { 1, "test" }); + } + + @AllowFailure(message = "Criteria API does not allow collection parameter") public void testParameters5() { String jpql = "SELECT c FROM Customer c Where c.status IN (:coll)"; CriteriaQuery q = cb.create(); @@ -551,147 +530,176 @@ public class TestTypesafeCriteria extends CriteriaTest { List vals = new ArrayList(); vals.add(1); vals.add(2); + assertEquivalence(q, jpql, new String[] {"coll"}, + new Object[] {vals}); + } + + @AllowFailure(message="Value() expression not implemented") + public void testSelectList1() { + String jpql = "SELECT v.location.street, KEY(i).title, VALUE(i) FROM " + + "VideoStore v JOIN v.videoInventory i WHERE v.location.zipCode = " + + "'94301' AND VALUE(i) > 0"; + CriteriaQuery q = cb.create(); + Root v = q.from(VideoStore.class); + MapJoin inv = v + .join(VideoStore_.videoInventory); + q.where(cb.equal(v.get(VideoStore_.location).get(Address_.zipCode), + "94301"), cb.gt(inv.value(), 0)); + q.select(v.get(VideoStore_.location).get(Address_.street), inv.key() + .get(Movie_.title), inv.value()); - // assertEquivalence(q, jpql, new String[] {"coll"}, new Object[] - // {vals}); + assertEquivalence(q, jpql); } - // @AllowFailure(message="Value() expression not implemented") - // public void testSelectList1() { - // String jpql = "SELECT v.location.street, KEY(i).title, VALUE(i) FROM " - // + "VideoStore v JOIN v.videoInventory i WHERE v.location.zipCode = " - // + "'94301' AND VALUE(i) > 0"; - // CriteriaQuery q = cb.create(); - // Root v = q.from(VideoStore.class); - // MapJoin inv = v - // .join(VideoStore_.videoInventory); - // q.where(cb.equal(v.get(VideoStore_.location).get(Address_.zipCode), - // "94301"), cb.gt(inv.value(), 0)); - // q.select(v.get(VideoStore_.location).get(Address_.street), inv.key() - // .get(Movie_.title), inv.value()); - // - // assertEquivalence(q, jpql); - // } - // - // @AllowFailure(message="new() in projection is broken") - // public void testSelectList2() { - // String jpql = - // "SELECT NEW CustomerDetails(c.id, c.status, o.quantity) FROM " - // + "Customer c JOIN c.orders o WHERE o.quantity > 100"; - // CriteriaQuery q = cb.create(); - // Root c = q.from(Customer.class); - // Join o = c.join(Customer_.orders); - // q.where(cb.gt(o.get(Order_.quantity), 100)); - // q.select(cb.select(CustomerDetails.class, c.get(Customer_.id), c - // .get(Customer_.status), o.get(Order_.quantity))); - // - // assertEquivalence(q, jpql); - // } + public void testNewConstruct() { + String jpql = "SELECT NEW CustomerDetails(c.id, c.status) FROM " + + "Customer c"; + + CriteriaQuery q = cb.create(); -// @AllowFailure(message="Subqueries not implemented") -// public void testSubqueries1() { -// String jpql = "SELECT goodCustomer FROM Customer goodCustomer WHERE " -// + "goodCustomer.balanceOwed < (SELECT AVG(c.balanceOwed) " -// + " FROM " -// + "Customer c)"; -// CriteriaQuery q = cb.create(); -// Root goodCustomer = q.from(Customer.class); -// Subquery sq = q.subquery(Double.class); -// Root c = sq.from(Customer.class); -// q.where(cb.lt(goodCustomer.get(Customer_.balanceOwed), sq.select(cb -// .avg(c.get(Customer_.balanceOwed))))); -// q.select(goodCustomer); -// -// assertEquivalence(q, jpql); -// } -// -// @AllowFailure(message="Subqueries not implemented") -// public void testSubqueries2() { -// String jpql = "SELECT DISTINCT emp FROM Employee emp WHERE EXISTS (" -// + "SELECT spouseEmp FROM Employee spouseEmp WHERE spouseEmp =" -// + " emp.spouse)"; -// CriteriaQuery q = cb.create(); -// Root emp = q.from(Employee.class); -// Subquery sq = q.subquery(Employee.class); -// Root spouseEmp = sq.from(Employee.class); -// sq.select(spouseEmp); -// sq.where(cb.equal(spouseEmp, emp.get(Employee_.spouse))); -// q.where(cb.exists(sq)); -// q.select(emp).distinct(true); -// -// assertEquivalence(q, jpql); -// } -// -// @AllowFailure(message="Subqueries not implemented") -// public void testSubqueries3() { -// String jpql = "SELECT emp FROM Employee emp WHERE emp.salary > ALL (" -// + "SELECT m.salary FROM Manager m WHERE m.department = " -// + "emp.department)"; -// CriteriaQuery q = cb.create(); -// Root emp = q.from(Employee.class); -// q.select(emp); -// Subquery sq = q.subquery(BigDecimal.class); -// Root m = sq.from(Manager.class); -// sq.select(m.get(Manager_.salary)); -// sq.where(cb.equal(m.get(Manager_.department), emp -// .get(Employee_.department))); -// q.where(cb.gt(emp.get(Employee_.salary), cb.all(sq))); -// -// assertEquivalence(q, jpql); -// } -// -// @AllowFailure(message="Subqueries not implemented") -// public void testSubqueries4() { -// String jpql = "SELECT c FROM Customer c WHERE " -// + "(SELECT COUNT(o) FROM c.orders o) > 10"; -// CriteriaQuery q = cb.create(); -// Root c1 = q.from(Customer.class); -// q.select(c1); -// Subquery sq3 = q.subquery(Long.class); -// Root c2 = sq3.correlate(c1); -// Join o = c2.join(Customer_.orders); -// q.where(cb.gt(sq3.select(cb.count(o)), 10)); -// -// assertEquivalence(q, jpql); -// } -// -// @AllowFailure(message="Subqueries not implemented") -// public void testSubqueries5() { -// String jpql = "SELECT o FROM Order o WHERE 10000 < ALL (" -// + "SELECT a.balance FROM o.customer c JOIN c.accounts a)"; -// CriteriaQuery q = cb.create(); -// Root o = q.from(Order.class); -// q.select(o); -// Subquery sq = q.subquery(Integer.class); -// Root osq = sq.correlate(o); -// Join c = osq.join(Order_.customer); -// Join a = c.join(Customer_.accounts); -// sq.select(a.get(Account_.balance)); -// q.where(cb.lt(cb.literal(10000), cb.all(sq))); -// -// assertEquivalence(q, jpql); -// } -// -// @AllowFailure(message="Subqueries not implemented") -// public void testSubqueries6() { -// String jpql = "SELECT o FROM Order o JOIN o.customer c WHERE 10000 < " -// + "ALL (SELECT a.balance FROM c.accounts a)"; -// CriteriaQuery q = cb.create(); -// Root o = q.from(Order.class); -// q.select(o); -// Join c = o.join(Order_.customer); -// Subquery sq = q.subquery(Integer.class); -// Join csq = sq.correlate(c); -// Join a = csq.join(Customer_.accounts); -// sq.select(a.get(Account_.balance)); -// q.where(cb.lt(cb.literal(10000), cb.all(sq))); -// -// assertEquivalence(q, jpql); -// } + Root c = q.from(Customer.class); + q.select(cb.select(CustomerDetails.class, c.get(Customer_.id), + c.get(Customer_.status)) + ); + assertEquivalence(q, jpql); + } + + @AllowFailure(message="new() in projection with join is broken") + public void testNewConstruct1() { + String jpql = + "SELECT NEW CustomerDetails(c.id, c.status, o.quantity) FROM " + + "Customer c JOIN c.orders o WHERE o.quantity > 100"; + CriteriaQuery q = cb.create(); + Root c = q.from(Customer.class); + Join o = c.join(Customer_.orders); + q.where(cb.gt(o.get(Order_.quantity), 100)); + q.select(cb.select(CustomerDetails.class, c.get(Customer_.id), c + .get(Customer_.status), o.get(Order_.quantity))); + + assertEquivalence(q, jpql); + } + + @AllowFailure(message="JPQL does not support multiple constructors") + public void testNewConstruct2() { + String jpql = "SELECT NEW CustomerDetails(c.id, c.status), " + + "NEW CustomerFullName(c.firstName, c.lastName) FROM " + + "Customer c"; + + CriteriaQuery q = cb.create(); + Root c = q.from(Customer.class); + q.select(cb.select(CustomerDetails.class, c.get(Customer_.id), + c.get(Customer_.status)), + cb.select(CustomerFullName.class, c.get(Customer_.firstName), + c.get(Customer_.lastName)) + ); + assertEquivalence(q, jpql); + } + + + + public void testSubqueries1() { + String jpql = "SELECT goodCustomer FROM Customer goodCustomer WHERE " + + "goodCustomer.balanceOwed < (SELECT AVG(c.balanceOwed) " + + " FROM " + + "Customer c)"; + CriteriaQuery q = cb.create(); + Root goodCustomer = q.from(Customer.class); + Subquery sq = q.subquery(Double.class); + Root c = sq.from(Customer.class); + q.where(cb.lt(goodCustomer.get(Customer_.balanceOwed), sq.select(cb + .avg(c.get(Customer_.balanceOwed))))); + q.select(goodCustomer); + + assertEquivalence(q, jpql); + } + + @AllowFailure(message="SQL is incorrect for JPQL, correct for Criteria") + public void testSubqueries2() { + String jpql = "SELECT DISTINCT emp FROM Employee emp WHERE EXISTS (" + + "SELECT spouseEmp FROM Employee spouseEmp WHERE spouseEmp =" + + " emp.spouse)"; + CriteriaQuery q = cb.create(); + Root emp = q.from(Employee.class); + Subquery sq = q.subquery(Employee.class); + Root spouseEmp = sq.from(Employee.class); + sq.select(spouseEmp); + sq.where(cb.equal(spouseEmp, emp.get(Employee_.spouse))); + q.where(cb.exists(sq)); + q.select(emp).distinct(true); + + assertEquivalence(q, jpql); + } + + public void testSubqueries3() { + String jpql = "SELECT emp FROM Employee emp WHERE emp.salary > ALL (" + + "SELECT m.salary FROM Manager m WHERE m.department = " + + "emp.department)"; + CriteriaQuery q = cb.create(); + Root emp = q.from(Employee.class); + q.select(emp); + Subquery sq = q.subquery(BigDecimal.class); + Root m = sq.from(Manager.class); + sq.select(m.get(Manager_.salary)); + sq.where(cb.equal(m.get(Manager_.department), emp + .get(Employee_.department))); + q.where(cb.gt(emp.get(Employee_.salary), cb.all(sq))); + + assertEquivalence(q, jpql); + } + + @AllowFailure(message="SQL is incorrect for JPQL, correct for " + + "Criteria is correct with redundant outer joins") + public void testSubqueries4() { + String jpql = "SELECT c FROM Customer c WHERE " + + "(SELECT COUNT(o) FROM c.orders o) > 10"; + CriteriaQuery q = cb.create(); + Root c1 = q.from(Customer.class); + q.select(c1); + Subquery sq3 = q.subquery(Long.class); + Root c2 = sq3.correlate(c1); + Join o = c2.join(Customer_.orders); + q.where(cb.gt(sq3.select(cb.count(o)), 10)); + + assertEquivalence(q, jpql); + } + + @AllowFailure(message="Subqueries not implemented") + public void testSubqueries5() { + String jpql = "SELECT o FROM Order o WHERE 10000 < ALL (" + + "SELECT a.balance FROM o.customer c JOIN c.accounts a)"; + CriteriaQuery q = cb.create(); + Root o = q.from(Order.class); + q.select(o); + Subquery sq = q.subquery(Integer.class); + Root osq = sq.correlate(o); + Join c = osq.join(Order_.customer); + Join a = c.join(Customer_.accounts); + sq.select(a.get(Account_.balance)); + q.where(cb.lt(cb.literal(10000), cb.all(sq))); + + assertEquivalence(q, jpql); + } + + @AllowFailure(message="Subqueries not implemented") + public void testSubqueries6() { + String jpql = "SELECT o FROM Order o JOIN o.customer c WHERE 10000 < " + + "ALL (SELECT a.balance FROM c.accounts a)"; + CriteriaQuery q = cb.create(); + Root o = q.from(Order.class); + q.select(o); + Join c = o.join(Order_.customer); + Subquery sq = q.subquery(Integer.class); + Join csq = sq.correlate(c); + Join a = csq.join(Customer_.accounts); + sq.select(a.get(Account_.balance)); + q.where(cb.lt(cb.literal(10000), cb.all(sq))); + + assertEquivalence(q, jpql); + } public void testGroupByAndHaving() { String jpql = "SELECT c.status, AVG(c.filledOrderCount), COUNT(c) FROM " - + "Customer c GROUP BY c.status HAVING c.status IN (1, 2)"; + + "Customer c GROUP BY c.status HAVING c.status IN (1, 2)"; CriteriaQuery q = cb.create(); Root c = q.from(Customer.class); q.groupBy(c.get(Customer_.status)); @@ -702,137 +710,84 @@ public class TestTypesafeCriteria extends CriteriaTest { assertEquivalence(q, jpql); } - // @AllowFailure(message="AbstractExpressionExecutor.assertNotContainer() - // not happy") - // public void testOrdering() { - // String jpql = "SELECT c FROM Customer c JOIN c.orders o " - // + "JOIN c.address a WHERE a.state = 'CA' ORDER BY o.quantity DESC, " - // + "o.totalCost"; - // CriteriaQuery q = cb.create(); - // Root c = q.from(Customer.class); - // Join o = c.join(Customer_.orders); - // Join a = c.join(Customer_.address); - // q.where(cb.equal(a.get(Address_.state), "CA")); - // q.orderBy(cb.desc(o.get(Order_.quantity)), cb.asc(o - // .get(Order_.totalCost))); - // q.select(o); - // - // assertEquivalence(q, jpql); - // - // jpql = "SELECT o.quantity, a.zipCode FROM Customer c JOIN c.orders " - // + "JOIN c.address a WHERE a.state = 'CA' ORDER BY o.quantity, " - // + "a.zipCode"; - // q = cb.create(); - // Root c1 = q.from(Customer.class); - // Join o1 = c1.join(Customer_.orders); - // Join a1 = c1.join(Customer_.address); - // q.where(cb.equal(a1.get(Address_.state), "CA")); - // q.orderBy(cb.asc(o1.get(Order_.quantity)), cb.asc(a1 - // .get(Address_.zipCode))); - // q.select(o1.get(Order_.quantity), a1.get(Address_.zipCode)); - // - // assertEquivalence(q, jpql); - // - // jpql = "SELECT o.quantity, o.cost * 1.08 AS taxedCost, a.zipCode " - // + "FROM Customer c JOIN c.orders o JOIN c.address a " - // + "WHERE a.state = 'CA' AND a.county = 'Santa Clara' " - // + "ORDER BY o.quantity, taxedCost, a.zipCode"; - // q = cb.create(); - // Root c2 = q.from(Customer.class); - // Join o2 = c2.join(Customer_.orders); - // Join a2 = c2.join(Customer_.address); - // q.where(cb.equal(a.get(Address_.state), "CA"), cb.equal(a - // .get(Address_.county), "Santa Clara")); - // q.orderBy(cb.asc(o.get(Order_.quantity)), cb.asc(cb.prod( - // o.get(Order_.totalCost), 1.08)), - // cb.asc(a.get(Address_.zipCode))); - // q.select(o.get(Order_.quantity), cb.prod( - // o.get(Order_.totalCost), 1.08), a.get(Address_.zipCode)); - // - // assertEquivalence(q, jpql); - // } - // - // @AllowFailure(message="AbstractExpressionExecutor.assertNotContainer()"+ - // "not happy") - // public void testOrdering1() { - // String jpql = "SELECT o FROM Customer c JOIN c.orders o " - // + "JOIN c.address a WHERE a.state = 'CA' ORDER BY o.quantity DESC, " - // + "o.totalCost"; - // CriteriaQuery q = cb.create(); - // Root c = q.from(Customer.class); - // Join o = c.join(Customer_.orders); - // Join a = c.join(Customer_.address); - // q.where(cb.equal(a.get(Address_.state), "CA")); - // q.orderBy(cb.desc(o.get(Order_.quantity)), cb.asc(o - // .get(Order_.totalCost))); - // q.select(o); - // - // assertEquivalence(q, jpql); - // } - // - // @AllowFailure(message="The JPQL is broken!") - // public void testOrdering2() { - // String jpql = "SELECT o.quantity, a.zipCode FROM Customer c " - // + "JOIN c.orders JOIN c.address a WHERE a.state = 'CA' " - // + "ORDER BY o.quantity, a.zipCode"; - // CriteriaQuery q = cb.create(); - // Root c = q.from(Customer.class); - // Join o = c.join(Customer_.orders); - // Join a = c.join(Customer_.address); - // q.where(cb.equal(a.get(Address_.state), "CA")); - // q.orderBy(cb.asc(o.get(Order_.quantity)), cb.asc(a - // .get(Address_.zipCode))); - // q.select(o.get(Order_.quantity), a.get(Address_.zipCode)); - // - // assertEquivalence(q, jpql); - // } - // - // @AllowFailure(message="QueryExpression.ordering not initialized") - // public void testOrdering3() { - // String jpql = "SELECT o.quantity, o.totalCost * 1.08 AS taxedCost, " - // + "a.zipCode FROM Customer c JOIN c.orders o JOIN c.address a " - // + "WHERE a.state = 'CA' AND a.county = 'Santa Clara' " - // + "ORDER BY o.quantity, taxedCost, a.zipCode"; - // CriteriaQuery q = cb.create(); - // Root c = q.from(Customer.class); - // Join o = c.join(Customer_.orders); - // Join a = c.join(Customer_.address); - // q.where(cb.equal(a.get(Address_.state), "CA"), cb.equal(a - // .get(Address_.county), "Santa Clara")); - // q.orderBy(cb.asc(o.get(Order_.quantity)), cb.asc(cb.prod( - // o.get(Order_.totalCost), 1.08)), - // cb.asc(a.get(Address_.zipCode))); - // q.select(o.get(Order_.quantity), cb.prod( - // o.get(Order_.totalCost), 1.08), a.get(Address_.zipCode)); - // - // assertEquivalence(q, jpql); - // } - // - // - // @AllowFailure(message="QueryExpression.ordering not initialized") - // public void testOrdering4() { - // String jpql = "SELECT c FROM Customer c " - // + "ORDER BY c.name DESC, c.status"; - // CriteriaQuery q = cb.create(); - // Root c = q.from(Customer.class); - // q.orderBy(cb.desc(c.get(Customer_.name)), cb.asc(c - // .get(Customer_.status))); - // q.select(c); - // - // assertEquivalence(q, jpql); - // } - // - // @AllowFailure(message="QueryExpression.ordering not initialized") - // public void testOrdering5() { - // String jpql = "SELECT c.firstName, c.lastName, c.balanceOwed " - // + "FROM Customer c ORDER BY c.name DESC, c.status"; - // CriteriaQuery q = cb.create(); - // Root c = q.from(Customer.class); - // q.orderBy(cb.desc(c.get(Customer_.name)), cb.asc(c - // .get(Customer_.status))); - // q.select(c.get(Customer_.firstName), c.get(Customer_.lastName), c - // .get(Customer_.balanceOwed)); - // - // assertEquivalence(q, jpql); - // } + @AllowFailure(message="AbstractExpressionExecutor.assertNotContainer()"+ + "not happy") + public void testOrdering1() { + String jpql = "SELECT o FROM Customer c JOIN c.orders o " + + "JOIN c.address a WHERE a.state = 'CA' ORDER BY o.quantity DESC, " + + "o.totalCost"; + CriteriaQuery q = cb.create(); + Root c = q.from(Customer.class); + Join o = c.join(Customer_.orders); + Join a = c.join(Customer_.address); + q.where(cb.equal(a.get(Address_.state), "CA")); + q.orderBy(cb.desc(o.get(Order_.quantity)), cb.asc(o + .get(Order_.totalCost))); + q.select(o); + + assertEquivalence(q, jpql); + } + + @AllowFailure + public void testOrdering2() { + String jpql = "SELECT o.quantity, a.zipCode FROM Customer c " + + "JOIN c.orders o JOIN c.address a WHERE a.state = 'CA' " + + "ORDER BY o.quantity, a.zipCode"; + CriteriaQuery q = cb.create(); + Root c = q.from(Customer.class); + Join o = c.join(Customer_.orders); + Join a = c.join(Customer_.address); + q.where(cb.equal(a.get(Address_.state), "CA")); + q.orderBy(cb.asc(o.get(Order_.quantity)), cb.asc(a + .get(Address_.zipCode))); + q.select(o.get(Order_.quantity), a.get(Address_.zipCode)); + + assertEquivalence(q, jpql); + } + + @AllowFailure + public void testOrdering3() { + String jpql = "SELECT o.quantity, o.totalCost * 1.08 AS taxedCost, " + + "a.zipCode FROM Customer c JOIN c.orders o JOIN c.address a " + + "WHERE a.state = 'CA' AND a.county = 'Santa Clara' " + + "ORDER BY o.quantity, taxedCost, a.zipCode"; + CriteriaQuery q = cb.create(); + Root c = q.from(Customer.class); + Join o = c.join(Customer_.orders); + Join a = c.join(Customer_.address); + q.where(cb.equal(a.get(Address_.state), "CA"), cb.equal(a + .get(Address_.county), "Santa Clara")); + q.orderBy(cb.asc(o.get(Order_.quantity)), cb.asc(cb.prod( + o.get(Order_.totalCost), 1.08)), + cb.asc(a.get(Address_.zipCode))); + q.select(o.get(Order_.quantity), cb.prod( + o.get(Order_.totalCost), 1.08), a.get(Address_.zipCode)); + + assertEquivalence(q, jpql); + } + + public void testOrdering4() { + String jpql = "SELECT c FROM Customer c " + + "ORDER BY c.name DESC, c.status"; + CriteriaQuery q = cb.create(); + Root c = q.from(Customer.class); + q.orderBy(cb.desc(c.get(Customer_.name)), cb.asc(c + .get(Customer_.status))); + q.select(c); + + assertEquivalence(q, jpql); + } + + public void testOrdering5() { + String jpql = "SELECT c.firstName, c.lastName, c.balanceOwed " + + "FROM Customer c ORDER BY c.name DESC, c.status"; + CriteriaQuery q = cb.create(); + Root c = q.from(Customer.class); + q.orderBy(cb.desc(c.get(Customer_.name)), cb.asc(c + .get(Customer_.status))); + q.select(c.get(Customer_.firstName), c.get(Customer_.lastName), c + .get(Customer_.balanceOwed)); + + assertEquivalence(q, jpql); + } } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java index bc4637189..356713c87 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaBuilder.java @@ -96,7 +96,7 @@ public class CriteriaBuilder implements QueryBuilder, ExpressionParser { } public Expression all(Subquery subquery) { - throw new AbstractMethodError(); + return new Expressions.All(subquery); } public Predicate and(Predicate... restrictions) { @@ -108,7 +108,7 @@ public class CriteriaBuilder implements QueryBuilder, ExpressionParser { } public Expression any(Subquery subquery) { - throw new AbstractMethodError(); + return new Expressions.Any(subquery); } public Order asc(Expression x) { @@ -208,15 +208,19 @@ public class CriteriaBuilder implements QueryBuilder, ExpressionParser { } public Predicate equal(Expression x, Expression y) { + if (y == null) + return new Expressions.IsNull((ExpressionImpl )x); return new Expressions.Equal(x, y); } public Predicate equal(Expression x, Object y) { + if (y == null) + return new Expressions.IsNull((ExpressionImpl )x); return new Expressions.Equal(x, y); } public Predicate exists(Subquery subquery) { - throw new AbstractMethodError(); + return new Expressions.Exists(subquery); } public Expression function(String name, Class type, @@ -326,7 +330,7 @@ public class CriteriaBuilder implements QueryBuilder, ExpressionParser { } public Expression length(Expression x) { - throw new AbstractMethodError(); + return new Expressions.Length(x); } @@ -385,29 +389,29 @@ public class CriteriaBuilder implements QueryBuilder, ExpressionParser { public Expression locate(Expression x, Expression pattern) { - throw new AbstractMethodError(); + return new Expressions.Locate(x, pattern); } public Expression locate(Expression x, String pattern) { - throw new AbstractMethodError(); + return new Expressions.Locate(x, pattern); } public Expression locate(Expression x, Expression pattern, Expression from) { - throw new AbstractMethodError(); + return new Expressions.Locate(x, pattern, from); } public Expression locate(Expression x, String pattern, int from) { - throw new AbstractMethodError(); + return new Expressions.Locate(x, pattern, from); } public Expression lower(Expression x) { - throw new AbstractMethodError(); + return new Expressions.Lower(x); } @@ -486,12 +490,12 @@ public class CriteriaBuilder implements QueryBuilder, ExpressionParser { } public Expression nullif(Expression x, Expression y) { - throw new AbstractMethodError(); + return new Expressions.Nullif(x, y); } public Expression nullif(Expression x, Y y) { - throw new AbstractMethodError(); + return new Expressions.Nullif(x, y); } @@ -563,7 +567,7 @@ public class CriteriaBuilder implements QueryBuilder, ExpressionParser { } public Expression some(Subquery subquery) { - throw new AbstractMethodError(); + return new Expressions.Some(subquery); } public Expression sqrt(Expression x) { @@ -572,7 +576,7 @@ public class CriteriaBuilder implements QueryBuilder, ExpressionParser { public Expression substring(Expression x, Expression from) { - return new Expressions.Substring(x); + return new Expressions.Substring(x, from); } public Expression substring(Expression x, int from) { @@ -665,7 +669,7 @@ public class CriteriaBuilder implements QueryBuilder, ExpressionParser { } public Expression upper(Expression x) { - throw new AbstractMethodError(); + return new Expressions.Upper(x); } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpressionBuilder.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpressionBuilder.java new file mode 100644 index 000000000..f48e14bd6 --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaExpressionBuilder.java @@ -0,0 +1,235 @@ +/* + * 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.criteria; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import javax.persistence.criteria.Expression; +import javax.persistence.criteria.Join; +import javax.persistence.criteria.Order; +import javax.persistence.criteria.Root; +import javax.persistence.criteria.Selection; + +import org.apache.openjpa.kernel.exps.ExpressionFactory; +import org.apache.openjpa.kernel.exps.QueryExpressions; +import org.apache.openjpa.kernel.exps.Value; +import org.apache.openjpa.meta.ClassMetaData; +import org.apache.openjpa.persistence.meta.MetamodelImpl; +import org.apache.openjpa.persistence.meta.Types; + +/** + * Subquery is an expression as its selection item. + * + */ +public class CriteriaExpressionBuilder { + + private int aliasCount = 0; + + private CriteriaQueryImpl criteriaQuery = null; + + public CriteriaExpressionBuilder(CriteriaQueryImpl criteriaQuery) { + this.criteriaQuery = criteriaQuery; + } + + public QueryExpressions getQueryExpressions(ExpressionFactory factory, + CriteriaQueryImpl q) { + QueryExpressions exps = new QueryExpressions(); + + evalAccessPaths(exps, factory, q); + //exps.alias = null; // String + exps.ascending = new boolean[]{false}; + evalDistinct(exps, factory, q); + evalFetchJoin(exps, factory, q); + + evalFilter(exps, factory, q); + + evalGrouping(exps, factory, q); + + evalOrdering(exps, factory, q); + //exps.operation = QueryOperations.OP_SELECT; + + evalProjections(exps, factory, q); + + + //exps.range = null; // Value[] + //exps.resultClass = null; // Class + if (q.getParameterTypes() != null) + exps.parameterTypes = q.getParameterTypes(); + return exps; + } + + protected void evalAccessPaths(QueryExpressions exps, + ExpressionFactory factory, CriteriaQueryImpl q) { + Set> roots = q.getRoots(); + if (roots != null) { + exps.accessPath = new ClassMetaData[roots.size()]; + int i = 0; + for (Root r : roots) + exps.accessPath[i++] = ((Types.Managed)r.getModel()).meta; + } + } + + protected void evalOrdering(QueryExpressions exps, + ExpressionFactory factory, CriteriaQueryImpl q) { + List orders = q.getOrderList(); + MetamodelImpl model = q.getMetamodel(); + if (orders == null) + return; + int ordercount = orders.size(); + exps.ordering = new Value[ordercount]; + exps.orderingClauses = new String[ordercount]; + exps.orderingAliases = new String[ordercount]; + exps.ascending = new boolean[ordercount]; + for (int i = 0; i < ordercount; i++) { + OrderImpl order = (OrderImpl)orders.get(i); + //Expression expr = order.getExpression(); + Expression expr = order.getExpression5(); + exps.ordering[i] = Expressions.toValue( + (ExpressionImpl)expr, factory, model, q); + + //exps.orderingClauses[i] = assemble(firstChild); + //exps.orderingAliases[i] = firstChild.text; + exps.ascending[i] = order.isAscending(); + } + } + + protected void evalGrouping(QueryExpressions exps, + ExpressionFactory factory, CriteriaQueryImpl q) { + // exps.grouping = null; // Value[] + // exps.groupingClauses = null; // String[] + List> groups = q.getGroupList(); + MetamodelImpl model = q.getMetamodel(); + PredicateImpl having = q.getGroupRestriction(); + if (groups == null) + return; + int groupByCount = groups.size(); + exps.grouping = new Value[groupByCount]; + for (int i = 0; i < groupByCount; i++) { + Expression groupBy = groups.get(i); + exps.grouping[i] = Expressions.toValue( + (ExpressionImpl)groupBy, factory, model, q);; + } + + exps.having = having == null ? factory.emptyExpression() + : having.toKernelExpression(factory, model, q); + } + + protected void evalDistinct(QueryExpressions exps, + ExpressionFactory factory, CriteriaQueryImpl q) { + Boolean distinct = q.getDistinct(); + if (distinct == null) { + exps.distinct = QueryExpressions.DISTINCT_FALSE; + } else if (distinct) { + exps.distinct = QueryExpressions.DISTINCT_TRUE + | QueryExpressions.DISTINCT_AUTO; + } + //exps.distinct &= ~QueryExpressions.DISTINCT_AUTO; + } + + protected void evalFilter(QueryExpressions exps, ExpressionFactory factory, + CriteriaQueryImpl q) { + Set> roots = q.getRoots(); + MetamodelImpl model = q.getMetamodel(); + PredicateImpl where = q.getRestriction(); + q.assertRoot(); + org.apache.openjpa.kernel.exps.Expression filter = null; + for (Root root : roots) { + if (root.getJoins() != null) { + for (Join join : root.getJoins()) { + filter = and(factory, ((ExpressionImpl)join) + .toKernelExpression(factory, model, q), filter); + } + } + if (((RootImpl)root).getCorrelatedParent() != null) { + filter = and(factory, ((RootImpl)root) + .toKernelExpression(factory, model, q), filter); + } + } + if (where != null) { + filter = and(factory, where.toKernelExpression + (factory, model, q), filter); + } + if (filter == null) + filter = factory.emptyExpression(); + exps.filter = filter; + } + + protected void evalProjections(QueryExpressions exps, + ExpressionFactory factory, CriteriaQueryImpl q) { + List> selections = q.getSelectionList(); + MetamodelImpl model = q.getMetamodel(); + // TODO: fill in projection clauses + // exps.projectionClauses = null; // String[] + if (isDefaultProjection(selections, q)) { + exps.projections = new Value[0]; + return ; + } + exps.projections = new Value[selections.size()]; + List projections = new ArrayList(); + List aliases = new ArrayList(); + getProjections(exps, selections, projections, aliases, factory, q, + model); + exps.projections = projections.toArray(new Value[0]); + exps.projectionAliases = aliases.toArray(new String[0]); + } + + private void getProjections(QueryExpressions exps, + List> selections, List projections, List aliases, + ExpressionFactory factory, CriteriaQueryImpl q, MetamodelImpl model) { + for (Selection s : selections) { + List> sels = ((SelectionImpl)s).getSelections(); + if (sels == null) { + projections.add(((ExpressionImpl)s). + toValue(factory, model, q)); + aliases.add(nextAlias()); + } else { + // this is for constructor expression in the selection + exps.resultClass = s.getJavaType(); + getProjections(exps, sels, projections, aliases, factory, q, + model); + } + } + } + + protected boolean isDefaultProjection(List> selections, + CriteriaQueryImpl q) { + return selections == null + || (selections.size() == 1 && selections.get(0) == q.getRoot()); + } + + protected void evalFetchJoin(QueryExpressions exps, + ExpressionFactory factory, CriteriaQueryImpl q) { + //exps.fetchInnerPaths = null; // String[] + //exps.fetchPaths = null; // String[] + } + + protected org.apache.openjpa.kernel.exps.Expression and ( + ExpressionFactory factory, + org.apache.openjpa.kernel.exps.Expression e1, + org.apache.openjpa.kernel.exps.Expression e2) { + return e1 == null ? e2 : e2 == null ? e1 : factory.and(e1, e2); + } + + protected String nextAlias() { + return "jpqlalias" + (++aliasCount); + } +} diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java index 4c37243fd..aa63e1e2f 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/CriteriaQueryImpl.java @@ -20,7 +20,6 @@ package org.apache.openjpa.persistence.criteria; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; @@ -28,7 +27,6 @@ import java.util.Set; import javax.persistence.Parameter; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; -import javax.persistence.criteria.Join; import javax.persistence.criteria.Order; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; @@ -37,14 +35,8 @@ import javax.persistence.criteria.Subquery; import javax.persistence.metamodel.Entity; import org.apache.commons.collections.map.LinkedMap; -import org.apache.openjpa.kernel.exps.AbstractExpressionBuilder; import org.apache.openjpa.kernel.exps.ExpressionFactory; -import org.apache.openjpa.kernel.exps.Path; import org.apache.openjpa.kernel.exps.QueryExpressions; -import org.apache.openjpa.kernel.exps.Value; -import org.apache.openjpa.meta.ClassMetaData; -import org.apache.openjpa.meta.FieldMetaData; -import org.apache.openjpa.persistence.meta.Members; import org.apache.openjpa.persistence.meta.MetamodelImpl; import org.apache.openjpa.persistence.meta.Types; @@ -69,16 +61,28 @@ public class CriteriaQueryImpl implements CriteriaQuery { private List> _selections; private List> _groups; private PredicateImpl _having; + private List> _subqueries; private Boolean _distinct; private LinkedMap _parameterTypes; - private Class _resultClass; - private Value[] _projections; - private int _aliasCount = 0; + private CriteriaExpressionBuilder _exprBuilder; + private SubqueryImpl _context; public CriteriaQueryImpl(MetamodelImpl model) { this._model = model; } - + + public void setContext(SubqueryImpl context) { + _context = context; + } + + public SubqueryImpl getContext() { + return _context; + } + + public MetamodelImpl getMetamodel() { + return _model; + } + public CriteriaQuery distinct(boolean distinct) { _distinct = distinct; return this; @@ -154,7 +158,7 @@ public class CriteriaQueryImpl implements CriteriaQuery { return _groups; } - public Predicate getGroupRestriction() { + public PredicateImpl getGroupRestriction() { return _having; } @@ -166,6 +170,10 @@ public class CriteriaQueryImpl implements CriteriaQuery { return _roots; } + public void setRoots (Set> roots) { + this._roots = roots; + } + public Root getRoot() { assertRoot(); return _roots.iterator().next(); @@ -175,9 +183,16 @@ public class CriteriaQueryImpl implements CriteriaQuery { return _distinct; } + public Boolean getDistinct() { + return _distinct; + } + public Subquery subquery(Class type) { - // TODO Auto-generated method stub - return null; + if (_subqueries == null) + _subqueries = new ArrayList>(); + Subquery subquery = new SubqueryImpl(type, this); + _subqueries.add(subquery); + return subquery; } public LinkedMap getParameterTypes() { @@ -188,12 +203,8 @@ public class CriteriaQueryImpl implements CriteriaQuery { _parameterTypes = parameterTypes; } - public void setResultClass(Class resultClass) { - _resultClass = resultClass; - } - - public void setProjections(Value[] projections) { - _projections = projections; + public CriteriaExpressionBuilder getExprBuilder() { + return _exprBuilder; } /** @@ -201,242 +212,12 @@ public class CriteriaQueryImpl implements CriteriaQuery { * receiver with the help of the given {@link ExpressionFactory}. */ QueryExpressions getQueryExpressions(ExpressionFactory factory) { - QueryExpressions exps = new QueryExpressions(); - - evalAccessPaths(exps, factory); -// exps.alias = null; // String - exps.ascending = new boolean[]{false}; - evalDistinct(exps, factory); - evalFetchJoin(exps, factory); - - evalFilter(exps, factory); - - evalGrouping(exps, factory); - exps.having = _having == null ? factory.emptyExpression() - : _having.toKernelExpression(factory, _model, this); - - evalOrdering(exps, factory); - // exps.operation = QueryOperations.OP_SELECT; - - - // exps.parameterTypes = null; // LinkedMap<> - evalProjections(exps, factory); - - evalProjection(exps, factory); - - - // exps.range = null; // Value[] - // exps.resultClass = null; // Class - if (_parameterTypes != null) - exps.parameterTypes = _parameterTypes; - exps.resultClass = _resultClass; - return exps; - } - - void evalAccessPaths(QueryExpressions exps, ExpressionFactory factory) { - if (_roots != null) { - exps.accessPath = new ClassMetaData[_roots.size()]; - int i = 0; - for (Root r : _roots) - exps.accessPath[i++] = ((Types.Managed)r.getModel()).meta; - } - } - - void evalOrdering(QueryExpressions exps, ExpressionFactory factory) { - if (_orders == null) - return; - int ordercount = _orders.size(); - exps.ordering = new Value[ordercount]; - exps.orderingClauses = new String[ordercount]; - exps.orderingAliases = new String[ordercount]; - exps.ascending = new boolean[ordercount]; - for (int i = 0; i < ordercount; i++) { - OrderImpl order = (OrderImpl)_orders.get(i); - //Expression expr = order.getExpression(); - Expression expr = order.getExpression5(); - exps.ordering[i] = Expressions.toValue( - (ExpressionImpl)expr, factory, _model, this); - - //exps.orderingClauses[i] = assemble(firstChild); - //exps.orderingAliases[i] = firstChild.text; - exps.ascending[i] = order.isAscending(); - } - } - - void evalGrouping(QueryExpressions exps, ExpressionFactory factory) { - // exps.grouping = null; // Value[] - // exps.groupingClauses = null; // String[] - if (_groups == null) - return; - int groupByCount = _groups.size(); - exps.grouping = new Value[groupByCount]; - for (int i = 0; i < groupByCount; i++) { - Expression groupBy = _groups.get(i); - exps.grouping[i] = Expressions.toValue( - (ExpressionImpl)groupBy, factory, _model, this);; - } - } - - void evalProjections(QueryExpressions exps, ExpressionFactory factory) { - // TODO: fill in projection aliases and clauses - // exps.projectionAliases = null; // String[] - // exps.projectionClauses = null; // String[] - if (isDefaultProjection()) { - exps.projections = new Value[0]; - return ; - } - exps.projections = new Value[_selections.size()]; - int i = 0; - for (Selection s : _selections) { - exps.projections[i++] = ((ExpressionImpl)s) - .toValue(factory, _model, this); - } - return; - } - - boolean isDefaultProjection() { - return _selections == null - || (_selections.size() == 1 && _selections.get(0) == getRoot()); - } - - void evalDistinct(QueryExpressions exps, ExpressionFactory factory) { - if (_distinct == null) { - exps.distinct = QueryExpressions.DISTINCT_FALSE; - } else if (_distinct) { - exps.distinct = QueryExpressions.DISTINCT_TRUE - | QueryExpressions.DISTINCT_AUTO; - } - exps.distinct &= ~QueryExpressions.DISTINCT_AUTO; - } - - void evalFilter(QueryExpressions exps, ExpressionFactory factory) { - assertRoot(); - org.apache.openjpa.kernel.exps.Expression filter = null; - for (Root root : _roots) { - if (root.getJoins() != null) { - for (Join join : root.getJoins()) { - filter = and(factory, ((ExpressionImpl)join) - .toKernelExpression(factory, _model, this), filter); - } - } - } - if (_where != null) { - filter = and(factory, _where.toKernelExpression - (factory, _model, this), filter); - } - if (filter == null) - filter = factory.emptyExpression(); - exps.filter = filter; - } - - void evalProjection(QueryExpressions exps, ExpressionFactory factory) { - Value [] projs = toValues(exps, factory, getSelectionList()); - if (projs.length == 1 && projs[0] == null) - exps.projections = _projections; - else - exps.projections = projs; - //exps.projectionClauses = String[]; + _exprBuilder = new CriteriaExpressionBuilder(this); + return _exprBuilder.getQueryExpressions(factory, this); } - - Value[] toValues(QueryExpressions exps, ExpressionFactory factory, - List> sels) { - if (sels == null || (sels.size() == 1 && sels.get(0) == getRoot())) - return new Value[0]; - Value[] result = new Value[sels.size()]; - String[] aliases = new String[sels.size()]; - int i = 0; - for (Selection s : sels) { - result[i] = ((SelectionImpl)s).toValue(factory, _model, - this); - aliases[i] = nextAlias(); - i++; - } - exps.projectionAliases = aliases; - - return result; - } - void evalFetchJoin(QueryExpressions exps, ExpressionFactory factory) { - // exps.fetchInnerPaths = null; // String[] - // exps.fetchPaths = null; // String[] - } - - - org.apache.openjpa.kernel.exps.Expression and(ExpressionFactory factory, - org.apache.openjpa.kernel.exps.Expression e1, - org.apache.openjpa.kernel.exps.Expression e2) { - return e1 == null ? e2 : e2 == null ? e1 : factory.and(e1, e2); - } - - void assertRoot() { + public void assertRoot() { if (_roots == null || _roots.isEmpty()) throw new IllegalStateException("no root is set"); } - - void setImplicitTypes(Value val1, Value val2, Class expected) { - Class c1 = (val1 == null ? null : val1.getType()); - Class c2 = (val2 == null ? null : val2.getType()); - - boolean o1 = c1 == AbstractExpressionBuilder.TYPE_OBJECT; - boolean o2 = c2 == AbstractExpressionBuilder.TYPE_OBJECT; - - if (o1 && !o2) { - val1.setImplicitType(c2); - if (val1.getMetaData() == null && !val1.isXPath()) - val1.setMetaData(val2.getMetaData()); - } else if (!o1 && o2) { - val2.setImplicitType(c1); - if (val2.getMetaData() == null && !val1.isXPath()) - val2.setMetaData(val1.getMetaData()); - } else if (o1 && o2 && expected != null) { - // we never expect a pc type, so don't bother with metadata - val1.setImplicitType(expected); - val2.setImplicitType(expected); - } else if (c1 != null && c2 != null && - AbstractExpressionBuilder.isNumeric(c1) - != AbstractExpressionBuilder.isNumeric(c2)) { - AbstractExpressionBuilder.convertTypes(val1, val2); - } - - // as well as setting the types for conversions, we also need to - // ensure that any parameters are declared with the correct type, - // since the JPA spec expects that these will be validated - org.apache.openjpa.kernel.exps.Parameter param = - val1 instanceof org.apache.openjpa.kernel.exps.Parameter ? - (org.apache.openjpa.kernel.exps.Parameter) val1 - : val2 instanceof org.apache.openjpa.kernel.exps.Parameter ? - (org.apache.openjpa.kernel.exps.Parameter) val2 : null; - Path path = val1 instanceof Path ? (Path) val1 - : val2 instanceof Path ? (Path) val2 : null; - - // we only check for parameter-to-path comparisons - if (param == null || path == null || _parameterTypes == null) - return; - - FieldMetaData fmd = path.last(); - if (fmd == null) - return; - - //TODO: - //if (expected == null) - // checkEmbeddable(path); - - Class type = path.getType(); - if (type == null) - return; - - Object paramKey = param.getParameterKey(); - if (paramKey == null) - return; - - // make sure we have already declared the parameter - if (_parameterTypes.containsKey(paramKey)) - _parameterTypes.put(paramKey, type); - } - - private String nextAlias() { - return "jpqlalias" + (++_aliasCount); - } - - } 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 e5e829029..d5d384017 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 @@ -21,7 +21,6 @@ package org.apache.openjpa.persistence.criteria; import java.util.Collection; -import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.QueryBuilder.In; @@ -41,13 +40,13 @@ public abstract class ExpressionImpl extends SelectionImpl implements Expression { Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { throw new AbstractMethodError(this.getClass().getName()); } org.apache.openjpa.kernel.exps.Expression toKernelExpression( ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { throw new AbstractMethodError(this.getClass().getName()); } 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 bfb4b7bc5..bf4c990e5 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 @@ -23,22 +23,21 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; -import javax.persistence.criteria.ListJoin; -import javax.persistence.criteria.Path; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.QueryBuilder; +import javax.persistence.criteria.Subquery; import javax.persistence.criteria.QueryBuilder.Trimspec; -import org.apache.openjpa.persistence.meta.Types; import org.apache.openjpa.kernel.exps.ExpressionFactory; import org.apache.openjpa.kernel.exps.Literal; import org.apache.openjpa.kernel.exps.Value; import org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder; import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.persistence.meta.MetamodelImpl; +import org.apache.openjpa.persistence.meta.Types; +import serp.util.Numbers; public class Expressions { /** @@ -46,21 +45,21 @@ public class Expressions { * using the given ExpressionFactory. * Also sets the alias of the resulting value. */ - static Value toValue(ExpressionImpl e, ExpressionFactory factory, - MetamodelImpl model, CriteriaQuery q) { + static Value toValue(ExpressionImpl e, ExpressionFactory factory, + MetamodelImpl model, CriteriaQueryImpl q) { Value v = e == null ? factory.getNull() : e.toValue(factory, model, q); - v.setImplicitType(e.getJavaType()); - v.setAlias(e.getAlias()); + //v.setImplicitType(e.getJavaType()); + //v.setAlias(e.getAlias()); - return v; - } - - /** - * Unary Functional Expression applies a unary function on a input - * Expression. - * - * @param the type of the resultant expression - */ + return v; + } + + /** + * Unary Functional Expression applies a unary function on a input + * Expression. + * + * @param the type of the resultant expression + */ public static class UnaryFunctionalExpression extends ExpressionImpl { protected ExpressionImpl e; @@ -80,7 +79,7 @@ public class Expressions { * input Expression. * * - * @param the type of the resultant expression + * @param the type of the resultant expression */ public static class BinarayFunctionalExpression extends ExpressionImpl{ @@ -88,7 +87,7 @@ public class Expressions { protected ExpressionImpl e2; public BinarayFunctionalExpression(Class t, Expression x, - Expression y) { + Expression y) { super(t); e1 = (ExpressionImpl)x; e2 = (ExpressionImpl)y; @@ -110,101 +109,106 @@ public class Expressions { e1 = (ExpressionImpl)x; e2 = (ExpressionImpl)y; } + + @Override + public PredicateImpl clone() { + return new BinaryLogicalExpression(e1, e2); + } } public static class Abs extends UnaryFunctionalExpression { - public Abs(Expression x) { - super(x); - } + public Abs(Expression x) { + super(x); + } - @Override + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return factory.abs(Expressions.toValue(e, factory, model, q)); } } public static class Count extends UnaryFunctionalExpression { - private boolean _distinct; - public Count(Expression x) { - this(x, false); - } - - public Count(Expression x, boolean distinct) { - super(Long.class, x); - _distinct = distinct; - - } + private boolean _distinct; + public Count(Expression x) { + this(x, false); + } + + public Count(Expression x, boolean distinct) { + super(Long.class, x); + _distinct = distinct; + + } - @Override + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { Value v = factory.count(Expressions.toValue(e, factory, model, q)); return _distinct ? factory.distinct(v) : v; } } public static class Avg extends UnaryFunctionalExpression { - public Avg(Expression x) { - super(Double.class, x); - } + public Avg(Expression x) { + super(Double.class, x); + } - @Override + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return factory.avg(Expressions.toValue(e, factory, model, q)); } } public static class Sqrt extends UnaryFunctionalExpression { - public Sqrt(Expression x) { - super(Double.class, x); - } + public Sqrt(Expression x) { + super(Double.class, x); + } - @Override + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return factory.sqrt(Expressions.toValue(e, factory, model, q)); } } public static class Max extends UnaryFunctionalExpression { - public Max(Expression x) { - super(x); - } + public Max(Expression x) { + super(x); + } - @Override + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return factory.max(Expressions.toValue(e, factory, model, q)); } } public static class Min extends UnaryFunctionalExpression { - public Min(Expression x) { - super(x); - } + public Min(Expression x) { + super(x); + } - @Override + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return factory.min(Expressions.toValue(e, factory, model, q)); } } public static class Size extends UnaryFunctionalExpression { - public Size(Expression> x) { - super(Integer.class, x); - } - - public Size(Collection x) { - this(new Constant>(x)); - } + public Size(Expression> x) { + super(Integer.class, x); + } + + public Size(Collection x) { + this(new Constant>(x)); + } - @Override + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return factory.size(Expressions.toValue(e, factory, model, q)); } } @@ -218,293 +222,340 @@ public class Expressions { @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return factory.type(Expressions.toValue(e, factory, model, q)); } } public static class Cast extends UnaryFunctionalExpression { - Class b; - public Cast(Expression x, Class b) { - super(b, x); - } + Class b; + public Cast(Expression x, Class b) { + super(b, x); + } - @Override + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return factory.cast(Expressions.toValue(e, factory, model, q), b); } } public static class Concat extends BinarayFunctionalExpression { - public Concat(Expression x, Expression y) { - super(String.class, x, y); - } - - public Concat(Expression x, String y) { - this(x, new Constant(y)); - } - - public Concat(String x, Expression y) { - this(new Constant(x), y); - } - - @Override + public Concat(Expression x, Expression y) { + super(String.class, x, y); + } + + public Concat(Expression x, String y) { + this(x, new Constant(y)); + } + + public Concat(String x, Expression y) { + this(new Constant(x), y); + } + + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return factory.concat( - Expressions.toValue(e1, factory, model, q), - Expressions.toValue(e2, factory, model, q)); + Expressions.toValue(e1, factory, model, q), + Expressions.toValue(e2, factory, model, q)); } } public static class Substring extends UnaryFunctionalExpression { - private ExpressionImpl from; - private ExpressionImpl len; - - public Substring(Expression s, Expression from, - Expression len) { - super(s); - this.from = (ExpressionImpl)from; - this.len = (ExpressionImpl)len; - } - - public Substring(Expression s) { - this(s, (Expression)null, (Expression)null); - } - - public Substring(Expression s, Integer from) { - this(s, new Constant(from), null); - } - - public Substring(Expression s, Integer from, Integer len) { + private ExpressionImpl from; + private ExpressionImpl len; + + public Substring(Expression s, Expression from, + Expression len) { + super(s); + this.from = (ExpressionImpl)from; + this.len = (ExpressionImpl)len; + } + + public Substring(Expression s, Expression from) { + this(s, (ExpressionImpl)from, null); + } + + public Substring(Expression s) { + this(s, (Expression)null, (Expression)null); + } + + public Substring(Expression s, Integer from) { + this(s, new Constant(from), null); + } + + public Substring(Expression s, Integer from, Integer len) { this(s, new Constant(from), new Constant(len)); - } - - @Override + } + + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return JPQLExpressionBuilder.convertSubstringArguments(factory, - Expressions.toValue(e, factory, model, q), - from == null ? null : from.toValue(factory, model, q), - len == null ? null : len.toValue(factory, model, q)); + Expressions.toValue(e, factory, model, q), + from == null ? null : from.toValue(factory, model, q), + len == null ? null : len.toValue(factory, model, q)); + } + } + + public static class Locate extends ExpressionImpl { + private ExpressionImpl pattern; + private ExpressionImpl from; + private ExpressionImpl path; + + public Locate(Expression x, Expression y, + Expression from) { + super(Integer.class); + path = (ExpressionImpl)x; + pattern = (ExpressionImpl)y; + this.from = (ExpressionImpl)from; + } + + public Locate(Expression x, Expression y) { + this(x, y, null); + } + + public Locate(Expression x, String y) { + this(x, new Constant(y), null); + } + + public Locate(String x, Expression y) { + this(new Constant(x), y, null); + } + + public Locate(Expression x, String y, + int from) { + this(x, new Constant(y), new Constant(from)); + } + + @Override + public Value toValue(ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + Value locateSearch = path.toValue(factory, model, q); + Value locateFromIndex = (from == null ? + null : Expressions.toValue(from, factory, model, q)); + Value locatePath = Expressions.toValue(pattern, factory, model, q); + + return factory.add(factory.indexOf(locateSearch, + locateFromIndex == null ? locatePath + : factory.newArgumentList(locatePath, + factory.subtract(locateFromIndex, + factory.newLiteral(Numbers.valueOf(1), + Literal.TYPE_NUMBER)))), + factory.newLiteral(Numbers.valueOf(1), + Literal.TYPE_NUMBER)); } } public static class Trim extends BinarayFunctionalExpression { - static Expression defaultTrim = new Constant - (Character.class, new Character(' ')); - static Trimspec defaultSpec = Trimspec.BOTH; - Trimspec ts; - public Trim(Expression x, Expression y, - Trimspec ts) { - super(String.class, x, y); - this.ts = ts; - } - - public Trim(Expression x, Expression y) { - this(x, y, defaultSpec); - } - - public Trim(Expression x) { - this(x, defaultTrim, defaultSpec); - } - - public Trim(Expression x, Character t) { + static Expression defaultTrim = new Constant + (Character.class, new Character(' ')); + static Trimspec defaultSpec = Trimspec.BOTH; + Trimspec ts; + public Trim(Expression x, Expression y, + Trimspec ts) { + super(String.class, x, y); + this.ts = ts; + } + + public Trim(Expression x, Expression y) { + this(x, y, defaultSpec); + } + + public Trim(Expression x) { + this(x, defaultTrim, defaultSpec); + } + + public Trim(Expression x, Character t) { this(x, new Constant(Character.class, t), defaultSpec); - } - - public Trim(Expression x, Character t, Trimspec ts) { - this(x, new Constant(Character.class, t), ts); - } - - public Trim(Expression x, Trimspec ts) { - this(x, defaultTrim, ts); - } + } + + public Trim(Expression x, Character t, Trimspec ts) { + this(x, new Constant(Character.class, t), ts); + } + + public Trim(Expression x, Trimspec ts) { + this(x, defaultTrim, ts); + } - @Override + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { - Boolean spec = null; - if (ts != null) { - switch (ts) { - case LEADING : spec = true; break; - case TRAILING : spec = false; break; - case BOTH : spec = null; break; - } - } + CriteriaQueryImpl q) { + Boolean spec = null; + if (ts != null) { + switch (ts) { + case LEADING : spec = true; break; + case TRAILING : spec = false; break; + case BOTH : spec = null; break; + } + } return factory.trim( - Expressions.toValue(e1, factory, model, q), - Expressions.toValue(e2, factory, model, q), spec); + Expressions.toValue(e1, factory, model, q), + Expressions.toValue(e2, factory, model, q), spec); } } - - public static class Sum extends BinarayFunctionalExpression { - public Sum(Expression x, - Expression y) { - super((Class)x.getJavaType(), x, y); - } - - public Sum(Expression x) { - this(x, (Expression)null); - } - + public Sum(Expression x, + Expression y) { + super((Class)x.getJavaType(), x, y); + } + + public Sum(Expression x) { + this(x, (Expression)null); + } - public Sum(Expression x, Number y) { - this(x, new Constant(Number.class, y)); - } + public Sum(Expression x, Number y) { + this(x, new Constant(Number.class, y)); + } - public Sum(Number x, Expression y) { - this(new Constant(Number.class, x), y); - } - - @Override + public Sum(Number x, Expression y) { + this(new Constant(Number.class, x), y); + } + + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { - return (e2 == null) + CriteriaQueryImpl q) { + return (e2 == null) ? factory.sum(Expressions.toValue(e1, factory, model, q)) - : factory.add( - Expressions.toValue(e1, factory, model, q), - Expressions.toValue(e2, factory, model, q)); + : factory.add( + Expressions.toValue(e1, factory, model, q), + Expressions.toValue(e2, factory, model, q)); } } public static class Product extends BinarayFunctionalExpression { - public Product(Expression x, - Expression y) { - super((Class)x.getJavaType(), x, y); - } + public Product(Expression x, + Expression y) { + super((Class)x.getJavaType(), x, y); + } - public Product(Expression x, Number y) { - this(x, new Constant(Number.class, y)); - } + public Product(Expression x, Number y) { + this(x, new Constant(Number.class, y)); + } - public Product(Number x, Expression y) { - this(new Constant(Number.class, x), y); - } - - @Override + public Product(Number x, Expression y) { + this(new Constant(Number.class, x), y); + } + + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return factory.multiply( - Expressions.toValue(e1, factory, model, q), - Expressions.toValue(e2, factory, model, q)); + Expressions.toValue(e1, factory, model, q), + Expressions.toValue(e2, factory, model, q)); } } public static class Diff extends BinarayFunctionalExpression { - public Diff(Expression x, - Expression y) { - super((Class)x.getJavaType(), x, y); - } + public Diff(Expression x, + Expression y) { + super((Class)x.getJavaType(), x, y); + } - public Diff(Expression x, Number y) { - this(x, new Constant(Number.class, y)); - } + public Diff(Expression x, Number y) { + this(x, new Constant(Number.class, y)); + } - public Diff(Number x, Expression y) { - this(new Constant(Number.class, x), y); - } - - @Override + public Diff(Number x, Expression y) { + this(new Constant(Number.class, x), y); + } + + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return factory.subtract( - Expressions.toValue(e1, factory, model, q), - Expressions.toValue(e2, factory, model, q)); + Expressions.toValue(e1, factory, model, q), + Expressions.toValue(e2, factory, model, q)); } } public static class Quotient extends BinarayFunctionalExpression { - public Quotient(Expression x, - Expression y) { - super((Class)x.getJavaType(), x, y); - } + public Quotient(Expression x, + Expression y) { + super((Class)x.getJavaType(), x, y); + } - public Quotient(Expression x, Number y) { - this(x, new Constant(y)); - } + public Quotient(Expression x, Number y) { + this(x, new Constant(y)); + } - public Quotient(Number x, Expression y) { - this(new Constant(x), y); - } - - @Override + public Quotient(Number x, Expression y) { + this(new Constant(x), y); + } + + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return factory.divide( - Expressions.toValue(e1, factory, model, q), - Expressions.toValue(e2, factory, model, q)); + Expressions.toValue(e1, factory, model, q), + Expressions.toValue(e2, factory, model, q)); } } - - public static class Mod extends BinarayFunctionalExpression { - public Mod(Expression x, Expression y) { - super(Integer.class, x,y); - } - public Mod(Expression x, Integer y) { - this(x,new Constant(Integer.class, y)); - } - public Mod(Integer x, Expression y) { - this(new Constant(Integer.class, x),y); - } + public Mod(Expression x, Expression y) { + super(Integer.class, x,y); + } + public Mod(Expression x, Integer y) { + this(x,new Constant(Integer.class, y)); + } + public Mod(Integer x, Expression y) { + this(new Constant(Integer.class, x),y); + } - @Override + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return factory.mod( - Expressions.toValue(e1, factory, model, q), - Expressions.toValue(e2, factory, model, q)); + Expressions.toValue(e1, factory, model, q), + Expressions.toValue(e2, factory, model, q)); } } public static class CurrentDate extends ExpressionImpl { - public CurrentDate() { - super(java.sql.Date.class); - } + public CurrentDate() { + super(java.sql.Date.class); + } - @Override + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return factory.getCurrentDate(); } } public static class CurrentTime extends ExpressionImpl { - public CurrentTime() { - super(java.sql.Time.class); - } + public CurrentTime() { + super(java.sql.Time.class); + } - @Override + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return factory.getCurrentTime(); } } public static class CurrentTimestamp extends ExpressionImpl { - public CurrentTimestamp() { - super(java.sql.Timestamp.class); - } + public CurrentTimestamp() { + super(java.sql.Timestamp.class); + } - @Override + @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return factory.getCurrentTimestamp(); } } public static class Equal extends BinaryLogicalExpression { - boolean negate; public Equal(Expression x, Expression y) { super(x,y); } @@ -513,23 +564,20 @@ public class Expressions { this(x, new Constant(Object.class, y)); } + @Override + public PredicateImpl clone() { + return new Equal(e1, e2); + } + @Override org.apache.openjpa.kernel.exps.Expression toKernelExpression( - ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) { + ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { boolean isTypeExpr = false; Value val1 = Expressions.toValue(e1, factory, model, q); Value val2 = Expressions.toValue(e2, factory, model, q); -// if (e1 instanceof TypePathImpl) { -// PathImpl path = (PathImpl)e1; -// isTypeExpr = path.isTypeExpr(); -// if (isTypeExpr) { -// ((Constant)e2).setTypeLit(isTypeExpr); -// val2 = Expressions.toValue(e2, factory, model, q); -// Class clzz = (Class)((Literal)val2).getValue(); -// val2.setMetaData(((Types.Managed)model.type(clzz)).meta); -// } -// } - ((CriteriaQueryImpl)q).setImplicitTypes(val1, val2, null); + JPQLExpressionBuilder.setImplicitTypes(val1, val2, null, null, + ((CriteriaQueryImpl)q).getParameterTypes(), null); return isNegated() ? factory.notEqual(val1, val2) : factory.equal(val1, val2); } @@ -546,10 +594,13 @@ public class Expressions { @Override org.apache.openjpa.kernel.exps.Expression toKernelExpression( - ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) { - return factory.greaterThan( - Expressions.toValue(e1, factory, model, q), - Expressions.toValue(e2, factory, model, q)); + ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + Value val1 = Expressions.toValue(e1, factory, model, q); + Value val2 = Expressions.toValue(e2, factory, model, q); + JPQLExpressionBuilder.setImplicitTypes(val1, val2, null, null, + ((CriteriaQueryImpl)q).getParameterTypes(), null); + return factory.greaterThan(val1, val2); } } @@ -564,13 +615,15 @@ public class Expressions { @Override org.apache.openjpa.kernel.exps.Expression toKernelExpression( - ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) { - return factory.greaterThanEqual( - Expressions.toValue(e1, factory, model, q), - Expressions.toValue(e2, factory, model, q)); + ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + Value val1 = Expressions.toValue(e1, factory, model, q); + Value val2 = Expressions.toValue(e2, factory, model, q); + JPQLExpressionBuilder.setImplicitTypes(val1, val2, null, null, + ((CriteriaQueryImpl)q).getParameterTypes(), null); + return factory.greaterThanEqual(val1, val2); } } - public static class LessThan extends BinaryLogicalExpression { public LessThan(Expression x, Expression y) { @@ -583,10 +636,13 @@ public class Expressions { @Override org.apache.openjpa.kernel.exps.Expression toKernelExpression( - ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) { - return factory.lessThan( - Expressions.toValue(e1, factory, model, q), - Expressions.toValue(e2, factory, model, q)); + ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + Value val1 = Expressions.toValue(e1, factory, model, q); + Value val2 = Expressions.toValue(e2, factory, model, q); + JPQLExpressionBuilder.setImplicitTypes(val1, val2, null, null, + ((CriteriaQueryImpl)q).getParameterTypes(), null); + return factory.lessThan(val1, val2); } } @@ -601,11 +657,13 @@ public class Expressions { @Override org.apache.openjpa.kernel.exps.Expression toKernelExpression( - ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) { - return factory.lessThanEqual( - Expressions.toValue(e1, factory, model, q), - Expressions.toValue(e2, factory, model, q)); - + ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + Value val1 = Expressions.toValue(e1, factory, model, q); + Value val2 = Expressions.toValue(e2, factory, model, q); + JPQLExpressionBuilder.setImplicitTypes(val1, val2, null, null, + ((CriteriaQueryImpl)q).getParameterTypes(), null); + return factory.lessThanEqual(val1, val2); } } @@ -629,12 +687,12 @@ public class Expressions { } public Constant(X x) { - this((Class)x.getClass(),x); + this((Class)x.getClass(),x); } @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { int literalType = Literal.TYPE_UNKNOWN; if (arg != null) { Class literalClass = arg.getClass(); @@ -649,12 +707,17 @@ public class Expressions { else if (Class.class.isAssignableFrom(literalClass)) { literalType = Literal.TYPE_CLASS; Literal lit = factory.newTypeLiteral(arg, - Literal.TYPE_CLASS); - lit.setMetaData(model.repos.getMetaData((Class)arg, + Literal.TYPE_CLASS); + ClassMetaData can = + ((Types.Entity)q.getRoot().getModel()).meta; + Class candidate = can.getDescribedType(); + if (candidate.isAssignableFrom((Class)arg)) + lit.setMetaData(model.repos.getMetaData((Class)arg, null, true)); + else + lit.setMetaData(can); return lit; } - } return factory.newLiteral(arg, literalType); } @@ -667,21 +730,27 @@ public class Expressions { @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { return factory.newTypeLiteral(arg, Literal.TYPE_CLASS); } } public static class IsEmpty extends PredicateImpl { - ExpressionImpl collection; - public IsEmpty(Expression collection) { - super(); - this.collection = (ExpressionImpl)collection; - } - + ExpressionImpl collection; + public IsEmpty(Expression collection) { + super(); + this.collection = (ExpressionImpl)collection; + } + + @Override + public PredicateImpl clone() { + return new IsEmpty(collection); + } + @Override public org.apache.openjpa.kernel.exps.Expression toKernelExpression( - ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) { + ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { Value val = Expressions.toValue(collection, factory, model, q); return (isNegated()) ? factory.isNotEmpty(val) : factory.isEmpty(val); @@ -695,7 +764,8 @@ public class Expressions { @Override public org.apache.openjpa.kernel.exps.Value toValue( - ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) { + ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { Value v = Expressions.toValue(e, factory, model, q); ClassMetaData meta = ((PathImpl)e)._member.fmd.getElement() .getTypeMetaData(); @@ -705,33 +775,32 @@ public class Expressions { } public static class IsMember extends PredicateImpl { - ExpressionImpl element; - ExpressionImpl collection; - boolean negate; - - public IsMember(Class t, Expression element, - Expression collection) { - this.element = (ExpressionImpl)element; - this.collection = (ExpressionImpl)collection; - } - - public IsMember(Class t, E element, Expression collection) { - this(t, new Constant(element), collection); - } - - public IsMember(E element, Expression collection) { - this((Class)element.getClass(), element, collection); - } - - public IsMember negate() { - negate = true; - return this; - } - + ExpressionImpl element; + ExpressionImpl collection; + + public IsMember(Class t, Expression element, + Expression collection) { + this.element = (ExpressionImpl)element; + this.collection = (ExpressionImpl)collection; + } + + public IsMember(Class t, E element, Expression collection) { + this(t, new Constant(element), collection); + } + + public IsMember(E element, Expression collection) { + this((Class)element.getClass(), element, collection); + } + + @Override + public PredicateImpl clone() { + return new IsMember(element, collection); + } + @Override public org.apache.openjpa.kernel.exps.Expression toKernelExpression( - ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { return factory.contains( Expressions.toValue(collection, factory, model, q), Expressions.toValue(element, factory, model, q)); @@ -739,162 +808,210 @@ public class Expressions { } public static class Like extends PredicateImpl { - ExpressionImpl str; - ExpressionImpl pattern; - ExpressionImpl escapeChar; - - public Like(Expression x, Expression pattern, - Expression escapeChar) { - super(); - this.str = (ExpressionImpl)x; - this.pattern = (ExpressionImpl)pattern; - this.escapeChar = (ExpressionImpl)escapeChar; - } - - public Like(Expression x, Expression pat, char esc) { - this(x, pat, new Constant(Character.class, esc)); - } - - public Like(Expression x, Expression pattern) { - this(x, pattern, null); - } - - public Like(Expression x, String pattern) { - this(x, new Constant(pattern), null); - } - public Like(Expression x, String pat, - Expression esc) { - this(x, new Constant(pat), esc); - } - public Like(Expression x, String pat, Character esc) { + ExpressionImpl str; + ExpressionImpl pattern; + ExpressionImpl escapeChar; + + public Like(Expression x, Expression pattern, + Expression escapeChar) { + super(); + this.str = (ExpressionImpl)x; + this.pattern = (ExpressionImpl)pattern; + this.escapeChar = (ExpressionImpl)escapeChar; + } + + public Like(Expression x, Expression pat, char esc) { + this(x, pat, new Constant(Character.class, esc)); + } + + public Like(Expression x, Expression pattern) { + this(x, pattern, null); + } + + public Like(Expression x, String pattern) { + this(x, new Constant(pattern), null); + } + + public Like(Expression x, String pat, + Expression esc) { + this(x, new Constant(pat), esc); + } + + public Like(Expression x, String pat, Character esc) { this(x, new Constant(pat), new Constant(esc)); - } + } - @Override + @Override + public PredicateImpl clone() { + return new Like(str, pattern, escapeChar); + } + + @Override public org.apache.openjpa.kernel.exps.Expression toKernelExpression( - ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { - String escapeStr = escapeChar == null ? null : - ((Character)((Literal)Expressions.toValue( - escapeChar, factory, model, q)).getValue()).toString(); - + ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + String escapeStr = escapeChar == null ? null : + ((Character)((Literal)Expressions.toValue( + escapeChar, factory, model, q)).getValue()).toString(); + return factory.matches( - Expressions.toValue(str, factory, model, q), - Expressions.toValue(pattern, factory, model, q), "_", "%", - escapeStr); + Expressions.toValue(str, factory, model, q), + Expressions.toValue(pattern, factory, model, q), "_", "%", + escapeStr); } } public static class Coalesce extends ExpressionImpl - implements QueryBuilder.Coalesce { - private List> values = - new ArrayList>(); - - public Coalesce() { - super(null); - } - - public Coalesce(Class cls) { - super(cls); - } - + implements QueryBuilder.Coalesce { + private List> values = + new ArrayList>(); + + public Coalesce() { + super(null); + } + + public Coalesce(Class cls) { + super(cls); + } + public Coalesce value(T value) { - return value(new Constant(value)); + values.add(new Constant(value)); + return this; } public Coalesce value(Expression value) { - values.add(value); - return this; + values.add(value); + return this; } - - - @Override + + @Override public org.apache.openjpa.kernel.exps.Value toValue( - ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { - Value[] vs = new Value[values.size()]; - int i = 0; - for (Expression e : values) - vs[i++] = Expressions.toValue((ExpressionImpl)e, - factory, model, q); + ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + Value[] vs = new Value[values.size()]; + int i = 0; + for (Expression e : values) + vs[i++] = Expressions.toValue((ExpressionImpl)e, + factory, model, q); return factory.coalesceExpression(vs); } } + public static class Nullif extends ExpressionImpl { + private Expression val1; + private Expression val2; + + public Nullif(Expression x, Expression y) { + super(x.getJavaType()); + val1 = x; + val2 = y; + } + + public Nullif(Expression x, T y) { + super(x.getJavaType()); + val1 = x; + val2 = new Constant(y); + } + + @Override + public org.apache.openjpa.kernel.exps.Value toValue( + ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + Value value1 = Expressions.toValue((ExpressionImpl)val1, + factory, model, q); + Value value2 = Expressions.toValue((ExpressionImpl)val2, + factory, model, q); + return factory.nullIfExpression(value1, value2); + } + } + public static class IsNull extends PredicateImpl { - ExpressionImpl e; - public IsNull(ExpressionImpl e) { - super(); - this.e = e; - } - - @Override + ExpressionImpl e; + public IsNull(ExpressionImpl e) { + super(); + this.e = e; + } + + @Override + public PredicateImpl negate() { + return new Expressions.IsNotNull(e); + } + + @Override org.apache.openjpa.kernel.exps.Expression toKernelExpression( - ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) { - return factory.equal( - Expressions.toValue(e, factory, model, q), - factory.getNull()); - } + ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + return factory.equal( + Expressions.toValue(e, factory, model, q), + factory.getNull()); + } } public static class IsNotNull extends PredicateImpl { - ExpressionImpl e; - public IsNotNull(ExpressionImpl e) { - super(); - this.e = e; - } - - @Override + ExpressionImpl e; + public IsNotNull(ExpressionImpl e) { + super(); + this.e = e; + } + + @Override + public PredicateImpl negate() { + return new Expressions.IsNull(e); + } + + @Override org.apache.openjpa.kernel.exps.Expression toKernelExpression( - ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) { - return factory.notEqual( - Expressions.toValue(e, factory, model, q), - factory.getNull()); - } + ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + return factory.notEqual( + Expressions.toValue(e, factory, model, q), + factory.getNull()); + } } public static class In extends PredicateImpl.Or - implements QueryBuilder.In { - ExpressionImpl e; - boolean negate; - public In(Expression e) { - super((Predicate[])null); - this.e = (ExpressionImpl)e; - } - - public Expression getExpression() { - return null; - } + implements QueryBuilder.In { + ExpressionImpl e; + boolean negate; + public In(Expression e) { + super((Predicate[])null); + this.e = (ExpressionImpl)e; + } + + public Expression getExpression() { + return null; + } - public In value(T value) { - add(new Expressions.Equal(e,value)); - return this; - } + public In value(T value) { + add(new Expressions.Equal(e,value)); + return this; + } - public In value(Expression value) { - add(new Expressions.Equal(e,value)); - return this; - } - - public In negate() { - this.negate = true; - return this; - } + public In value(Expression value) { + add(new Expressions.Equal(e,value)); + return this; + } + + public In negate() { + this.negate = true; + return this; + } - @Override + @Override org.apache.openjpa.kernel.exps.Expression toKernelExpression( - ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) { - org.apache.openjpa.kernel.exps.Expression inExpr = - super.toKernelExpression(factory, model, q); - IsNotNull notNull = new Expressions.IsNotNull(e); - if (negate) - inExpr = factory.not(inExpr); - - return factory.and( - inExpr, - notNull.toKernelExpression(factory, model, q)); - } + ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + org.apache.openjpa.kernel.exps.Expression inExpr = + super.toKernelExpression(factory, model, q); + IsNotNull notNull = new Expressions.IsNotNull(e); + if (negate) + inExpr = factory.not(inExpr); + + return factory.and( + inExpr, + notNull.toKernelExpression(factory, model, q)); + } } public static class Case extends ExpressionImpl @@ -943,7 +1060,7 @@ public class Expressions { @Override public org.apache.openjpa.kernel.exps.Value toValue( ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { int size = whens.size(); org.apache.openjpa.kernel.exps.Expression[] exps = new org.apache.openjpa.kernel.exps.Expression[size]; @@ -967,7 +1084,7 @@ public class Expressions { private List> thens = new ArrayList>(); - private List whens = new ArrayList(); + private List> whens = new ArrayList>(); private Expression otherwise; @@ -991,13 +1108,13 @@ public class Expressions { } public SimpleCase when(C when, Expression then) { - whens.add(when); + whens.add(new Constant(when)); thens.add(then); return this; } public SimpleCase when(C when, R then) { - whens.add(when); + whens.add(new Constant(when)); Expression thenExpr = new Expressions.Constant(then); thens.add(thenExpr); @@ -1017,19 +1134,18 @@ public class Expressions { @Override public org.apache.openjpa.kernel.exps.Value toValue( ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { Value caseOperandExpr = Expressions.toValue( (ExpressionImpl)caseOperand, factory, model, q); int size = whens.size(); org.apache.openjpa.kernel.exps.Expression[] exps = new org.apache.openjpa.kernel.exps.Expression[size]; for (int i = 0; i < size; i++) { - org.apache.openjpa.kernel.exps.Literal val = null; - //TODO: Boolean literal, String literal - val = factory.newLiteral(whens.get(i), Literal.TYPE_NUMBER); + Value when = Expressions.toValue( + (ExpressionImpl)whens.get(i), factory, model, q); Value action = Expressions.toValue( - (ExpressionImpl)thens.get(i), factory, model, q); - exps[i] = factory.whenScalar(val, action); + (ExpressionImpl)thens.get(i), factory, model, q); + exps[i] = factory.whenScalar(when, action); } Value other = Expressions.toValue( @@ -1037,4 +1153,113 @@ public class Expressions { return factory.simpleCaseExpression(caseOperandExpr, exps, other); } } + + public static class Lower extends UnaryFunctionalExpression { + public Lower(Expression x) { + super(String.class, x); + } + + @Override + public Value toValue(ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + return factory.toLowerCase( + Expressions.toValue(e, factory, model, q)); + } + } + + public static class Upper extends UnaryFunctionalExpression { + public Upper(Expression x) { + super(String.class, x); + } + + @Override + public Value toValue(ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + return factory.toUpperCase( + Expressions.toValue(e, factory, model, q)); + } + } + + public static class Length extends UnaryFunctionalExpression { + public Length(Expression x) { + super(Integer.class, x); + } + + @Override + public Value toValue(ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + return factory.stringLength( + Expressions.toValue(e, factory, model, q)); + } + } + + public static class Exists extends PredicateImpl { + SubqueryImpl e; + public Exists(Subquery x) { + super(); + e = (SubqueryImpl)x; + } + + @Override + public PredicateImpl clone() { + return new Exists(e); + } + + @Override + org.apache.openjpa.kernel.exps.Expression toKernelExpression( + ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + org.apache.openjpa.kernel.exps.Expression notEmpty = + factory.isNotEmpty(Expressions.toValue(e, factory, model, q)); + if (isNegated()) + return factory.not(notEmpty); + else + return notEmpty; + + } + } + + public static class All extends ExpressionImpl { + SubqueryImpl e; + public All(Subquery x) { + super(x.getJavaType()); + e = (SubqueryImpl)x; + } + + @Override + public Value toValue(ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + return factory.all(Expressions.toValue(e, factory, model, q)); + } + } + + public static class Any extends ExpressionImpl { + SubqueryImpl e; + public Any(Subquery x) { + super(x.getJavaType()); + e = (SubqueryImpl)x; + } + + @Override + public Value toValue(ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + return factory.any(Expressions.toValue(e, factory, model, q)); + } + } + + public static class Some extends ExpressionImpl { + SubqueryImpl e; + public Some(Subquery x) { + super(x.getJavaType()); + e = (SubqueryImpl)x; + } + + @Override + public Value toValue(ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + //return factory.some(Expressions.toValue(e, factory, model, q)); + return null; + } + } + } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Joins.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Joins.java index 409d6a46a..7d1d4e3fd 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Joins.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/Joins.java @@ -20,7 +20,6 @@ package org.apache.openjpa.persistence.criteria; import javax.persistence.criteria.AbstractCollectionJoin; import javax.persistence.criteria.CollectionJoin; -import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; import javax.persistence.criteria.Join; import javax.persistence.criteria.JoinType; @@ -74,7 +73,7 @@ public abstract class Joins { @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery c) { + CriteriaQueryImpl c) { boolean allowNull = joinType != JoinType.INNER; org.apache.openjpa.kernel.exps.Path path = (org.apache.openjpa.kernel.exps.Path) @@ -88,7 +87,8 @@ public abstract class Joins { @Override public org.apache.openjpa.kernel.exps.Expression toKernelExpression( - ExpressionFactory factory, MetamodelImpl model, CriteriaQuery c) { + ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl c) { org.apache.openjpa.kernel.exps.Value path = this.toValue (factory, model, c); ClassMetaData meta = _member.fmd.getDeclaredTypeMetaData(); @@ -150,7 +150,7 @@ public abstract class Joins { */ @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery c) { + CriteriaQueryImpl c) { boolean allowNull = joinType != JoinType.INNER; org.apache.openjpa.kernel.exps.Path path = (org.apache.openjpa.kernel.exps.Path) @@ -169,7 +169,8 @@ public abstract class Joins { */ @Override public org.apache.openjpa.kernel.exps.Expression toKernelExpression( - ExpressionFactory factory, MetamodelImpl model, CriteriaQuery c) { + ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl c) { org.apache.openjpa.kernel.exps.Value path = toValue (factory, model, c); diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterImpl.java index 88bd557b2..6b456704a 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/ParameterImpl.java @@ -19,8 +19,9 @@ package org.apache.openjpa.persistence.criteria; import java.util.Collection; + import javax.persistence.Parameter; -import javax.persistence.criteria.CriteriaQuery; + import org.apache.commons.collections.map.LinkedMap; import org.apache.openjpa.kernel.exps.ExpressionFactory; import org.apache.openjpa.kernel.exps.Value; @@ -57,7 +58,7 @@ public class ParameterImpl extends ExpressionImpl implements Parameter{ @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { boolean positional = false; LinkedMap parameterTypes = ((CriteriaQueryImpl)q).getParameterTypes(); if (parameterTypes == null) { 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 eb325f1a4..a6848e5ce 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 @@ -19,15 +19,16 @@ package org.apache.openjpa.persistence.criteria; -import javax.persistence.criteria.CriteriaQuery; +import java.util.Set; + import javax.persistence.criteria.Expression; import javax.persistence.criteria.Path; +import javax.persistence.criteria.Root; import javax.persistence.metamodel.AbstractCollection; import javax.persistence.metamodel.Attribute; import javax.persistence.metamodel.Bindable; import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.Map; -import javax.persistence.metamodel.Member; import javax.persistence.metamodel.Type; import org.apache.openjpa.kernel.exps.ExpressionFactory; @@ -78,14 +79,34 @@ public class PathImpl extends ExpressionImpl implements Path { return _parent; } + public PathImpl getInnermostParentPath() { + if (_parent == null) + return this; + PathImpl _p = _parent.getInnermostParentPath(); + if (_p == null) + return _parent; + else + return _p.getInnermostParentPath(); + } + /** * Convert this path to a kernel path value. */ @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { + CriteriaQueryImpl q) { Value var = null; - if (_parent != null) { + SubqueryImpl subquery = q.getContext(); + PathImpl parent = getInnermostParentPath(); + if (subquery != null && inSubquery(parent, subquery)) { + org.apache.openjpa.kernel.exps.Subquery subQ = + subquery.getSubQ(); + org.apache.openjpa.kernel.exps.Path path = factory.newPath(subQ); + path.setMetaData(subQ.getMetaData()); + boolean allowNull = false; + path.get(_member.fmd, allowNull); + var = path; + } else if (_parent != null) { org.apache.openjpa.kernel.exps.Path path = (org.apache.openjpa.kernel.exps.Path) _parent.toValue(factory, model, q); @@ -104,6 +125,16 @@ public class PathImpl extends ExpressionImpl implements Path { var.setAlias(getAlias()); return var; } + + public static boolean inSubquery(PathImpl parent, SubqueryImpl subquery) { + Set> roots = subquery.getRoots(); + for (Root r : roots) { + if (parent == r) + return true; + } + return false; + } + public Path get(Attribute attr) { return new PathImpl(this, (Members.Attribute)attr, diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PredicateImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PredicateImpl.java index b252d90c5..2b1438f48 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PredicateImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/PredicateImpl.java @@ -21,7 +21,6 @@ package org.apache.openjpa.persistence.criteria; import java.util.ArrayList; import java.util.List; -import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; import javax.persistence.criteria.Predicate; @@ -29,27 +28,27 @@ import org.apache.openjpa.kernel.exps.ExpressionFactory; import org.apache.openjpa.persistence.meta.MetamodelImpl; public class PredicateImpl extends ExpressionImpl - implements Predicate { +implements Predicate { List> _exps; BooleanOperator _op; boolean _negated = false; - + protected PredicateImpl() { - super(Boolean.class); + super(Boolean.class); } - + protected PredicateImpl(BooleanOperator op) { this(); _op = op; } - + protected PredicateImpl(BooleanOperator op, Predicate...restrictions) { - this(op); - if (restrictions != null) { - for (Predicate p : restrictions) - add((PredicateImpl)p); - } - } + this(op); + if (restrictions != null) { + for (Predicate p : restrictions) + add((PredicateImpl)p); + } + } public PredicateImpl add(Expression s) { if (_exps == null) @@ -71,60 +70,64 @@ public class PredicateImpl extends ExpressionImpl } public PredicateImpl negate() { - PredicateImpl not = new PredicateImpl(_op); + PredicateImpl not = clone(); not._negated = true; - if (_exps != null) - not._exps = new ArrayList>(this._exps); - not._op = this._op; return not; } - + + public PredicateImpl clone() { + PredicateImpl clone = new PredicateImpl(_op); + if (_exps != null) + clone._exps = new ArrayList>(this._exps); + return clone; + } + @Override org.apache.openjpa.kernel.exps.Expression toKernelExpression( - ExpressionFactory factory, MetamodelImpl model, CriteriaQuery q) { - if (_exps == null || _exps.isEmpty()) - return factory.emptyExpression(); - if (_exps.size() == 1) - return ((ExpressionImpl)_exps.get(0)) - .toKernelExpression(factory, model, q); - ExpressionImpl e1 = (ExpressionImpl)_exps.get(0); - ExpressionImpl e2 = (ExpressionImpl)_exps.get(1); - org.apache.openjpa.kernel.exps.Expression ke1 = - e1.toKernelExpression(factory, model, q); - org.apache.openjpa.kernel.exps.Expression ke2 = - e2.toKernelExpression(factory, model, q); - org.apache.openjpa.kernel.exps.Expression result = - _op == BooleanOperator.AND - ? factory.and(ke1,ke2) : factory.or(ke1, ke2); + ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl q) { + if (_exps == null || _exps.isEmpty()) + return factory.emptyExpression(); + if (_exps.size() == 1) + return ((ExpressionImpl)_exps.get(0)) + .toKernelExpression(factory, model, q); + ExpressionImpl e1 = (ExpressionImpl)_exps.get(0); + ExpressionImpl e2 = (ExpressionImpl)_exps.get(1); + org.apache.openjpa.kernel.exps.Expression ke1 = + e1.toKernelExpression(factory, model, q); + org.apache.openjpa.kernel.exps.Expression ke2 = + e2.toKernelExpression(factory, model, q); + org.apache.openjpa.kernel.exps.Expression result = + _op == BooleanOperator.AND + ? factory.and(ke1,ke2) : factory.or(ke1, ke2); - for (int i = 2; i < _exps.size(); i++) { - ExpressionImpl e = (ExpressionImpl)_exps.get(i); - result = _op == BooleanOperator.AND + for (int i = 2; i < _exps.size(); i++) { + ExpressionImpl e = (ExpressionImpl)_exps.get(i); + result = _op == BooleanOperator.AND ? factory.and(result, e.toKernelExpression(factory, model, q)) - : factory.or(result, e.toKernelExpression(factory,model,q)); - } - return _negated ? factory.not(result) : result; + : factory.or(result, e.toKernelExpression(factory,model,q)); + } + return _negated ? factory.not(result) : result; } - + public static class And extends PredicateImpl { - public And(Expression x, Expression y) { - super(BooleanOperator.AND); - add(x).add(y); - } - - public And(Predicate...restrictions) { - super(BooleanOperator.AND, restrictions); - } - } - + public And(Expression x, Expression y) { + super(BooleanOperator.AND); + add(x).add(y); + } + + public And(Predicate...restrictions) { + super(BooleanOperator.AND, restrictions); + } + } + public static class Or extends PredicateImpl { - public Or(Expression x, Expression y) { - super(BooleanOperator.OR); - add(x).add(y); - } - - public Or(Predicate...restrictions) { - super(BooleanOperator.OR, restrictions); - } + public Or(Expression x, Expression y) { + super(BooleanOperator.OR); + add(x).add(y); + } + + public Or(Predicate...restrictions) { + super(BooleanOperator.OR, restrictions); + } } } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/RootImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/RootImpl.java index eab24a8d3..e7724c619 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/RootImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/RootImpl.java @@ -19,13 +19,11 @@ package org.apache.openjpa.persistence.criteria; -import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Root; import javax.persistence.metamodel.Entity; import org.apache.openjpa.kernel.exps.ExpressionFactory; import org.apache.openjpa.kernel.exps.Value; -import org.apache.openjpa.persistence.criteria.FromImpl; import org.apache.openjpa.persistence.meta.MetamodelImpl; import org.apache.openjpa.persistence.meta.Types; @@ -37,8 +35,9 @@ import org.apache.openjpa.persistence.meta.Types; * @param */ public class RootImpl extends FromImpl implements Root { - private final Types.Entity _entity; - + private final Types.Entity _entity; + private RootImpl _correlatedParent; + public RootImpl(Types.Entity type) { super(type); _entity = type; @@ -48,13 +47,28 @@ public class RootImpl extends FromImpl implements Root { return _entity; } + public void setCorrelatedParent(RootImpl correlatedParent) { + _correlatedParent = correlatedParent; + } + + public RootImpl getCorrelatedParent() { + return _correlatedParent; + } + /** * Convert this path to a kernel path value. */ @Override public Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery c) { - Value var = factory.newPath(); + CriteriaQueryImpl c) { + SubqueryImpl subquery = c.getContext(); + Value var = null; + if (subquery != null && PathImpl.inSubquery(this, subquery)) { + org.apache.openjpa.kernel.exps.Subquery subQ = + subquery.getSubQ(); + var = factory.newPath(subQ); + } else + var = factory.newPath(); var.setMetaData(_entity.meta); return var; } @@ -65,7 +79,7 @@ public class RootImpl extends FromImpl implements Root { */ @Override public org.apache.openjpa.kernel.exps.Expression toKernelExpression( - ExpressionFactory factory, MetamodelImpl model, CriteriaQuery c) { + ExpressionFactory factory, MetamodelImpl model, CriteriaQueryImpl c) { org.apache.openjpa.kernel.exps.Value path = toValue(factory, model, c); Value var = factory.newBoundVariable(getAlias(), @@ -73,6 +87,14 @@ public class RootImpl extends FromImpl implements Root { org.apache.openjpa.kernel.exps.Expression exp = factory.bindVariable(var, path); - return exp; + if (_correlatedParent == null) + return exp; + org.apache.openjpa.kernel.exps.Value path1 = + _correlatedParent.toValue(factory, model, c); + org.apache.openjpa.kernel.exps.Expression equal = + factory.equal(path1, path); + //return factory.and(exp, equal); + return equal; + } } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SelectionImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SelectionImpl.java index 29c7914e3..e379313f7 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SelectionImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SelectionImpl.java @@ -21,13 +21,9 @@ package org.apache.openjpa.persistence.criteria; import java.util.Arrays; import java.util.List; -import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Selection; -import org.apache.openjpa.kernel.exps.ExpressionFactory; -import org.apache.openjpa.kernel.exps.Value; import org.apache.openjpa.persistence.ResultItemImpl; -import org.apache.openjpa.persistence.meta.MetamodelImpl; /** * An item selected in the projection clause of Criteria query. @@ -53,17 +49,4 @@ public class SelectionImpl extends ResultItemImpl public List> getSelections() { return _sels; } - - Value toValue(ExpressionFactory factory, MetamodelImpl model, - CriteriaQuery q) { - ((CriteriaQueryImpl)q).setResultClass(getJavaType()); - Value[] result = new Value[_sels.size()]; - int i = 0; - for (Selection s : _sels) { - result[i++] = ((ExpressionImpl)s).toValue(factory, model, - q); - } - ((CriteriaQueryImpl)q).setProjections(result); - return null; - } } diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java new file mode 100644 index 000000000..be7dba2bc --- /dev/null +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/criteria/SubqueryImpl.java @@ -0,0 +1,180 @@ +package org.apache.openjpa.persistence.criteria; + +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +import javax.persistence.criteria.AbstractQuery; +import javax.persistence.criteria.CollectionJoin; +import javax.persistence.criteria.Expression; +import javax.persistence.criteria.Join; +import javax.persistence.criteria.ListJoin; +import javax.persistence.criteria.MapJoin; +import javax.persistence.criteria.Predicate; +import javax.persistence.criteria.Root; +import javax.persistence.criteria.SetJoin; +import javax.persistence.criteria.Subquery; +import javax.persistence.metamodel.Entity; + +import org.apache.openjpa.kernel.exps.ExpressionFactory; +import org.apache.openjpa.kernel.exps.Value; +import org.apache.openjpa.meta.ClassMetaData; +import org.apache.openjpa.persistence.meta.MetamodelImpl; +import org.apache.openjpa.persistence.meta.Types; +import org.apache.openjpa.kernel.exps.QueryExpressions; +import org.apache.openjpa.kernel.jpql.JPQLExpressionBuilder; + + +public class SubqueryImpl extends ExpressionImpl implements Subquery { + private final CriteriaQueryImpl _parent; + private final CriteriaQueryImpl _delegate; + private java.util.Set> _joins; + private Expression _select; + private org.apache.openjpa.kernel.exps.Subquery _subq; + + public SubqueryImpl(Class cls, CriteriaQueryImpl parent) { + super(cls); + _parent = parent; + _delegate = new CriteriaQueryImpl(parent.getMetamodel()); + _delegate.setContext(this); + } + + public AbstractQuery getParent() { + return _parent; + } + + public Subquery select(Expression expression) { + _select = expression; + _delegate.select(expression); + return this; + } + + public Expression getSelection() { + return _select; + } + + public Root from(Entity entity) { + return _delegate.from(entity); + } + + public Root from(Class entityClass) { + return _delegate.from(entityClass); + } + + public Set> getRoots() { + return _delegate.getRoots(); + } + + public Root getRoot() { + return _delegate.getRoot(); + } + + public Subquery where(Expression restriction) { + _delegate.where(restriction); + return this; + } + + public Subquery where(Predicate... restrictions) { + _delegate.where(restrictions); + return this; + } + + public Subquery groupBy(Expression... grouping) { + _delegate.groupBy(grouping); + return this; + } + + public Subquery having(Expression restriction) { + _delegate.having(restriction); + return this; + } + + public Subquery having(Predicate... restrictions) { + _delegate.having(restrictions); + return this; + } + + public Subquery distinct(boolean distinct) { + _delegate.distinct(distinct); + return this; + } + + public List> getGroupList() { + return _delegate.getGroupList(); + } + + public Predicate getRestriction() { + return _delegate.getRestriction(); + } + + public Predicate getGroupRestriction() { + return _delegate.getGroupRestriction(); + } + + public boolean isDistinct() { + return _delegate.isDistinct(); + } + + public Subquery subquery(Class type) { + return new SubqueryImpl(type, _delegate); + } + + public Root correlate(Root root) { + Types.Entity entity = + (Types.Entity)((RootImpl)root).getModel(); + RootImpl corrRoot = new RootImpl(entity); + corrRoot.setCorrelatedParent((RootImpl)root); + Set> roots = getRoots(); + if (roots == null) { + roots = new LinkedHashSet>(); + _delegate.setRoots(roots); + } + roots.add(corrRoot); + return corrRoot; + } + + public Join correlate(Join join) { + return join; + } + public CollectionJoin correlate(CollectionJoin join) { + return join; + } + public SetJoin correlate(SetJoin join) { + return join; + } + public ListJoin correlate(ListJoin join) { + return join; + } + public MapJoin correlate(MapJoin join) { + return join; + } + + public java.util.Set> getJoins() { + return _joins; + } + + public org.apache.openjpa.kernel.exps.Subquery getSubQ() { + return _subq; + } + + /** + * Convert this path to a kernel path value. + */ + @Override + public Value toValue(ExpressionFactory factory, MetamodelImpl model, + CriteriaQueryImpl q) { + final boolean subclasses = true; + CriteriaExpressionBuilder queryEval = q.getExprBuilder(); + String alias = queryEval.nextAlias(); + ClassMetaData candidate = + ((Types.Managed)getRoot().getModel()).meta; + _subq = factory.newSubquery(candidate, subclasses, alias); + _subq.setMetaData(candidate); + QueryExpressions subexp = q.getExprBuilder(). + getQueryExpressions(factory, _delegate); + _subq.setQueryExpressions(subexp); + if (subexp.projections.length > 0) + JPQLExpressionBuilder.checkEmbeddable(subexp.projections[0], null); + return _subq; + } +}