#vulnerable code 
                                @Override
    public ExactRelation rewriteWithSubsampledErrorBounds() {
        // if this is not an approximate relation effectively, we don't need any special rewriting.
        if (!doesIncludeSample()) {
            return getOriginalRelation();
        }
        
        ExactRelation r = rewriteWithPartition(true);
//        String newAlias = genTableAlias();
        
        // put another layer to combine per-partition aggregates
        List<SelectElem> newElems = new ArrayList<SelectElem>();
        List<SelectElem> oldElems = ((AggregatedRelation) r).getElemList();
        List<Expr> newGroupby = new ArrayList<Expr>();
        
        for (int i = 0; i < oldElems.size(); i++) {
            SelectElem elem = oldElems.get(i);
            
            // used to identify the original aggregation type
            Optional<SelectElem> originalElem = Optional.absent();
            if (i < this.elems.size()) {
                originalElem = Optional.fromNullable(this.elems.get(i));
            }
            
            if (!elem.isagg()) {
                // skip the partition number
                if (elem.aliasPresent() && elem.getAlias().equals(partitionColumnName())) {
                    continue;
                }
                
                SelectElem newElem = null;
                Expr newExpr = null;
                if (elem.getAlias() == null) {
                    newExpr = elem.getExpr().withTableSubstituted(r.getAlias());
                    newElem = new SelectElem(vc, newExpr, elem.getAlias());
                } else {
                    newExpr = new ColNameExpr(vc, elem.getAlias(), r.getAlias());
                    newElem = new SelectElem(vc, newExpr, elem.getAlias());
                }
                
                // groupby element may not be present in the select list.
                if (originalElem.isPresent()) {
                    newElems.add(newElem);
                }
                newGroupby.add(newExpr);
            }
            else {
                // skip the partition size column
                if (elem.getAlias().equals(partitionSizeAlias)) {
                    continue;
                }
                
                // skip the extra columns inserted
                if (!originalElem.isPresent()) {
                    continue;
                }

                ColNameExpr est = new ColNameExpr(vc, elem.getAlias(), r.getAlias());
                ColNameExpr psize = new ColNameExpr(vc, partitionSizeAlias, r.getAlias());

                // average estimate
                Expr averaged = null;
                Expr originalExpr = originalElem.get().getExpr();
                if (originalExpr.isCountDistinct()) {
                    // for count-distinct (i.e., universe samples), weighted average should not be used.
                    averaged = FuncExpr.round(FuncExpr.avg(est));
                } else if (originalExpr.isMax()) {
                    averaged = FuncExpr.max(est);
                } else if (originalExpr.isMin()) {
                    averaged = FuncExpr.min(est);
                } else {
                 // weighted average
                    averaged = BinaryOpExpr.from(vc, FuncExpr.sum(BinaryOpExpr.from(vc, est, psize, "*")),
                            FuncExpr.sum(psize), "/");
                    if (originalElem.get().getExpr().isCount()) {
                        averaged = FuncExpr.round(averaged);
                    }
                }
                newElems.add(new SelectElem(vc, averaged, elem.getAlias()));

                // error estimation
                // scale by sqrt(subsample size) / sqrt(sample size)
                if (originalExpr.isMax() || originalExpr.isMin()) {
                    // no error estimations for extreme statistics
                } else {
                    Expr error = BinaryOpExpr.from(vc,
                            BinaryOpExpr.from(vc, FuncExpr.stddev(est), FuncExpr.sqrt(FuncExpr.avg(psize)), "*"),
                            FuncExpr.sqrt(FuncExpr.sum(psize)),
                            "/");
                    error = BinaryOpExpr.from(vc, error, ConstantExpr.from(vc, confidenceIntervalMultiplier()), "*");
                    newElems.add(new SelectElem(vc, error, Relation.errorBoundColumn(elem.getAlias())));
                }
            }
        }
        
        // this extra aggregation stage should be grouped by non-agg elements except for __vpart
//        List<Expr> newGroupby = new ArrayList<Expr>();
//        if (source instanceof ApproxGroupedRelation) {
//            for (Expr g : ((ApproxGroupedRelation) source).getGroupby()) {
//                if (g instanceof ColNameExpr && ((ColNameExpr) g).getCol().equals(partitionColumnName())) {
//                    continue;
//                } else {
//                    newGroupby.add(g.withTableSubstituted(r.getAlias()));
//                }
//            }
//        }
        
        for (SelectElem elem : elems) {
            if (!elem.isagg()) {
                if (elem.aliasPresent()) {
                    if (!elem.getAlias().equals(partitionColumnName())) {
                        newGroupby.add(new ColNameExpr(vc, elem.getAlias(), r.getAlias()));
                    }
                } else {
                    if (!elem.getExpr().toString().equals(partitionColumnName())) {
                        newGroupby.add(elem.getExpr().withTableSubstituted(r.getAlias()));
                    }
                }
            }
        }
        if (newGroupby.size() > 0) {
            r = new GroupedRelation(vc, r, newGroupby);
        }
        
        r = new AggregatedRelation(vc, r, newElems);
        r.setAlias(getAlias());
        return r;
    } 
                            #location 112 
                            #vulnerability type NULL_DEREFERENCE
#fixed code
                                @Override
    public ExactRelation rewriteWithSubsampledErrorBounds() {
        // if this is not an approximate relation effectively, we don't need any special rewriting.
        if (!doesIncludeSample()) {
            return getOriginalRelation();
        }
        
        ExactRelation r = rewriteWithPartition(true);
//        String newAlias = genTableAlias();
        
        // put another layer to combine per-partition aggregates
        List<SelectElem> newElems = new ArrayList<SelectElem>();
        List<SelectElem> oldElems = ((AggregatedRelation) r).getElemList();
        List<Expr> newGroupby = new ArrayList<Expr>();
        
        for (int i = 0; i < oldElems.size(); i++) {
            SelectElem elem = oldElems.get(i);
            
            // used to identify the original aggregation type
            Optional<SelectElem> originalElem = Optional.absent();
            if (i < this.elems.size()) {
                originalElem = Optional.fromNullable(this.elems.get(i));
            }
            
            if (!elem.isagg()) {
                // skip the partition number
                if (elem.aliasPresent() && elem.getAlias().equals(partitionColumnName())) {
                    continue;
                }
                
                SelectElem newElem = null;
                Expr newExpr = null;
                if (elem.getAlias() == null) {
                    newExpr = elem.getExpr().withTableSubstituted(r.getAlias());
                    newElem = new SelectElem(vc, newExpr, elem.getAlias());
                } else {
                    newExpr = new ColNameExpr(vc, elem.getAlias(), r.getAlias());
                    newElem = new SelectElem(vc, newExpr, elem.getAlias());
                }
                
                // groupby element may not be present in the select list.
                if (originalElem.isPresent()) {
                    newElems.add(newElem);
                }
                newGroupby.add(newExpr);
            }
            else {
                // skip the partition size column
                if (elem.getAlias().equals(partitionSizeAlias)) {
                    continue;
                }
                
                // skip the extra columns inserted
                if (!originalElem.isPresent()) {
                    continue;
                }

                ColNameExpr est = new ColNameExpr(vc, elem.getAlias(), r.getAlias());
                ColNameExpr psize = new ColNameExpr(vc, partitionSizeAlias, r.getAlias());

                // average estimate
                Expr averaged = null;
                Expr originalExpr = originalElem.get().getExpr();
                if (originalExpr.isCountDistinct()) {
                    // for count-distinct (i.e., universe samples), weighted average should not be used.
                    averaged = FuncExpr.round(FuncExpr.avg(est));
                } else if (originalExpr.isMax()) {
                    averaged = FuncExpr.max(est);
                } else if (originalExpr.isMin()) {
                    averaged = FuncExpr.min(est);
                } else {
                 // weighted average
                    averaged = BinaryOpExpr.from(vc, FuncExpr.sum(BinaryOpExpr.from(vc, est, psize, "*")),
                            FuncExpr.sum(psize), "/");
                    if (originalElem.get().getExpr().isCount()) {
                        averaged = FuncExpr.round(averaged);
                    }
                }
                newElems.add(new SelectElem(vc, averaged, elem.getAlias()));

                // error estimation
                // scale by sqrt(subsample size) / sqrt(sample size)
                if (originalExpr.isMax() || originalExpr.isMin()) {
                    // no error estimations for extreme statistics
                } else {
                    Expr error = BinaryOpExpr.from(vc,
                            BinaryOpExpr.from(vc, FuncExpr.stddev(est), FuncExpr.sqrt(FuncExpr.avg(psize)), "*"),
                            FuncExpr.sqrt(FuncExpr.sum(psize)),
                            "/");
                    error = BinaryOpExpr.from(vc, error, ConstantExpr.from(vc, confidenceIntervalMultiplier()), "*");
                    newElems.add(new SelectElem(vc, error, Relation.errorBoundColumn(elem.getAlias())));
                }
            }
        }
        
        // this extra aggregation stage should be grouped by non-agg elements except for __vpart
//        List<Expr> newGroupby = new ArrayList<Expr>();
//        if (source instanceof ApproxGroupedRelation) {
//            for (Expr g : ((ApproxGroupedRelation) source).getGroupby()) {
//                if (g instanceof ColNameExpr && ((ColNameExpr) g).getCol().equals(partitionColumnName())) {
//                    continue;
//                } else {
//                    newGroupby.add(g.withTableSubstituted(r.getAlias()));
//                }
//            }
//        }
        
//        for (SelectElem elem : elems) {
//            if (!elem.isagg()) {
//                if (elem.aliasPresent()) {
//                    if (!elem.getAlias().equals(partitionColumnName())) {
//                        newGroupby.add(new ColNameExpr(vc, elem.getAlias(), r.getAlias()));
//                    }
//                } else {        // does not happen
//                    if (!elem.getExpr().toString().equals(partitionColumnName())) {
//                        newGroupby.add(elem.getExpr().withTableSubstituted(r.getAlias()));
//                    }
//                }
//            }
//        }
        if (newGroupby.size() > 0) {
            r = new GroupedRelation(vc, r, newGroupby);
        }
        
        r = new AggregatedRelation(vc, r, newElems);
        r.setAlias(getAlias());
        return r;
    }