}
}
@Override
protected void visit(SelectStmt s) throws VisitException {
SymbolTable outTable = null;
mSelectNestingDepth++;
// Visiting a source pushes one or more symbol tables on the stack,
// declaring the fields of this source. While visiting our clauses, we
// also push a symbol table declaring the names of any windows defined
// with WINDOW .. AS clauses. Make sure we pop them on our way out by
// resetting the stack to its current height.
int symbolStackHeight = mSymTableContext.size();
SymbolTable originalSymtab = mSymTableContext.top();
try {
// Visit the window clauses first; if their types are okay, create a new
// symbol table to use when visiting our sources, that contains the
// window names.
SymbolTable symbolsForSources = new HashSymbolTable(originalSymtab);
List<WindowDef> windowDefs = s.getWindowDefs();
for (WindowDef def : windowDefs) {
def.accept(this);
symbolsForSources.addSymbol(new WindowSymbol(def.getName(), def.getWindowSpec()));
}
mSymTableContext.push(symbolsForSources);
// Now visit the sources, with the symbols for any windows pushed.
SQLStatement source = s.getSource();
visitValidSource(source);
SymbolTable exprTable = mSymTableContext.top();
outTable = new HashSymbolTable(originalSymtab);
// The "stream name" representing this SELECT stmt in the parent
// statement.
String stmtAlias = s.getAlias();
// Nested SELECT statements require an alias.
if (mSelectNestingDepth > 1 && null == stmtAlias) {
throw new TypeCheckException("Each derived stream must have its own alias.");
}
// Type check all the selected expressions using the symbols from our source.
for (AliasedExpr aliasedExpr : s.getSelectExprs()) {
aliasedExpr.accept(this);
// Add our output symbols to the output symbol table.
if (aliasedExpr.getExpr() instanceof AllFieldsExpr) {
// Add all symbols in the source's table into this one,
// to add fields pulled in by the "*" operator.
// Resolve away all aliased symbols to their final version, and rename
// any "qualifier.field" -> "field".
Iterator<Symbol> sourceSymbols = exprTable.levelIterator();
while (sourceSymbols.hasNext()) {
Symbol srcSym = sourceSymbols.next().resolveAliases();
String symName = StringUtils.dequalify(srcSym.getName());
if (null != stmtAlias) {