public Object process(Node nd, Stack<Node> stack,
NodeProcessorCtx procCtx, Object... nodeOutputs)
throws SemanticException
{
TypeCheckCtx ctx = (TypeCheckCtx) procCtx;
ExprNodeDesc desc = TypeCheckProcFactory.processGByExpr(nd, procCtx);
if (desc != null)
{
// Here we know nd represents a group by expression.
// During the DFS traversal of the AST, a descendant of nd
// likely set an
// error because a sub-tree of nd is unlikely to also be a group
// by
// expression. For example, in a query such as
// SELECT *concat(key)* FROM src GROUP BY concat(key), 'key'
// will be
// processed before 'concat(key)' and since 'key' is not a group
// by
// expression, an error will be set in ctx by
// ColumnExprProcessor.
// We can clear the global error when we see that it was set in
// a
// descendant node of a group by expression because
// processGByExpr() returns a ExprNodeDesc that effectively
// ignores
// its children. Although the error can be set multiple times by
// descendant nodes, DFS traversal ensures that the error only
// needs to
// be cleared once. Also, for a case like
// SELECT concat(value, concat(value))... the logic still works
// as the
// error is only set with the first 'value'; all node pocessors
// quit
// early if the global error is set.
if (isDescendant(nd, ctx.getErrorSrcNode()))
{
ctx.setError(null, null);
}
return desc;
}
if (ctx.getError() != null)
{
return null;
}
ASTNode expr = (ASTNode) nd;
// If the first child is a TOK_TABLE_OR_COL, and nodeOutput[0] is
// NULL,
// and the operator is a DOT, then it's a table column reference.
if (expr.getType() == Windowing2Parser.DOT
&& expr.getChild(0).getType() == Windowing2Parser.TABLEORCOL
&& nodeOutputs[0] == null)
{
RowResolver input = ctx.getInputRR();
String tableAlias = BaseSemanticAnalyzer
.unescapeIdentifier(expr.getChild(0).getChild(0)
.getText());
// NOTE: tableAlias must be a valid non-ambiguous table alias,
// because we've checked that in TOK_TABLE_OR_COL's process
// method.
ColumnInfo colInfo = input.get(tableAlias,
((ExprNodeConstantDesc) nodeOutputs[1]).getValue()
.toString());
if (colInfo == null)
{
ctx.setError(
ErrorMsg.INVALID_COLUMN.getMsg(expr.getChild(1)),
expr);
return null;
}
return new ExprNodeColumnDesc(colInfo.getType(),