duckdb 0.8.2-dev2700.0 → 0.8.2-dev2842.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/package.json +1 -1
- package/src/duckdb/extension/icu/icu-makedate.cpp +12 -6
- package/src/duckdb/extension/json/include/json_deserializer.hpp +1 -1
- package/src/duckdb/extension/json/include/json_serializer.hpp +1 -1
- package/src/duckdb/extension/json/json_deserializer.cpp +10 -10
- package/src/duckdb/extension/json/json_scan.cpp +2 -2
- package/src/duckdb/extension/json/json_serializer.cpp +11 -10
- package/src/duckdb/extension/json/serialize_json.cpp +44 -44
- package/src/duckdb/extension/parquet/parquet_extension.cpp +11 -10
- package/src/duckdb/extension/parquet/serialize_parquet.cpp +6 -6
- package/src/duckdb/src/common/adbc/adbc.cpp +52 -21
- package/src/duckdb/src/common/adbc/driver_manager.cpp +12 -2
- package/src/duckdb/src/common/enum_util.cpp +5 -0
- package/src/duckdb/src/common/extra_type_info.cpp +2 -2
- package/src/duckdb/src/common/serializer/binary_deserializer.cpp +5 -3
- package/src/duckdb/src/common/serializer/binary_serializer.cpp +10 -5
- package/src/duckdb/src/common/types/column/column_data_collection.cpp +4 -4
- package/src/duckdb/src/common/types/row/row_data_collection_scanner.cpp +35 -5
- package/src/duckdb/src/common/types/value.cpp +33 -33
- package/src/duckdb/src/common/types/vector.cpp +20 -20
- package/src/duckdb/src/core_functions/aggregate/holistic/approximate_quantile.cpp +2 -2
- package/src/duckdb/src/core_functions/aggregate/holistic/quantile.cpp +6 -6
- package/src/duckdb/src/core_functions/aggregate/holistic/reservoir_quantile.cpp +4 -4
- package/src/duckdb/src/core_functions/scalar/list/list_lambdas.cpp +4 -4
- package/src/duckdb/src/execution/operator/aggregate/physical_window.cpp +283 -91
- package/src/duckdb/src/execution/operator/filter/physical_filter.cpp +1 -1
- package/src/duckdb/src/execution/operator/join/physical_comparison_join.cpp +1 -2
- package/src/duckdb/src/execution/operator/scan/physical_table_scan.cpp +1 -1
- package/src/duckdb/src/execution/physical_plan_generator.cpp +1 -6
- package/src/duckdb/src/execution/window_executor.cpp +10 -1
- package/src/duckdb/src/function/table/read_csv.cpp +4 -4
- package/src/duckdb/src/function/table/table_scan.cpp +14 -14
- package/src/duckdb/src/function/table/version/pragma_version.cpp +5 -2
- package/src/duckdb/src/include/duckdb/common/adbc/adbc.hpp +2 -0
- package/src/duckdb/src/include/duckdb/common/enums/pending_execution_result.hpp +1 -1
- package/src/duckdb/src/include/duckdb/common/index_vector.hpp +2 -2
- package/src/duckdb/src/include/duckdb/common/serializer/binary_deserializer.hpp +7 -3
- package/src/duckdb/src/include/duckdb/common/serializer/binary_serializer.hpp +2 -1
- package/src/duckdb/src/include/duckdb/common/serializer/format_deserializer.hpp +18 -17
- package/src/duckdb/src/include/duckdb/common/serializer/format_serializer.hpp +10 -9
- package/src/duckdb/src/include/duckdb/common/serializer/serialization_traits.hpp +4 -0
- package/src/duckdb/src/include/duckdb/common/types/row/row_data_collection_scanner.hpp +5 -1
- package/src/duckdb/src/include/duckdb/execution/physical_operator.hpp +0 -2
- package/src/duckdb/src/include/duckdb/function/function_serialization.hpp +10 -10
- package/src/duckdb/src/include/duckdb/main/pending_query_result.hpp +5 -0
- package/src/duckdb/src/include/duckdb/main/relation/aggregate_relation.hpp +4 -1
- package/src/duckdb/src/include/duckdb/optimizer/join_order/cardinality_estimator.hpp +37 -63
- package/src/duckdb/src/include/duckdb/optimizer/join_order/cost_model.hpp +37 -0
- package/src/duckdb/src/include/duckdb/optimizer/join_order/join_node.hpp +14 -29
- package/src/duckdb/src/include/duckdb/optimizer/join_order/join_order_optimizer.hpp +7 -21
- package/src/duckdb/src/include/duckdb/optimizer/join_order/join_relation.hpp +0 -11
- package/src/duckdb/src/include/duckdb/optimizer/join_order/plan_enumerator.hpp +89 -0
- package/src/duckdb/src/include/duckdb/optimizer/join_order/query_graph.hpp +17 -31
- package/src/duckdb/src/include/duckdb/optimizer/join_order/query_graph_manager.hpp +113 -0
- package/src/duckdb/src/include/duckdb/optimizer/join_order/relation_manager.hpp +73 -0
- package/src/duckdb/src/include/duckdb/optimizer/join_order/relation_statistics_helper.hpp +73 -0
- package/src/duckdb/src/include/duckdb/parallel/task_scheduler.hpp +4 -1
- package/src/duckdb/src/include/duckdb/parser/group_by_node.hpp +11 -0
- package/src/duckdb/src/include/duckdb/parser/parser.hpp +4 -0
- package/src/duckdb/src/include/duckdb/planner/logical_operator.hpp +0 -2
- package/src/duckdb/src/include/duckdb.h +11 -1
- package/src/duckdb/src/main/capi/pending-c.cpp +17 -0
- package/src/duckdb/src/main/pending_query_result.cpp +9 -1
- package/src/duckdb/src/main/relation/aggregate_relation.cpp +20 -10
- package/src/duckdb/src/main/relation.cpp +4 -4
- package/src/duckdb/src/optimizer/join_order/cardinality_estimator.cpp +79 -325
- package/src/duckdb/src/optimizer/join_order/cost_model.cpp +19 -0
- package/src/duckdb/src/optimizer/join_order/join_node.cpp +5 -37
- package/src/duckdb/src/optimizer/join_order/join_order_optimizer.cpp +48 -1078
- package/src/duckdb/src/optimizer/join_order/plan_enumerator.cpp +552 -0
- package/src/duckdb/src/optimizer/join_order/query_graph.cpp +32 -29
- package/src/duckdb/src/optimizer/join_order/query_graph_manager.cpp +409 -0
- package/src/duckdb/src/optimizer/join_order/relation_manager.cpp +356 -0
- package/src/duckdb/src/optimizer/join_order/relation_statistics_helper.cpp +351 -0
- package/src/duckdb/src/parallel/executor.cpp +6 -0
- package/src/duckdb/src/parallel/task_scheduler.cpp +7 -0
- package/src/duckdb/src/parser/parser.cpp +18 -3
- package/src/duckdb/src/parser/tableref/pivotref.cpp +6 -6
- package/src/duckdb/src/planner/binder/statement/bind_execute.cpp +1 -1
- package/src/duckdb/src/planner/expression/bound_aggregate_expression.cpp +10 -10
- package/src/duckdb/src/planner/expression/bound_function_expression.cpp +6 -6
- package/src/duckdb/src/planner/expression/bound_window_expression.cpp +24 -24
- package/src/duckdb/src/planner/operator/logical_extension_operator.cpp +2 -2
- package/src/duckdb/src/planner/operator/logical_get.cpp +26 -22
- package/src/duckdb/src/storage/serialization/serialize_constraint.cpp +26 -26
- package/src/duckdb/src/storage/serialization/serialize_create_info.cpp +66 -66
- package/src/duckdb/src/storage/serialization/serialize_expression.cpp +78 -78
- package/src/duckdb/src/storage/serialization/serialize_logical_operator.cpp +250 -250
- package/src/duckdb/src/storage/serialization/serialize_macro_function.cpp +10 -10
- package/src/duckdb/src/storage/serialization/serialize_nodes.cpp +206 -206
- package/src/duckdb/src/storage/serialization/serialize_parse_info.cpp +116 -116
- package/src/duckdb/src/storage/serialization/serialize_parsed_expression.cpp +110 -110
- package/src/duckdb/src/storage/serialization/serialize_query_node.cpp +48 -48
- package/src/duckdb/src/storage/serialization/serialize_result_modifier.cpp +16 -16
- package/src/duckdb/src/storage/serialization/serialize_statement.cpp +2 -2
- package/src/duckdb/src/storage/serialization/serialize_table_filter.cpp +10 -10
- package/src/duckdb/src/storage/serialization/serialize_tableref.cpp +54 -54
- package/src/duckdb/src/storage/serialization/serialize_types.cpp +22 -22
- package/src/duckdb/src/storage/table/update_segment.cpp +1 -1
- package/src/duckdb/ub_src_optimizer_join_order.cpp +10 -0
@@ -0,0 +1,356 @@
|
|
1
|
+
#include "duckdb/optimizer/join_order/relation_manager.hpp"
|
2
|
+
#include "duckdb/optimizer/join_order/join_order_optimizer.hpp"
|
3
|
+
#include "duckdb/optimizer/join_order/relation_statistics_helper.hpp"
|
4
|
+
#include "duckdb/common/printer.hpp"
|
5
|
+
#include "duckdb/common/string_util.hpp"
|
6
|
+
#include "duckdb/parser/expression_map.hpp"
|
7
|
+
#include "duckdb/planner/expression_iterator.hpp"
|
8
|
+
#include "duckdb/planner/expression/list.hpp"
|
9
|
+
#include "duckdb/planner/operator/list.hpp"
|
10
|
+
|
11
|
+
#include <cmath>
|
12
|
+
|
13
|
+
namespace duckdb {
|
14
|
+
|
15
|
+
const vector<RelationStats> RelationManager::GetRelationStats() {
|
16
|
+
vector<RelationStats> ret;
|
17
|
+
for (idx_t i = 0; i < relations.size(); i++) {
|
18
|
+
ret.push_back(relations[i]->stats);
|
19
|
+
}
|
20
|
+
return ret;
|
21
|
+
}
|
22
|
+
|
23
|
+
vector<unique_ptr<SingleJoinRelation>> RelationManager::GetRelations() {
|
24
|
+
return std::move(relations);
|
25
|
+
}
|
26
|
+
|
27
|
+
idx_t RelationManager::NumRelations() {
|
28
|
+
return relations.size();
|
29
|
+
}
|
30
|
+
|
31
|
+
void RelationManager::AddAggregateRelation(LogicalOperator &op, optional_ptr<LogicalOperator> parent,
|
32
|
+
const RelationStats &stats) {
|
33
|
+
auto relation = make_uniq<SingleJoinRelation>(op, parent, stats);
|
34
|
+
auto relation_id = relations.size();
|
35
|
+
|
36
|
+
auto table_indexes = op.GetTableIndex();
|
37
|
+
for (auto &index : table_indexes) {
|
38
|
+
D_ASSERT(relation_mapping.find(index) == relation_mapping.end());
|
39
|
+
relation_mapping[index] = relation_id;
|
40
|
+
}
|
41
|
+
relations.push_back(std::move(relation));
|
42
|
+
}
|
43
|
+
|
44
|
+
void RelationManager::AddRelation(LogicalOperator &op, optional_ptr<LogicalOperator> parent,
|
45
|
+
const RelationStats &stats) {
|
46
|
+
|
47
|
+
// if parent is null, then this is a root relation
|
48
|
+
// if parent is not null, it should have multiple children
|
49
|
+
D_ASSERT(!parent || parent->children.size() >= 2);
|
50
|
+
auto relation = make_uniq<SingleJoinRelation>(op, parent, stats);
|
51
|
+
auto relation_id = relations.size();
|
52
|
+
|
53
|
+
auto table_indexes = op.GetTableIndex();
|
54
|
+
if (table_indexes.empty()) {
|
55
|
+
// relation represents a non-reorderable relation, most likely a join relation
|
56
|
+
// Get the tables referenced in the non-reorderable relation and add them to the relation mapping
|
57
|
+
// This should all table references, even if there are nested non-reorderable joins.
|
58
|
+
unordered_set<idx_t> table_references;
|
59
|
+
LogicalJoin::GetTableReferences(op, table_references);
|
60
|
+
D_ASSERT(table_references.size() > 0);
|
61
|
+
for (auto &reference : table_references) {
|
62
|
+
D_ASSERT(relation_mapping.find(reference) == relation_mapping.end());
|
63
|
+
relation_mapping[reference] = relation_id;
|
64
|
+
}
|
65
|
+
} else {
|
66
|
+
// Relations should never return more than 1 table index
|
67
|
+
D_ASSERT(table_indexes.size() == 1);
|
68
|
+
idx_t table_index = table_indexes.at(0);
|
69
|
+
D_ASSERT(relation_mapping.find(table_index) == relation_mapping.end());
|
70
|
+
relation_mapping[table_index] = relation_id;
|
71
|
+
}
|
72
|
+
relations.push_back(std::move(relation));
|
73
|
+
}
|
74
|
+
|
75
|
+
static bool OperatorNeedsRelation(LogicalOperatorType op_type) {
|
76
|
+
switch (op_type) {
|
77
|
+
case LogicalOperatorType::LOGICAL_PROJECTION:
|
78
|
+
case LogicalOperatorType::LOGICAL_EXPRESSION_GET:
|
79
|
+
case LogicalOperatorType::LOGICAL_GET:
|
80
|
+
case LogicalOperatorType::LOGICAL_DELIM_GET:
|
81
|
+
case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY:
|
82
|
+
case LogicalOperatorType::LOGICAL_WINDOW:
|
83
|
+
return true;
|
84
|
+
default:
|
85
|
+
return false;
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
static bool OperatorIsNonReorderable(LogicalOperatorType op_type) {
|
90
|
+
switch (op_type) {
|
91
|
+
case LogicalOperatorType::LOGICAL_UNION:
|
92
|
+
case LogicalOperatorType::LOGICAL_EXCEPT:
|
93
|
+
case LogicalOperatorType::LOGICAL_INTERSECT:
|
94
|
+
case LogicalOperatorType::LOGICAL_DELIM_JOIN:
|
95
|
+
case LogicalOperatorType::LOGICAL_ANY_JOIN:
|
96
|
+
case LogicalOperatorType::LOGICAL_ASOF_JOIN:
|
97
|
+
return true;
|
98
|
+
default:
|
99
|
+
return false;
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
static bool HasNonReorderableChild(LogicalOperator &op) {
|
104
|
+
LogicalOperator *tmp = &op;
|
105
|
+
while (tmp->children.size() == 1) {
|
106
|
+
if (OperatorNeedsRelation(tmp->type) || OperatorIsNonReorderable(tmp->type)) {
|
107
|
+
return true;
|
108
|
+
}
|
109
|
+
tmp = tmp->children[0].get();
|
110
|
+
if (tmp->type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN) {
|
111
|
+
auto &join = tmp->Cast<LogicalComparisonJoin>();
|
112
|
+
if (join.join_type != JoinType::INNER) {
|
113
|
+
return true;
|
114
|
+
}
|
115
|
+
}
|
116
|
+
}
|
117
|
+
return tmp->children.empty();
|
118
|
+
}
|
119
|
+
|
120
|
+
bool RelationManager::ExtractJoinRelations(LogicalOperator &input_op,
|
121
|
+
vector<reference<LogicalOperator>> &filter_operators,
|
122
|
+
optional_ptr<LogicalOperator> parent) {
|
123
|
+
LogicalOperator *op = &input_op;
|
124
|
+
vector<reference<LogicalOperator>> datasource_filters;
|
125
|
+
// pass through single child operators
|
126
|
+
while (op->children.size() == 1 && !OperatorNeedsRelation(op->type)) {
|
127
|
+
if (op->type == LogicalOperatorType::LOGICAL_FILTER) {
|
128
|
+
if (HasNonReorderableChild(*op)) {
|
129
|
+
datasource_filters.push_back(*op);
|
130
|
+
}
|
131
|
+
filter_operators.push_back(*op);
|
132
|
+
}
|
133
|
+
if (op->type == LogicalOperatorType::LOGICAL_SHOW) {
|
134
|
+
return false;
|
135
|
+
}
|
136
|
+
op = op->children[0].get();
|
137
|
+
}
|
138
|
+
bool non_reorderable_operation = false;
|
139
|
+
if (OperatorIsNonReorderable(op->type)) {
|
140
|
+
// set operation, optimize separately in children
|
141
|
+
non_reorderable_operation = true;
|
142
|
+
}
|
143
|
+
|
144
|
+
if (op->type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN) {
|
145
|
+
auto &join = op->Cast<LogicalComparisonJoin>();
|
146
|
+
if (join.join_type == JoinType::INNER) {
|
147
|
+
// extract join conditions from inner join
|
148
|
+
filter_operators.push_back(*op);
|
149
|
+
} else {
|
150
|
+
non_reorderable_operation = true;
|
151
|
+
}
|
152
|
+
}
|
153
|
+
if (non_reorderable_operation) {
|
154
|
+
// we encountered a non-reordable operation (setop or non-inner join)
|
155
|
+
// we do not reorder non-inner joins yet, however we do want to expand the potential join graph around them
|
156
|
+
// non-inner joins are also tricky because we can't freely make conditions through them
|
157
|
+
// e.g. suppose we have (left LEFT OUTER JOIN right WHERE right IS NOT NULL), the join can generate
|
158
|
+
// new NULL values in the right side, so pushing this condition through the join leads to incorrect results
|
159
|
+
// for this reason, we just start a new JoinOptimizer pass in each of the children of the join
|
160
|
+
// stats.cardinality will be initiated to highest cardinality of the children.
|
161
|
+
vector<RelationStats> children_stats;
|
162
|
+
for (auto &child : op->children) {
|
163
|
+
auto stats = RelationStats();
|
164
|
+
JoinOrderOptimizer optimizer(context);
|
165
|
+
child = optimizer.Optimize(std::move(child), &stats);
|
166
|
+
children_stats.push_back(stats);
|
167
|
+
}
|
168
|
+
|
169
|
+
auto combined_stats = RelationStatisticsHelper::CombineStatsOfNonReorderableOperator(*op, children_stats);
|
170
|
+
if (!datasource_filters.empty()) {
|
171
|
+
combined_stats.cardinality =
|
172
|
+
(idx_t)MaxValue(combined_stats.cardinality * RelationStatisticsHelper::DEFAULT_SELECTIVITY, (double)1);
|
173
|
+
}
|
174
|
+
AddRelation(input_op, parent, combined_stats);
|
175
|
+
return true;
|
176
|
+
}
|
177
|
+
|
178
|
+
switch (op->type) {
|
179
|
+
case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY: {
|
180
|
+
// optimize children
|
181
|
+
RelationStats child_stats;
|
182
|
+
JoinOrderOptimizer optimizer(context);
|
183
|
+
op->children[0] = optimizer.Optimize(std::move(op->children[0]), &child_stats);
|
184
|
+
auto &aggr = op->Cast<LogicalAggregate>();
|
185
|
+
auto operator_stats = RelationStatisticsHelper::ExtractAggregationStats(aggr, child_stats);
|
186
|
+
AddAggregateRelation(input_op, parent, operator_stats);
|
187
|
+
return true;
|
188
|
+
}
|
189
|
+
case LogicalOperatorType::LOGICAL_WINDOW: {
|
190
|
+
// optimize children
|
191
|
+
RelationStats child_stats;
|
192
|
+
JoinOrderOptimizer optimizer(context);
|
193
|
+
op->children[0] = optimizer.Optimize(std::move(op->children[0]), &child_stats);
|
194
|
+
auto &window = op->Cast<LogicalWindow>();
|
195
|
+
auto operator_stats = RelationStatisticsHelper::ExtractWindowStats(window, child_stats);
|
196
|
+
AddAggregateRelation(input_op, parent, operator_stats);
|
197
|
+
return true;
|
198
|
+
}
|
199
|
+
case LogicalOperatorType::LOGICAL_COMPARISON_JOIN:
|
200
|
+
case LogicalOperatorType::LOGICAL_CROSS_PRODUCT: {
|
201
|
+
// Adding relations to the current join order optimizer
|
202
|
+
bool can_reorder_left = ExtractJoinRelations(*op->children[0], filter_operators, op);
|
203
|
+
bool can_reorder_right = ExtractJoinRelations(*op->children[1], filter_operators, op);
|
204
|
+
return can_reorder_left && can_reorder_right;
|
205
|
+
}
|
206
|
+
case LogicalOperatorType::LOGICAL_DUMMY_SCAN: {
|
207
|
+
auto &dummy_scan = op->Cast<LogicalDummyScan>();
|
208
|
+
auto stats = RelationStatisticsHelper::ExtractDummyScanStats(dummy_scan, context);
|
209
|
+
AddRelation(input_op, parent, stats);
|
210
|
+
return true;
|
211
|
+
}
|
212
|
+
case LogicalOperatorType::LOGICAL_EXPRESSION_GET: {
|
213
|
+
// base table scan, add to set of relations.
|
214
|
+
// create empty stats for dummy scan or logical expression get
|
215
|
+
auto &expression_get = op->Cast<LogicalExpressionGet>();
|
216
|
+
auto stats = RelationStatisticsHelper::ExtractExpressionGetStats(expression_get, context);
|
217
|
+
AddRelation(input_op, parent, stats);
|
218
|
+
return true;
|
219
|
+
}
|
220
|
+
case LogicalOperatorType::LOGICAL_GET: {
|
221
|
+
// TODO: Get stats from a logical GET
|
222
|
+
auto &get = op->Cast<LogicalGet>();
|
223
|
+
auto stats = RelationStatisticsHelper::ExtractGetStats(get, context);
|
224
|
+
// if there is another logical filter that could not be pushed down into the
|
225
|
+
// table scan, apply another selectivity.
|
226
|
+
if (!datasource_filters.empty()) {
|
227
|
+
stats.cardinality =
|
228
|
+
(idx_t)MaxValue(stats.cardinality * RelationStatisticsHelper::DEFAULT_SELECTIVITY, (double)1);
|
229
|
+
}
|
230
|
+
AddRelation(input_op, parent, stats);
|
231
|
+
return true;
|
232
|
+
}
|
233
|
+
case LogicalOperatorType::LOGICAL_DELIM_GET: {
|
234
|
+
auto &delim_get = op->Cast<LogicalDelimGet>();
|
235
|
+
auto stats = RelationStatisticsHelper::ExtractDelimGetStats(delim_get, context);
|
236
|
+
AddRelation(input_op, parent, stats);
|
237
|
+
return true;
|
238
|
+
}
|
239
|
+
case LogicalOperatorType::LOGICAL_PROJECTION: {
|
240
|
+
auto child_stats = RelationStats();
|
241
|
+
// optimize the child and copy the stats
|
242
|
+
JoinOrderOptimizer optimizer(context);
|
243
|
+
op->children[0] = optimizer.Optimize(std::move(op->children[0]), &child_stats);
|
244
|
+
auto &proj = op->Cast<LogicalProjection>();
|
245
|
+
// Projection can create columns so we need to add them here
|
246
|
+
auto proj_stats = RelationStatisticsHelper::ExtractProjectionStats(proj, child_stats);
|
247
|
+
AddRelation(input_op, parent, proj_stats);
|
248
|
+
return true;
|
249
|
+
}
|
250
|
+
default:
|
251
|
+
return false;
|
252
|
+
}
|
253
|
+
}
|
254
|
+
|
255
|
+
bool RelationManager::ExtractBindings(Expression &expression, unordered_set<idx_t> &bindings) {
|
256
|
+
if (expression.type == ExpressionType::BOUND_COLUMN_REF) {
|
257
|
+
auto &colref = expression.Cast<BoundColumnRefExpression>();
|
258
|
+
D_ASSERT(colref.depth == 0);
|
259
|
+
D_ASSERT(colref.binding.table_index != DConstants::INVALID_INDEX);
|
260
|
+
// map the base table index to the relation index used by the JoinOrderOptimizer
|
261
|
+
if (expression.alias == "SUBQUERY" &&
|
262
|
+
relation_mapping.find(colref.binding.table_index) == relation_mapping.end()) {
|
263
|
+
// most likely a BoundSubqueryExpression that was created from an uncorrelated subquery
|
264
|
+
// Here we return true and don't fill the bindings, the expression can be reordered.
|
265
|
+
// A filter will be created using this expression, and pushed back on top of the parent
|
266
|
+
// operator during plan reconstruction
|
267
|
+
return true;
|
268
|
+
}
|
269
|
+
D_ASSERT(relation_mapping.find(colref.binding.table_index) != relation_mapping.end());
|
270
|
+
bindings.insert(relation_mapping[colref.binding.table_index]);
|
271
|
+
}
|
272
|
+
if (expression.type == ExpressionType::BOUND_REF) {
|
273
|
+
// bound expression
|
274
|
+
bindings.clear();
|
275
|
+
return false;
|
276
|
+
}
|
277
|
+
D_ASSERT(expression.type != ExpressionType::SUBQUERY);
|
278
|
+
bool can_reorder = true;
|
279
|
+
ExpressionIterator::EnumerateChildren(expression, [&](Expression &expr) {
|
280
|
+
if (!ExtractBindings(expr, bindings)) {
|
281
|
+
can_reorder = false;
|
282
|
+
return;
|
283
|
+
}
|
284
|
+
});
|
285
|
+
return can_reorder;
|
286
|
+
}
|
287
|
+
|
288
|
+
vector<unique_ptr<FilterInfo>> RelationManager::ExtractEdges(LogicalOperator &op,
|
289
|
+
vector<reference<LogicalOperator>> &filter_operators,
|
290
|
+
JoinRelationSetManager &set_manager) {
|
291
|
+
// now that we know we are going to perform join ordering we actually extract the filters, eliminating duplicate
|
292
|
+
// filters in the process
|
293
|
+
vector<unique_ptr<FilterInfo>> filters_and_bindings;
|
294
|
+
expression_set_t filter_set;
|
295
|
+
for (auto &filter_op : filter_operators) {
|
296
|
+
auto &f_op = filter_op.get();
|
297
|
+
if (f_op.type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN ||
|
298
|
+
f_op.type == LogicalOperatorType::LOGICAL_ASOF_JOIN) {
|
299
|
+
auto &join = f_op.Cast<LogicalComparisonJoin>();
|
300
|
+
D_ASSERT(join.join_type == JoinType::INNER);
|
301
|
+
D_ASSERT(join.expressions.empty());
|
302
|
+
for (auto &cond : join.conditions) {
|
303
|
+
auto comparison =
|
304
|
+
make_uniq<BoundComparisonExpression>(cond.comparison, std::move(cond.left), std::move(cond.right));
|
305
|
+
if (filter_set.find(*comparison) == filter_set.end()) {
|
306
|
+
filter_set.insert(*comparison);
|
307
|
+
unordered_set<idx_t> bindings;
|
308
|
+
ExtractBindings(*comparison, bindings);
|
309
|
+
auto &set = set_manager.GetJoinRelation(bindings);
|
310
|
+
auto filter_info = make_uniq<FilterInfo>(std::move(comparison), set, filters_and_bindings.size());
|
311
|
+
filters_and_bindings.push_back(std::move(filter_info));
|
312
|
+
}
|
313
|
+
}
|
314
|
+
join.conditions.clear();
|
315
|
+
} else {
|
316
|
+
for (auto &expression : f_op.expressions) {
|
317
|
+
if (filter_set.find(*expression) == filter_set.end()) {
|
318
|
+
filter_set.insert(*expression);
|
319
|
+
unordered_set<idx_t> bindings;
|
320
|
+
ExtractBindings(*expression, bindings);
|
321
|
+
auto &set = set_manager.GetJoinRelation(bindings);
|
322
|
+
auto filter_info = make_uniq<FilterInfo>(std::move(expression), set, filters_and_bindings.size());
|
323
|
+
filters_and_bindings.push_back(std::move(filter_info));
|
324
|
+
}
|
325
|
+
}
|
326
|
+
f_op.expressions.clear();
|
327
|
+
}
|
328
|
+
}
|
329
|
+
|
330
|
+
return filters_and_bindings;
|
331
|
+
}
|
332
|
+
|
333
|
+
// LCOV_EXCL_START
|
334
|
+
|
335
|
+
void RelationManager::PrintRelationStats() {
|
336
|
+
#ifdef DEBUG
|
337
|
+
string to_print;
|
338
|
+
for (idx_t i = 0; i < relations.size(); i++) {
|
339
|
+
auto &relation = relations.at(i);
|
340
|
+
auto &stats = relation->stats;
|
341
|
+
D_ASSERT(stats.column_names.size() == stats.column_distinct_count.size());
|
342
|
+
for (idx_t i = 0; i < stats.column_names.size(); i++) {
|
343
|
+
to_print = stats.column_names.at(i) + " has estimated distinct count " +
|
344
|
+
to_string(stats.column_distinct_count.at(i).distinct_count);
|
345
|
+
Printer::Print(to_print);
|
346
|
+
}
|
347
|
+
to_print = stats.table_name + " has estimated cardinality " + to_string(stats.cardinality);
|
348
|
+
to_print += " and relation id " + to_string(i) + "\n";
|
349
|
+
Printer::Print(to_print);
|
350
|
+
}
|
351
|
+
#endif
|
352
|
+
}
|
353
|
+
|
354
|
+
// LCOV_EXCL_STOP
|
355
|
+
|
356
|
+
} // namespace duckdb
|