if (!field.isPersistent())
{
continue;
}
Operator op = field.getOperator();
if (op != null)
{
if (op.getType() instanceof Primitive)
{
field.setBind(m_adapter.getBind((Primitive)op.getType()));
}
}
else
{
Column column = ((RelationalPrimitiveMapping)field.getAttributeMapping()).getColumn();
SQLJoin join = addTable(query, column.getTable());
join.isEnabled = true;
field.setMapping(join);
field.setItem(column);
field.setConverter(m_adapter.getConverter((Primitive)field.getAttribute().getType(), column));
field.setBind(m_adapter.getBind(column));
}
// Add the output columns to the join
if (field.isOutput() && field.getBind() != null)
{
addOutputField(field);
}
}
assert query.getMapping() != null;
}
return true;
}
public boolean postVisit(final Query query)
{
if (query.isMatch()) // only postprocess operators if any require it
{
opVisit(query);
}
// Determine if a subquery should be generated
Operator where = query.getWhere();
if (where != null && !query.isRoot() && !query.isQuantorRoot())
{
for (Iterator itr = query.getAssocIterator(Query.ASSOC_WHERE); itr.hasNext();)
{
Query assoc = (Query)itr.next();
if (assoc.isSameRoot(query))
{
SQLJoin join = (SQLJoin)assoc.getMapping();
do
{
if (join.isEnabled)
{
query.setSubquery(true);
break;
}
join = join.parent;
}
while (join != query.getMapping());
}
}
if (!query.isSubquery())
{
where.visit(new Operator.Visitor()
{
public boolean visit(Operator op)
{
if (!m_adapter.isJoinSupported(query, op))
{
query.setSubquery(true);
return false;
}
return true;
}
public boolean isEligible(Operator op)
{
return !op.isConstant();
}
}, Operator.VISIT_POSTORDER);
}
}
return true;
}
/**
* Visit all operators of a query.
* @param query The query which operators to visit.
*/
private void opVisit(final Query query)
{
// list of seen objects to corresponding SQLJoins, of max possible size,
// seenObjectList{MatchOperator1, SQLJoin1, MatchOperator2, SQLJoin2, ...}
// cannot do lazy init because Visitor requires object to be final
final List seenObjectList = new ArrayList(query.getFieldCount());
Operator.Visitor visitor = new Operator.Visitor()
{
public boolean isEligible(Operator op)
{
return true; // visit all operators as they might contain MatchOperator in branch
}
public boolean visit(Operator op)
{
if (!(op instanceof MatchOperator))
{
return true; // visit other branches and look for MatchOperators
}
MatchOperator matchOp = (MatchOperator)op;
SQLJoin join = null;
for (int i = 0, nCount = seenObjectList.size();
i < nCount && join == null;
i += 2)
{
MatchOperator seenOp = (MatchOperator)seenObjectList.get(i);
if (seenOp.getAttribute().getSource() == matchOp.getAttribute().getSource() &&
seenOp.getExpression().equals(matchOp.getExpression()))
{
join = (SQLJoin)seenObjectList.get(i + 1);
}
}
// optimize for the case where same join table is used multiple times
// by reusing it in any other operators of the same query
if (join != null)
{
matchOp.setMapping(join);
}
else // if null then not seen before or no join table created
{
Source source = matchOp.getAttribute().getSource();
Table table = m_adapter.getMatchJoin(
((RelationalPrimitiveMapping)source.getAttributeMapping()).getColumn(),
matchOp.getExpression());
if (table != null) // if adapter needs a table join
{
join = addTable(source.getQuery(), table);
join.isEnabled = true; // enable and set operator value to join alias
matchOp.setMapping(join); // for s_appenderArray...appendOperator()
seenObjectList.add(matchOp); // store join to reuse later
seenObjectList.add(join); // store join to reuse later
}
}
return true; // visit all branches on this level
}
};
Operator whereOp = query.getWhere();
if (whereOp != null) // only dereference if there is a "where" condition
{
whereOp.visit(visitor, Operator.VISIT_PREORDER);
}
for (int i = 0, nCount = query.getOrderByCount(); i < nCount; ++i)
{
query.getOrderByOperator(i).visit(visitor, Operator.VISIT_PREORDER);