DbRelationship dbRel = rel.getDbRelationships().get(0);
List joins = dbRel.getJoins();
int len = joins.size();
for (int i = 0; i < len; i++) {
DbJoin join = (DbJoin) joins.get(i);
DbAttribute src = join.getSource();
appendColumn(columns, null, src, attributes, null);
}
}
};
if (query.isResolvingInherited()) {
descriptor.visitAllProperties(visitor);
}
else {
descriptor.visitProperties(visitor);
}
// add remaining needed attrs from DbEntity
DbEntity table = getRootDbEntity();
for (final DbAttribute dba : table.getPrimaryKeys()) {
appendColumn(columns, null, dba, attributes, null);
}
// special handling of a disjoint query...
// TODO, Andrus 11/17/2005 - resultPath mechanism is generic and should probably
// be moved in the superclass (SelectQuery), replacing customDbAttributes.
if (query instanceof PrefetchSelectQuery) {
Iterator extraPaths = ((PrefetchSelectQuery) query)
.getResultPaths()
.iterator();
// for each relationship path add closest FK or PK, for each attribute path,
// add specified column
while (extraPaths.hasNext()) {
String path = (String) extraPaths.next();
Expression pathExp = oe.translateToDbPath(Expression.fromString(path));
Iterator<CayenneMapEntry> it = table.resolvePathComponents(pathExp);
// add joins and find terminating element
CayenneMapEntry pathComponent = null;
while (it.hasNext()) {
pathComponent = it.next();
// do not add join for the last DB Rel
if (it.hasNext() && pathComponent instanceof DbRelationship) {
dbRelationshipAdded((DbRelationship) pathComponent);
}
}
String labelPrefix = pathExp.toString().substring("db:".length());
// process terminating element
if (pathComponent instanceof DbAttribute) {
// label prefix already includes relationship name
appendColumn(
columns,
null,
(DbAttribute) pathComponent,
attributes,
labelPrefix);
}
else if (pathComponent instanceof DbRelationship) {
DbRelationship relationship = (DbRelationship) pathComponent;
// add last join
if (relationship.isToMany()) {
dbRelationshipAdded(relationship);
}
for (DbJoin j : relationship.getJoins()) {
DbAttribute attribute = relationship.isToMany()
? j.getTarget()
: j.getSource();
// note that we my select a source attribute, but label it as
// target for simplified snapshot processing
appendColumn(columns, null, attribute, attributes, labelPrefix
+ '.'
+ j.getTargetName());
}
}
}
}
// handle joint prefetches directly attached to this query...
if (query.getPrefetchTree() != null) {
for (PrefetchTreeNode prefetch : query.getPrefetchTree().adjacentJointNodes()) {
// for each prefetch add all joins plus columns from the target entity
Expression prefetchExp = Expression.fromString(prefetch.getPath());
Expression dbPrefetch = oe.translateToDbPath(prefetchExp);
Iterator it = table.resolvePathComponents(dbPrefetch);
DbRelationship r = null;
while (it.hasNext()) {
r = (DbRelationship) it.next();
dbRelationshipAdded(r);
}
if (r == null) {
throw new CayenneRuntimeException("Invalid joint prefetch '"
+ prefetch
+ "' for entity: "
+ oe.getName());
}
// add columns from the target entity, skipping those that are an FK to
// source entity
Collection skipColumns = Collections.EMPTY_LIST;
if (r.getSourceEntity() == table) {
skipColumns = new ArrayList(2);
Iterator joins = r.getJoins().iterator();
while (joins.hasNext()) {
DbJoin join = (DbJoin) joins.next();
if (attributes.contains(join.getSource())) {
skipColumns.add(join.getTarget());
}
}
}
// go via target OE to make sure that Java types are mapped correctly...