Program: 96064
Project: 96064
Buggy source:
/** 
 * Parses a depth-one select statement. If there exist subqueries, this function will be called recursively.
 */
@Override public ExactRelation visitQuery_specification(VerdictSQLParser.Query_specificationContext ctx){
  List<ExactRelation> tableSources=new ArrayList<ExactRelation>();
  for (  Table_sourceContext s : ctx.table_source()) {
    TableSourceExtractor e=new TableSourceExtractor();
    ExactRelation r1=e.visit(s);
    tableSources.add(r1);
  }
  Cond where=null;
  if (ctx.WHERE() != null) {
    where=Cond.from(vc,ctx.where);
    ColNameResolver resolver=new ColNameResolver(tableAliasAndColNames);
    where=resolver.visit(where);
  }
  ExactRelation joinedTabeSource=null;
  while (where != null && tableSources.size() > 0) {
    Pair<Cond,Pair<ExactRelation,ExactRelation>> joinCondAndTabName=where.searchForJoinCondition(tableSources);
    if (joinCondAndTabName == null) {
      break;
    }
    Cond joinCond=joinCondAndTabName.getKey();
    Pair<ExactRelation,ExactRelation> pairsToJoin=joinCondAndTabName.getValue();
    List<ExactRelation> newTableSources=new ArrayList<ExactRelation>();
    ExactRelation joined=JoinedRelation.from(vc,pairsToJoin.getLeft(),pairsToJoin.getRight(),joinCond);
    newTableSources.add(joined);
    for (    ExactRelation t : tableSources) {
      if (t != pairsToJoin.getLeft() && t != pairsToJoin.getRight()) {
        newTableSources.add(t);
      }
    }
    tableSources=newTableSources;
    where=where.remove(joinCond);
  }
  for (  ExactRelation r : tableSources) {
    if (joinedTabeSource == null) {
      joinedTabeSource=r;
    }
 else {
      joinedTabeSource=new JoinedRelation(vc,joinedTabeSource,r,null);
    }
  }
  if (where != null) {
    joinedTabeSource=new FilteredRelation(vc,joinedTabeSource,where);
  }
  SelectListExtractor select=new SelectListExtractor();
  Triple<List<SelectElem>,List<SelectElem>,List<SelectElem>> elems=select.visit(ctx.select_list());
  List<SelectElem> nonaggs=elems.getLeft();
  List<SelectElem> aggs=elems.getMiddle();
  List<SelectElem> bothInOrder=elems.getRight();
  TableSourceResolver resolver=new TableSourceResolver(vc,tableAliasAndColNames);
  nonaggs=replaceTableNamesWithAliasesIn(nonaggs,resolver);
  aggs=replaceTableNamesWithAliasesIn(aggs,resolver);
  bothInOrder=replaceTableNamesWithAliasesIn(bothInOrder,resolver);
  selectElems=bothInOrder;
  if (aggs.size() == 0) {
    joinedTabeSource=new ProjectedRelation(vc,joinedTabeSource,bothInOrder);
  }
 else {
    if (ctx.GROUP() != null) {
      List<Expr> groupby=new ArrayList<Expr>();
      for (      Group_by_itemContext g : ctx.group_by_item()) {
        Expr gexpr=resolver.visit(Expr.from(vc,g.expression()));
        boolean aliasFound=false;
        if (!aliasFound) {
          groupby.add(gexpr);
        }
      }
      joinedTabeSource=new GroupedRelation(vc,joinedTabeSource,groupby);
    }
    joinedTabeSource=new AggregatedRelation(vc,joinedTabeSource,bothInOrder);
  }
  return joinedTabeSource;
}

Fixed version (ground truth):
/** 
 * Parses a depth-one select statement. If there exist subqueries, this function will be called recursively.
 */
@Override public ExactRelation visitQuery_specification(VerdictSQLParser.Query_specificationContext ctx){
  List<ExactRelation> tableSources=new ArrayList<ExactRelation>();
  for (  Table_sourceContext s : ctx.table_source()) {
    TableSourceExtractor e=new TableSourceExtractor();
    ExactRelation r1=e.visit(s);
    tableSources.add(r1);
  }
  Cond where=null;
  if (ctx.WHERE() != null) {
    where=Cond.from(vc,ctx.where);
    ColNameResolver resolver=new ColNameResolver(tableAliasAndColNames);
    where=resolver.visit(where);
  }
  ExactRelation joinedTableSource=null;
  Map<Set<ExactRelation>,List<Cond>> joinMap=new HashMap<>();
  while (where != null) {
    Pair<Cond,Pair<ExactRelation,ExactRelation>> joinCondAndTabName=where.extractJoinCondition(tableSources);
    if (joinCondAndTabName == null) {
      break;
    }
    Set<ExactRelation> joinTableSet=new HashSet<>();
    joinTableSet.add(joinCondAndTabName.getRight().getLeft());
    joinTableSet.add(joinCondAndTabName.getRight().getRight());
    if (!joinMap.containsKey(joinTableSet)) {
      joinMap.put(joinTableSet,new ArrayList<Cond>());
    }
    List<Cond> joinCondList=joinMap.get(joinTableSet);
    joinCondList.add(joinCondAndTabName.getLeft());
    Cond joinCond=joinCondAndTabName.getKey();
    where=where.remove(joinCond);
  }
  for (  Set<ExactRelation> joinSet : joinMap.keySet()) {
    List<Cond> joinCondList=joinMap.get(joinSet);
    Cond joinCond=null;
    if (joinCondList.size() == 1) {
      joinCond=joinCondList.get(0);
    }
 else {
      joinCond=AndCond.from(joinCondList.get(0),joinCondList.get(1));
      for (int i=2; i < joinCondList.size(); ++i) {
        joinCond=AndCond.from(joinCond,joinCondList.get(i));
      }
    }
    ExactRelation[] joinSetArray=new ExactRelation[2];
    joinSet.toArray(joinSetArray);
    ExactRelation left=joinSetArray[0];
    ExactRelation right=joinSetArray[1];
    for (    ExactRelation r : tableSources) {
      if (r instanceof JoinedRelation) {
        JoinedRelation j=(JoinedRelation)r;
        if (j.containsRelation(left,left.getAlias())) {
          left=r;
          break;
        }
      }
    }
    for (    ExactRelation r : tableSources) {
      if (r instanceof JoinedRelation) {
        JoinedRelation j=(JoinedRelation)r;
        if (j.containsRelation(right,right.getAlias())) {
          right=r;
          break;
        }
      }
    }
    ExactRelation joined=JoinedRelation.from(vc,left,right,joinCond);
    List<ExactRelation> newTableSources=new ArrayList<>();
    newTableSources.add(joined);
    for (    ExactRelation t : tableSources) {
      if (t != left && t != right) {
        newTableSources.add(t);
      }
    }
    tableSources=newTableSources;
  }
  for (  ExactRelation r : tableSources) {
    if (joinedTableSource == null) {
      joinedTableSource=r;
    }
 else {
      joinedTableSource=new JoinedRelation(vc,joinedTableSource,r,null);
    }
  }
  if (where != null) {
    joinedTableSource=new FilteredRelation(vc,joinedTableSource,where);
  }
  SelectListExtractor select=new SelectListExtractor();
  Triple<List<SelectElem>,List<SelectElem>,List<SelectElem>> elems=select.visit(ctx.select_list());
  List<SelectElem> nonaggs=elems.getLeft();
  List<SelectElem> aggs=elems.getMiddle();
  List<SelectElem> bothInOrder=elems.getRight();
  TableSourceResolver resolver=new TableSourceResolver(vc,tableAliasAndColNames);
  nonaggs=replaceTableNamesWithAliasesIn(nonaggs,resolver);
  aggs=replaceTableNamesWithAliasesIn(aggs,resolver);
  bothInOrder=replaceTableNamesWithAliasesIn(bothInOrder,resolver);
  selectElems=bothInOrder;
  if (aggs.size() == 0) {
    joinedTableSource=new ProjectedRelation(vc,joinedTableSource,bothInOrder);
  }
 else {
    if (ctx.GROUP() != null) {
      List<Expr> groupby=new ArrayList<Expr>();
      for (      Group_by_itemContext g : ctx.group_by_item()) {
        Expr gexpr=resolver.visit(Expr.from(vc,g.expression()));
        boolean aliasFound=false;
        if (!aliasFound) {
          groupby.add(gexpr);
        }
      }
      joinedTableSource=new GroupedRelation(vc,joinedTableSource,groupby);
    }
    joinedTableSource=new AggregatedRelation(vc,joinedTableSource,bothInOrder);
  }
  return joinedTableSource;
}