@Override
  public void visit(Column column) {
    // extract type for the column
    String tableSchemaName = _tan.getSchemaName(ParserUtil.getComponentName(column.getTable()));
    String columnName = column.getColumnName();
    TypeConversion tc = _schema.getType(tableSchemaName, columnName);

    // extract the position (index) of the required column
    int position =
        HierarchyExtractor.extractComponentIndex(
            column, _affectedComponent, _queryPlan, _schema, _tan);

    ValueExpression ve = new ColumnReference(tc, position);
    _exprStack.push(ve);
  }
  private int attachToQueryPlan() {
    if (_aggOps.isEmpty()) {
      ProjectionOperator project = new ProjectionOperator(_selectExpr);
      _affectedComponent.setProjection(project);
      return NON_AGG;
    } else if (_aggOps.size() == 1) {
      // all the others are group by
      AggregateOperator firstAgg = _aggOps.get(0);

      if (ParserUtil.isAllColumnRefs(_selectExpr)) {
        // plain fields in select
        List<Integer> groupByColumns = ParserUtil.extractColumnIndexes(_selectExpr);
        firstAgg.setGroupByColumns(groupByColumns);

        // Setting new level of components is necessary for correctness only for distinct in
        // aggregates
        //  but it's certainly pleasant to have the final result grouped on nodes by group by
        // columns.
        boolean newLevel = !(HierarchyExtractor.isHashedBy(_affectedComponent, groupByColumns));
        if (newLevel) {
          _affectedComponent.setHashIndexes(groupByColumns);
          OperatorComponent newComponent =
              new OperatorComponent(
                      _affectedComponent, ParserUtil.generateUniqueName("OPERATOR"), _queryPlan)
                  .setAggregation(firstAgg);

          // this now becomes "active component"
          _affectedComponent = newComponent;
        } else {
          _affectedComponent.setAggregation(firstAgg);
        }
      } else {
        // Sometimes selectExpr contains other functions, so we have to use projections instead of
        // simple groupBy
        // Check for complexity
        if (_affectedComponent.getHashExpressions() != null
            && !_affectedComponent.getHashExpressions().isEmpty()) {
          throw new RuntimeException(
              "Too complex: cannot have hashExpression both for joinCondition and groupBy!");
        }

        // WARNING: _selectExpr cannot be used on two places: that's why we do deep copy
        _affectedComponent.setHashExpressions((List<ValueExpression>) DeepCopy.copy(_selectExpr));

        // always new level
        ProjectionOperator groupByProj =
            new ProjectionOperator((List<ValueExpression>) DeepCopy.copy(_selectExpr));
        firstAgg.setGroupByProjection(groupByProj);
        OperatorComponent newComponent =
            new OperatorComponent(
                    _affectedComponent, ParserUtil.generateUniqueName("OPERATOR"), _queryPlan)
                .setAggregation(firstAgg);

        // this now becomes "active component"
        _affectedComponent = newComponent;
      }
      return AGG;
    } else {
      throw new RuntimeException("For now only one aggregate function supported!");
    }
  }