private AbstractExpression generateProjectionColumnExpression(
ParsedSelectStmt.ParsedColInfo outputCol,
List<Integer> sourceColumns) throws CloneNotSupportedException
{
Stack<AbstractExpression> stack = new Stack<AbstractExpression>();
AbstractExpression expression = (AbstractExpression) outputCol.expression.clone();
AbstractExpression currExp = expression;
while (currExp != null) {
// Found an aggregate expression. This is already computed by
// an earlier plannode and the column should be directly in
// the output columns. Look it up by the column alias.
// We don't actually need to do the work in this if but this
// allows the planner to barf if the aggregate column doesn't
// exist.
if (currExp instanceof AggregateExpression)
{
boolean found = false;
int offset = 0;
for (Integer colguid : sourceColumns) {
PlanColumn plancol = m_context.get(colguid);
/* System.out.printf("Expression: %s/%s. Candidate column: %s/%s\n",
tve.getColumnAlias(), tve.getTableName(),
plancol.originColumnName(), plancol.originTableName()); */
if (outputCol.alias.equals(plancol.getDisplayName()))
{
found = true;
expression = (AbstractExpression) plancol.m_expression.clone();
assert(expression instanceof TupleValueExpression);
TupleValueExpression tve = (TupleValueExpression) expression;
tve.setColumnIndex(offset);
break;
}
++offset;
}
if (!found) {
LOG.error("PLANNER ERROR: could not match aggregate column alias");
LOG.error(getSQLText());
throw new RuntimeException("Could not match aggregate column alias.");
}
break;
}
// found a TVE - calculate its offset into the sourceColumns
else if (currExp instanceof TupleValueExpression) {
TupleValueExpression tve = (TupleValueExpression)currExp;
boolean found = false;
int offset = 0;
for (Integer colguid : sourceColumns) {
PlanColumn plancol = m_context.get(colguid);
/* System.out.printf("Expression: %s/%s. Candidate column: %s/%s\n",
tve.getColumnAlias(), tve.getTableName(),
plancol.originColumnName(), plancol.originTableName()); */
if (tve.getColumnName().equals(plancol.originColumnName()) &&
tve.getTableName().equals(plancol.originTableName()))
{
tve.setColumnIndex(offset);
found = true;
break;
}
++offset;
}
if (!found) {
// rtb: would like to throw here but doing so breaks sqlcoverage suite.
// for now - make this error obvious at least.
LOG.error("PLANNER ERROR: could not match tve column alias");
LOG.error(getSQLText());
throw new RuntimeException("Could not match TVE column alias.");
}
}
// save rhs. process lhs. when lhs is leaf, process a rhs.
if (currExp.getRight() != null) {
stack.push(currExp.getRight());
}
currExp = currExp.getLeft();
if (currExp == null) {
if (!stack.empty())
currExp = stack.pop();
}
}