duckdb 0.3.5-dev591.0 → 0.3.5-dev602.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/duckdb.cpp CHANGED
@@ -38514,11 +38514,39 @@ bool ChunkCollection::Equals(ChunkCollection &other) {
38514
38514
  if (ColumnCount() != other.ColumnCount()) {
38515
38515
  return false;
38516
38516
  }
38517
- // if count is equal amount of chunks should be equal
38517
+ // first try to compare the results as-is
38518
+ bool compare_equals = true;
38518
38519
  for (idx_t row_idx = 0; row_idx < count; row_idx++) {
38519
38520
  for (idx_t col_idx = 0; col_idx < ColumnCount(); col_idx++) {
38520
38521
  auto lvalue = GetValue(col_idx, row_idx);
38521
38522
  auto rvalue = other.GetValue(col_idx, row_idx);
38523
+ if (!Value::ValuesAreEqual(lvalue, rvalue)) {
38524
+ compare_equals = false;
38525
+ break;
38526
+ }
38527
+ }
38528
+ if (!compare_equals) {
38529
+ break;
38530
+ }
38531
+ }
38532
+ if (compare_equals) {
38533
+ return true;
38534
+ }
38535
+ // if the results are not equal,
38536
+ // sort both chunk collections to ensure the comparison is not order insensitive
38537
+ vector<OrderType> desc(ColumnCount(), OrderType::DESCENDING);
38538
+ vector<OrderByNullType> null_order(ColumnCount(), OrderByNullType::NULLS_FIRST);
38539
+ auto this_order = unique_ptr<idx_t[]>(new idx_t[count]);
38540
+ auto other_order = unique_ptr<idx_t[]>(new idx_t[count]);
38541
+ Sort(desc, null_order, this_order.get());
38542
+ other.Sort(desc, null_order, other_order.get());
38543
+
38544
+ for (idx_t row_idx = 0; row_idx < count; row_idx++) {
38545
+ auto lrow = this_order[row_idx];
38546
+ auto rrow = other_order[row_idx];
38547
+ for (idx_t col_idx = 0; col_idx < ColumnCount(); col_idx++) {
38548
+ auto lvalue = GetValue(col_idx, lrow);
38549
+ auto rvalue = other.GetValue(col_idx, rrow);
38522
38550
  if (!Value::ValuesAreEqual(lvalue, rvalue)) {
38523
38551
  return false;
38524
38552
  }
@@ -112991,6 +113019,7 @@ private:
112991
113019
 
112992
113020
 
112993
113021
 
113022
+
112994
113023
  namespace duckdb {
112995
113024
 
112996
113025
  struct ActiveQueryContext {
@@ -113698,14 +113727,16 @@ void ClientContext::DisableProfiling() {
113698
113727
  }
113699
113728
 
113700
113729
  struct VerifyStatement {
113701
- VerifyStatement(unique_ptr<SelectStatement> statement_p, string statement_name_p, bool require_equality = true)
113730
+ VerifyStatement(unique_ptr<SelectStatement> statement_p, string statement_name_p, bool require_equality = true,
113731
+ bool disable_optimizer = false)
113702
113732
  : statement(move(statement_p)), statement_name(move(statement_name_p)), require_equality(require_equality),
113703
- select_list(statement->node->GetSelectList()) {
113733
+ disable_optimizer(disable_optimizer), select_list(statement->node->GetSelectList()) {
113704
113734
  }
113705
113735
 
113706
113736
  unique_ptr<SelectStatement> statement;
113707
113737
  string statement_name;
113708
113738
  bool require_equality;
113739
+ bool disable_optimizer;
113709
113740
  const vector<unique_ptr<ParsedExpression>> &select_list;
113710
113741
  };
113711
113742
 
@@ -113733,8 +113764,9 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
113733
113764
  BufferedDeserializer source(serializer);
113734
113765
  auto deserialized_stmt = SelectStatement::Deserialize(source);
113735
113766
 
113767
+ auto query_str = select_stmt->ToString();
113736
113768
  Parser parser;
113737
- parser.ParseQuery(select_stmt->ToString());
113769
+ parser.ParseQuery(query_str);
113738
113770
  D_ASSERT(parser.statements.size() == 1);
113739
113771
  D_ASSERT(parser.statements[0]->type == StatementType::SELECT_STATEMENT);
113740
113772
  auto parsed_statement = move(parser.statements[0]);
@@ -113745,6 +113777,8 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
113745
113777
  verify_statements.emplace_back(move(deserialized_stmt), "Deserialized statement");
113746
113778
  verify_statements.emplace_back(unique_ptr_cast<SQLStatement, SelectStatement>(move(parsed_statement)),
113747
113779
  "Parsed statement", false);
113780
+ verify_statements.emplace_back(unique_ptr_cast<SQLStatement, SelectStatement>(move(unoptimized_stmt)),
113781
+ "Unoptimized", true, true);
113748
113782
 
113749
113783
  // all the statements should be equal
113750
113784
  for (idx_t i = 1; i < verify_statements.size(); i++) {
@@ -113809,9 +113843,11 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
113809
113843
  auto statement_copy_for_explain = select_stmt->Copy();
113810
113844
 
113811
113845
  // execute the original statement
113846
+ auto optimizer_enabled = config.enable_optimizer;
113812
113847
  vector<unique_ptr<MaterializedQueryResult>> results;
113813
113848
  for (idx_t i = 0; i < verify_statements.size(); i++) {
113814
113849
  interrupted = false;
113850
+ config.enable_optimizer = !verify_statements[i].disable_optimizer;
113815
113851
  try {
113816
113852
  auto result = RunStatementInternal(lock, query, move(verify_statements[i].statement), false, false);
113817
113853
  results.push_back(unique_ptr_cast<QueryResult, MaterializedQueryResult>(move(result)));
@@ -113819,6 +113855,7 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
113819
113855
  results.push_back(make_unique<MaterializedQueryResult>(ex.what()));
113820
113856
  }
113821
113857
  }
113858
+ config.enable_optimizer = optimizer_enabled;
113822
113859
 
113823
113860
  // check explain, only if q does not already contain EXPLAIN
113824
113861
  if (results[0]->success) {
@@ -113831,8 +113868,6 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
113831
113868
  } // LCOV_EXCL_STOP
113832
113869
  }
113833
113870
 
113834
- config.enable_optimizer = true;
113835
-
113836
113871
  if (profiling_is_enabled) {
113837
113872
  config.enable_profiler = true;
113838
113873
  }
@@ -129547,37 +129582,37 @@ private:
129547
129582
  Expression *GetNode(Expression *expr);
129548
129583
  idx_t GetEquivalenceSet(Expression *expr);
129549
129584
  FilterResult AddConstantComparison(vector<ExpressionValueInformation> &info_list, ExpressionValueInformation info);
129550
-
129551
- //! Functions used to push and generate OR Filters
129552
- void LookUpConjunctions(Expression *expr);
129553
- bool BFSLookUpConjunctions(BoundConjunctionExpression *conjunction);
129554
- void VerifyOrsToPush(Expression &expr);
129555
-
129556
- bool UpdateConjunctionFilter(BoundComparisonExpression *comparison_expr);
129557
- bool UpdateFilterByColumn(BoundColumnRefExpression *column_ref, BoundComparisonExpression *comparison_expr);
129558
- void GenerateORFilters(TableFilterSet &table_filter, vector<idx_t> &column_ids);
129559
-
129560
- template <typename CONJUNCTION_TYPE>
129561
- void GenerateConjunctionFilter(BoundConjunctionExpression *conjunction, ConjunctionFilter *last_conj_filter) {
129562
- auto new_filter = NextConjunctionFilter<CONJUNCTION_TYPE>(conjunction);
129563
- auto conj_filter_ptr = (ConjunctionFilter *)new_filter.get();
129564
- last_conj_filter->child_filters.push_back(move(new_filter));
129565
- last_conj_filter = conj_filter_ptr;
129566
- }
129567
-
129568
- template <typename CONJUNCTION_TYPE>
129569
- unique_ptr<TableFilter> NextConjunctionFilter(BoundConjunctionExpression *conjunction) {
129570
- unique_ptr<ConjunctionFilter> conj_filter = make_unique<CONJUNCTION_TYPE>();
129571
- for (auto &expr : conjunction->children) {
129572
- auto comp_expr = (BoundComparisonExpression *)expr.get();
129573
- auto &const_expr =
129574
- (comp_expr->left->type == ExpressionType::VALUE_CONSTANT) ? *comp_expr->left : *comp_expr->right;
129575
- auto const_value = ExpressionExecutor::EvaluateScalar(const_expr);
129576
- auto const_filter = make_unique<ConstantFilter>(comp_expr->type, const_value);
129577
- conj_filter->child_filters.push_back(move(const_filter));
129578
- }
129579
- return move(conj_filter);
129580
- }
129585
+ //
129586
+ // //! Functions used to push and generate OR Filters
129587
+ // void LookUpConjunctions(Expression *expr);
129588
+ // bool BFSLookUpConjunctions(BoundConjunctionExpression *conjunction);
129589
+ // void VerifyOrsToPush(Expression &expr);
129590
+ //
129591
+ // bool UpdateConjunctionFilter(BoundComparisonExpression *comparison_expr);
129592
+ // bool UpdateFilterByColumn(BoundColumnRefExpression *column_ref, BoundComparisonExpression *comparison_expr);
129593
+ // void GenerateORFilters(TableFilterSet &table_filter, vector<idx_t> &column_ids);
129594
+ //
129595
+ // template <typename CONJUNCTION_TYPE>
129596
+ // void GenerateConjunctionFilter(BoundConjunctionExpression *conjunction, ConjunctionFilter *last_conj_filter) {
129597
+ // auto new_filter = NextConjunctionFilter<CONJUNCTION_TYPE>(conjunction);
129598
+ // auto conj_filter_ptr = (ConjunctionFilter *)new_filter.get();
129599
+ // last_conj_filter->child_filters.push_back(move(new_filter));
129600
+ // last_conj_filter = conj_filter_ptr;
129601
+ // }
129602
+ //
129603
+ // template <typename CONJUNCTION_TYPE>
129604
+ // unique_ptr<TableFilter> NextConjunctionFilter(BoundConjunctionExpression *conjunction) {
129605
+ // unique_ptr<ConjunctionFilter> conj_filter = make_unique<CONJUNCTION_TYPE>();
129606
+ // for (auto &expr : conjunction->children) {
129607
+ // auto comp_expr = (BoundComparisonExpression *)expr.get();
129608
+ // auto &const_expr =
129609
+ // (comp_expr->left->type == ExpressionType::VALUE_CONSTANT) ? *comp_expr->left : *comp_expr->right;
129610
+ // auto const_value = ExpressionExecutor::EvaluateScalar(const_expr);
129611
+ // auto const_filter = make_unique<ConstantFilter>(comp_expr->type, const_value);
129612
+ // conj_filter->child_filters.push_back(move(const_filter));
129613
+ // }
129614
+ // return move(conj_filter);
129615
+ // }
129581
129616
 
129582
129617
  private:
129583
129618
  vector<unique_ptr<Expression>> remaining_filters;
@@ -129587,26 +129622,26 @@ private:
129587
129622
  unordered_map<idx_t, vector<ExpressionValueInformation>> constant_values;
129588
129623
  unordered_map<idx_t, vector<Expression *>> equivalence_map;
129589
129624
  idx_t set_index = 0;
129590
-
129591
- //! Structures used for OR Filters
129592
-
129593
- struct ConjunctionsToPush {
129594
- BoundConjunctionExpression *root_or;
129595
-
129596
- // only preserve AND if there is a single column in the expression
129597
- bool preserve_and = true;
129598
-
129599
- // conjunction chain for this column
129600
- vector<unique_ptr<BoundConjunctionExpression>> conjunctions;
129601
- };
129602
-
129603
- expression_map_t<vector<unique_ptr<ConjunctionsToPush>>> map_col_conjunctions;
129604
- vector<BoundColumnRefExpression *> vec_colref_insertion_order;
129605
-
129606
- BoundConjunctionExpression *cur_root_or;
129607
- BoundConjunctionExpression *cur_conjunction;
129608
-
129609
- BoundColumnRefExpression *cur_colref_to_push;
129625
+ //
129626
+ // //! Structures used for OR Filters
129627
+ //
129628
+ // struct ConjunctionsToPush {
129629
+ // BoundConjunctionExpression *root_or;
129630
+ //
129631
+ // // only preserve AND if there is a single column in the expression
129632
+ // bool preserve_and = true;
129633
+ //
129634
+ // // conjunction chain for this column
129635
+ // vector<unique_ptr<BoundConjunctionExpression>> conjunctions;
129636
+ // };
129637
+ //
129638
+ // expression_map_t<vector<unique_ptr<ConjunctionsToPush>>> map_col_conjunctions;
129639
+ // vector<BoundColumnRefExpression *> vec_colref_insertion_order;
129640
+ //
129641
+ // BoundConjunctionExpression *cur_root_or;
129642
+ // BoundConjunctionExpression *cur_conjunction;
129643
+ //
129644
+ // BoundColumnRefExpression *cur_colref_to_push;
129610
129645
  };
129611
129646
 
129612
129647
  } // namespace duckdb
@@ -129691,7 +129726,7 @@ FilterResult FilterCombiner::AddConstantComparison(vector<ExpressionValueInforma
129691
129726
  }
129692
129727
 
129693
129728
  FilterResult FilterCombiner::AddFilter(unique_ptr<Expression> expr) {
129694
- LookUpConjunctions(expr.get());
129729
+ // LookUpConjunctions(expr.get());
129695
129730
  // try to push the filter into the combiner
129696
129731
  auto result = AddFilter(expr.get());
129697
129732
  if (result == FilterResult::UNSUPPORTED) {
@@ -130161,7 +130196,7 @@ TableFilterSet FilterCombiner::GenerateTableScanFilters(vector<idx_t> &column_id
130161
130196
  }
130162
130197
  }
130163
130198
 
130164
- GenerateORFilters(table_filters, column_ids);
130199
+ // GenerateORFilters(table_filters, column_ids);
130165
130200
 
130166
130201
  return table_filters;
130167
130202
  }
@@ -130630,176 +130665,176 @@ ValueComparisonResult CompareValueInformation(ExpressionValueInformation &left,
130630
130665
  return InvertValueComparisonResult(CompareValueInformation(right, left));
130631
130666
  }
130632
130667
  }
130633
-
130634
- void FilterCombiner::LookUpConjunctions(Expression *expr) {
130635
- if (expr->GetExpressionType() == ExpressionType::CONJUNCTION_OR) {
130636
- auto root_or_expr = (BoundConjunctionExpression *)expr;
130637
- for (const auto &entry : map_col_conjunctions) {
130638
- for (const auto &conjs_to_push : entry.second) {
130639
- if (conjs_to_push->root_or->Equals(root_or_expr)) {
130640
- return;
130641
- }
130642
- }
130643
- }
130644
-
130645
- cur_root_or = root_or_expr;
130646
- cur_conjunction = root_or_expr;
130647
- cur_colref_to_push = nullptr;
130648
- if (!BFSLookUpConjunctions(cur_root_or)) {
130649
- if (cur_colref_to_push) {
130650
- auto entry = map_col_conjunctions.find(cur_colref_to_push);
130651
- auto &vec_conjs_to_push = entry->second;
130652
- if (vec_conjs_to_push.size() == 1) {
130653
- map_col_conjunctions.erase(entry);
130654
- return;
130655
- }
130656
- vec_conjs_to_push.pop_back();
130657
- }
130658
- }
130659
- return;
130660
- }
130661
-
130662
- // Verify if the expression has a column already pushed down by other OR expression
130663
- VerifyOrsToPush(*expr);
130664
- }
130665
-
130666
- bool FilterCombiner::BFSLookUpConjunctions(BoundConjunctionExpression *conjunction) {
130667
- vector<BoundConjunctionExpression *> conjunctions_to_visit;
130668
-
130669
- for (auto &child : conjunction->children) {
130670
- switch (child->GetExpressionClass()) {
130671
- case ExpressionClass::BOUND_CONJUNCTION: {
130672
- auto child_conjunction = (BoundConjunctionExpression *)child.get();
130673
- conjunctions_to_visit.emplace_back(child_conjunction);
130674
- break;
130675
- }
130676
- case ExpressionClass::BOUND_COMPARISON: {
130677
- if (!UpdateConjunctionFilter((BoundComparisonExpression *)child.get())) {
130678
- return false;
130679
- }
130680
- break;
130681
- }
130682
- default: {
130683
- return false;
130684
- }
130685
- }
130686
- }
130687
-
130688
- for (auto child_conjunction : conjunctions_to_visit) {
130689
- cur_conjunction = child_conjunction;
130690
- // traverse child conjuction
130691
- if (!BFSLookUpConjunctions(child_conjunction)) {
130692
- return false;
130693
- }
130694
- }
130695
- return true;
130696
- }
130697
-
130698
- void FilterCombiner::VerifyOrsToPush(Expression &expr) {
130699
- if (expr.type == ExpressionType::BOUND_COLUMN_REF) {
130700
- auto colref = (BoundColumnRefExpression *)&expr;
130701
- auto entry = map_col_conjunctions.find(colref);
130702
- if (entry == map_col_conjunctions.end()) {
130703
- return;
130704
- }
130705
- map_col_conjunctions.erase(entry);
130706
- }
130707
- ExpressionIterator::EnumerateChildren(expr, [&](Expression &child) { VerifyOrsToPush(child); });
130708
- }
130709
-
130710
- bool FilterCombiner::UpdateConjunctionFilter(BoundComparisonExpression *comparison_expr) {
130711
- bool left_is_scalar = comparison_expr->left->IsFoldable();
130712
- bool right_is_scalar = comparison_expr->right->IsFoldable();
130713
-
130714
- Expression *non_scalar_expr;
130715
- if (left_is_scalar || right_is_scalar) {
130716
- // only support comparison with scalar
130717
- non_scalar_expr = left_is_scalar ? comparison_expr->right.get() : comparison_expr->left.get();
130718
-
130719
- if (non_scalar_expr->GetExpressionType() == ExpressionType::BOUND_COLUMN_REF) {
130720
- return UpdateFilterByColumn((BoundColumnRefExpression *)non_scalar_expr, comparison_expr);
130721
- }
130722
- }
130723
-
130724
- return false;
130725
- }
130726
-
130727
- bool FilterCombiner::UpdateFilterByColumn(BoundColumnRefExpression *column_ref,
130728
- BoundComparisonExpression *comparison_expr) {
130729
- if (cur_colref_to_push == nullptr) {
130730
- cur_colref_to_push = column_ref;
130731
-
130732
- auto or_conjunction = make_unique<BoundConjunctionExpression>(ExpressionType::CONJUNCTION_OR);
130733
- or_conjunction->children.emplace_back(comparison_expr->Copy());
130734
-
130735
- unique_ptr<ConjunctionsToPush> conjs_to_push = make_unique<ConjunctionsToPush>();
130736
- conjs_to_push->conjunctions.emplace_back(move(or_conjunction));
130737
- conjs_to_push->root_or = cur_root_or;
130738
-
130739
- auto &&vec_col_conjs = map_col_conjunctions[column_ref];
130740
- vec_col_conjs.emplace_back(move(conjs_to_push));
130741
- vec_colref_insertion_order.emplace_back(column_ref);
130742
- return true;
130743
- }
130744
-
130745
- auto entry = map_col_conjunctions.find(cur_colref_to_push);
130746
- D_ASSERT(entry != map_col_conjunctions.end());
130747
- auto &conjunctions_to_push = entry->second.back();
130748
-
130749
- if (!cur_colref_to_push->Equals(column_ref)) {
130750
- // check for multiple colunms in the same root OR node
130751
- if (cur_root_or == cur_conjunction) {
130752
- return false;
130753
- }
130754
- // found an AND using a different column, we should stop the look up
130755
- if (cur_conjunction->GetExpressionType() == ExpressionType::CONJUNCTION_AND) {
130756
- return false;
130757
- }
130758
-
130759
- // found a different column, AND conditions cannot be preserved anymore
130760
- conjunctions_to_push->preserve_and = false;
130761
- return true;
130762
- }
130763
-
130764
- auto &last_conjunction = conjunctions_to_push->conjunctions.back();
130765
- if (cur_conjunction->GetExpressionType() == last_conjunction->GetExpressionType()) {
130766
- last_conjunction->children.emplace_back(comparison_expr->Copy());
130767
- } else {
130768
- auto new_conjunction = make_unique<BoundConjunctionExpression>(cur_conjunction->GetExpressionType());
130769
- new_conjunction->children.emplace_back(comparison_expr->Copy());
130770
- conjunctions_to_push->conjunctions.emplace_back(move(new_conjunction));
130771
- }
130772
- return true;
130773
- }
130774
-
130775
- void FilterCombiner::GenerateORFilters(TableFilterSet &table_filter, vector<idx_t> &column_ids) {
130776
- for (const auto colref : vec_colref_insertion_order) {
130777
- auto column_index = column_ids[colref->binding.column_index];
130778
- if (column_index == COLUMN_IDENTIFIER_ROW_ID) {
130779
- break;
130780
- }
130781
-
130782
- for (const auto &conjunctions_to_push : map_col_conjunctions[colref]) {
130783
- // root OR filter to push into the TableFilter
130784
- auto root_or_filter = make_unique<ConjunctionOrFilter>();
130785
- // variable to hold the last conjuntion filter pointer
130786
- // the next filter will be added into it, i.e., we create a chain of conjunction filters
130787
- ConjunctionFilter *last_conj_filter = root_or_filter.get();
130788
-
130789
- for (auto &conjunction : conjunctions_to_push->conjunctions) {
130790
- if (conjunction->GetExpressionType() == ExpressionType::CONJUNCTION_AND &&
130791
- conjunctions_to_push->preserve_and) {
130792
- GenerateConjunctionFilter<ConjunctionAndFilter>(conjunction.get(), last_conj_filter);
130793
- } else {
130794
- GenerateConjunctionFilter<ConjunctionOrFilter>(conjunction.get(), last_conj_filter);
130795
- }
130796
- }
130797
- table_filter.PushFilter(column_index, move(root_or_filter));
130798
- }
130799
- }
130800
- map_col_conjunctions.clear();
130801
- vec_colref_insertion_order.clear();
130802
- }
130668
+ //
130669
+ // void FilterCombiner::LookUpConjunctions(Expression *expr) {
130670
+ // if (expr->GetExpressionType() == ExpressionType::CONJUNCTION_OR) {
130671
+ // auto root_or_expr = (BoundConjunctionExpression *)expr;
130672
+ // for (const auto &entry : map_col_conjunctions) {
130673
+ // for (const auto &conjs_to_push : entry.second) {
130674
+ // if (conjs_to_push->root_or->Equals(root_or_expr)) {
130675
+ // return;
130676
+ // }
130677
+ // }
130678
+ // }
130679
+ //
130680
+ // cur_root_or = root_or_expr;
130681
+ // cur_conjunction = root_or_expr;
130682
+ // cur_colref_to_push = nullptr;
130683
+ // if (!BFSLookUpConjunctions(cur_root_or)) {
130684
+ // if (cur_colref_to_push) {
130685
+ // auto entry = map_col_conjunctions.find(cur_colref_to_push);
130686
+ // auto &vec_conjs_to_push = entry->second;
130687
+ // if (vec_conjs_to_push.size() == 1) {
130688
+ // map_col_conjunctions.erase(entry);
130689
+ // return;
130690
+ // }
130691
+ // vec_conjs_to_push.pop_back();
130692
+ // }
130693
+ // }
130694
+ // return;
130695
+ // }
130696
+ //
130697
+ // // Verify if the expression has a column already pushed down by other OR expression
130698
+ // VerifyOrsToPush(*expr);
130699
+ //}
130700
+ //
130701
+ // bool FilterCombiner::BFSLookUpConjunctions(BoundConjunctionExpression *conjunction) {
130702
+ // vector<BoundConjunctionExpression *> conjunctions_to_visit;
130703
+ //
130704
+ // for (auto &child : conjunction->children) {
130705
+ // switch (child->GetExpressionClass()) {
130706
+ // case ExpressionClass::BOUND_CONJUNCTION: {
130707
+ // auto child_conjunction = (BoundConjunctionExpression *)child.get();
130708
+ // conjunctions_to_visit.emplace_back(child_conjunction);
130709
+ // break;
130710
+ // }
130711
+ // case ExpressionClass::BOUND_COMPARISON: {
130712
+ // if (!UpdateConjunctionFilter((BoundComparisonExpression *)child.get())) {
130713
+ // return false;
130714
+ // }
130715
+ // break;
130716
+ // }
130717
+ // default: {
130718
+ // return false;
130719
+ // }
130720
+ // }
130721
+ // }
130722
+ //
130723
+ // for (auto child_conjunction : conjunctions_to_visit) {
130724
+ // cur_conjunction = child_conjunction;
130725
+ // // traverse child conjuction
130726
+ // if (!BFSLookUpConjunctions(child_conjunction)) {
130727
+ // return false;
130728
+ // }
130729
+ // }
130730
+ // return true;
130731
+ //}
130732
+ //
130733
+ // void FilterCombiner::VerifyOrsToPush(Expression &expr) {
130734
+ // if (expr.type == ExpressionType::BOUND_COLUMN_REF) {
130735
+ // auto colref = (BoundColumnRefExpression *)&expr;
130736
+ // auto entry = map_col_conjunctions.find(colref);
130737
+ // if (entry == map_col_conjunctions.end()) {
130738
+ // return;
130739
+ // }
130740
+ // map_col_conjunctions.erase(entry);
130741
+ // }
130742
+ // ExpressionIterator::EnumerateChildren(expr, [&](Expression &child) { VerifyOrsToPush(child); });
130743
+ //}
130744
+ //
130745
+ // bool FilterCombiner::UpdateConjunctionFilter(BoundComparisonExpression *comparison_expr) {
130746
+ // bool left_is_scalar = comparison_expr->left->IsFoldable();
130747
+ // bool right_is_scalar = comparison_expr->right->IsFoldable();
130748
+ //
130749
+ // Expression *non_scalar_expr;
130750
+ // if (left_is_scalar || right_is_scalar) {
130751
+ // // only support comparison with scalar
130752
+ // non_scalar_expr = left_is_scalar ? comparison_expr->right.get() : comparison_expr->left.get();
130753
+ //
130754
+ // if (non_scalar_expr->GetExpressionType() == ExpressionType::BOUND_COLUMN_REF) {
130755
+ // return UpdateFilterByColumn((BoundColumnRefExpression *)non_scalar_expr, comparison_expr);
130756
+ // }
130757
+ // }
130758
+ //
130759
+ // return false;
130760
+ //}
130761
+ //
130762
+ // bool FilterCombiner::UpdateFilterByColumn(BoundColumnRefExpression *column_ref,
130763
+ // BoundComparisonExpression *comparison_expr) {
130764
+ // if (cur_colref_to_push == nullptr) {
130765
+ // cur_colref_to_push = column_ref;
130766
+ //
130767
+ // auto or_conjunction = make_unique<BoundConjunctionExpression>(ExpressionType::CONJUNCTION_OR);
130768
+ // or_conjunction->children.emplace_back(comparison_expr->Copy());
130769
+ //
130770
+ // unique_ptr<ConjunctionsToPush> conjs_to_push = make_unique<ConjunctionsToPush>();
130771
+ // conjs_to_push->conjunctions.emplace_back(move(or_conjunction));
130772
+ // conjs_to_push->root_or = cur_root_or;
130773
+ //
130774
+ // auto &&vec_col_conjs = map_col_conjunctions[column_ref];
130775
+ // vec_col_conjs.emplace_back(move(conjs_to_push));
130776
+ // vec_colref_insertion_order.emplace_back(column_ref);
130777
+ // return true;
130778
+ // }
130779
+ //
130780
+ // auto entry = map_col_conjunctions.find(cur_colref_to_push);
130781
+ // D_ASSERT(entry != map_col_conjunctions.end());
130782
+ // auto &conjunctions_to_push = entry->second.back();
130783
+ //
130784
+ // if (!cur_colref_to_push->Equals(column_ref)) {
130785
+ // // check for multiple colunms in the same root OR node
130786
+ // if (cur_root_or == cur_conjunction) {
130787
+ // return false;
130788
+ // }
130789
+ // // found an AND using a different column, we should stop the look up
130790
+ // if (cur_conjunction->GetExpressionType() == ExpressionType::CONJUNCTION_AND) {
130791
+ // return false;
130792
+ // }
130793
+ //
130794
+ // // found a different column, AND conditions cannot be preserved anymore
130795
+ // conjunctions_to_push->preserve_and = false;
130796
+ // return true;
130797
+ // }
130798
+ //
130799
+ // auto &last_conjunction = conjunctions_to_push->conjunctions.back();
130800
+ // if (cur_conjunction->GetExpressionType() == last_conjunction->GetExpressionType()) {
130801
+ // last_conjunction->children.emplace_back(comparison_expr->Copy());
130802
+ // } else {
130803
+ // auto new_conjunction = make_unique<BoundConjunctionExpression>(cur_conjunction->GetExpressionType());
130804
+ // new_conjunction->children.emplace_back(comparison_expr->Copy());
130805
+ // conjunctions_to_push->conjunctions.emplace_back(move(new_conjunction));
130806
+ // }
130807
+ // return true;
130808
+ //}
130809
+ //
130810
+ // void FilterCombiner::GenerateORFilters(TableFilterSet &table_filter, vector<idx_t> &column_ids) {
130811
+ // for (const auto colref : vec_colref_insertion_order) {
130812
+ // auto column_index = column_ids[colref->binding.column_index];
130813
+ // if (column_index == COLUMN_IDENTIFIER_ROW_ID) {
130814
+ // break;
130815
+ // }
130816
+ //
130817
+ // for (const auto &conjunctions_to_push : map_col_conjunctions[colref]) {
130818
+ // // root OR filter to push into the TableFilter
130819
+ // auto root_or_filter = make_unique<ConjunctionOrFilter>();
130820
+ // // variable to hold the last conjuntion filter pointer
130821
+ // // the next filter will be added into it, i.e., we create a chain of conjunction filters
130822
+ // ConjunctionFilter *last_conj_filter = root_or_filter.get();
130823
+ //
130824
+ // for (auto &conjunction : conjunctions_to_push->conjunctions) {
130825
+ // if (conjunction->GetExpressionType() == ExpressionType::CONJUNCTION_AND &&
130826
+ // conjunctions_to_push->preserve_and) {
130827
+ // GenerateConjunctionFilter<ConjunctionAndFilter>(conjunction.get(), last_conj_filter);
130828
+ // } else {
130829
+ // GenerateConjunctionFilter<ConjunctionOrFilter>(conjunction.get(), last_conj_filter);
130830
+ // }
130831
+ // }
130832
+ // table_filter.PushFilter(column_index, move(root_or_filter));
130833
+ // }
130834
+ // }
130835
+ // map_col_conjunctions.clear();
130836
+ // vec_colref_insertion_order.clear();
130837
+ //}
130803
130838
 
130804
130839
  } // namespace duckdb
130805
130840
  //===----------------------------------------------------------------------===//
@@ -133238,6 +133273,7 @@ private:
133238
133273
  unique_ptr<BaseStatistics> PropagateExpression(BoundBetweenExpression &expr, unique_ptr<Expression> *expr_ptr);
133239
133274
  unique_ptr<BaseStatistics> PropagateExpression(BoundCaseExpression &expr, unique_ptr<Expression> *expr_ptr);
133240
133275
  unique_ptr<BaseStatistics> PropagateExpression(BoundCastExpression &expr, unique_ptr<Expression> *expr_ptr);
133276
+ unique_ptr<BaseStatistics> PropagateExpression(BoundConjunctionExpression &expr, unique_ptr<Expression> *expr_ptr);
133241
133277
  unique_ptr<BaseStatistics> PropagateExpression(BoundFunctionExpression &expr, unique_ptr<Expression> *expr_ptr);
133242
133278
  unique_ptr<BaseStatistics> PropagateExpression(BoundComparisonExpression &expr, unique_ptr<Expression> *expr_ptr);
133243
133279
  unique_ptr<BaseStatistics> PropagateExpression(BoundConstantExpression &expr, unique_ptr<Expression> *expr_ptr);
@@ -136257,6 +136293,73 @@ unique_ptr<BaseStatistics> StatisticsPropagator::PropagateExpression(BoundCompar
136257
136293
 
136258
136294
 
136259
136295
 
136296
+
136297
+
136298
+
136299
+
136300
+
136301
+ namespace duckdb {
136302
+
136303
+ unique_ptr<BaseStatistics> StatisticsPropagator::PropagateExpression(BoundConjunctionExpression &expr,
136304
+ unique_ptr<Expression> *expr_ptr) {
136305
+ auto is_and = expr.type == ExpressionType::CONJUNCTION_AND;
136306
+ for (idx_t expr_idx = 0; expr_idx < expr.children.size(); expr_idx++) {
136307
+ auto &child = expr.children[expr_idx];
136308
+ auto stats = PropagateExpression(child);
136309
+ if (!child->IsFoldable()) {
136310
+ continue;
136311
+ }
136312
+ // we have a constant in a conjunction
136313
+ // we (1) either prune the child
136314
+ // or (2) replace the entire conjunction with a constant
136315
+ auto constant = ExpressionExecutor::EvaluateScalar(*child);
136316
+ if (constant.IsNull()) {
136317
+ continue;
136318
+ }
136319
+ auto b = BooleanValue::Get(constant);
136320
+ bool prune_child = false;
136321
+ bool constant_value = true;
136322
+ if (b) {
136323
+ // true
136324
+ if (is_and) {
136325
+ // true in and: prune child
136326
+ prune_child = true;
136327
+ } else {
136328
+ // true in OR: replace with TRUE
136329
+ constant_value = true;
136330
+ }
136331
+ } else {
136332
+ // false
136333
+ if (is_and) {
136334
+ // false in AND: replace with FALSE
136335
+ constant_value = false;
136336
+ } else {
136337
+ // false in OR: prune child
136338
+ prune_child = true;
136339
+ }
136340
+ }
136341
+ if (prune_child) {
136342
+ expr.children.erase(expr.children.begin() + expr_idx);
136343
+ expr_idx--;
136344
+ continue;
136345
+ }
136346
+ *expr_ptr = make_unique<BoundConstantExpression>(Value::BOOLEAN(constant_value));
136347
+ return PropagateExpression(*expr_ptr);
136348
+ }
136349
+ if (expr.children.empty()) {
136350
+ // if there are no children left, replace the conjunction with TRUE (for AND) or FALSE (for OR)
136351
+ *expr_ptr = make_unique<BoundConstantExpression>(Value::BOOLEAN(is_and));
136352
+ return PropagateExpression(*expr_ptr);
136353
+ } else if (expr.children.size() == 1) {
136354
+ // if there is one child left, replace the conjunction with that one child
136355
+ *expr_ptr = move(expr.children[0]);
136356
+ }
136357
+ return nullptr;
136358
+ }
136359
+
136360
+ } // namespace duckdb
136361
+
136362
+
136260
136363
  //===----------------------------------------------------------------------===//
136261
136364
  // DuckDB
136262
136365
  //
@@ -136577,7 +136680,7 @@ bool StatisticsPropagator::ExpressionIsConstant(Expression &expr, const Value &v
136577
136680
  }
136578
136681
  auto &bound_constant = (BoundConstantExpression &)expr;
136579
136682
  D_ASSERT(bound_constant.value.type() == val.type());
136580
- return bound_constant.value == val;
136683
+ return Value::NotDistinctFrom(bound_constant.value, val);
136581
136684
  }
136582
136685
 
136583
136686
  bool StatisticsPropagator::ExpressionIsConstantOrNull(Expression &expr, const Value &val) {
@@ -137361,6 +137464,8 @@ unique_ptr<BaseStatistics> StatisticsPropagator::PropagateExpression(Expression
137361
137464
  return PropagateExpression((BoundBetweenExpression &)expr, expr_ptr);
137362
137465
  case ExpressionClass::BOUND_CASE:
137363
137466
  return PropagateExpression((BoundCaseExpression &)expr, expr_ptr);
137467
+ case ExpressionClass::BOUND_CONJUNCTION:
137468
+ return PropagateExpression((BoundConjunctionExpression &)expr, expr_ptr);
137364
137469
  case ExpressionClass::BOUND_FUNCTION:
137365
137470
  return PropagateExpression((BoundFunctionExpression &)expr, expr_ptr);
137366
137471
  case ExpressionClass::BOUND_CAST: