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:
Catalina Wei 2009-04-09 05:11:20 +00:00
parent 2901ea6e52
commit be8731aafa
4 changed files with 39 additions and 47 deletions

View File

@ -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) {

View File

@ -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

View File

@ -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,25 +46,36 @@ 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) {
if (_disc != null && _disc.getColumns().length > 0)
sel.select(_disc.getColumns(), state.joins);
else
getValue().select(sel, ctx, state, pks); getValue().select(sel, ctx, state, pks);
} }

View File

@ -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);