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.SQLBuffer;
|
||||||
import org.apache.openjpa.jdbc.sql.Select;
|
import org.apache.openjpa.jdbc.sql.Select;
|
||||||
import org.apache.openjpa.kernel.exps.ExpressionVisitor;
|
import org.apache.openjpa.kernel.exps.ExpressionVisitor;
|
||||||
|
import org.apache.openjpa.kernel.exps.Path;
|
||||||
import org.apache.openjpa.kernel.exps.Value;
|
import org.apache.openjpa.kernel.exps.Value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -109,5 +110,9 @@ abstract class AbstractVal
|
||||||
public Value getSelectAs() {
|
public Value getSelectAs() {
|
||||||
return _alias != null ? this : null;
|
return _alias != null ? this : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Path getPath() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ class ContainsExpression
|
||||||
Val val1 = getValue1();
|
Val val1 = getValue1();
|
||||||
if (contains != null && val1 instanceof PCPath) {
|
if (contains != null && val1 instanceof PCPath) {
|
||||||
PCPath sql = (PCPath) val1;
|
PCPath sql = (PCPath) val1;
|
||||||
String path = sql.getPath();
|
String path = sql.getPCPathString();
|
||||||
|
|
||||||
// update the count for this path
|
// update the count for this path
|
||||||
Integer count = (Integer) contains.get(path);
|
Integer count = (Integer) contains.get(path);
|
||||||
|
|
|
@ -124,4 +124,11 @@ public class MapKey
|
||||||
public void setMetaData(ClassMetaData meta) {
|
public void setMetaData(ClassMetaData meta) {
|
||||||
_meta = 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();
|
return xpath.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPath() {
|
public String getPCPathString() {
|
||||||
if (_actions == null)
|
if (_actions == null)
|
||||||
return (_varName == null) ? "" : _varName + ".";
|
return (_varName == null) ? "" : _varName + ".";
|
||||||
|
|
||||||
|
@ -293,10 +293,14 @@ public class PCPath
|
||||||
case JavaTypes.COLLECTION:
|
case JavaTypes.COLLECTION:
|
||||||
ValueMapping elem = pstate.field.getElementMapping();
|
ValueMapping elem = pstate.field.getElementMapping();
|
||||||
if (pstate.field.isElementCollection() &&
|
if (pstate.field.isElementCollection() &&
|
||||||
pstate.field.getElement().isEmbedded())
|
pstate.field.getElement().isEmbedded()) {
|
||||||
return ((HandlerCollectionTableFieldStrategy)
|
Strategy strategy = pstate.field.getStrategy();
|
||||||
pstate.field.getStrategy()).getElementColumns(
|
if (strategy instanceof
|
||||||
elem.getTypeMapping());
|
HandlerCollectionTableFieldStrategy)
|
||||||
|
return ((HandlerCollectionTableFieldStrategy)
|
||||||
|
strategy).getElementColumns(
|
||||||
|
elem.getTypeMapping());
|
||||||
|
}
|
||||||
if (pstate.joinedRel && elem.getTypeCode() == JavaTypes.PC)
|
if (pstate.joinedRel && elem.getTypeCode() == JavaTypes.PC)
|
||||||
return elem.getTypeMapping().getPrimaryKeyColumns();
|
return elem.getTypeMapping().getPrimaryKeyColumns();
|
||||||
if (elem.getColumns().length > 0)
|
if (elem.getColumns().length > 0)
|
||||||
|
|
|
@ -69,7 +69,7 @@ class SubQ
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class getType() {
|
public Class getType() {
|
||||||
if (_exps != null) {
|
if (_exps != null && _type == null) {
|
||||||
if (_exps.projections.length == 0)
|
if (_exps.projections.length == 0)
|
||||||
return _candidate.getDescribedType();
|
return _candidate.getDescribedType();
|
||||||
if (_exps.projections.length == 1)
|
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.SQLBuffer;
|
||||||
import org.apache.openjpa.jdbc.sql.Select;
|
import org.apache.openjpa.jdbc.sql.Select;
|
||||||
import org.apache.openjpa.kernel.exps.ExpressionVisitor;
|
import org.apache.openjpa.kernel.exps.ExpressionVisitor;
|
||||||
|
import org.apache.openjpa.kernel.exps.Path;
|
||||||
import org.apache.openjpa.meta.ClassMetaData;
|
import org.apache.openjpa.meta.ClassMetaData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -75,6 +76,10 @@ class Variable
|
||||||
return _path;
|
return _path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Path getPath() {
|
||||||
|
return _path;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the path this variable is aliased to.
|
* Set the path this variable is aliased to.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -131,4 +131,8 @@ public abstract class Val
|
||||||
public Value getSelectAs() {
|
public Value getSelectAs() {
|
||||||
return _alias != null ? this : null;
|
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
|
* Return 'this' concrete class if alias is set, otherwise null
|
||||||
*/
|
*/
|
||||||
public Value getSelectAs();
|
public Value getSelectAs();
|
||||||
|
|
||||||
|
public Path getPath();
|
||||||
}
|
}
|
||||||
|
|
|
@ -651,7 +651,13 @@ public class JPQLExpressionBuilder
|
||||||
// clause, since we might be in a subquery against a collection
|
// clause, since we might be in a subquery against a collection
|
||||||
if (isPath(left)) {
|
if (isPath(left)) {
|
||||||
Path path = getPath(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);
|
Path subpath = factory.newPath(ctx().subquery);
|
||||||
subpath.setMetaData(ctx().subquery.getMetaData());
|
subpath.setMetaData(ctx().subquery.getMetaData());
|
||||||
|
@ -1491,6 +1497,14 @@ public class JPQLExpressionBuilder
|
||||||
private Value validateMapPath(JPQLNode node, JPQLNode id) {
|
private Value validateMapPath(JPQLNode node, JPQLNode id) {
|
||||||
Path path = (Path) getValue(id);
|
Path path = (Path) getValue(id);
|
||||||
FieldMetaData fld = path.last();
|
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) {
|
if (fld != null) {
|
||||||
// validate the field is of type java.util.Map
|
// validate the field is of type java.util.Map
|
||||||
|
@ -1503,7 +1517,11 @@ public class JPQLExpressionBuilder
|
||||||
throw parseException(EX_USER, "bad-qualified-identifier",
|
throw parseException(EX_USER, "bad-qualified-identifier",
|
||||||
new Object[]{ id.text, oper}, null);
|
new Object[]{ id.text, oper}, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
throw parseException(EX_USER, "unknown-type",
|
||||||
|
new Object[]{ id.text}, null);
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1517,7 +1535,9 @@ public class JPQLExpressionBuilder
|
||||||
FieldMetaData fld = path.last();
|
FieldMetaData fld = path.last();
|
||||||
path = (Path) factory.getKey(path);
|
path = (Path) factory.getKey(path);
|
||||||
ClassMetaData meta = fld.getKey().getTypeMetaData();
|
ClassMetaData meta = fld.getKey().getTypeMetaData();
|
||||||
if (inWhereClause && meta != null)
|
if (inWhereClause && meta != null &&
|
||||||
|
fld.isElementCollection() &&
|
||||||
|
fld.getElement().getEmbeddedMetaData() != null)
|
||||||
// check basic type
|
// check basic type
|
||||||
throw parseException(EX_USER, "bad-general-identifier",
|
throw parseException(EX_USER, "bad-general-identifier",
|
||||||
new Object[]{ id.text, "KEY" }, null);
|
new Object[]{ id.text, "KEY" }, null);
|
||||||
|
|
|
@ -746,6 +746,18 @@ public class TestEmbeddable extends SingleEMFTestCase {
|
||||||
assertEmployee(e);
|
assertEmployee(e);
|
||||||
}
|
}
|
||||||
tran.commit();
|
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();
|
em.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2145,6 +2157,25 @@ public class TestEmbeddable extends SingleEMFTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
tran.commit();
|
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();
|
em.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2290,6 +2321,66 @@ public class TestEmbeddable extends SingleEMFTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
tran.commit();
|
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();
|
em.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2308,6 +2399,56 @@ public class TestEmbeddable extends SingleEMFTestCase {
|
||||||
assertCompany2(c);
|
assertCompany2(c);
|
||||||
}
|
}
|
||||||
tran.commit();
|
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();
|
em.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue