mirror of https://github.com/apache/openjpa.git
OPENJPA-967 JPA2 Query support for MapKey fixes
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@763516 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
2901ea6e52
commit
be8731aafa
|
@ -108,7 +108,7 @@ public class MapKey
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class getType() {
|
public Class getType() {
|
||||||
return Object.class;
|
return _key.getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setImplicitType(Class type) {
|
public void setImplicitType(Class type) {
|
||||||
|
|
|
@ -77,13 +77,11 @@ public class PCPath
|
||||||
private final ClassMapping _candidate;
|
private final ClassMapping _candidate;
|
||||||
private ClassMapping _class = null;
|
private ClassMapping _class = null;
|
||||||
private boolean _key = false;
|
private boolean _key = false;
|
||||||
private boolean _keyPath = false;
|
|
||||||
private int _type = PATH;
|
private int _type = PATH;
|
||||||
private String _varName = null;
|
private String _varName = null;
|
||||||
private Class _cast = null;
|
private Class _cast = null;
|
||||||
private boolean _cid = false;
|
private boolean _cid = false;
|
||||||
private FieldMetaData _xmlfield = null;
|
private FieldMetaData _xmlfield = null;
|
||||||
private FieldMetaData _mapfield = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a path starting with the 'this' ptr.
|
* Return a path starting with the 'this' ptr.
|
||||||
|
@ -249,8 +247,7 @@ public class PCPath
|
||||||
if (pstate.field.getKey().getTypeCode() == JavaTypes.PC)
|
if (pstate.field.getKey().getTypeCode() == JavaTypes.PC)
|
||||||
return pstate.field.getKeyMapping().getTypeMapping();
|
return pstate.field.getKeyMapping().getTypeMapping();
|
||||||
return null;
|
return null;
|
||||||
} else if (_keyPath)
|
}
|
||||||
return pstate.field.getDefiningMapping();
|
|
||||||
if (pstate.field.getElement().getTypeCode() == JavaTypes.PC) {
|
if (pstate.field.getElement().getTypeCode() == JavaTypes.PC) {
|
||||||
if (pstate.field.isElementCollection() &&
|
if (pstate.field.isElementCollection() &&
|
||||||
pstate.field.getElement().isEmbedded())
|
pstate.field.getElement().isEmbedded())
|
||||||
|
@ -372,10 +369,14 @@ public class PCPath
|
||||||
if (_cid)
|
if (_cid)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_mapfield = last();
|
// replace the last field action to a get key
|
||||||
// change the last action to a get key
|
Action action = lastFieldAction();
|
||||||
Action action = (Action) _actions.getLast();
|
Action key = new Action();
|
||||||
action.op = Action.GET_KEY;
|
key.op = Action.GET_KEY;
|
||||||
|
key.data = action.data;
|
||||||
|
int pos = _actions.indexOf(action);
|
||||||
|
_actions.remove(action);
|
||||||
|
_actions.add(pos, key);
|
||||||
_cast = null;
|
_cast = null;
|
||||||
_key = true;
|
_key = true;
|
||||||
_type = PATH;
|
_type = PATH;
|
||||||
|
@ -383,7 +384,7 @@ public class PCPath
|
||||||
|
|
||||||
public FieldMetaData last() {
|
public FieldMetaData last() {
|
||||||
Action act = lastFieldAction();
|
Action act = lastFieldAction();
|
||||||
return (act == null || act.op == Action.GET_KEY) ? null : isXPath() ?
|
return (act == null) ? null : isXPath() ?
|
||||||
_xmlfield : (FieldMetaData) act.data;
|
_xmlfield : (FieldMetaData) act.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,7 +417,6 @@ public class PCPath
|
||||||
return ((XMLMetaData) act.data).getType();
|
return ((XMLMetaData) act.data).getType();
|
||||||
|
|
||||||
FieldMetaData fld = act == null ? null :
|
FieldMetaData fld = act == null ? null :
|
||||||
act.op == Action.GET_KEY ? _mapfield :
|
|
||||||
(FieldMetaData) act.data;
|
(FieldMetaData) act.data;
|
||||||
boolean key = act != null && act.op == Action.GET_KEY;
|
boolean key = act != null && act.op == Action.GET_KEY;
|
||||||
if (fld != null) {
|
if (fld != null) {
|
||||||
|
@ -480,22 +480,8 @@ public class PCPath
|
||||||
rel.getTable());
|
rel.getTable());
|
||||||
} else {
|
} else {
|
||||||
// move past the previous field, if any
|
// move past the previous field, if any
|
||||||
field = (action.op == Action.GET_XPATH) ?
|
field = (FieldMapping) ((action.op == Action.GET_XPATH) ?
|
||||||
(FieldMapping) _xmlfield :
|
_xmlfield : action.data);
|
||||||
(action.op == Action.GET_KEY) ? null :
|
|
||||||
(FieldMapping) action.data;
|
|
||||||
|
|
||||||
// mark if the next traversal should go through
|
|
||||||
// the key rather than value
|
|
||||||
key = action.op == Action.GET_KEY;
|
|
||||||
forceOuter |= action.op == Action.GET_OUTER;
|
|
||||||
|
|
||||||
// if last action is get map key, use the previous field mapping
|
|
||||||
if (key && !itr.hasNext()) {
|
|
||||||
field = pstate.field;
|
|
||||||
pstate.joins = pstate.joins.setVariable((String)
|
|
||||||
action.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pstate.field != null) {
|
if (pstate.field != null) {
|
||||||
// if this is the second-to-last field and the last is
|
// if this is the second-to-last field and the last is
|
||||||
|
@ -509,15 +495,14 @@ public class PCPath
|
||||||
rel = traverseField(pstate, key, forceOuter, false);
|
rel = traverseField(pstate, key, forceOuter, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mark if the next traversal should go through
|
||||||
|
// the key rather than value
|
||||||
|
key = action.op == Action.GET_KEY;
|
||||||
|
forceOuter |= action.op == Action.GET_OUTER;
|
||||||
|
|
||||||
// get mapping for the current field
|
// get mapping for the current field
|
||||||
pstate.field = field;
|
pstate.field = field;
|
||||||
|
|
||||||
if (key && itr.hasNext()) {
|
|
||||||
// path navigation thru KEY
|
|
||||||
_keyPath = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
owner = pstate.field.getDefiningMapping();
|
owner = pstate.field.getDefiningMapping();
|
||||||
if (pstate.field.getManagement()
|
if (pstate.field.getManagement()
|
||||||
!= FieldMapping.MANAGE_PERSISTENT)
|
!= FieldMapping.MANAGE_PERSISTENT)
|
||||||
|
@ -555,11 +540,6 @@ public class PCPath
|
||||||
if (_varName != null)
|
if (_varName != null)
|
||||||
pstate.joins = pstate.joins.setVariable(_varName);
|
pstate.joins = pstate.joins.setVariable(_varName);
|
||||||
|
|
||||||
// if last action is key action, avoid redundant joins
|
|
||||||
if (key) {
|
|
||||||
return pstate;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we're not comparing to null or doing an isEmpty, then
|
// if we're not comparing to null or doing an isEmpty, then
|
||||||
// join into the data on the final field; obviously we can't do these
|
// join into the data on the final field; obviously we can't do these
|
||||||
// joins when comparing to null b/c the whole purpose is to see
|
// joins when comparing to null b/c the whole purpose is to see
|
||||||
|
@ -737,7 +717,7 @@ public class PCPath
|
||||||
boolean pks) {
|
boolean pks) {
|
||||||
ClassMapping mapping = getClassMapping(state);
|
ClassMapping mapping = getClassMapping(state);
|
||||||
PathExpState pstate = (PathExpState) state;
|
PathExpState pstate = (PathExpState) state;
|
||||||
if (mapping == null || !pstate.joinedRel || _keyPath ||
|
if (mapping == null || !pstate.joinedRel ||
|
||||||
pstate.isEmbedElementColl)
|
pstate.isEmbedElementColl)
|
||||||
sel.select(getColumns(state), pstate.joins);
|
sel.select(getColumns(state), pstate.joins);
|
||||||
else if (_key && pstate.field.getKey().isEmbedded())
|
else if (_key && pstate.field.getKey().isEmbedded())
|
||||||
|
@ -760,7 +740,7 @@ public class PCPath
|
||||||
public void groupBy(Select sel, ExpContext ctx, ExpState state) {
|
public void groupBy(Select sel, ExpContext ctx, ExpState state) {
|
||||||
ClassMapping mapping = getClassMapping(state);
|
ClassMapping mapping = getClassMapping(state);
|
||||||
PathExpState pstate = (PathExpState) state;
|
PathExpState pstate = (PathExpState) state;
|
||||||
if (mapping == null || !pstate.joinedRel || _keyPath)
|
if (mapping == null || !pstate.joinedRel)
|
||||||
sel.groupBy(getColumns(state), sel.outer(pstate.joins));
|
sel.groupBy(getColumns(state), sel.outer(pstate.joins));
|
||||||
else {
|
else {
|
||||||
int subs = (_type == UNBOUND_VAR) ? Select.SUBS_JOINABLE
|
int subs = (_type == UNBOUND_VAR) ? Select.SUBS_JOINABLE
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.apache.openjpa.util.InternalException;
|
||||||
* Entity Type expression.
|
* Entity Type expression.
|
||||||
*
|
*
|
||||||
* @author Catalina Wei
|
* @author Catalina Wei
|
||||||
|
* @since 2.0.0
|
||||||
*/
|
*/
|
||||||
class Type
|
class Type
|
||||||
extends UnaryOp {
|
extends UnaryOp {
|
||||||
|
@ -45,26 +46,37 @@ class Type
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExpState initialize(Select sel, ExpContext ctx, int flags) {
|
public ExpState initialize(Select sel, ExpContext ctx, int flags) {
|
||||||
// initialize the value with a null test
|
return initializeValue(sel, ctx, flags);
|
||||||
return initializeValue(sel, ctx, NULL_CMP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object load(ExpContext ctx, ExpState state, Result res)
|
public Object load(ExpContext ctx, ExpState state, Result res)
|
||||||
throws SQLException {
|
throws SQLException {
|
||||||
Object type = getValue().load(ctx, state, res);
|
Object type = null;
|
||||||
|
if (_disc != null && _disc.getColumns().length > 0) {
|
||||||
|
type = res.getObject(_disc.getColumns()[0], null, state.joins);
|
||||||
|
ClassMapping sup = (ClassMapping) getMetaData();
|
||||||
|
ClassMapping[] subs = sup.getMappedPCSubclassMappings();
|
||||||
|
for (ClassMapping sub : subs) {
|
||||||
|
if (sub.getDiscriminator().getValue().equals(type))
|
||||||
|
return sub.getDescribedType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
type = getValue().load(ctx, state, res);
|
||||||
return type.getClass();
|
return type.getClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void calculateValue(Select sel, ExpContext ctx, ExpState state,
|
public void calculateValue(Select sel, ExpContext ctx, ExpState state,
|
||||||
Val other, ExpState otherState) {
|
Val other, ExpState otherState) {
|
||||||
super.calculateValue(sel, ctx, state, null, null);
|
super.calculateValue(sel, ctx, state, null, null);
|
||||||
if (_disc != null)
|
|
||||||
_disc.select(sel, (ClassMapping) getMetaData());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void select(Select sel, ExpContext ctx, ExpState state,
|
public void select(Select sel, ExpContext ctx, ExpState state,
|
||||||
boolean pks) {
|
boolean pks) {
|
||||||
getValue().select(sel, ctx, state, pks);
|
if (_disc != null && _disc.getColumns().length > 0)
|
||||||
|
sel.select(_disc.getColumns(), state.joins);
|
||||||
|
else
|
||||||
|
getValue().select(sel, ctx, state, pks);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void appendTo(Select sel, ExpContext ctx, ExpState state,
|
public void appendTo(Select sel, ExpContext ctx, ExpState state,
|
||||||
|
|
|
@ -95,7 +95,7 @@ public class TestSpec10_1_26_Ex3 extends SQLListenerTestCase {
|
||||||
|
|
||||||
// test ORDER BY qualified path
|
// test ORDER BY qualified path
|
||||||
query = "select KEY(e), KEY(e).fName from Department d, " +
|
query = "select KEY(e), KEY(e).fName from Department d, " +
|
||||||
" in (d.emps) e order by d.deptId";
|
" in (d.emps) e order by KEY(e).fName";
|
||||||
q = em.createQuery(query);
|
q = em.createQuery(query);
|
||||||
if (inMemory)
|
if (inMemory)
|
||||||
setCandidate(q, Department.class);
|
setCandidate(q, Department.class);
|
||||||
|
|
Loading…
Reference in New Issue