mirror of https://github.com/apache/openjpa.git
OPENJPA-1094 JPA2 Query support KEY to appear in subquery
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@776117 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
e5e4cc122a
commit
2ce5299a73
|
@ -21,6 +21,7 @@ package org.apache.openjpa.jdbc.kernel.exps;
|
|||
import org.apache.openjpa.jdbc.sql.SQLBuffer;
|
||||
import org.apache.openjpa.jdbc.sql.Select;
|
||||
import org.apache.openjpa.kernel.exps.ExpressionVisitor;
|
||||
import org.apache.openjpa.kernel.exps.Path;
|
||||
import org.apache.openjpa.kernel.exps.Value;
|
||||
|
||||
/**
|
||||
|
@ -109,5 +110,9 @@ abstract class AbstractVal
|
|||
public Value getSelectAs() {
|
||||
return _alias != null ? this : null;
|
||||
}
|
||||
|
||||
public Path getPath() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ class ContainsExpression
|
|||
Val val1 = getValue1();
|
||||
if (contains != null && val1 instanceof PCPath) {
|
||||
PCPath sql = (PCPath) val1;
|
||||
String path = sql.getPath();
|
||||
String path = sql.getPCPathString();
|
||||
|
||||
// update the count for this path
|
||||
Integer count = (Integer) contains.get(path);
|
||||
|
|
|
@ -124,4 +124,11 @@ public class MapKey
|
|||
public void setMetaData(ClassMetaData meta) {
|
||||
_meta = meta;
|
||||
}
|
||||
|
||||
public Object toDataStoreValue(Select sel, ExpContext ctx, ExpState state,
|
||||
Object val) {
|
||||
KeyExpState estate = (KeyExpState) state;
|
||||
return _key.toDataStoreValue(sel, ctx,
|
||||
estate.key, val);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -218,7 +218,7 @@ public class PCPath
|
|||
return xpath.toString();
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
public String getPCPathString() {
|
||||
if (_actions == null)
|
||||
return (_varName == null) ? "" : _varName + ".";
|
||||
|
||||
|
@ -293,10 +293,14 @@ public class PCPath
|
|||
case JavaTypes.COLLECTION:
|
||||
ValueMapping elem = pstate.field.getElementMapping();
|
||||
if (pstate.field.isElementCollection() &&
|
||||
pstate.field.getElement().isEmbedded())
|
||||
return ((HandlerCollectionTableFieldStrategy)
|
||||
pstate.field.getStrategy()).getElementColumns(
|
||||
elem.getTypeMapping());
|
||||
pstate.field.getElement().isEmbedded()) {
|
||||
Strategy strategy = pstate.field.getStrategy();
|
||||
if (strategy instanceof
|
||||
HandlerCollectionTableFieldStrategy)
|
||||
return ((HandlerCollectionTableFieldStrategy)
|
||||
strategy).getElementColumns(
|
||||
elem.getTypeMapping());
|
||||
}
|
||||
if (pstate.joinedRel && elem.getTypeCode() == JavaTypes.PC)
|
||||
return elem.getTypeMapping().getPrimaryKeyColumns();
|
||||
if (elem.getColumns().length > 0)
|
||||
|
|
|
@ -69,7 +69,7 @@ class SubQ
|
|||
}
|
||||
|
||||
public Class getType() {
|
||||
if (_exps != null) {
|
||||
if (_exps != null && _type == null) {
|
||||
if (_exps.projections.length == 0)
|
||||
return _candidate.getDescribedType();
|
||||
if (_exps.projections.length == 1)
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.apache.openjpa.jdbc.sql.Result;
|
|||
import org.apache.openjpa.jdbc.sql.SQLBuffer;
|
||||
import org.apache.openjpa.jdbc.sql.Select;
|
||||
import org.apache.openjpa.kernel.exps.ExpressionVisitor;
|
||||
import org.apache.openjpa.kernel.exps.Path;
|
||||
import org.apache.openjpa.meta.ClassMetaData;
|
||||
|
||||
/**
|
||||
|
@ -75,6 +76,10 @@ class Variable
|
|||
return _path;
|
||||
}
|
||||
|
||||
public Path getPath() {
|
||||
return _path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the path this variable is aliased to.
|
||||
*/
|
||||
|
|
|
@ -131,4 +131,8 @@ public abstract class Val
|
|||
public Value getSelectAs() {
|
||||
return _alias != null ? this : null;
|
||||
}
|
||||
|
||||
public Path getPath() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,4 +88,6 @@ public interface Value
|
|||
* Return 'this' concrete class if alias is set, otherwise null
|
||||
*/
|
||||
public Value getSelectAs();
|
||||
|
||||
public Path getPath();
|
||||
}
|
||||
|
|
|
@ -651,7 +651,13 @@ public class JPQLExpressionBuilder
|
|||
// clause, since we might be in a subquery against a collection
|
||||
if (isPath(left)) {
|
||||
Path path = getPath(left);
|
||||
setCandidate(getFieldType(path.last()), alias);
|
||||
FieldMetaData fmd = path.last();
|
||||
ClassMetaData candidate = getFieldType(fmd);
|
||||
|
||||
if (candidate == null && fmd.isElementCollection())
|
||||
candidate = fmd.getDefiningMetaData();
|
||||
|
||||
setCandidate(candidate, alias);
|
||||
|
||||
Path subpath = factory.newPath(ctx().subquery);
|
||||
subpath.setMetaData(ctx().subquery.getMetaData());
|
||||
|
@ -1491,6 +1497,14 @@ public class JPQLExpressionBuilder
|
|||
private Value validateMapPath(JPQLNode node, JPQLNode id) {
|
||||
Path path = (Path) getValue(id);
|
||||
FieldMetaData fld = path.last();
|
||||
|
||||
if (fld == null && ctx().subquery != null) {
|
||||
Value var = getVariable(id.text, false);
|
||||
if (var != null) {
|
||||
path = factory.newPath(var);
|
||||
fld = path.last();
|
||||
}
|
||||
}
|
||||
|
||||
if (fld != null) {
|
||||
// validate the field is of type java.util.Map
|
||||
|
@ -1503,7 +1517,11 @@ public class JPQLExpressionBuilder
|
|||
throw parseException(EX_USER, "bad-qualified-identifier",
|
||||
new Object[]{ id.text, oper}, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
throw parseException(EX_USER, "unknown-type",
|
||||
new Object[]{ id.text}, null);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
@ -1517,7 +1535,9 @@ public class JPQLExpressionBuilder
|
|||
FieldMetaData fld = path.last();
|
||||
path = (Path) factory.getKey(path);
|
||||
ClassMetaData meta = fld.getKey().getTypeMetaData();
|
||||
if (inWhereClause && meta != null)
|
||||
if (inWhereClause && meta != null &&
|
||||
fld.isElementCollection() &&
|
||||
fld.getElement().getEmbeddedMetaData() != null)
|
||||
// check basic type
|
||||
throw parseException(EX_USER, "bad-general-identifier",
|
||||
new Object[]{ id.text, "KEY" }, null);
|
||||
|
|
|
@ -746,6 +746,18 @@ public class TestEmbeddable extends SingleEMFTestCase {
|
|||
assertEmployee(e);
|
||||
}
|
||||
tran.commit();
|
||||
em.clear();
|
||||
// test range variable over element collection
|
||||
String[] query = {
|
||||
"select e from Employee e, in (e.nickNames) n " +
|
||||
" where n like '%1'",
|
||||
};
|
||||
for (int i = 0; i < query.length; i++) {
|
||||
es = em.createQuery(query[i]).getResultList();
|
||||
for (Employee e : es){
|
||||
assertEmployee(e);
|
||||
}
|
||||
}
|
||||
em.close();
|
||||
}
|
||||
|
||||
|
@ -2145,6 +2157,25 @@ public class TestEmbeddable extends SingleEMFTestCase {
|
|||
}
|
||||
|
||||
tran.commit();
|
||||
|
||||
String query[] = {
|
||||
"select d from Department1 d join d.empMap e " +
|
||||
" where KEY(e) > 1 order by d",
|
||||
"select d from Department1 d join d.empMap e" +
|
||||
" where d.deptId = KEY(e) order by d",
|
||||
"select d from Department1 d " +
|
||||
" where d.deptId < ANY " +
|
||||
" (select KEY(e) from in(d.empMap) e) " +
|
||||
" order by d",
|
||||
"select d from Department1 d " +
|
||||
" where d.deptId < SOME " +
|
||||
" (select KEY(e) from Department1 d1, in(d1.empMap) e) " +
|
||||
" order by d",
|
||||
};
|
||||
for (int i = 0; i < query.length; i++) {
|
||||
ds1 = em.createQuery(query[i]).getResultList();
|
||||
assertDepartment1(ds1.get(0));
|
||||
}
|
||||
em.close();
|
||||
}
|
||||
|
||||
|
@ -2290,6 +2321,66 @@ public class TestEmbeddable extends SingleEMFTestCase {
|
|||
}
|
||||
|
||||
tran.commit();
|
||||
|
||||
String imageKey1 = (String) is1.get(0).getImages().
|
||||
keySet().toArray()[0];
|
||||
String imageKey2 = (String) is2.get(0).getImages().
|
||||
keySet().toArray()[0];
|
||||
String imageKey3 = (String) is3.get(0).getImages().
|
||||
keySet().toArray()[0];
|
||||
String[] query = {
|
||||
"select i from Item1 i" +
|
||||
" where ?1 = any " +
|
||||
" (select KEY(e) from Item1 i, in(i.images) e) " +
|
||||
" order by i",
|
||||
"select i from Item2 i" +
|
||||
" where ?1 = any " +
|
||||
" (select KEY(e) from Item2 i, in(i.images) e) " +
|
||||
" order by i",
|
||||
"select i from Item3 i" +
|
||||
" where ?1 = any " +
|
||||
" (select KEY(e) from Item3 i, in(i.images) e) " +
|
||||
" order by i",
|
||||
"select i from Item1 i" +
|
||||
" where exists " +
|
||||
" (select e from Item1 i, in(i.images) e" +
|
||||
" where ?1 = KEY(e)) " +
|
||||
" order by i",
|
||||
"select i from Item2 i" +
|
||||
" where exists " +
|
||||
" (select e from Item2 i, in(i.images) e" +
|
||||
" where ?1 = KEY(e)) " +
|
||||
" order by i",
|
||||
"select i from Item3 i" +
|
||||
" where exists " +
|
||||
" (select e from Item3 i, in(i.images) e" +
|
||||
" where ?1 = KEY(e)) " +
|
||||
" order by i",
|
||||
};
|
||||
|
||||
for (int i = 0; i < query.length; i++) {
|
||||
Query q = em.createQuery(query[i]);
|
||||
switch (i) {
|
||||
case 0:
|
||||
case 3:
|
||||
q.setParameter(1, imageKey1);
|
||||
is1 = q.getResultList();
|
||||
assertItem1(is1.get(0));
|
||||
break;
|
||||
case 1:
|
||||
case 4:
|
||||
q.setParameter(1, imageKey2);
|
||||
is2 = q.getResultList();
|
||||
assertItem2(is2.get(0));
|
||||
break;
|
||||
case 2:
|
||||
case 5:
|
||||
q.setParameter(1, imageKey3);
|
||||
is3 = q.getResultList();
|
||||
assertItem3(is3.get(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
em.close();
|
||||
}
|
||||
|
||||
|
@ -2308,6 +2399,56 @@ public class TestEmbeddable extends SingleEMFTestCase {
|
|||
assertCompany2(c);
|
||||
}
|
||||
tran.commit();
|
||||
|
||||
em.clear();
|
||||
// test KEY(e) appeared in subquery
|
||||
Division d1 = (Division) ((Company1) cs1.get(0)).getOrganization().
|
||||
keySet().toArray()[0];
|
||||
Division d2 = (Division) ((Company2) cs2.get(0)).getOrganization().
|
||||
keySet().toArray()[0];
|
||||
String[] query = {
|
||||
"select c from Company1 c, in(c.organization) d " +
|
||||
" where KEY(d) = ?1",
|
||||
"select c from Company1 c " +
|
||||
" where ?1 = " +
|
||||
" (select KEY(d) from Company1 c, in(c.organization) d" +
|
||||
" where d.id = 1)" +
|
||||
" order by c ",
|
||||
"select c from Company2 c" +
|
||||
" where ?1 = " +
|
||||
" (select KEY(d) from Company2 c, in(c.organization) d" +
|
||||
" where d.id = 3)" +
|
||||
" order by c ",
|
||||
"select c from Company1 c where exists" +
|
||||
" (select d from in(c.organization) d" +
|
||||
" where KEY(d) = ?1)" +
|
||||
" order by c ",
|
||||
"select c from Company2 c where exists" +
|
||||
" (select d from in(c.organization) d" +
|
||||
" where KEY(d) = ?1)" +
|
||||
" order by c ",
|
||||
};
|
||||
|
||||
for (int i = 0; i < query.length; i++) {
|
||||
Query q = em.createQuery(query[i]);
|
||||
switch (i) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 3:
|
||||
q.setParameter(1, d1);
|
||||
cs1 = q.getResultList();
|
||||
if (cs1.size() > 0)
|
||||
assertCompany1(cs1.get(0));
|
||||
break;
|
||||
case 2:
|
||||
case 4:
|
||||
q.setParameter(1, d2);
|
||||
cs2 = q.getResultList();
|
||||
if (cs2.size() > 0)
|
||||
assertCompany2(cs2.get(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
em.close();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue