Author: faywang
Date: Fri Jul  3 23:58:09 2009
New Revision: 791040

URL: http://svn.apache.org/viewvc?rev=791040&view=rev
Log:
fix nested subquery correlation problem and AND precedence problem when calling 
from OR

Added:
    
openjpa/branches/subquery/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Request.java
Modified:
    
openjpa/branches/subquery/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AndExpression.java
    
openjpa/branches/subquery/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
    
openjpa/branches/subquery/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Account.java
    
openjpa/branches/subquery/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestJPQLSubquery.java

Modified: 
openjpa/branches/subquery/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AndExpression.java
URL: 
http://svn.apache.org/viewvc/openjpa/branches/subquery/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AndExpression.java?rev=791040&r1=791039&r2=791040&view=diff
==============================================================================
--- 
openjpa/branches/subquery/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AndExpression.java
 (original)
+++ 
openjpa/branches/subquery/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AndExpression.java
 Fri Jul  3 23:58:09 2009
@@ -54,6 +54,7 @@
         BinaryOpExpState bstate = (BinaryOpExpState) state;
         boolean paren1 = _exp1 instanceof OrExpression;
         boolean paren2 = _exp2 instanceof OrExpression;
+        buf.append("(");
         if (paren1)
             buf.append("(");
         _exp1.appendTo(sel, ctx, bstate.state1, buf);
@@ -65,6 +66,7 @@
         _exp2.appendTo(sel, ctx, bstate.state2, buf);
         if (paren2)
             buf.append(")");
+        buf.append(")");
         sel.append(buf, state.joins);
     }
 

Modified: 
openjpa/branches/subquery/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
URL: 
http://svn.apache.org/viewvc/openjpa/branches/subquery/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java?rev=791040&r1=791039&r2=791040&view=diff
==============================================================================
--- 
openjpa/branches/subquery/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
 (original)
+++ 
openjpa/branches/subquery/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
 Fri Jul  3 23:58:09 2009
@@ -615,8 +615,27 @@
             pstate.joins.moveJoinsToParent();
         }
         pstate.joins.setJoinContext(null);
+        
+        if (_actions == null) {
+            String subqAlias = findSubqAlias(sel);
+            pstate.joins = pstate.joins.setSubselect(subqAlias);
+            pstate.joins.setCorrelatedVariable(_schemaAlias);
+        }
+        
         return pstate;
     }
+    
+    public String findSubqAlias(Select sel) {
+        Select pSel = sel.getParent();
+        if (pSel == null)
+            return null;
+        Context pCtx = pSel.ctx();
+        if (pCtx.subquery == null)
+            return null;
+        if (pCtx.getSchema(_schemaAlias) != null)
+            return ((SubQ)pCtx.subquery).getCandidateAlias();
+        return findSubqAlias(pSel);
+    }
 
     /**
      * When a PCPath is in subselect, and it is simply a navigation

Modified: 
openjpa/branches/subquery/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Account.java
URL: 
http://svn.apache.org/viewvc/openjpa/branches/subquery/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Account.java?rev=791040&r1=791039&r2=791040&view=diff
==============================================================================
--- 
openjpa/branches/subquery/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Account.java
 (original)
+++ 
openjpa/branches/subquery/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Account.java
 Fri Jul  3 23:58:09 2009
@@ -19,8 +19,10 @@
 package org.apache.openjpa.persistence.criteria;
 
 import javax.persistence.Entity;
+import javax.persistence.FetchType;
 import javax.persistence.GeneratedValue;
 import javax.persistence.Id;
+import javax.persistence.ManyToOne;
 import javax.persistence.OneToOne;
 import javax.persistence.Table;
 
@@ -40,6 +42,12 @@
     @OneToOne
     private Person owner;
     
+    @ManyToOne
+    private Customer customer;
+    
+    @ManyToOne(optional = false, fetch = FetchType.LAZY)
+    private Product product;
+    
     private String name;
 
     public long getId() {
@@ -77,4 +85,20 @@
     public void setLoan(Integer loan) {
         this.loan = loan;
     }
+    
+    public Product getProduct() {
+        return product;
+    }
+    
+    public void setProduct(Product product) {
+        this.product = product;
+    }
+
+    public Customer getCustomer() {
+        return customer;
+    }
+    
+    public void setCustomer(Customer customer) {
+        this.customer = customer;
+    }
 }

Added: 
openjpa/branches/subquery/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Request.java
URL: 
http://svn.apache.org/viewvc/openjpa/branches/subquery/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Request.java?rev=791040&view=auto
==============================================================================
--- 
openjpa/branches/subquery/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Request.java
 (added)
+++ 
openjpa/branches/subquery/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/Request.java
 Fri Jul  3 23:58:09 2009
@@ -0,0 +1,52 @@
+package org.apache.openjpa.persistence.criteria;
+
+import java.sql.Date;
+
+import javax.persistence.*;
+
+...@entity
+public class Request {
+     @Id
+     int id;
+     
+     private short status;
+    
+     @ManyToOne(optional = false, fetch = FetchType.LAZY)
+     private Account account;
+
+     Date requestTime;
+
+     public int getId() {
+         return id;
+     }
+     
+     public void setId(int id) {
+         this.id = id;
+     }
+     
+     public short getStatus() {
+         return status;
+     }
+
+     public void setStatus(short status) {
+         this.status = status;
+     }
+
+     
+     public Account getAccount() {
+         return account;
+     }
+
+     public void setAccount(Account account) {
+         this.account = account;
+     }
+    
+     public Date getRequestTime() {
+         return requestTime;
+     }
+     
+     public void setRequestTime(Date requestTime) {
+         this.requestTime = requestTime;
+     }
+     
+}

Modified: 
openjpa/branches/subquery/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestJPQLSubquery.java
URL: 
http://svn.apache.org/viewvc/openjpa/branches/subquery/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestJPQLSubquery.java?rev=791040&r1=791039&r2=791040&view=diff
==============================================================================
--- 
openjpa/branches/subquery/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestJPQLSubquery.java
 (original)
+++ 
openjpa/branches/subquery/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/criteria/TestJPQLSubquery.java
 Fri Jul  3 23:58:09 2009
@@ -170,6 +170,20 @@
         execute(jpql, expectedSQL);
     }
 
+    public void testSubqueries4e() {
+        String jpql = "SELECT c FROM Customer c WHERE EXISTS "
+            + "(SELECT o.id FROM Order o WHERE o.customer = c)";
+        String expectedSQL = "SELECT t1.id, t1.accountNum, t2.id, t2.city, 
t2.country, t2.county, t2.state, " + 
+        "t2.street, t3.userid, t3.DTYPE, t3.age, t3.compName, t3.creditRating, 
t3.name, t2.zipCode, t1.balanceOwed, " + 
+        "t1.creditRating, t1.filledOrderCount, t1.firstName, t1.lastName, 
t1.name, t1.status " + 
+        "FROM CR_CUST t1 " + 
+        "LEFT OUTER JOIN CR_ADDR t2 ON t1.ADDRESS_ID = t2.id " + 
+        "LEFT OUTER JOIN CompUser t3 ON t2.id = t3.ADD_ID WHERE " + 
+        "(EXISTS (SELECT t0.id FROM CR_ODR t0 WHERE (t0.CUSTOMER_ID = t1.id) 
))";
+
+        execute(jpql, expectedSQL);
+    }
+
     public void testSubqueries5() {
         String jpql = "SELECT o FROM Order o WHERE 10000 < ALL ("
             + "SELECT a.balance FROM o.customer c JOIN c.accounts a)";
@@ -283,10 +297,11 @@
             + "LEFT OUTER JOIN CR_CUST t5 ON t2.CUSTOMER_ID = t5.id "
             + "INNER JOIN CR_ADDR t4 ON t3.ADDRESS_ID = t4.id "
             + "LEFT OUTER JOIN CR_ADDR t6 ON t5.ADDRESS_ID = t6.id "
-            + "LEFT OUTER JOIN CompUser t7 ON t6.id = t7.ADD_ID WHERE (? < ALL 
("
-            + "SELECT t1.age FROM CR_ADDR t0 INNER JOIN CompUser t1 ON t0.id = 
t1.ADD_ID WHERE (t4.city = t0.city AND "
-            + "t3.ADDRESS_ID = t0.id) ) AND 1 = 1)";
-
+            + "LEFT OUTER JOIN CompUser t7 ON t6.id = t7.ADD_ID " 
+            + "WHERE ((? < ALL (" 
+            + "SELECT t1.age FROM CR_ADDR t0 INNER JOIN CompUser t1 ON t0.id = 
t1.ADD_ID WHERE ((t4.city = t0.city AND "
+            + "t3.ADDRESS_ID = t0.id)) ) AND 1 = 1))"; 
+        
         execute(jpql, expectedSQL);
     }
 
@@ -303,8 +318,8 @@
             + "INNER JOIN CR_ADDR t2 ON t1.ADDRESS_ID = t2.id "
             + "LEFT OUTER JOIN CR_ADDR t6 ON t5.ADDRESS_ID = t6.id "
             + "LEFT OUTER JOIN CompUser t7 ON t6.id = t7.ADD_ID "
-            + "WHERE (? < ALL (SELECT t4.age FROM  CompUser t3, CompUser t4 "
-            + "WHERE (t3.userid = t4.userid) AND (t2.id = t3.ADD_ID) ) AND 1 = 
1)";
+            + "WHERE ((? < ALL (SELECT t4.age FROM  CompUser t3, CompUser t4 "
+            + "WHERE (t3.userid = t4.userid) AND (t2.id = t3.ADD_ID) ) AND 1 = 
1))"; 
 
         execute(jpql, expectedSQL);
     }
@@ -384,9 +399,10 @@
             + "LEFT OUTER JOIN CR_ODR t1 ON t0.id = t1.CUSTOMER_ID "
             + "LEFT OUTER JOIN CR_ODR t2 ON t0.id = t2.CUSTOMER_ID "
             + "LEFT OUTER JOIN CR_ADDR t5 ON t0.ADDRESS_ID = t5.id "
-            + "LEFT OUTER JOIN CompUser t6 ON t5.id = t6.ADD_ID WHERE (EXISTS 
("
-            + "SELECT t4.id FROM  CR_ODR t3, CR_ODR t4 WHERE (t2.id = t4.id 
AND t3.id = t4.id) "
-            + "AND (t0.id = t3.CUSTOMER_ID) ))";
+            + "LEFT OUTER JOIN CompUser t6 ON t5.id = t6.ADD_ID "
+            + "WHERE (EXISTS (" + 
+            "SELECT t4.id FROM  CR_ODR t3, CR_ODR t4 WHERE ((t2.id = t4.id AND 
t3.id = t4.id)) "
+            + "AND (t0.id = t3.CUSTOMER_ID) ))"; 
 
         execute(jpql, expectedSQL);
     }
@@ -413,9 +429,10 @@
             + "LEFT OUTER JOIN CR_ODR t1 ON t0.id = t1.CUSTOMER_ID "
             + "LEFT OUTER JOIN CR_ODR t2 ON t0.id = t2.CUSTOMER_ID "
             + "LEFT OUTER JOIN CR_ADDR t5 ON t0.ADDRESS_ID = t5.id "
-            + "LEFT OUTER JOIN CompUser t6 ON t5.id = t6.ADD_ID WHERE (NOT 
(EXISTS ("
-            + "SELECT t4.id FROM  CR_ODR t3, CR_ODR t4 WHERE (t2.id = t4.id 
AND t3.id = t4.id) "
-            + "AND (t0.id = t3.CUSTOMER_ID) )))";
+            + "LEFT OUTER JOIN CompUser t6 ON t5.id = t6.ADD_ID "
+            + "WHERE (NOT (EXISTS ("
+            + "SELECT t4.id FROM  CR_ODR t3, CR_ODR t4 WHERE ((t2.id = t4.id 
AND t3.id = t4.id)) " 
+            + "AND (t0.id = t3.CUSTOMER_ID) )))"; 
 
         execute(jpql, expectedSQL);
     }
@@ -442,10 +459,11 @@
             + " (select distinct o.id from LineItem i, Order o"
             + " where i.quantity > 10 and o.count > 1000 and i.id = o.id)";
 
-        String expectedSQL = "SELECT t0.id FROM CR_ODR t0 WHERE (t0.id IN ("
+        String expectedSQL = "SELECT t0.id FROM CR_ODR t0 "
+            + "WHERE (t0.id IN ("
             + "SELECT DISTINCT t2.id "
-            + "FROM CR_ODR t1 JOIN CR_ODR t2 ON (1 = 1), CR_LI t3 WHERE (" 
-            + "t3.quantity > ? AND t2.count > ? AND t3.id = t2.id) ))";
+            + "FROM CR_ODR t1 JOIN CR_ODR t2 ON (1 = 1), CR_LI t3 WHERE ("
+            + "(t3.quantity > ? AND (t2.count > ? AND t3.id = t2.id))) ))"; 
 
         execute(jpql, expectedSQL);
     }
@@ -528,10 +546,10 @@
             + "or exists (select o from c.orders o where o.id = 2)";
 
         String expectedSQL = "SELECT t0.name FROM CR_CUST t0 WHERE (EXISTS ("
-            + "SELECT t2.id FROM  CR_ODR t1, CR_ODR t2 "
-            + "WHERE (t2.id = ? AND t1.id = t2.id) AND (t0.id = 
t1.CUSTOMER_ID) ) OR EXISTS ("
+            + "SELECT t2.id FROM  CR_ODR t1, CR_ODR t2 " 
+            + "WHERE ((t2.id = ? AND t1.id = t2.id)) AND (t0.id = 
t1.CUSTOMER_ID) ) OR EXISTS ("
             + "SELECT t4.id FROM  CR_ODR t3, CR_ODR t4 "
-            + "WHERE (t4.id = ? AND t3.id = t4.id) AND (t0.id = 
t3.CUSTOMER_ID) ))";
+            + "WHERE ((t4.id = ? AND t3.id = t4.id)) AND (t0.id = 
t3.CUSTOMER_ID) ))"; 
         execute(jpql, expectedSQL);
     }
 
@@ -543,8 +561,8 @@
 
         String expectedSQL = "SELECT t0.name "
             + "FROM CR_CUST t0 INNER JOIN CR_ODR t1 ON t0.id = t1.CUSTOMER_ID 
WHERE ("
-            + "t1.quantity >= (SELECT MAX(t2.quantity) FROM CR_ODR t2 ) AND "
-            + "t1.quantity <= (SELECT AVG(t3.quantity) FROM CR_ODR t3 ))";
+            + "(t1.quantity >= (SELECT MAX(t2.quantity) FROM CR_ODR t2 ) AND "
+            + "t1.quantity <= (SELECT AVG(t3.quantity) FROM CR_ODR t3 )))"; 
         execute(jpql, expectedSQL);
     }
 
@@ -564,12 +582,14 @@
             + " and (select min(o2.quantity) from Customer c, in(c.orders)"
             + " o2)";
 
-        String expectedSQL = "SELECT t4.id FROM CR_ODR t4 WHERE (t4.quantity 
>= ("
-            + "SELECT AVG(t1.quantity) "
+        String expectedSQL = "SELECT t4.id FROM CR_ODR t4 WHERE "
+            + "((t4.quantity >= ("
+            + "SELECT AVG(t1.quantity) " 
             + "FROM CR_CUST t0 INNER JOIN CR_ODR t1 ON t0.id = t1.CUSTOMER_ID 
) AND "
             + "t4.quantity <= ("
             + "SELECT MIN(t3.quantity) "
-            + "FROM CR_CUST t2 INNER JOIN CR_ODR t3 ON t2.id = t3.CUSTOMER_ID 
))";
+            + "FROM CR_CUST t2 INNER JOIN CR_ODR t3 ON t2.id = t3.CUSTOMER_ID 
)))"; 
+
         execute(jpql, expectedSQL);
     }
 
@@ -606,10 +626,11 @@
             + "WHERE m3.idPublisher.id = p.id)) ";
 
         String expectedSQL = "SELECT t0.id, t1.id, t1.date_published, 
t1.id_publisher, t1.name "
-            + "FROM Publisher t0 LEFT OUTER JOIN Magazine t1 ON t0.id = 
t1.id_publisher WHERE (t1.id = ("
-            + "SELECT MAX(t2.id) FROM Magazine t2 WHERE ("
+            + "FROM Publisher t0 LEFT OUTER JOIN Magazine t1 ON t0.id = 
t1.id_publisher WHERE "
+            + "(t1.id = ("
+            + "SELECT MAX(t2.id) FROM Magazine t2 WHERE (("
             + "t2.id_publisher = t0.id AND "
-            + "t2.id = (SELECT MAX(t3.id) FROM Magazine t3 WHERE 
(t3.id_publisher = t0.id) )) ))";
+            + "t2.id = (SELECT MAX(t3.id) FROM Magazine t3 WHERE 
(t3.id_publisher = t0.id) ))) ))"; 
         execute(jpql, expectedSQL);
     }
 
@@ -633,7 +654,7 @@
             + "o.id)";
         String expectedSQL = "SELECT t0.id FROM CR_ODR t0 WHERE (t0.quantity > 
("
             + "SELECT (t2.quantity * ?) FROM CR_ODR t1 JOIN CR_ODR t2 ON (1 = 
1), CR_LI t3 WHERE ("
-            + "t3.quantity > ? AND t2.quantity > ? AND t3.id = t2.id) ))";
+            + "(t3.quantity > ? AND (t2.quantity > ? AND t3.id = t2.id))) ))"; 
         execute(jpql, expectedSQL);
     }
 
@@ -821,6 +842,39 @@
             }
         }
     }
+    
+    public void testCorrelatedNestedSubquery1() {
+        String jpql = "Select Object (c) From Customer c Where Not Exists ("
+                + "   Select a.id From Account As a Where "
+                + "        a.customer = c  And "
+                + "        exists (select o.id from Order o where o.customer = 
c and o.count = 1))";
+
+        String expectedSQL = "SELECT t1.id, t1.accountNum, t3.id, t3.city, 
t3.country, t3.county, t3.state, "
+            + "t3.street, t4.userid, t4.DTYPE, t4.age, t4.compName, 
t4.creditRating, t4.name, t3.zipCode, "
+            + "t1.balanceOwed, t1.creditRating, t1.filledOrderCount, 
t1.firstName, t1.lastName, t1.name, "
+            + "t1.status "
+            + "FROM CR_CUST t1 LEFT OUTER JOIN CR_ADDR t3 ON t1.ADDRESS_ID = 
t3.id "
+            + "LEFT OUTER JOIN CompUser t4 ON t3.id = t4.ADD_ID WHERE (NOT 
(EXISTS ("
+            + "SELECT t0.id FROM CR_ACCT t0 WHERE ((t0.CUSTOMER_ID = t1.id AND 
EXISTS ("
+            + "SELECT t2.id FROM CR_ODR t2 WHERE ((t2.CUSTOMER_ID = t1.id AND 
t2.count = ?)) ))) )))";
+        
+        execute(jpql, expectedSQL);
+    }
+    
+    public void testCorrelatedNestedSubquery1a() {
+        String jpql = "Select Object (o) From Product o Where Not Exists ("
+            + "   Select a.id From Account As a Where "
+            + "        a.product = o  And "
+            + "        exists (select r.id from Request r where r.account = a 
and r.status = 1))";
+
+        String expectedSQL = "SELECT t1.pid, t1.version, t1.productType FROM 
CR_PRDT t1 WHERE (NOT (EXISTS ("
+            + "SELECT t0.id FROM CR_ACCT t0 WHERE ((t0.PRODUCT_PID = t1.pid 
AND EXISTS ("
+            + "SELECT t2.id FROM Request t2 WHERE ((t2.ACCOUNT_ID = t0.id AND 
t2.status = ?)) ))) )))";
+        
+        execute(jpql, expectedSQL);
+    }
+
+    
 
     void execute(String jpql, String expectedSQL) {
         sql.clear();


Reply via email to