Program: 9879
Project: 9879
Buggy source:
public static SqlNode union(ColRelGenerator generator,List<SqlNode> sqlNodes){
  if (sqlNodes.isEmpty()) {
    return new SqlNodeEmpty();
  }
  if (sqlNodes.size() == 1) {
    return sqlNodes.get(0);
  }
  Multimap<Var,TermDef> commons=HashMultimap.create();
  List<Multimap<Var,TermDef>> projections=new ArrayList<Multimap<Var,TermDef>>();
  for (int i=0; i < sqlNodes.size(); ++i) {
    Multimap<Var,TermDef> tmp=HashMultimap.create();
    projections.add(tmp);
  }
  Multimap<Var,Integer> varToSqlNode=HashMultimap.create();
  for (int i=0; i < sqlNodes.size(); ++i) {
    SqlNode sqlNode=sqlNodes.get(i);
    for (    Node var : sqlNode.getSparqlVarsMentioned()) {
      varToSqlNode.put((Var)var,i);
    }
  }
  Generator aliasGen=Gensym.create("String_Node_Str");
  ExprCommonFactor factorizer=new ExprCommonFactor(aliasGen);
  Map<String,SqlDatatype> allColumnsToDatatype=new HashMap<String,SqlDatatype>();
  for (  Entry<Var,Collection<Integer>> entry : varToSqlNode.asMap().entrySet()) {
    Var var=entry.getKey();
    Multimap<Integer,ArgExpr> cluster=HashMultimap.create();
    RestrictionSet restrictionsForVar=new RestrictionSet(false);
    for (    int index : entry.getValue()) {
      SqlNode sqlNode=sqlNodes.get(index);
      Collection<TermDef> exprsForVar=sqlNode.getSparqlVarToExprs().get(var);
      for (      TermDef def : exprsForVar) {
        restrictionsForVar.addAlternatives(def.getRestrictions());
        Map<String,SqlDatatype> columnToDatatype=SqlNodeUtil.getColumnToDatatype(sqlNode);
        Integer hash=ExprDatatypeHash.hash(def.getExpr(),columnToDatatype);
        cluster.put(hash,new ArgExpr(def.getExpr(),index));
      }
    }
    for (    Entry<Integer,Collection<ArgExpr>> clusterEntry : cluster.asMap().entrySet()) {
      Collection<ArgExpr> argExprs=clusterEntry.getValue();
      List<Expr> exprs=new ArrayList<Expr>();
      Map<Integer,Integer> exprToNode=new HashMap<Integer,Integer>();
      int i=0;
      for (      ArgExpr argExpr : argExprs) {
        exprs.add(argExpr.getExpr());
        exprToNode.put(i,argExpr.getIndex());
        ++i;
      }
      List<Map<Var,Expr>> partialProjections=new ArrayList<Map<Var,Expr>>();
      Expr common=factorizer.transform(exprs,partialProjections);
      commons.put(var,new TermDef(common,restrictionsForVar));
      for (int j=0; j < partialProjections.size(); ++j) {
        int originalIndex=exprToNode.get(j);
        Multimap<Var,TermDef> projection=projections.get(originalIndex);
        Map<Var,Expr> partialProjection=partialProjections.get(j);
        for (        Entry<Var,Expr> ppEntry : partialProjection.entrySet()) {
          projection.put(ppEntry.getKey(),new TermDef(ppEntry.getValue()));
        }
      }
    }
  }
  for (int i=0; i < projections.size(); ++i) {
    SqlNode tmp=sqlNodes.get(i);
    Multimap<Var,TermDef> projection=projections.get(i);
    NodeExprSubstitutor substitutor=createSubstitutor(tmp);
    Map<String,SqlExpr> subbedProj=new HashMap<String,SqlExpr>();
    for (    Entry<Var,TermDef> entry : projection.entries()) {
      Expr subbed=substitutor.transformMM(entry.getValue().getExpr());
      Expr pushed=PushDown.pushDownMM(subbed);
      if (!(pushed instanceof ExprSqlBridge)) {
        throw new RuntimeException("String_Node_Str");
      }
      SqlExpr sqlExpr=((ExprSqlBridge)pushed).getSqlExpr();
      subbedProj.put(entry.getKey().getName(),sqlExpr);
      allColumnsToDatatype.put(entry.getKey().getName(),sqlExpr.getDatatype());
    }
    tmp.getAliasToColumn().clear();
    tmp.getAliasToColumn().putAll(subbedProj);
    tmp.getSparqlVarToExprs().clear();
    tmp.getSparqlVarToExprs().putAll(commons);
  }
  for (  SqlNode sqlNode : sqlNodes) {
    Set<String> unboundColumns=Sets.difference(allColumnsToDatatype.keySet(),sqlNode.getAliasToColumn().keySet());
    for (    String columnName : unboundColumns) {
      SqlDatatype datatype=allColumnsToDatatype.get(columnName);
      sqlNode.getAliasToColumn().put(columnName,SqlExprValue.createNull(datatype));
    }
  }
  String unionAlias=generator.nextRelation();
  SqlNode result=new SqlUnionN(unionAlias,sqlNodes);
  result.getSparqlVarToExprs().putAll(commons);
  for (  Entry<String,SqlDatatype> entry : allColumnsToDatatype.entrySet()) {
    String columnName=entry.getKey();
    SqlDatatype datatype=entry.getValue();
    result.getAliasToColumn().put(columnName,new SqlExprColumn(unionAlias,columnName,datatype));
  }
  return result;
}

Fixed version (ground truth):
public static SqlNode union(ColRelGenerator generator,List<SqlNode> sqlNodes){
  if (sqlNodes.isEmpty()) {
    return new SqlNodeEmpty();
  }
  if (sqlNodes.size() == 1) {
    return sqlNodes.get(0);
  }
  Multimap<Var,TermDef> commons=HashMultimap.create();
  List<Multimap<Var,TermDef>> projections=new ArrayList<Multimap<Var,TermDef>>();
  for (int i=0; i < sqlNodes.size(); ++i) {
    Multimap<Var,TermDef> tmp=HashMultimap.create();
    projections.add(tmp);
  }
  Multimap<Var,Integer> varToSqlNode=HashMultimap.create();
  Generator aliasGen=Gensym.create("String_Node_Str");
  for (int i=0; i < sqlNodes.size(); ++i) {
    SqlNode sqlNode=sqlNodes.get(i);
    Set<Var> vars=new HashSet<Var>(sqlNode.getSparqlVarsMentioned());
    for (    Var var : vars) {
      List<TermDef> termDefs=new ArrayList<TermDef>(sqlNode.getSparqlVarToExprs().get(var));
      for (      TermDef termDef : termDefs) {
        Expr expr=termDef.getExpr();
        if (termDef.getExpr().isConstant()) {
          sqlNode.getSparqlVarToExprs().remove(var,termDef);
          NodeValue nv=ExprUtils.eval(expr);
          Object o=NodeValueUtils.getValue(nv);
          SqlExprValue sv=new SqlExprValue(o);
          String columnAlias=aliasGen.next();
          List<Expr> newArgs=new ArrayList<Expr>(expr.getFunction().getArgs());
          newArgs.set(1,new ExprVar(columnAlias));
          Expr newExpr=ExprCopy.getInstance().copy(expr,newArgs);
          TermDef newTermDef=new TermDef(newExpr);
          sqlNode.getSparqlVarToExprs().put(var,newTermDef);
          sqlNode.getAliasToColumn().put(columnAlias,sv);
          sqlNode.getSparqlVarToExprs().put(var,newTermDef);
        }
      }
    }
  }
  for (int i=0; i < sqlNodes.size(); ++i) {
    SqlNode sqlNode=sqlNodes.get(i);
    for (    Node var : sqlNode.getSparqlVarsMentioned()) {
      varToSqlNode.put((Var)var,i);
    }
  }
  ExprCommonFactor factorizer=new ExprCommonFactor(aliasGen);
  Map<String,SqlDatatype> allColumnsToDatatype=new HashMap<String,SqlDatatype>();
  for (  Entry<Var,Collection<Integer>> entry : varToSqlNode.asMap().entrySet()) {
    Var var=entry.getKey();
    Multimap<Integer,ArgExpr> cluster=HashMultimap.create();
    RestrictionSet restrictionsForVar=new RestrictionSet(false);
    for (    int index : entry.getValue()) {
      SqlNode sqlNode=sqlNodes.get(index);
      Collection<TermDef> exprsForVar=sqlNode.getSparqlVarToExprs().get(var);
      for (      TermDef def : exprsForVar) {
        restrictionsForVar.addAlternatives(def.getRestrictions());
        Map<String,SqlDatatype> columnToDatatype=SqlNodeUtil.getColumnToDatatype(sqlNode);
        Integer hash=ExprDatatypeHash.hash(def.getExpr(),columnToDatatype);
        cluster.put(hash,new ArgExpr(def.getExpr(),index));
      }
    }
    for (    Entry<Integer,Collection<ArgExpr>> clusterEntry : cluster.asMap().entrySet()) {
      Collection<ArgExpr> argExprs=clusterEntry.getValue();
      List<Expr> exprs=new ArrayList<Expr>();
      Map<Integer,Integer> exprToNode=new HashMap<Integer,Integer>();
      int i=0;
      for (      ArgExpr argExpr : argExprs) {
        exprs.add(argExpr.getExpr());
        exprToNode.put(i,argExpr.getIndex());
        ++i;
      }
      List<Map<Var,Expr>> partialProjections=new ArrayList<Map<Var,Expr>>();
      Expr common=factorizer.transform(exprs,partialProjections);
      commons.put(var,new TermDef(common,restrictionsForVar));
      for (int j=0; j < partialProjections.size(); ++j) {
        int originalIndex=exprToNode.get(j);
        Multimap<Var,TermDef> projection=projections.get(originalIndex);
        Map<Var,Expr> partialProjection=partialProjections.get(j);
        for (        Entry<Var,Expr> ppEntry : partialProjection.entrySet()) {
          projection.put(ppEntry.getKey(),new TermDef(ppEntry.getValue()));
        }
      }
    }
  }
  for (int i=0; i < projections.size(); ++i) {
    SqlNode tmp=sqlNodes.get(i);
    Multimap<Var,TermDef> projection=projections.get(i);
    NodeExprSubstitutor substitutor=createSubstitutor(tmp);
    Map<String,SqlExpr> subbedProj=new HashMap<String,SqlExpr>();
    for (    Entry<Var,TermDef> entry : projection.entries()) {
      Expr subbed=substitutor.transformMM(entry.getValue().getExpr());
      Expr pushed=PushDown.pushDownMM(subbed);
      if (!(pushed instanceof ExprSqlBridge)) {
        throw new RuntimeException("String_Node_Str");
      }
      SqlExpr sqlExpr=((ExprSqlBridge)pushed).getSqlExpr();
      subbedProj.put(entry.getKey().getName(),sqlExpr);
      allColumnsToDatatype.put(entry.getKey().getName(),sqlExpr.getDatatype());
    }
    tmp.getAliasToColumn().clear();
    tmp.getAliasToColumn().putAll(subbedProj);
    tmp.getSparqlVarToExprs().clear();
    tmp.getSparqlVarToExprs().putAll(commons);
  }
  for (  SqlNode sqlNode : sqlNodes) {
    Set<String> unboundColumns=Sets.difference(allColumnsToDatatype.keySet(),sqlNode.getAliasToColumn().keySet());
    for (    String columnName : unboundColumns) {
      SqlDatatype datatype=allColumnsToDatatype.get(columnName);
      sqlNode.getAliasToColumn().put(columnName,SqlExprValue.createNull(datatype));
    }
  }
  String unionAlias=generator.nextRelation();
  SqlNode result=new SqlUnionN(unionAlias,sqlNodes);
  result.getSparqlVarToExprs().putAll(commons);
  for (  Entry<String,SqlDatatype> entry : allColumnsToDatatype.entrySet()) {
    String columnName=entry.getKey();
    SqlDatatype datatype=entry.getValue();
    result.getAliasToColumn().put(columnName,new SqlExprColumn(unionAlias,columnName,datatype));
  }
  return result;
}