diff --git a/src/duckdb/src/common/enum_util.cpp b/src/duckdb/src/common/enum_util.cpp index 1bf5c17c8..c2399720c 100644 --- a/src/duckdb/src/common/enum_util.cpp +++ b/src/duckdb/src/common/enum_util.cpp @@ -4093,8 +4093,6 @@ const char* EnumUtil::ToChars(PhysicalOperatorType value) return "IE_JOIN"; case PhysicalOperatorType::DELIM_JOIN: return "DELIM_JOIN"; - case PhysicalOperatorType::INDEX_JOIN: - return "INDEX_JOIN"; case PhysicalOperatorType::POSITIONAL_JOIN: return "POSITIONAL_JOIN"; case PhysicalOperatorType::ASOF_JOIN: @@ -4284,9 +4282,6 @@ PhysicalOperatorType EnumUtil::FromString(const char *valu if (StringUtil::Equals(value, "DELIM_JOIN")) { return PhysicalOperatorType::DELIM_JOIN; } - if (StringUtil::Equals(value, "INDEX_JOIN")) { - return PhysicalOperatorType::INDEX_JOIN; - } if (StringUtil::Equals(value, "POSITIONAL_JOIN")) { return PhysicalOperatorType::POSITIONAL_JOIN; } diff --git a/src/duckdb/src/common/enums/physical_operator_type.cpp b/src/duckdb/src/common/enums/physical_operator_type.cpp index e07942d1e..ecb384884 100644 --- a/src/duckdb/src/common/enums/physical_operator_type.cpp +++ b/src/duckdb/src/common/enums/physical_operator_type.cpp @@ -59,8 +59,6 @@ string PhysicalOperatorToString(PhysicalOperatorType type) { return "NESTED_LOOP_JOIN"; case PhysicalOperatorType::HASH_JOIN: return "HASH_JOIN"; - case PhysicalOperatorType::INDEX_JOIN: - return "INDEX_JOIN"; case PhysicalOperatorType::PIECEWISE_MERGE_JOIN: return "PIECEWISE_MERGE_JOIN"; case PhysicalOperatorType::IE_JOIN: diff --git a/src/duckdb/src/execution/operator/join/physical_index_join.cpp b/src/duckdb/src/execution/operator/join/physical_index_join.cpp deleted file mode 100644 index 3035e0ecd..000000000 --- a/src/duckdb/src/execution/operator/join/physical_index_join.cpp +++ /dev/null @@ -1,242 +0,0 @@ -#include "duckdb/execution/operator/join/physical_index_join.hpp" - -#include "duckdb/common/vector_operations/vector_operations.hpp" -#include "duckdb/execution/expression_executor.hpp" -#include "duckdb/execution/index/art/art.hpp" -#include "duckdb/execution/operator/scan/physical_table_scan.hpp" -#include "duckdb/function/table/table_scan.hpp" -#include "duckdb/parallel/meta_pipeline.hpp" -#include "duckdb/parallel/thread_context.hpp" -#include "duckdb/storage/buffer_manager.hpp" -#include "duckdb/storage/storage_manager.hpp" -#include "duckdb/storage/table/append_state.hpp" -#include "duckdb/transaction/duck_transaction.hpp" -#include "duckdb/catalog/catalog_entry/duck_table_entry.hpp" -#include "duckdb/storage/table/scan_state.hpp" -#include "duckdb/execution/index/art/art_key.hpp" - -namespace duckdb { - -class IndexJoinOperatorState : public CachingOperatorState { -public: - IndexJoinOperatorState(ClientContext &context, const PhysicalIndexJoin &op) - : probe_executor(context), arena_allocator(BufferAllocator::Get(context)), keys(STANDARD_VECTOR_SIZE) { - auto &allocator = Allocator::Get(context); - rhs_rows.resize(STANDARD_VECTOR_SIZE); - result_sizes.resize(STANDARD_VECTOR_SIZE); - - join_keys.Initialize(allocator, op.condition_types); - for (auto &cond : op.conditions) { - probe_executor.AddExpression(*cond.left); - } - if (!op.fetch_types.empty()) { - rhs_chunk.Initialize(allocator, op.fetch_types); - } - rhs_sel.Initialize(STANDARD_VECTOR_SIZE); - } - - bool first_fetch = true; - idx_t lhs_idx = 0; - idx_t rhs_idx = 0; - idx_t result_size = 0; - vector result_sizes; - DataChunk join_keys; - DataChunk rhs_chunk; - SelectionVector rhs_sel; - - //! Vector of rows that mush be fetched for every LHS key - vector> rhs_rows; - ExpressionExecutor probe_executor; - - ArenaAllocator arena_allocator; - vector keys; - unique_ptr fetch_state; - -public: - void Finalize(const PhysicalOperator &op, ExecutionContext &context) override { - context.thread.profiler.Flush(op, probe_executor, "probe_executor", 0); - } -}; - -PhysicalIndexJoin::PhysicalIndexJoin(LogicalOperator &op, unique_ptr left, - unique_ptr right, vector cond, JoinType join_type, - const vector &left_projection_map_p, vector right_projection_map_p, - vector column_ids_p, Index &index_p, bool lhs_first, - idx_t estimated_cardinality) - : CachingPhysicalOperator(PhysicalOperatorType::INDEX_JOIN, std::move(op.types), estimated_cardinality), - left_projection_map(left_projection_map_p), right_projection_map(std::move(right_projection_map_p)), - index(index_p), conditions(std::move(cond)), join_type(join_type), lhs_first(lhs_first) { - D_ASSERT(right->type == PhysicalOperatorType::TABLE_SCAN); - auto &tbl_scan = right->Cast(); - column_ids = std::move(column_ids_p); - children.push_back(std::move(left)); - children.push_back(std::move(right)); - for (auto &condition : conditions) { - condition_types.push_back(condition.left->return_type); - } - //! Only add to fetch_ids columns that are not indexed - for (auto &index_id : index.column_ids) { - index_ids.insert(index_id); - } - - for (idx_t i = 0; i < column_ids.size(); i++) { - auto column_id = column_ids[i]; - auto it = index_ids.find(column_id); - if (it == index_ids.end()) { - fetch_ids.push_back(column_id); - if (column_id == COLUMN_IDENTIFIER_ROW_ID) { - fetch_types.emplace_back(LogicalType::ROW_TYPE); - } else { - fetch_types.push_back(tbl_scan.returned_types[column_id]); - } - } - } - if (right_projection_map.empty()) { - for (column_t i = 0; i < column_ids.size(); i++) { - right_projection_map.push_back(i); - } - } - if (left_projection_map.empty()) { - for (column_t i = 0; i < children[0]->types.size(); i++) { - left_projection_map.push_back(i); - } - } -} - -unique_ptr PhysicalIndexJoin::GetOperatorState(ExecutionContext &context) const { - return make_uniq(context.client, *this); -} - -void PhysicalIndexJoin::Output(ExecutionContext &context, DataChunk &input, DataChunk &chunk, - OperatorState &state_p) const { - auto &phy_tbl_scan = children[1]->Cast(); - auto &bind_tbl = phy_tbl_scan.bind_data->Cast(); - auto &transaction = DuckTransaction::Get(context.client, bind_tbl.table.catalog); - auto &state = state_p.Cast(); - - auto &tbl = bind_tbl.table.GetStorage(); - idx_t output_sel_idx = 0; - vector fetch_rows; - - while (output_sel_idx < STANDARD_VECTOR_SIZE && state.lhs_idx < input.size()) { - if (state.rhs_idx < state.result_sizes[state.lhs_idx]) { - state.rhs_sel.set_index(output_sel_idx++, state.lhs_idx); - if (!fetch_types.empty()) { - //! We need to collect the rows we want to fetch - fetch_rows.push_back(state.rhs_rows[state.lhs_idx][state.rhs_idx]); - } - state.rhs_idx++; - } else { - //! We are done with the matches from this LHS Key - state.rhs_idx = 0; - state.lhs_idx++; - } - } - //! Now we fetch the RHS data - if (!fetch_types.empty()) { - if (fetch_rows.empty()) { - return; - } - state.rhs_chunk.Reset(); - state.fetch_state = make_uniq(); - Vector row_ids(LogicalType::ROW_TYPE, data_ptr_cast(&fetch_rows[0])); - tbl.Fetch(transaction, state.rhs_chunk, fetch_ids, row_ids, output_sel_idx, *state.fetch_state); - } - - //! Now we actually produce our result chunk - idx_t left_offset = lhs_first ? 0 : right_projection_map.size(); - idx_t right_offset = lhs_first ? left_projection_map.size() : 0; - idx_t rhs_column_idx = 0; - for (idx_t i = 0; i < right_projection_map.size(); i++) { - auto it = index_ids.find(column_ids[right_projection_map[i]]); - if (it == index_ids.end()) { - chunk.data[right_offset + i].Reference(state.rhs_chunk.data[rhs_column_idx++]); - } else { - chunk.data[right_offset + i].Slice(state.join_keys.data[0], state.rhs_sel, output_sel_idx); - } - } - for (idx_t i = 0; i < left_projection_map.size(); i++) { - chunk.data[left_offset + i].Slice(input.data[left_projection_map[i]], state.rhs_sel, output_sel_idx); - } - - state.result_size = output_sel_idx; - chunk.SetCardinality(state.result_size); -} - -void PhysicalIndexJoin::GetRHSMatches(ExecutionContext &context, DataChunk &input, OperatorState &state_p) const { - - auto &state = state_p.Cast(); - auto &art = index.Cast(); - - // generate the keys for this chunk - state.arena_allocator.Reset(); - ART::GenerateKeys(state.arena_allocator, state.join_keys, state.keys); - - for (idx_t i = 0; i < input.size(); i++) { - state.rhs_rows[i].clear(); - if (!state.keys[i].Empty()) { - if (fetch_types.empty()) { - IndexLock lock; - index.InitializeLock(lock); - art.SearchEqualJoinNoFetch(state.keys[i], state.result_sizes[i]); - } else { - IndexLock lock; - index.InitializeLock(lock); - art.SearchEqual(state.keys[i], (idx_t)-1, state.rhs_rows[i]); - state.result_sizes[i] = state.rhs_rows[i].size(); - } - } else { - //! This is null so no matches - state.result_sizes[i] = 0; - } - } - for (idx_t i = input.size(); i < STANDARD_VECTOR_SIZE; i++) { - //! No LHS chunk value so result size is empty - state.result_sizes[i] = 0; - } -} - -OperatorResultType PhysicalIndexJoin::ExecuteInternal(ExecutionContext &context, DataChunk &input, DataChunk &chunk, - GlobalOperatorState &gstate, OperatorState &state_p) const { - auto &state = state_p.Cast(); - - state.result_size = 0; - if (state.first_fetch) { - state.probe_executor.Execute(input, state.join_keys); - - //! Fill Matches for the current LHS chunk - GetRHSMatches(context, input, state_p); - state.first_fetch = false; - } - //! Check if we need to get a new LHS chunk - if (state.lhs_idx >= input.size()) { - state.lhs_idx = 0; - state.rhs_idx = 0; - state.first_fetch = true; - // reset the LHS chunk to reset the validity masks - state.join_keys.Reset(); - return OperatorResultType::NEED_MORE_INPUT; - } - //! Output vectors - if (state.lhs_idx < input.size()) { - Output(context, input, chunk, state_p); - } - return OperatorResultType::HAVE_MORE_OUTPUT; -} - -//===--------------------------------------------------------------------===// -// Pipeline Construction -//===--------------------------------------------------------------------===// -void PhysicalIndexJoin::BuildPipelines(Pipeline ¤t, MetaPipeline &meta_pipeline) { - // index join: we only continue into the LHS - // the right side is probed by the index join - // so we don't need to do anything in the pipeline with this child - meta_pipeline.GetState().AddPipelineOperator(current, *this); - children[0]->BuildPipelines(current, meta_pipeline); -} - -vector> PhysicalIndexJoin::GetSources() const { - return children[0]->GetSources(); -} - -} // namespace duckdb diff --git a/src/duckdb/src/execution/physical_plan/plan_comparison_join.cpp b/src/duckdb/src/execution/physical_plan/plan_comparison_join.cpp index 2dcd035fb..f85be4ec8 100644 --- a/src/duckdb/src/execution/physical_plan/plan_comparison_join.cpp +++ b/src/duckdb/src/execution/physical_plan/plan_comparison_join.cpp @@ -2,7 +2,6 @@ #include "duckdb/execution/operator/join/physical_cross_product.hpp" #include "duckdb/execution/operator/join/physical_hash_join.hpp" #include "duckdb/execution/operator/join/physical_iejoin.hpp" -#include "duckdb/execution/operator/join/physical_index_join.hpp" #include "duckdb/execution/operator/join/physical_nested_loop_join.hpp" #include "duckdb/execution/operator/join/physical_piecewise_merge_join.hpp" #include "duckdb/execution/operator/scan/physical_table_scan.hpp" @@ -19,21 +18,6 @@ namespace duckdb { -static bool CanPlanIndexJoin(ClientContext &context, TableScanBindData &bind_data, PhysicalTableScan &scan) { - auto &table = bind_data.table; - auto &transaction = DuckTransaction::Get(context, table.catalog); - auto &local_storage = LocalStorage::Get(transaction); - if (local_storage.Find(table.GetStorage())) { - // transaction local appends: skip index join - return false; - } - if (scan.table_filters && !scan.table_filters->filters.empty()) { - // table scan filters - return false; - } - return true; -} - bool ExtractNumericValue(Value val, int64_t &result) { if (!val.type().IsIntegral()) { switch (val.type().InternalType()) { @@ -136,105 +120,6 @@ void CheckForPerfectJoinOpt(LogicalComparisonJoin &op, PerfectHashJoinStats &joi return; } -static optional_ptr CanUseIndexJoin(TableScanBindData &tbl, Expression &expr) { - optional_ptr result; - tbl.table.GetStorage().info->indexes.Scan([&](Index &index) { - if (index.unbound_expressions.size() != 1) { - return false; - } - if (expr.alias == index.unbound_expressions[0]->alias) { - result = &index; - return true; - } - return false; - }); - return result; -} - -optional_ptr CheckIndexJoin(ClientContext &context, LogicalComparisonJoin &op, PhysicalOperator &plan, - Expression &condition) { - if (op.type == LogicalOperatorType::LOGICAL_DELIM_JOIN) { - return nullptr; - } - // check if one of the tables has an index on column - if (op.join_type != JoinType::INNER) { - return nullptr; - } - if (op.conditions.size() != 1) { - return nullptr; - } - // check if the child is (1) a table scan, and (2) has an index on the join condition - if (plan.type != PhysicalOperatorType::TABLE_SCAN) { - return nullptr; - } - auto &tbl_scan = plan.Cast(); - auto tbl_data = dynamic_cast(tbl_scan.bind_data.get()); - if (!tbl_data) { - return nullptr; - } - optional_ptr result; - if (CanPlanIndexJoin(context, *tbl_data, tbl_scan)) { - result = CanUseIndexJoin(*tbl_data, condition); - } - return result; -} - -static bool PlanIndexJoin(ClientContext &context, LogicalComparisonJoin &op, unique_ptr &plan, - unique_ptr &left, unique_ptr &right, - optional_ptr index, bool swap_condition = false) { - if (!index) { - return false; - } - - // index joins are disabled if enable_optimizer is false - if (!ClientConfig::GetConfig(context).enable_optimizer) { - return false; - } - - // index joins are disabled on default - auto force_index_join = ClientConfig::GetConfig(context).force_index_join; - if (!ClientConfig::GetConfig(context).enable_index_join && !force_index_join) { - return false; - } - - // check if the cardinality difference justifies an index join - auto index_join_is_applicable = left->estimated_cardinality < 0.01 * right->estimated_cardinality; - if (!index_join_is_applicable && !force_index_join) { - return false; - } - - // plan the index join - if (swap_condition) { - swap(op.conditions[0].left, op.conditions[0].right); - swap(op.left_projection_map, op.right_projection_map); - } - D_ASSERT(right->type == PhysicalOperatorType::TABLE_SCAN); - auto &tbl_scan = right->Cast(); - - plan = make_uniq(op, std::move(left), std::move(right), std::move(op.conditions), op.join_type, - op.left_projection_map, op.right_projection_map, tbl_scan.column_ids, *index, - !swap_condition, op.estimated_cardinality); - return true; -} - -static bool PlanIndexJoin(ClientContext &context, LogicalComparisonJoin &op, unique_ptr &plan, - unique_ptr &left, unique_ptr &right) { - if (op.conditions.empty()) { - return false; - } - // check if we can plan an index join on the RHS - auto right_index = CheckIndexJoin(context, op, *right, *op.conditions[0].right); - if (PlanIndexJoin(context, op, plan, left, right, right_index)) { - return true; - } - // else check if we can plan an index join on the left side - auto left_index = CheckIndexJoin(context, op, *left, *op.conditions[0].left); - if (PlanIndexJoin(context, op, plan, right, left, left_index, true)) { - return true; - } - return false; -} - static void RewriteJoinCondition(Expression &expr, idx_t offset) { if (expr.type == ExpressionType::BOUND_REF) { auto &ref = expr.Cast(); @@ -300,10 +185,6 @@ unique_ptr PhysicalPlanGenerator::PlanComparisonJoin(LogicalCo unique_ptr plan; if (has_equality && !prefer_range_joins) { - // check if we can use an index join - if (PlanIndexJoin(context, op, plan, left, right)) { - return plan; - } // Equality join with small number of keys : possible perfect join optimization PerfectHashJoinStats perfect_join_stats; CheckForPerfectJoinOpt(op, perfect_join_stats); diff --git a/src/duckdb/src/function/pragma/pragma_functions.cpp b/src/duckdb/src/function/pragma/pragma_functions.cpp index b4a3f6ce9..e312ab02b 100644 --- a/src/duckdb/src/function/pragma/pragma_functions.cpp +++ b/src/duckdb/src/function/pragma/pragma_functions.cpp @@ -80,14 +80,6 @@ static void PragmaEnableForceParallelism(ClientContext &context, const FunctionP ClientConfig::GetConfig(context).verify_parallelism = true; } -static void PragmaEnableIndexJoin(ClientContext &context, const FunctionParameters ¶meters) { - ClientConfig::GetConfig(context).enable_index_join = true; -} - -static void PragmaEnableForceIndexJoin(ClientContext &context, const FunctionParameters ¶meters) { - ClientConfig::GetConfig(context).force_index_join = true; -} - static void PragmaForceCheckpoint(ClientContext &context, const FunctionParameters ¶meters) { DBConfig::GetConfig(context).options.force_checkpoint = true; } @@ -144,8 +136,6 @@ void PragmaFunctions::RegisterFunction(BuiltinFunctions &set) { set.AddFunction(PragmaFunction::PragmaStatement("enable_optimizer", PragmaEnableOptimizer)); set.AddFunction(PragmaFunction::PragmaStatement("disable_optimizer", PragmaDisableOptimizer)); - set.AddFunction(PragmaFunction::PragmaStatement("enable_index_join", PragmaEnableIndexJoin)); - set.AddFunction(PragmaFunction::PragmaStatement("force_index_join", PragmaEnableForceIndexJoin)); set.AddFunction(PragmaFunction::PragmaStatement("force_checkpoint", PragmaForceCheckpoint)); set.AddFunction(PragmaFunction::PragmaStatement("enable_progress_bar", PragmaEnableProgressBar)); diff --git a/src/duckdb/src/function/table/version/pragma_version.cpp b/src/duckdb/src/function/table/version/pragma_version.cpp index ffbb9291c..7a836bcde 100644 --- a/src/duckdb/src/function/table/version/pragma_version.cpp +++ b/src/duckdb/src/function/table/version/pragma_version.cpp @@ -1,8 +1,8 @@ #ifndef DUCKDB_VERSION -#define DUCKDB_VERSION "v0.9.3-dev764" +#define DUCKDB_VERSION "v0.9.3-dev772" #endif #ifndef DUCKDB_SOURCE_ID -#define DUCKDB_SOURCE_ID "5080b78720" +#define DUCKDB_SOURCE_ID "0a18eb0028" #endif #include "duckdb/function/table/system_functions.hpp" #include "duckdb/main/database.hpp" diff --git a/src/duckdb/src/include/duckdb/common/enums/physical_operator_type.hpp b/src/duckdb/src/include/duckdb/common/enums/physical_operator_type.hpp index 5b15d39fa..81d49ac33 100644 --- a/src/duckdb/src/include/duckdb/common/enums/physical_operator_type.hpp +++ b/src/duckdb/src/include/duckdb/common/enums/physical_operator_type.hpp @@ -59,7 +59,6 @@ enum class PhysicalOperatorType : uint8_t { PIECEWISE_MERGE_JOIN, IE_JOIN, DELIM_JOIN, - INDEX_JOIN, POSITIONAL_JOIN, ASOF_JOIN, // ----------------------------- diff --git a/src/duckdb/src/include/duckdb/execution/operator/join/physical_index_join.hpp b/src/duckdb/src/include/duckdb/execution/operator/join/physical_index_join.hpp deleted file mode 100644 index ebe2cb23a..000000000 --- a/src/duckdb/src/include/duckdb/execution/operator/join/physical_index_join.hpp +++ /dev/null @@ -1,79 +0,0 @@ -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/operator/join/physical_index_join.hpp -// -// -//===----------------------------------------------------------------------===// - -#pragma once - -#include "duckdb/common/types/chunk_collection.hpp" -#include "duckdb/execution/operator/join/physical_comparison_join.hpp" -#include "duckdb/execution/physical_operator.hpp" -#include "duckdb/planner/operator/logical_join.hpp" -#include "duckdb/storage/index.hpp" - -namespace duckdb { - -//! PhysicalIndexJoin represents an index join between two tables -class PhysicalIndexJoin : public CachingPhysicalOperator { -public: - static constexpr const PhysicalOperatorType TYPE = PhysicalOperatorType::INDEX_JOIN; - -public: - PhysicalIndexJoin(LogicalOperator &op, unique_ptr left, unique_ptr right, - vector cond, JoinType join_type, const vector &left_projection_map, - vector right_projection_map, vector column_ids, Index &index, bool lhs_first, - idx_t estimated_cardinality); - - //! Columns from RHS used in the query - vector column_ids; - //! Columns to be fetched - vector fetch_ids; - //! Types of fetch columns - vector fetch_types; - //! Columns indexed by index - unordered_set index_ids; - //! Projected ids from LHS - vector left_projection_map; - //! Projected ids from RHS - vector right_projection_map; - //! The types of the keys - vector condition_types; - //! The types of all conditions - vector build_types; - //! Index used for join - Index &index; - - vector conditions; - - JoinType join_type; - //! In case we swap rhs with lhs we need to output columns related to rhs first. - bool lhs_first = true; - -public: - unique_ptr GetOperatorState(ExecutionContext &context) const override; - - OrderPreservationType OperatorOrder() const override { - return OrderPreservationType::NO_ORDER; - } - bool ParallelOperator() const override { - return true; - } - -protected: - OperatorResultType ExecuteInternal(ExecutionContext &context, DataChunk &input, DataChunk &chunk, - GlobalOperatorState &gstate, OperatorState &state) const override; - -public: - void BuildPipelines(Pipeline ¤t, MetaPipeline &meta_pipeline) override; - vector> GetSources() const override; - -private: - void GetRHSMatches(ExecutionContext &context, DataChunk &input, OperatorState &state_p) const; - //! Fills result chunk - void Output(ExecutionContext &context, DataChunk &input, DataChunk &chunk, OperatorState &state_p) const; -}; - -} // namespace duckdb diff --git a/src/duckdb/src/include/duckdb/main/client_config.hpp b/src/duckdb/src/include/duckdb/main/client_config.hpp index 56c67f470..c49dd9a00 100644 --- a/src/duckdb/src/include/duckdb/main/client_config.hpp +++ b/src/duckdb/src/include/duckdb/main/client_config.hpp @@ -67,10 +67,6 @@ struct ClientConfig { bool enable_caching_operators = true; //! Force parallelism of small tables, used for testing bool verify_parallelism = false; - //! Enable the optimizer to consider index joins, which are disabled on default - bool enable_index_join = false; - //! Force index join independent of table cardinality, used for testing - bool force_index_join = false; //! Force out-of-core computation for operators that support it, used for testing bool force_external = false; //! Force disable cross product generation when hyper graph isn't connected, used for testing diff --git a/src/duckdb/src/optimizer/statistics/operator/propagate_join.cpp b/src/duckdb/src/optimizer/statistics/operator/propagate_join.cpp index 810d0054e..21d7ebe94 100644 --- a/src/duckdb/src/optimizer/statistics/operator/propagate_join.cpp +++ b/src/duckdb/src/optimizer/statistics/operator/propagate_join.cpp @@ -142,8 +142,8 @@ void StatisticsPropagator::PropagateStatistics(LogicalComparisonJoin &join, uniq auto updated_stats_right = PropagateExpression(condition.right); // Try to push lhs stats down rhs and vice versa - if (!context.config.force_index_join && stats_left && stats_right && updated_stats_left && - updated_stats_right && condition.left->type == ExpressionType::BOUND_COLUMN_REF && + if (stats_left && stats_right && updated_stats_left && updated_stats_right && + condition.left->type == ExpressionType::BOUND_COLUMN_REF && condition.right->type == ExpressionType::BOUND_COLUMN_REF) { CreateFilterFromJoinStats(join.children[0], condition.left, *stats_left, *updated_stats_left); CreateFilterFromJoinStats(join.children[1], condition.right, *stats_right, *updated_stats_right); diff --git a/src/duckdb/ub_src_execution_operator_join.cpp b/src/duckdb/ub_src_execution_operator_join.cpp index 035458115..a82b848b9 100644 --- a/src/duckdb/ub_src_execution_operator_join.cpp +++ b/src/duckdb/ub_src_execution_operator_join.cpp @@ -14,8 +14,6 @@ #include "src/execution/operator/join/physical_iejoin.cpp" -#include "src/execution/operator/join/physical_index_join.cpp" - #include "src/execution/operator/join/physical_join.cpp" #include "src/execution/operator/join/physical_nested_loop_join.cpp"