public ExpState initialize(Select sel, ExpContext ctx, int flags) {
PathExpState pstate = new PathExpState(sel.newJoins());
boolean key = false;
boolean forceOuter = false;
ClassMapping rel = _candidate;
sel.setSchemaAlias(_schemaAlias);
// iterate to the final field
ClassMapping owner;
ClassMapping from, to;
Action action;
Variable var;
Iterator itr = (_actions == null) ? null : _actions.iterator();
FieldMapping field = null;
Action prevaction = null;
boolean isCorrelatedPath = false;
boolean fromParentRootInSubselect = navigateFromParentRootInSubselect(sel);
while (itr != null && itr.hasNext()) {
action = (Action) itr.next();
// treat subqueries like variables for alias generation purposes
if (action.op == Action.VAR) {
if (sel.getParent() != null && action.var != null &&
prevaction != null && prevaction.data != null &&
sel.ctx().getVariable(action.var) == null) {
isCorrelatedPath = true;
pstate.joins = pstate.joins.setCorrelatedVariable(action.var);
} else
pstate.joins = pstate.joins.setVariable((String) action.data);
}
else if (action.op == Action.SUBQUERY) {
pstate.joins = pstate.joins.setSubselect((String) action.data);
}
else if (action.op == Action.UNBOUND_VAR) {
// unbound vars are cross-joined to the candidate table
var = (Variable) action.data;
rel = (ClassMapping) var.getMetaData();
if (rel == null)
throw new IllegalArgumentException(_loc.get(
"invalid-unbound-var", var.getName()).toString());
if (sel.getParent() != null && action.var != null &&
sel.ctx().getVariable(action.var) == null) {
//System.out.println("Correlated action var="+action.var);
isCorrelatedPath = true;
pstate.joins = pstate.joins.setCorrelatedVariable(var.getName());
} else
pstate.joins = pstate.joins.setVariable(var.getName());
pstate.joins = pstate.joins.crossJoin(_candidate.getTable(),
rel.getTable());
if (!itr.hasNext() && isVariable()) {
checkObjectPathInheritanceTypeJoined(pstate);
}
} else {
// move past the previous field, if any
field = (FieldMapping) ((action.op == Action.GET_XPATH) ?
_xmlfield : action.data);
if (pstate.field != null) {
// if this is the second-to-last field and the last is
// the related field this field joins to, no need to
// traverse: just use this field's fk columns
if (!itr.hasNext() && (flags & JOIN_REL) == 0
&& isJoinedField(pstate.field, key, field)) {
pstate.cmpfield = field;
break;
}
if (fromParentRootInSubselect) {
isCorrelatedPath = true;
pstate.joins = pstate.joins.setCorrelatedVariable(_schemaAlias);
pstate.joins.setJoinContext(null);
}
rel = traverseField(pstate, key, forceOuter ||
ctx.store.getDBDictionary().fullResultCollectionInOrderByRelation, 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;
if (key && itr.hasNext())
_keyPath = true;
// get mapping for the current field
pstate.field = field;
owner = pstate.field.getDefiningMapping();
if (pstate.field.getManagement()
!= FieldMapping.MANAGE_PERSISTENT)
throw new UserException(_loc.get("non-pers-field",
pstate.field));
// find the most-derived type between the declared relation
// type and the field's owner, and join from that type to
// the lesser derived type
if (rel != owner && rel != null) {
if (rel.getDescribedType().isAssignableFrom
(owner.getDescribedType())) {
from = owner;
to = rel;
} else {
from = rel;
to = owner;
}
for (; from != null && from != to;
from = from.getJoinablePCSuperclassMapping()) {
FieldMapping cast = from.getFieldMapping(pstate.field
.getName());
if (cast != null)
pstate.field = cast;
pstate.joins = from.joinSuperclass(pstate.joins, false);
}
}
// nothing more to do from here on as we encountered an xpath
// action
if (action.op == Action.GET_XPATH)