duckdb 0.3.5-dev593.0 → 0.3.5-dev604.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
@@ -4681,6 +4681,7 @@ CatalogEntry *CatalogSet::CreateEntryInternal(ClientContext &context, unique_ptr
4681
4681
  auto entry_index = current_entry++;
4682
4682
  auto catalog_entry = entry.get();
4683
4683
 
4684
+ entry->set = this;
4684
4685
  entry->timestamp = 0;
4685
4686
 
4686
4687
  PutMapping(context, name, entry_index);
@@ -5376,6 +5377,9 @@ void DependencyManager::AddObject(ClientContext &context, CatalogEntry *object,
5376
5377
  for (auto &dependency : dependencies) {
5377
5378
  idx_t entry_index;
5378
5379
  CatalogEntry *catalog_entry;
5380
+ if (!dependency->set) {
5381
+ throw InternalException("Dependency has no set");
5382
+ }
5379
5383
  if (!dependency->set->GetEntryInternal(context, dependency->name, entry_index, catalog_entry)) {
5380
5384
  throw InternalException("Dependency has already been deleted?");
5381
5385
  }
@@ -38514,11 +38518,39 @@ bool ChunkCollection::Equals(ChunkCollection &other) {
38514
38518
  if (ColumnCount() != other.ColumnCount()) {
38515
38519
  return false;
38516
38520
  }
38517
- // if count is equal amount of chunks should be equal
38521
+ // first try to compare the results as-is
38522
+ bool compare_equals = true;
38518
38523
  for (idx_t row_idx = 0; row_idx < count; row_idx++) {
38519
38524
  for (idx_t col_idx = 0; col_idx < ColumnCount(); col_idx++) {
38520
38525
  auto lvalue = GetValue(col_idx, row_idx);
38521
38526
  auto rvalue = other.GetValue(col_idx, row_idx);
38527
+ if (!Value::ValuesAreEqual(lvalue, rvalue)) {
38528
+ compare_equals = false;
38529
+ break;
38530
+ }
38531
+ }
38532
+ if (!compare_equals) {
38533
+ break;
38534
+ }
38535
+ }
38536
+ if (compare_equals) {
38537
+ return true;
38538
+ }
38539
+ // if the results are not equal,
38540
+ // sort both chunk collections to ensure the comparison is not order insensitive
38541
+ vector<OrderType> desc(ColumnCount(), OrderType::DESCENDING);
38542
+ vector<OrderByNullType> null_order(ColumnCount(), OrderByNullType::NULLS_FIRST);
38543
+ auto this_order = unique_ptr<idx_t[]>(new idx_t[count]);
38544
+ auto other_order = unique_ptr<idx_t[]>(new idx_t[count]);
38545
+ Sort(desc, null_order, this_order.get());
38546
+ other.Sort(desc, null_order, other_order.get());
38547
+
38548
+ for (idx_t row_idx = 0; row_idx < count; row_idx++) {
38549
+ auto lrow = this_order[row_idx];
38550
+ auto rrow = other_order[row_idx];
38551
+ for (idx_t col_idx = 0; col_idx < ColumnCount(); col_idx++) {
38552
+ auto lvalue = GetValue(col_idx, lrow);
38553
+ auto rvalue = other.GetValue(col_idx, rrow);
38522
38554
  if (!Value::ValuesAreEqual(lvalue, rvalue)) {
38523
38555
  return false;
38524
38556
  }
@@ -112991,6 +113023,7 @@ private:
112991
113023
 
112992
113024
 
112993
113025
 
113026
+
112994
113027
  namespace duckdb {
112995
113028
 
112996
113029
  struct ActiveQueryContext {
@@ -113698,14 +113731,16 @@ void ClientContext::DisableProfiling() {
113698
113731
  }
113699
113732
 
113700
113733
  struct VerifyStatement {
113701
- VerifyStatement(unique_ptr<SelectStatement> statement_p, string statement_name_p, bool require_equality = true)
113734
+ VerifyStatement(unique_ptr<SelectStatement> statement_p, string statement_name_p, bool require_equality = true,
113735
+ bool disable_optimizer = false)
113702
113736
  : statement(move(statement_p)), statement_name(move(statement_name_p)), require_equality(require_equality),
113703
- select_list(statement->node->GetSelectList()) {
113737
+ disable_optimizer(disable_optimizer), select_list(statement->node->GetSelectList()) {
113704
113738
  }
113705
113739
 
113706
113740
  unique_ptr<SelectStatement> statement;
113707
113741
  string statement_name;
113708
113742
  bool require_equality;
113743
+ bool disable_optimizer;
113709
113744
  const vector<unique_ptr<ParsedExpression>> &select_list;
113710
113745
  };
113711
113746
 
@@ -113733,8 +113768,9 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
113733
113768
  BufferedDeserializer source(serializer);
113734
113769
  auto deserialized_stmt = SelectStatement::Deserialize(source);
113735
113770
 
113771
+ auto query_str = select_stmt->ToString();
113736
113772
  Parser parser;
113737
- parser.ParseQuery(select_stmt->ToString());
113773
+ parser.ParseQuery(query_str);
113738
113774
  D_ASSERT(parser.statements.size() == 1);
113739
113775
  D_ASSERT(parser.statements[0]->type == StatementType::SELECT_STATEMENT);
113740
113776
  auto parsed_statement = move(parser.statements[0]);
@@ -113745,6 +113781,8 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
113745
113781
  verify_statements.emplace_back(move(deserialized_stmt), "Deserialized statement");
113746
113782
  verify_statements.emplace_back(unique_ptr_cast<SQLStatement, SelectStatement>(move(parsed_statement)),
113747
113783
  "Parsed statement", false);
113784
+ verify_statements.emplace_back(unique_ptr_cast<SQLStatement, SelectStatement>(move(unoptimized_stmt)),
113785
+ "Unoptimized", true, true);
113748
113786
 
113749
113787
  // all the statements should be equal
113750
113788
  for (idx_t i = 1; i < verify_statements.size(); i++) {
@@ -113809,9 +113847,11 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
113809
113847
  auto statement_copy_for_explain = select_stmt->Copy();
113810
113848
 
113811
113849
  // execute the original statement
113850
+ auto optimizer_enabled = config.enable_optimizer;
113812
113851
  vector<unique_ptr<MaterializedQueryResult>> results;
113813
113852
  for (idx_t i = 0; i < verify_statements.size(); i++) {
113814
113853
  interrupted = false;
113854
+ config.enable_optimizer = !verify_statements[i].disable_optimizer;
113815
113855
  try {
113816
113856
  auto result = RunStatementInternal(lock, query, move(verify_statements[i].statement), false, false);
113817
113857
  results.push_back(unique_ptr_cast<QueryResult, MaterializedQueryResult>(move(result)));
@@ -113819,6 +113859,7 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
113819
113859
  results.push_back(make_unique<MaterializedQueryResult>(ex.what()));
113820
113860
  }
113821
113861
  }
113862
+ config.enable_optimizer = optimizer_enabled;
113822
113863
 
113823
113864
  // check explain, only if q does not already contain EXPLAIN
113824
113865
  if (results[0]->success) {
@@ -113831,8 +113872,6 @@ string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query,
113831
113872
  } // LCOV_EXCL_STOP
113832
113873
  }
113833
113874
 
113834
- config.enable_optimizer = true;
113835
-
113836
113875
  if (profiling_is_enabled) {
113837
113876
  config.enable_profiler = true;
113838
113877
  }
@@ -129547,37 +129586,37 @@ private:
129547
129586
  Expression *GetNode(Expression *expr);
129548
129587
  idx_t GetEquivalenceSet(Expression *expr);
129549
129588
  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
- }
129589
+ //
129590
+ // //! Functions used to push and generate OR Filters
129591
+ // void LookUpConjunctions(Expression *expr);
129592
+ // bool BFSLookUpConjunctions(BoundConjunctionExpression *conjunction);
129593
+ // void VerifyOrsToPush(Expression &expr);
129594
+ //
129595
+ // bool UpdateConjunctionFilter(BoundComparisonExpression *comparison_expr);
129596
+ // bool UpdateFilterByColumn(BoundColumnRefExpression *column_ref, BoundComparisonExpression *comparison_expr);
129597
+ // void GenerateORFilters(TableFilterSet &table_filter, vector<idx_t> &column_ids);
129598
+ //
129599
+ // template <typename CONJUNCTION_TYPE>
129600
+ // void GenerateConjunctionFilter(BoundConjunctionExpression *conjunction, ConjunctionFilter *last_conj_filter) {
129601
+ // auto new_filter = NextConjunctionFilter<CONJUNCTION_TYPE>(conjunction);
129602
+ // auto conj_filter_ptr = (ConjunctionFilter *)new_filter.get();
129603
+ // last_conj_filter->child_filters.push_back(move(new_filter));
129604
+ // last_conj_filter = conj_filter_ptr;
129605
+ // }
129606
+ //
129607
+ // template <typename CONJUNCTION_TYPE>
129608
+ // unique_ptr<TableFilter> NextConjunctionFilter(BoundConjunctionExpression *conjunction) {
129609
+ // unique_ptr<ConjunctionFilter> conj_filter = make_unique<CONJUNCTION_TYPE>();
129610
+ // for (auto &expr : conjunction->children) {
129611
+ // auto comp_expr = (BoundComparisonExpression *)expr.get();
129612
+ // auto &const_expr =
129613
+ // (comp_expr->left->type == ExpressionType::VALUE_CONSTANT) ? *comp_expr->left : *comp_expr->right;
129614
+ // auto const_value = ExpressionExecutor::EvaluateScalar(const_expr);
129615
+ // auto const_filter = make_unique<ConstantFilter>(comp_expr->type, const_value);
129616
+ // conj_filter->child_filters.push_back(move(const_filter));
129617
+ // }
129618
+ // return move(conj_filter);
129619
+ // }
129581
129620
 
129582
129621
  private:
129583
129622
  vector<unique_ptr<Expression>> remaining_filters;
@@ -129587,26 +129626,26 @@ private:
129587
129626
  unordered_map<idx_t, vector<ExpressionValueInformation>> constant_values;
129588
129627
  unordered_map<idx_t, vector<Expression *>> equivalence_map;
129589
129628
  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;
129629
+ //
129630
+ // //! Structures used for OR Filters
129631
+ //
129632
+ // struct ConjunctionsToPush {
129633
+ // BoundConjunctionExpression *root_or;
129634
+ //
129635
+ // // only preserve AND if there is a single column in the expression
129636
+ // bool preserve_and = true;
129637
+ //
129638
+ // // conjunction chain for this column
129639
+ // vector<unique_ptr<BoundConjunctionExpression>> conjunctions;
129640
+ // };
129641
+ //
129642
+ // expression_map_t<vector<unique_ptr<ConjunctionsToPush>>> map_col_conjunctions;
129643
+ // vector<BoundColumnRefExpression *> vec_colref_insertion_order;
129644
+ //
129645
+ // BoundConjunctionExpression *cur_root_or;
129646
+ // BoundConjunctionExpression *cur_conjunction;
129647
+ //
129648
+ // BoundColumnRefExpression *cur_colref_to_push;
129610
129649
  };
129611
129650
 
129612
129651
  } // namespace duckdb
@@ -129691,7 +129730,7 @@ FilterResult FilterCombiner::AddConstantComparison(vector<ExpressionValueInforma
129691
129730
  }
129692
129731
 
129693
129732
  FilterResult FilterCombiner::AddFilter(unique_ptr<Expression> expr) {
129694
- LookUpConjunctions(expr.get());
129733
+ // LookUpConjunctions(expr.get());
129695
129734
  // try to push the filter into the combiner
129696
129735
  auto result = AddFilter(expr.get());
129697
129736
  if (result == FilterResult::UNSUPPORTED) {
@@ -130161,7 +130200,7 @@ TableFilterSet FilterCombiner::GenerateTableScanFilters(vector<idx_t> &column_id
130161
130200
  }
130162
130201
  }
130163
130202
 
130164
- GenerateORFilters(table_filters, column_ids);
130203
+ // GenerateORFilters(table_filters, column_ids);
130165
130204
 
130166
130205
  return table_filters;
130167
130206
  }
@@ -130630,176 +130669,176 @@ ValueComparisonResult CompareValueInformation(ExpressionValueInformation &left,
130630
130669
  return InvertValueComparisonResult(CompareValueInformation(right, left));
130631
130670
  }
130632
130671
  }
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
- }
130672
+ //
130673
+ // void FilterCombiner::LookUpConjunctions(Expression *expr) {
130674
+ // if (expr->GetExpressionType() == ExpressionType::CONJUNCTION_OR) {
130675
+ // auto root_or_expr = (BoundConjunctionExpression *)expr;
130676
+ // for (const auto &entry : map_col_conjunctions) {
130677
+ // for (const auto &conjs_to_push : entry.second) {
130678
+ // if (conjs_to_push->root_or->Equals(root_or_expr)) {
130679
+ // return;
130680
+ // }
130681
+ // }
130682
+ // }
130683
+ //
130684
+ // cur_root_or = root_or_expr;
130685
+ // cur_conjunction = root_or_expr;
130686
+ // cur_colref_to_push = nullptr;
130687
+ // if (!BFSLookUpConjunctions(cur_root_or)) {
130688
+ // if (cur_colref_to_push) {
130689
+ // auto entry = map_col_conjunctions.find(cur_colref_to_push);
130690
+ // auto &vec_conjs_to_push = entry->second;
130691
+ // if (vec_conjs_to_push.size() == 1) {
130692
+ // map_col_conjunctions.erase(entry);
130693
+ // return;
130694
+ // }
130695
+ // vec_conjs_to_push.pop_back();
130696
+ // }
130697
+ // }
130698
+ // return;
130699
+ // }
130700
+ //
130701
+ // // Verify if the expression has a column already pushed down by other OR expression
130702
+ // VerifyOrsToPush(*expr);
130703
+ //}
130704
+ //
130705
+ // bool FilterCombiner::BFSLookUpConjunctions(BoundConjunctionExpression *conjunction) {
130706
+ // vector<BoundConjunctionExpression *> conjunctions_to_visit;
130707
+ //
130708
+ // for (auto &child : conjunction->children) {
130709
+ // switch (child->GetExpressionClass()) {
130710
+ // case ExpressionClass::BOUND_CONJUNCTION: {
130711
+ // auto child_conjunction = (BoundConjunctionExpression *)child.get();
130712
+ // conjunctions_to_visit.emplace_back(child_conjunction);
130713
+ // break;
130714
+ // }
130715
+ // case ExpressionClass::BOUND_COMPARISON: {
130716
+ // if (!UpdateConjunctionFilter((BoundComparisonExpression *)child.get())) {
130717
+ // return false;
130718
+ // }
130719
+ // break;
130720
+ // }
130721
+ // default: {
130722
+ // return false;
130723
+ // }
130724
+ // }
130725
+ // }
130726
+ //
130727
+ // for (auto child_conjunction : conjunctions_to_visit) {
130728
+ // cur_conjunction = child_conjunction;
130729
+ // // traverse child conjuction
130730
+ // if (!BFSLookUpConjunctions(child_conjunction)) {
130731
+ // return false;
130732
+ // }
130733
+ // }
130734
+ // return true;
130735
+ //}
130736
+ //
130737
+ // void FilterCombiner::VerifyOrsToPush(Expression &expr) {
130738
+ // if (expr.type == ExpressionType::BOUND_COLUMN_REF) {
130739
+ // auto colref = (BoundColumnRefExpression *)&expr;
130740
+ // auto entry = map_col_conjunctions.find(colref);
130741
+ // if (entry == map_col_conjunctions.end()) {
130742
+ // return;
130743
+ // }
130744
+ // map_col_conjunctions.erase(entry);
130745
+ // }
130746
+ // ExpressionIterator::EnumerateChildren(expr, [&](Expression &child) { VerifyOrsToPush(child); });
130747
+ //}
130748
+ //
130749
+ // bool FilterCombiner::UpdateConjunctionFilter(BoundComparisonExpression *comparison_expr) {
130750
+ // bool left_is_scalar = comparison_expr->left->IsFoldable();
130751
+ // bool right_is_scalar = comparison_expr->right->IsFoldable();
130752
+ //
130753
+ // Expression *non_scalar_expr;
130754
+ // if (left_is_scalar || right_is_scalar) {
130755
+ // // only support comparison with scalar
130756
+ // non_scalar_expr = left_is_scalar ? comparison_expr->right.get() : comparison_expr->left.get();
130757
+ //
130758
+ // if (non_scalar_expr->GetExpressionType() == ExpressionType::BOUND_COLUMN_REF) {
130759
+ // return UpdateFilterByColumn((BoundColumnRefExpression *)non_scalar_expr, comparison_expr);
130760
+ // }
130761
+ // }
130762
+ //
130763
+ // return false;
130764
+ //}
130765
+ //
130766
+ // bool FilterCombiner::UpdateFilterByColumn(BoundColumnRefExpression *column_ref,
130767
+ // BoundComparisonExpression *comparison_expr) {
130768
+ // if (cur_colref_to_push == nullptr) {
130769
+ // cur_colref_to_push = column_ref;
130770
+ //
130771
+ // auto or_conjunction = make_unique<BoundConjunctionExpression>(ExpressionType::CONJUNCTION_OR);
130772
+ // or_conjunction->children.emplace_back(comparison_expr->Copy());
130773
+ //
130774
+ // unique_ptr<ConjunctionsToPush> conjs_to_push = make_unique<ConjunctionsToPush>();
130775
+ // conjs_to_push->conjunctions.emplace_back(move(or_conjunction));
130776
+ // conjs_to_push->root_or = cur_root_or;
130777
+ //
130778
+ // auto &&vec_col_conjs = map_col_conjunctions[column_ref];
130779
+ // vec_col_conjs.emplace_back(move(conjs_to_push));
130780
+ // vec_colref_insertion_order.emplace_back(column_ref);
130781
+ // return true;
130782
+ // }
130783
+ //
130784
+ // auto entry = map_col_conjunctions.find(cur_colref_to_push);
130785
+ // D_ASSERT(entry != map_col_conjunctions.end());
130786
+ // auto &conjunctions_to_push = entry->second.back();
130787
+ //
130788
+ // if (!cur_colref_to_push->Equals(column_ref)) {
130789
+ // // check for multiple colunms in the same root OR node
130790
+ // if (cur_root_or == cur_conjunction) {
130791
+ // return false;
130792
+ // }
130793
+ // // found an AND using a different column, we should stop the look up
130794
+ // if (cur_conjunction->GetExpressionType() == ExpressionType::CONJUNCTION_AND) {
130795
+ // return false;
130796
+ // }
130797
+ //
130798
+ // // found a different column, AND conditions cannot be preserved anymore
130799
+ // conjunctions_to_push->preserve_and = false;
130800
+ // return true;
130801
+ // }
130802
+ //
130803
+ // auto &last_conjunction = conjunctions_to_push->conjunctions.back();
130804
+ // if (cur_conjunction->GetExpressionType() == last_conjunction->GetExpressionType()) {
130805
+ // last_conjunction->children.emplace_back(comparison_expr->Copy());
130806
+ // } else {
130807
+ // auto new_conjunction = make_unique<BoundConjunctionExpression>(cur_conjunction->GetExpressionType());
130808
+ // new_conjunction->children.emplace_back(comparison_expr->Copy());
130809
+ // conjunctions_to_push->conjunctions.emplace_back(move(new_conjunction));
130810
+ // }
130811
+ // return true;
130812
+ //}
130813
+ //
130814
+ // void FilterCombiner::GenerateORFilters(TableFilterSet &table_filter, vector<idx_t> &column_ids) {
130815
+ // for (const auto colref : vec_colref_insertion_order) {
130816
+ // auto column_index = column_ids[colref->binding.column_index];
130817
+ // if (column_index == COLUMN_IDENTIFIER_ROW_ID) {
130818
+ // break;
130819
+ // }
130820
+ //
130821
+ // for (const auto &conjunctions_to_push : map_col_conjunctions[colref]) {
130822
+ // // root OR filter to push into the TableFilter
130823
+ // auto root_or_filter = make_unique<ConjunctionOrFilter>();
130824
+ // // variable to hold the last conjuntion filter pointer
130825
+ // // the next filter will be added into it, i.e., we create a chain of conjunction filters
130826
+ // ConjunctionFilter *last_conj_filter = root_or_filter.get();
130827
+ //
130828
+ // for (auto &conjunction : conjunctions_to_push->conjunctions) {
130829
+ // if (conjunction->GetExpressionType() == ExpressionType::CONJUNCTION_AND &&
130830
+ // conjunctions_to_push->preserve_and) {
130831
+ // GenerateConjunctionFilter<ConjunctionAndFilter>(conjunction.get(), last_conj_filter);
130832
+ // } else {
130833
+ // GenerateConjunctionFilter<ConjunctionOrFilter>(conjunction.get(), last_conj_filter);
130834
+ // }
130835
+ // }
130836
+ // table_filter.PushFilter(column_index, move(root_or_filter));
130837
+ // }
130838
+ // }
130839
+ // map_col_conjunctions.clear();
130840
+ // vec_colref_insertion_order.clear();
130841
+ //}
130803
130842
 
130804
130843
  } // namespace duckdb
130805
130844
  //===----------------------------------------------------------------------===//
@@ -133238,6 +133277,7 @@ private:
133238
133277
  unique_ptr<BaseStatistics> PropagateExpression(BoundBetweenExpression &expr, unique_ptr<Expression> *expr_ptr);
133239
133278
  unique_ptr<BaseStatistics> PropagateExpression(BoundCaseExpression &expr, unique_ptr<Expression> *expr_ptr);
133240
133279
  unique_ptr<BaseStatistics> PropagateExpression(BoundCastExpression &expr, unique_ptr<Expression> *expr_ptr);
133280
+ unique_ptr<BaseStatistics> PropagateExpression(BoundConjunctionExpression &expr, unique_ptr<Expression> *expr_ptr);
133241
133281
  unique_ptr<BaseStatistics> PropagateExpression(BoundFunctionExpression &expr, unique_ptr<Expression> *expr_ptr);
133242
133282
  unique_ptr<BaseStatistics> PropagateExpression(BoundComparisonExpression &expr, unique_ptr<Expression> *expr_ptr);
133243
133283
  unique_ptr<BaseStatistics> PropagateExpression(BoundConstantExpression &expr, unique_ptr<Expression> *expr_ptr);
@@ -136257,6 +136297,73 @@ unique_ptr<BaseStatistics> StatisticsPropagator::PropagateExpression(BoundCompar
136257
136297
 
136258
136298
 
136259
136299
 
136300
+
136301
+
136302
+
136303
+
136304
+
136305
+ namespace duckdb {
136306
+
136307
+ unique_ptr<BaseStatistics> StatisticsPropagator::PropagateExpression(BoundConjunctionExpression &expr,
136308
+ unique_ptr<Expression> *expr_ptr) {
136309
+ auto is_and = expr.type == ExpressionType::CONJUNCTION_AND;
136310
+ for (idx_t expr_idx = 0; expr_idx < expr.children.size(); expr_idx++) {
136311
+ auto &child = expr.children[expr_idx];
136312
+ auto stats = PropagateExpression(child);
136313
+ if (!child->IsFoldable()) {
136314
+ continue;
136315
+ }
136316
+ // we have a constant in a conjunction
136317
+ // we (1) either prune the child
136318
+ // or (2) replace the entire conjunction with a constant
136319
+ auto constant = ExpressionExecutor::EvaluateScalar(*child);
136320
+ if (constant.IsNull()) {
136321
+ continue;
136322
+ }
136323
+ auto b = BooleanValue::Get(constant);
136324
+ bool prune_child = false;
136325
+ bool constant_value = true;
136326
+ if (b) {
136327
+ // true
136328
+ if (is_and) {
136329
+ // true in and: prune child
136330
+ prune_child = true;
136331
+ } else {
136332
+ // true in OR: replace with TRUE
136333
+ constant_value = true;
136334
+ }
136335
+ } else {
136336
+ // false
136337
+ if (is_and) {
136338
+ // false in AND: replace with FALSE
136339
+ constant_value = false;
136340
+ } else {
136341
+ // false in OR: prune child
136342
+ prune_child = true;
136343
+ }
136344
+ }
136345
+ if (prune_child) {
136346
+ expr.children.erase(expr.children.begin() + expr_idx);
136347
+ expr_idx--;
136348
+ continue;
136349
+ }
136350
+ *expr_ptr = make_unique<BoundConstantExpression>(Value::BOOLEAN(constant_value));
136351
+ return PropagateExpression(*expr_ptr);
136352
+ }
136353
+ if (expr.children.empty()) {
136354
+ // if there are no children left, replace the conjunction with TRUE (for AND) or FALSE (for OR)
136355
+ *expr_ptr = make_unique<BoundConstantExpression>(Value::BOOLEAN(is_and));
136356
+ return PropagateExpression(*expr_ptr);
136357
+ } else if (expr.children.size() == 1) {
136358
+ // if there is one child left, replace the conjunction with that one child
136359
+ *expr_ptr = move(expr.children[0]);
136360
+ }
136361
+ return nullptr;
136362
+ }
136363
+
136364
+ } // namespace duckdb
136365
+
136366
+
136260
136367
  //===----------------------------------------------------------------------===//
136261
136368
  // DuckDB
136262
136369
  //
@@ -136577,7 +136684,7 @@ bool StatisticsPropagator::ExpressionIsConstant(Expression &expr, const Value &v
136577
136684
  }
136578
136685
  auto &bound_constant = (BoundConstantExpression &)expr;
136579
136686
  D_ASSERT(bound_constant.value.type() == val.type());
136580
- return bound_constant.value == val;
136687
+ return Value::NotDistinctFrom(bound_constant.value, val);
136581
136688
  }
136582
136689
 
136583
136690
  bool StatisticsPropagator::ExpressionIsConstantOrNull(Expression &expr, const Value &val) {
@@ -137361,6 +137468,8 @@ unique_ptr<BaseStatistics> StatisticsPropagator::PropagateExpression(Expression
137361
137468
  return PropagateExpression((BoundBetweenExpression &)expr, expr_ptr);
137362
137469
  case ExpressionClass::BOUND_CASE:
137363
137470
  return PropagateExpression((BoundCaseExpression &)expr, expr_ptr);
137471
+ case ExpressionClass::BOUND_CONJUNCTION:
137472
+ return PropagateExpression((BoundConjunctionExpression &)expr, expr_ptr);
137364
137473
  case ExpressionClass::BOUND_FUNCTION:
137365
137474
  return PropagateExpression((BoundFunctionExpression &)expr, expr_ptr);
137366
137475
  case ExpressionClass::BOUND_CAST: