Program: 30730
Project: 30730
Buggy source:
/** 
 * Rewrites order by clause to achieve simple column resolution for model parser. Order by must never reference column that doesn't exist in its own select list. <p> Because order by clause logically executes after "select" it must be able to reference results of arithmetic expression, aggregation function results, arithmetic with aggregation results and analytic functions. Somewhat contradictory to this order by must also be able to reference columns of table or sub-query that are not even in select clause.
 * @param model inbound model
 * @return outbound model
 * @throws ParserException when column names are ambiguos or not found at all.
 */
private QueryModel rewriteOrderBy(QueryModel model) throws ParserException {
  QueryModel result=model;
  QueryModel base=model;
  QueryModel baseParent=model;
  QueryModel wrapper=null;
  final int modelColumnCount=model.getColumns().size();
  boolean groupBy=false;
  while (base.getColumns().size() > 0) {
    baseParent=base;
    base=base.getNestedModel();
    groupBy=groupBy || baseParent.getSelectModelType() == QueryModel.SELECT_MODEL_GROUP_BY;
  }
  ObjList<ExprNode> orderByNodes=base.getOrderBy();
  int sz=orderByNodes.size();
  if (sz > 0) {
    boolean ascendColumns=true;
    for (int i=0; i < sz; i++) {
      final ExprNode orderBy=orderByNodes.getQuick(i);
      final String column=orderBy.token;
      final int dot=column.indexOf('.');
      if (dot > -1 || !model.getColumnNameTypeMap().contains(column)) {
        getIndexOfTableForColumn(base,column,dot,orderBy.position);
        if (ascendColumns && base != model) {
          final CharSequenceObjHashMap<String> map=baseParent.getColumnToAliasMap();
          int index=map.keyIndex(column);
          if (index > -1) {
            if (dot > -1) {
              index=map.keyIndex(column,dot + 1,column.length());
            }
 else {
              index=map.keyIndex(column);
            }
          }
          if (index < 0) {
            orderBy.token=map.valueAt(index);
          }
 else {
            if (groupBy) {
              ascendColumns=false;
            }
 else {
              if (baseParent.getSelectModelType() != QueryModel.SELECT_MODEL_CHOOSE) {
                QueryModel synthetic=queryModelPool.next();
                synthetic.setSelectModelType(QueryModel.SELECT_MODEL_CHOOSE);
                for (int j=0, z=baseParent.getColumns().size(); j < z; j++) {
                  synthetic.addColumn(baseParent.getColumns().getQuick(j));
                }
                synthetic.setNestedModel(base);
                baseParent.setNestedModel(synthetic);
                baseParent=synthetic;
              }
              String alias=createColumnAlias(column,dot,baseParent.getColumnNameTypeMap());
              baseParent.addColumn(queryColumnPool.next().of(alias,0,exprNodePool.next().of(ExprNode.LITERAL,column,0,0)));
              if (model != baseParent) {
                QueryColumn col=queryColumnPool.next().of(alias,0,exprNodePool.next().of(ExprNode.LITERAL,alias,0,0));
                QueryModel m=model;
                do {
                  m.addColumn(col);
                  m=m.getNestedModel();
                }
 while (m != baseParent);
              }
              orderBy.token=alias;
              if (wrapper == null) {
                wrapper=queryModelPool.next();
                wrapper.setSelectModelType(QueryModel.SELECT_MODEL_CHOOSE);
                for (int j=0; j < modelColumnCount; j++) {
                  String refAlias=model.getColumns().getQuick(j).getAlias();
                  wrapper.addColumn(queryColumnPool.next().of(refAlias,0,exprNodePool.next().of(ExprNode.LITERAL,refAlias,0,0)));
                }
                result=wrapper;
                wrapper.setNestedModel(model);
              }
            }
          }
        }
      }
      if (ascendColumns && base != model) {
        model.addOrderBy(orderBy,base.getOrderByDirection().getQuick(i));
      }
    }
    if (base != model) {
      base.clearOrderBy();
    }
  }
  QueryModel nested=base.getNestedModel();
  if (nested != null) {
    QueryModel rewritten=rewriteOrderBy(nested);
    if (rewritten != nested) {
      base.setNestedModel(rewritten);
    }
  }
  ObjList<QueryModel> joinModels=base.getJoinModels();
  for (int i=1, n=joinModels.size(); i < n; i++) {
    rewriteOrderBy(joinModels.getQuick(i));
  }
  return result;
}

Fixed version (ground truth):
/** 
 * Rewrites order by clause to achieve simple column resolution for model parser. Order by must never reference column that doesn't exist in its own select list. <p> Because order by clause logically executes after "select" it must be able to reference results of arithmetic expression, aggregation function results, arithmetic with aggregation results and analytic functions. Somewhat contradictory to this order by must also be able to reference columns of table or sub-query that are not even in select clause.
 * @param model inbound model
 * @return outbound model
 * @throws ParserException when column names are ambiguos or not found at all.
 */
private QueryModel rewriteOrderBy(QueryModel model) throws ParserException {
  QueryModel result=model;
  QueryModel base=model;
  QueryModel baseParent=model;
  QueryModel wrapper=null;
  final int modelColumnCount=model.getColumns().size();
  boolean groupBy=false;
  while (base.getColumns().size() > 0) {
    baseParent=base;
    base=base.getNestedModel();
    groupBy=groupBy || baseParent.getSelectModelType() == QueryModel.SELECT_MODEL_GROUP_BY;
  }
  ObjList<ExprNode> orderByNodes=base.getOrderBy();
  int sz=orderByNodes.size();
  if (sz > 0) {
    boolean ascendColumns=true;
    for (int i=0; i < sz; i++) {
      final ExprNode orderBy=orderByNodes.getQuick(i);
      final String column=orderBy.token;
      final int dot=column.indexOf('.');
      if (dot > -1 || !model.getColumnNameTypeMap().contains(column)) {
        getIndexOfTableForColumn(base,column,dot,orderBy.position);
        if (ascendColumns && base != model) {
          final CharSequenceObjHashMap<String> map=baseParent.getColumnToAliasMap();
          int index=map.keyIndex(column);
          if (index > -1) {
            if (dot > -1) {
              index=map.keyIndex(column,dot + 1,column.length());
            }
 else {
              index=map.keyIndex(column);
            }
          }
          if (index < 0) {
            orderBy.token=map.valueAt(index);
          }
 else {
            if (groupBy) {
              ascendColumns=false;
            }
 else {
              if (baseParent.getSelectModelType() != QueryModel.SELECT_MODEL_CHOOSE) {
                QueryModel synthetic=queryModelPool.next();
                synthetic.setSelectModelType(QueryModel.SELECT_MODEL_CHOOSE);
                for (int j=0, z=baseParent.getColumns().size(); j < z; j++) {
                  synthetic.addColumn(baseParent.getColumns().getQuick(j));
                }
                synthetic.setNestedModel(base);
                baseParent.setNestedModel(synthetic);
                baseParent=synthetic;
              }
              String alias=createColumnAlias(column,dot,baseParent.getColumnNameTypeMap());
              baseParent.addColumn(queryColumnPool.next().of(alias,exprNodePool.next().of(ExprNode.LITERAL,column,0,0)));
              if (model != baseParent) {
                QueryColumn col=queryColumnPool.next().of(alias,exprNodePool.next().of(ExprNode.LITERAL,alias,0,0));
                QueryModel m=model;
                do {
                  m.addColumn(col);
                  m=m.getNestedModel();
                }
 while (m != baseParent);
              }
              orderBy.token=alias;
              if (wrapper == null) {
                wrapper=queryModelPool.next();
                wrapper.setSelectModelType(QueryModel.SELECT_MODEL_CHOOSE);
                for (int j=0; j < modelColumnCount; j++) {
                  String refAlias=model.getColumns().getQuick(j).getAlias();
                  wrapper.addColumn(queryColumnPool.next().of(refAlias,exprNodePool.next().of(ExprNode.LITERAL,refAlias,0,0)));
                }
                result=wrapper;
                wrapper.setNestedModel(model);
              }
            }
          }
        }
      }
      if (ascendColumns && base != model) {
        model.addOrderBy(orderBy,base.getOrderByDirection().getQuick(i));
      }
    }
    if (base != model) {
      base.clearOrderBy();
    }
  }
  QueryModel nested=base.getNestedModel();
  if (nested != null) {
    QueryModel rewritten=rewriteOrderBy(nested);
    if (rewritten != nested) {
      base.setNestedModel(rewritten);
    }
  }
  ObjList<QueryModel> joinModels=base.getJoinModels();
  for (int i=1, n=joinModels.size(); i < n; i++) {
    rewriteOrderBy(joinModels.getQuick(i));
  }
  return result;
}