OPENJPA-1185 Subquery overhaul

fix subquery correlation involving association table

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@826135 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Catalina Wei 2009-10-17 00:07:04 +00:00
parent acab37ec81
commit a32bb62381
2 changed files with 130 additions and 10 deletions

View File

@ -2859,13 +2859,21 @@ public class SelectImpl
boolean createIndex = true;
Table table2 = (inverse) ? fk.getTable()
: fk.getPrimaryKeyTable();
if (table2.isAssociation())
createIndex = true;
boolean created = false;
int alias2 = -1;
if (table2.isAssociation()) {
alias2 = _sel.getTableIndex(table2, this, false);
if (alias2 == -1)
createIndex = true;
else
created = true;
}
else if (context == _sel.ctx())
createIndex = true;
else if (correlatedVar != null)
createIndex = false;
int alias2 = _sel.getTableIndex(table2, this, createIndex);
if (!created)
alias2 = _sel.getTableIndex(table2, this, createIndex);
Join j = new Join(table1, alias1, table2, alias2, fk, inverse);
j.setType((outer) ? Join.TYPE_OUTER : Join.TYPE_INNER);

View File

@ -34,8 +34,6 @@ import javax.persistence.criteria.Root;
import javax.persistence.criteria.SetJoin;
import javax.persistence.criteria.Subquery;
import org.apache.openjpa.persistence.test.AllowFailure;
/**
* Tests type-strict version of Criteria API.
*
@ -1575,13 +1573,22 @@ public class TestJPQLSubquery extends CriteriaTest {
q.where(cb.exists(sq).not());
assertEquivalence(q, jpql);
}
// Plural correlated Join
public void testCollectionJoin1() {
public void testPluralCorrelatedJoin1() {
String jpql = "SELECT o.quantity, o.totalCost*1.08, "
+ "a.zipCode FROM Customer c JOIN c.orders o JOIN c.address a "
+ "WHERE a.state = "
+ "(SELECT o.name from Customer c1 JOIN c1.orders o1 where o.quantity = o1.quantity)";
String expectedSQL = "SELECT t2.quantity, (t2.totalCost * ?), t1.zipCode "
+ "FROM CR_CUST t0 INNER JOIN CR_ODR t2 ON t0.id = t2.CUSTOMER_ID "
+ "INNER JOIN CR_ADDR t1 ON t0.ADDRESS_ID = t1.id "
+ "WHERE (t1.state = "
+ "(SELECT t2.name "
+ "FROM CR_CUST t3 INNER JOIN CR_ODR t4 ON t3.id = t4.CUSTOMER_ID "
+ "WHERE (t2.quantity = t4.quantity)) AND 1 = 1)";
executeAndCompareSQL(jpql, expectedSQL);
CriteriaQuery<?> q = cb.createQuery();
Root<Customer> cust = q.from(Customer.class);
SetJoin<Customer, Order> order = cust.joinSet("orders");
@ -1599,10 +1606,55 @@ public class TestJPQLSubquery extends CriteriaTest {
assertEquivalence(q, jpql);
}
// correlated Singular Join => Plural Join
public void testCollection3() {
public void testPluralCorrelatedJoin2() {
String jpql = "SELECT d.name FROM Department d JOIN d.employees e JOIN e.manager m "
+ "WHERE m.salary = (SELECT e1.salary from Employee e1 JOIN e1.manager m1 "
+ "where m.name = m1.name)";
String expectedSQL = "SELECT t0.name FROM CR_DEPT t0 "
+ "INNER JOIN CR_DEPT_CR_EMP t1 ON t0.deptNo = t1.DEPARTMENT_DEPTNO "
+ "INNER JOIN CR_EMP t2 ON t1.EMPLOYEES_EMPID = t2.empId "
+ "INNER JOIN CR_EMP t6 ON t1.EMPLOYEES_EMPID = t6.empId "
+ "INNER JOIN CR_MGR t3 ON t2.MANAGER_ID = t3.id "
+ "INNER JOIN CR_MGR t7 ON t6.MANAGER_ID = t7.id "
+ "WHERE (t3.salary = (SELECT t4.salary FROM CR_EMP t4 "
+ "INNER JOIN CR_MGR t5 ON t4.MANAGER_ID = t5.id "
+ "WHERE (t7.name = t5.name)) AND 1 = 1)";
executeAndCompareSQL(jpql, expectedSQL);
CriteriaQuery<String> q = cb.createQuery(String.class);
Root<Department> d = q.from(Department.class);
SetJoin<Department, Employee> e = d.joinSet("employees");
Join<Employee, Manager> m = e.join("manager");
Subquery<Long> sq = q.subquery(Long.class);
Root<Employee> e1 = sq.from(Employee.class);
Join<Employee, Manager> m1 = e1.join("manager");
Join<Employee, Manager> corrJoin = sq.correlate(m);
sq.where(cb.equal(corrJoin.get(Manager_.name), m1.get(Manager_.name)));
q.where(cb.equal(m.get(Manager_.salary), sq.select(e1.get(Employee_.salary))));
q.select(d.get(Department_.name));
assertEquivalence(q, jpql);
}
public void testPluralCorrelatedJoin3() {
String jpql = "SELECT o FROM Order o JOIN o.customer c JOIN c.accounts a WHERE 10000 < "
+ "ANY (SELECT a1.balance FROM Account a1 WHERE a.owner = a1.owner)";
String expectedSQL = "SELECT t0.id, t0.count, t6.id, t6.accountNum, t7.id, t7.city, "
+ "t7.country, t7.county, t7.state, t7.street, t8.userid, t8.DTYPE, t8.age, "
+ "t8.compName, t8.creditRating, t8.name, t7.zipCode, t6.balanceOwed, "
+ "t6.creditRating, t6.filledOrderCount, t6.firstName, t6.lastName, t6.name, "
+ "t6.status, t0.delivered, t0.name, t0.orderTs, t0.quantity, t0.totalCost "
+ "FROM CR_ODR t0 "
+ "INNER JOIN CR_CUST t1 ON t0.CUSTOMER_ID = t1.id "
+ "LEFT OUTER JOIN CR_CUST t6 ON t0.CUSTOMER_ID = t6.id "
+ "INNER JOIN CR_CUST_CR_ACCT t2 ON t1.id = t2.CUSTOMER_ID "
+ "LEFT OUTER JOIN CR_ADDR t7 ON t6.ADDRESS_ID = t7.id "
+ "INNER JOIN CR_ACCT t3 ON t2.ACCOUNTS_ID = t3.id "
+ "INNER JOIN CR_ACCT t4 ON t2.ACCOUNTS_ID = t4.id "
+ "LEFT OUTER JOIN CompUser t8 ON t7.id = t8.ADD_ID WHERE (? < "
+ "ANY (SELECT t5.balance FROM CR_ACCT t5 "
+ "WHERE (t4.OWNER_ID = t5.OWNER_ID)) AND 1 = 1)";
executeAndCompareSQL(jpql, expectedSQL);
CriteriaQuery<Order> q = cb.createQuery(Order.class);
Root<Order> o = q.from(Order.class);
@ -1618,4 +1670,64 @@ public class TestJPQLSubquery extends CriteriaTest {
assertEquivalence(q, jpql);
}
public void testPluralCorrelatedJoin4() {
String jpql =
"SELECT o.quantity FROM Order o JOIN o.customer c JOIN c.accounts a JOIN a.owner owner WHERE 10000 < "
+ "ANY (SELECT a1.balance FROM Account a1 JOIN a1.owner owner1 WHERE owner.name = owner1.name)";
String expectedSQL = "SELECT t0.quantity FROM CR_ODR t0 "
+ "INNER JOIN CR_CUST t1 ON t0.CUSTOMER_ID = t1.id "
+ "INNER JOIN CR_CUST_CR_ACCT t2 ON t1.id = t2.CUSTOMER_ID "
+ "INNER JOIN CR_ACCT t3 ON t2.ACCOUNTS_ID = t3.id "
+ "INNER JOIN CR_ACCT t7 ON t2.ACCOUNTS_ID = t7.id "
+ "INNER JOIN CR_PSN t4 ON t3.OWNER_ID = t4.id "
+ "INNER JOIN CR_PSN t8 ON t7.OWNER_ID = t8.id WHERE (? < "
+ "ANY (SELECT t5.balance "
+ "FROM CR_ACCT t5 INNER JOIN CR_PSN t6 ON t5.OWNER_ID = t6.id "
+ "WHERE (t8.name = t6.name)) AND 1 = 1)";
executeAndCompareSQL(jpql, expectedSQL);
CriteriaQuery<Integer> q = cb.createQuery(Integer.class);
Root<Order> o = q.from(Order.class);
Join<Order,Customer> c = o.join(Order_.customer);
ListJoin<Customer,Account> a = c.joinList("accounts");
Join<Account,Person> owner = a.join(Account_.owner);
Subquery<Integer> sq = q.subquery(Integer.class);
Root<Account> a1 = sq.from(Account.class);
Join<Account,Person> owner1 = a1.join(Account_.owner);
Join<Account,Person> corrJoin = sq.correlate(owner);
sq.where(cb.equal(corrJoin.get(Person_.name), owner1.get(Person_.name)));
q.where(cb.lt(cb.literal(10000), cb.any(sq.select(a1.get(Account_.balance)))));
q.select(o.get(Order_.quantity));
assertEquivalence(q, jpql);
}
public void testPluralCorrelatedJoin5() {
String jpql = "SELECT o.quantity FROM Order o JOIN o.customer c JOIN c.accounts a WHERE c.name = "
+ "ANY (SELECT owner.name FROM a.owner owner WHERE owner.id = 1)";
String expectedSQL = "SELECT t0.quantity FROM CR_ODR t0 "
+ "INNER JOIN CR_CUST t1 ON t0.CUSTOMER_ID = t1.id "
+ "INNER JOIN CR_CUST_CR_ACCT t2 ON t1.id = t2.CUSTOMER_ID "
+ "INNER JOIN CR_ACCT t3 ON t2.ACCOUNTS_ID = t3.id "
+ "INNER JOIN CR_ACCT t4 ON t2.ACCOUNTS_ID = t4.id "
+ "WHERE (t1.name = "
+ "ANY (SELECT t5.name FROM CR_PSN t5 WHERE (t5.id = ? AND t4.OWNER_ID = t5.id)) "
+ "AND 1 = 1)";
executeAndCompareSQL(jpql, expectedSQL);
CriteriaQuery<Integer> q = cb.createQuery(Integer.class);
Root<Order> o = q.from(Order.class);
Join<Order,Customer> c = o.join(Order_.customer);
ListJoin<Customer,Account> a = c.joinList("accounts");
Subquery<String> sq = q.subquery(String.class);
ListJoin<Customer,Account> a1 = sq.correlate(a);
Join<Account,Person> owner = a1.join(Account_.owner);
sq.where(cb.equal(owner.get(Person_.id), 1));
q.where(cb.equal(c.get(Customer_.name), cb.any(sq.select(owner.get(Person_.name)))));
q.select(o.get(Order_.quantity));
assertEquivalence(q, jpql);
}
}