message: Eliminate duplicate expressions in join order optimizer and fix cost of plans
diff: @@ -45,13 +45,6 @@ bool JoinOrderOptimizer::ExtractBindings(Expression &expression, unordered_set<i
  return can_reorder;
  }
  -static void ExtractFilters(LogicalOperator *op, vector<unique_ptr<Expression>> &filters) {
  - for (index_t i = 0; i < op->expressions.size(); i++) {
  - filters.push_back(move(op->expressions[i]));
  - }
  - op->expressions.clear();
  -}
  -
  static unique_ptr<LogicalOperator> PushFilter(unique_ptr<LogicalOperator> node, unique_ptr<Expression> expr) {
  // push an expression into a filter
  // first check if we have any filter to push it into
  @@ -201,7 +194,7 @@ static unique_ptr<JoinNode> CreateJoinTree(RelationSet *set, NeighborInfo *info,
  expected_cardinality = std::max(left->cardinality, right->cardinality);
  }
  // cost is expected_cardinality plus the cost of the previous plans
  - index_t cost = expected_cardinality;
  + index_t cost = left->cost + right->cost + expected_cardinality;
  return make_unique<JoinNode>(set, info, left, right, expected_cardinality, cost);
  }
  @@ -650,19 +643,29 @@ unique_ptr<LogicalOperator> JoinOrderOptimizer::Optimize(unique_ptr<LogicalOpera
  // at most one relation, nothing to reorder
  return plan;
  }
  - // now that we know we are going to perform join ordering we actually extract the filters
  + // now that we know we are going to perform join ordering we actually extract the filters, eliminating duplicate filters in the process
  + expression_set_t filter_set;
  for (auto &op : filter_operators) {
  if (op->type == LogicalOperatorType::COMPARISON_JOIN) {
  auto &join = (LogicalComparisonJoin &)*op;
  assert(join.type == JoinType::INNER);
  assert(join.expressions.size() == 0);
  for (auto &cond : join.conditions) {
  - filters.push_back(
  - make_unique<BoundComparisonExpression>(cond.comparison, move(cond.left), move(cond.right)));
  + auto comparison = make_unique<BoundComparisonExpression>(cond.comparison, move(cond.left), move(cond.right));
  + if (filter_set.find(comparison.get()) == filter_set.end()) {
  + filter_set.insert(comparison.get());
  + filters.push_back(move(comparison));
  + }
  }
  join.conditions.clear();
  } else {
  - ExtractFilters(op, filters);
  + for (index_t i = 0; i < op->expressions.size(); i++) {
  + if (filter_set.find(op->expressions[i].get()) == filter_set.end()) {
  + filter_set.insert(op->expressions[i].get());
  + filters.push_back(move(op->expressions[i]));
  + }
  + }
  + op->expressions.clear();
  }
  }
  // create potential edges from the comparisons
  