duckdb 0.8.2-dev2700.0 → 0.8.2-dev2809.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/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/types/row/row_data_collection_scanner.cpp +35 -5
- 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/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/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/main/pending_query_result.hpp +5 -0
- 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/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/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/planner/binder/statement/bind_execute.cpp +1 -1
- package/src/duckdb/src/planner/operator/logical_get.cpp +4 -0
- package/src/duckdb/ub_src_optimizer_join_order.cpp +10 -0
@@ -0,0 +1,351 @@
|
|
1
|
+
#include "duckdb/optimizer/join_order/relation_statistics_helper.hpp"
|
2
|
+
#include "duckdb/planner/expression/list.hpp"
|
3
|
+
#include "duckdb/planner/operator/list.hpp"
|
4
|
+
#include "duckdb/planner/filter/conjunction_filter.hpp"
|
5
|
+
#include "duckdb/planner/expression_iterator.hpp"
|
6
|
+
#include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp"
|
7
|
+
#include "duckdb/function/table/table_scan.hpp"
|
8
|
+
#include "duckdb/planner/operator/logical_get.hpp"
|
9
|
+
#include "duckdb/storage/data_table.hpp"
|
10
|
+
#include "duckdb/planner/filter/constant_filter.hpp"
|
11
|
+
|
12
|
+
namespace duckdb {
|
13
|
+
|
14
|
+
static ExpressionBinding GetChildColumnBinding(Expression &expr) {
|
15
|
+
auto ret = ExpressionBinding();
|
16
|
+
switch (expr.expression_class) {
|
17
|
+
case ExpressionClass::BOUND_FUNCTION: {
|
18
|
+
// TODO: Other expression classes that can have 0 children?
|
19
|
+
auto &func = expr.Cast<BoundFunctionExpression>();
|
20
|
+
// no children some sort of gen_random_uuid() or equivalent.
|
21
|
+
if (func.children.empty()) {
|
22
|
+
ret.found_expression = true;
|
23
|
+
ret.expression_is_constant = true;
|
24
|
+
return ret;
|
25
|
+
}
|
26
|
+
break;
|
27
|
+
}
|
28
|
+
case ExpressionClass::BOUND_COLUMN_REF: {
|
29
|
+
ret.found_expression = true;
|
30
|
+
auto &new_col_ref = expr.Cast<BoundColumnRefExpression>();
|
31
|
+
ret.child_binding = ColumnBinding(new_col_ref.binding.table_index, new_col_ref.binding.column_index);
|
32
|
+
return ret;
|
33
|
+
}
|
34
|
+
case ExpressionClass::BOUND_LAMBDA_REF:
|
35
|
+
case ExpressionClass::BOUND_CONSTANT:
|
36
|
+
case ExpressionClass::BOUND_DEFAULT:
|
37
|
+
case ExpressionClass::BOUND_PARAMETER:
|
38
|
+
case ExpressionClass::BOUND_REF:
|
39
|
+
ret.found_expression = true;
|
40
|
+
ret.expression_is_constant = true;
|
41
|
+
return ret;
|
42
|
+
default:
|
43
|
+
break;
|
44
|
+
}
|
45
|
+
ExpressionIterator::EnumerateChildren(expr, [&](unique_ptr<Expression> &child) {
|
46
|
+
auto recursive_result = GetChildColumnBinding(*child);
|
47
|
+
if (recursive_result.found_expression) {
|
48
|
+
ret = recursive_result;
|
49
|
+
}
|
50
|
+
});
|
51
|
+
// we didn't find a Bound Column Ref
|
52
|
+
return ret;
|
53
|
+
}
|
54
|
+
|
55
|
+
RelationStats RelationStatisticsHelper::ExtractGetStats(LogicalGet &get, ClientContext &context) {
|
56
|
+
auto return_stats = RelationStats();
|
57
|
+
|
58
|
+
auto base_table_cardinality = get.EstimateCardinality(context);
|
59
|
+
auto cardinality_after_filters = base_table_cardinality;
|
60
|
+
unique_ptr<BaseStatistics> column_statistics;
|
61
|
+
|
62
|
+
auto table_thing = get.GetTable();
|
63
|
+
auto name = string("some table");
|
64
|
+
if (table_thing) {
|
65
|
+
name = table_thing->name;
|
66
|
+
return_stats.table_name = name;
|
67
|
+
}
|
68
|
+
|
69
|
+
// if we can get the catalog table, then our column statistics will be accurate
|
70
|
+
// parquet readers etc. will still return statistics, but they initialize distinct column
|
71
|
+
// counts to 0.
|
72
|
+
// TODO: fix this, some file formats can encode distinct counts, we don't want to rely on
|
73
|
+
// getting a catalog table to know that we can use statistics.
|
74
|
+
bool have_catalog_table_statistics = false;
|
75
|
+
if (get.GetTable()) {
|
76
|
+
have_catalog_table_statistics = true;
|
77
|
+
}
|
78
|
+
|
79
|
+
// first push back basic distinct counts for each column (if we have them).
|
80
|
+
for (idx_t i = 0; i < get.column_ids.size(); i++) {
|
81
|
+
bool have_distinct_count_stats = false;
|
82
|
+
if (get.function.statistics) {
|
83
|
+
column_statistics = get.function.statistics(context, get.bind_data.get(), get.column_ids[i]);
|
84
|
+
if (column_statistics && have_catalog_table_statistics) {
|
85
|
+
auto column_distinct_count = DistinctCount({column_statistics->GetDistinctCount(), true});
|
86
|
+
return_stats.column_distinct_count.push_back(column_distinct_count);
|
87
|
+
return_stats.column_names.push_back(name + "." + get.names.at(get.column_ids.at(i)));
|
88
|
+
have_distinct_count_stats = true;
|
89
|
+
}
|
90
|
+
}
|
91
|
+
if (!have_distinct_count_stats) {
|
92
|
+
// currently treating the cardinality as the distinct count.
|
93
|
+
// the cardinality estimator will update these distinct counts based
|
94
|
+
// on the extra columns that are joined on.
|
95
|
+
auto column_distinct_count = DistinctCount({cardinality_after_filters, false});
|
96
|
+
return_stats.column_distinct_count.push_back(column_distinct_count);
|
97
|
+
auto column_name = string("column");
|
98
|
+
if (get.column_ids.at(i) < get.names.size()) {
|
99
|
+
column_name = get.names.at(get.column_ids.at(i));
|
100
|
+
}
|
101
|
+
return_stats.column_names.push_back(get.GetName() + "." + column_name);
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
if (!get.table_filters.filters.empty()) {
|
106
|
+
column_statistics = nullptr;
|
107
|
+
for (auto &it : get.table_filters.filters) {
|
108
|
+
if (get.bind_data && get.function.name.compare("seq_scan") == 0) {
|
109
|
+
auto &table_scan_bind_data = get.bind_data->Cast<TableScanBindData>();
|
110
|
+
column_statistics = get.function.statistics(context, &table_scan_bind_data, it.first);
|
111
|
+
}
|
112
|
+
|
113
|
+
if (column_statistics && it.second->filter_type == TableFilterType::CONJUNCTION_AND) {
|
114
|
+
auto &filter = it.second->Cast<ConjunctionAndFilter>();
|
115
|
+
idx_t cardinality_with_and_filter = RelationStatisticsHelper::InspectConjunctionAND(
|
116
|
+
base_table_cardinality, it.first, filter, *column_statistics);
|
117
|
+
cardinality_after_filters = MinValue(cardinality_after_filters, cardinality_with_and_filter);
|
118
|
+
}
|
119
|
+
}
|
120
|
+
// if the above code didn't find an equality filter (i.e country_code = "[us]")
|
121
|
+
// and there are other table filters (i.e cost > 50), use default selectivity.
|
122
|
+
bool has_equality_filter = (cardinality_after_filters != base_table_cardinality);
|
123
|
+
if (!has_equality_filter && !get.table_filters.filters.empty()) {
|
124
|
+
cardinality_after_filters =
|
125
|
+
MaxValue<idx_t>(base_table_cardinality * RelationStatisticsHelper::DEFAULT_SELECTIVITY, 1);
|
126
|
+
}
|
127
|
+
if (base_table_cardinality == 0) {
|
128
|
+
cardinality_after_filters = 0;
|
129
|
+
}
|
130
|
+
}
|
131
|
+
return_stats.cardinality = cardinality_after_filters;
|
132
|
+
// update the estimated cardinality of the get as well.
|
133
|
+
// This is not updated during plan reconstruction.
|
134
|
+
get.estimated_cardinality = cardinality_after_filters;
|
135
|
+
get.has_estimated_cardinality = true;
|
136
|
+
D_ASSERT(base_table_cardinality >= cardinality_after_filters);
|
137
|
+
return_stats.stats_initialized = true;
|
138
|
+
return return_stats;
|
139
|
+
}
|
140
|
+
|
141
|
+
RelationStats RelationStatisticsHelper::ExtractDelimGetStats(LogicalDelimGet &delim_get, ClientContext &context) {
|
142
|
+
RelationStats stats;
|
143
|
+
stats.table_name = delim_get.GetName();
|
144
|
+
idx_t card = delim_get.EstimateCardinality(context);
|
145
|
+
stats.cardinality = card;
|
146
|
+
stats.stats_initialized = true;
|
147
|
+
for (auto &binding : delim_get.GetColumnBindings()) {
|
148
|
+
stats.column_distinct_count.push_back(DistinctCount({1, false}));
|
149
|
+
stats.column_names.push_back("column" + to_string(binding.column_index));
|
150
|
+
}
|
151
|
+
return stats;
|
152
|
+
}
|
153
|
+
|
154
|
+
RelationStats RelationStatisticsHelper::ExtractProjectionStats(LogicalProjection &proj, RelationStats &child_stats) {
|
155
|
+
auto proj_stats = RelationStats();
|
156
|
+
proj_stats.cardinality = child_stats.cardinality;
|
157
|
+
proj_stats.table_name = proj.GetName();
|
158
|
+
for (auto &expr : proj.expressions) {
|
159
|
+
proj_stats.column_names.push_back(expr->GetName());
|
160
|
+
auto res = GetChildColumnBinding(*expr);
|
161
|
+
D_ASSERT(res.found_expression);
|
162
|
+
if (res.expression_is_constant) {
|
163
|
+
proj_stats.column_distinct_count.push_back(DistinctCount({1, true}));
|
164
|
+
} else {
|
165
|
+
auto column_index = res.child_binding.column_index;
|
166
|
+
if (column_index >= child_stats.column_distinct_count.size() && expr->ToString() == "count_star()") {
|
167
|
+
// only one value for a count star
|
168
|
+
proj_stats.column_distinct_count.push_back(DistinctCount({1, true}));
|
169
|
+
} else {
|
170
|
+
// TODO: add this back in
|
171
|
+
// D_ASSERT(column_index < stats.column_distinct_count.size());
|
172
|
+
if (column_index < child_stats.column_distinct_count.size()) {
|
173
|
+
proj_stats.column_distinct_count.push_back(child_stats.column_distinct_count.at(column_index));
|
174
|
+
} else {
|
175
|
+
proj_stats.column_distinct_count.push_back(DistinctCount({proj_stats.cardinality, false}));
|
176
|
+
}
|
177
|
+
}
|
178
|
+
}
|
179
|
+
}
|
180
|
+
proj_stats.stats_initialized = true;
|
181
|
+
return proj_stats;
|
182
|
+
}
|
183
|
+
|
184
|
+
RelationStats RelationStatisticsHelper::ExtractDummyScanStats(LogicalDummyScan &dummy_scan, ClientContext &context) {
|
185
|
+
auto stats = RelationStats();
|
186
|
+
idx_t card = dummy_scan.EstimateCardinality(context);
|
187
|
+
stats.cardinality = card;
|
188
|
+
for (idx_t i = 0; i < dummy_scan.GetColumnBindings().size(); i++) {
|
189
|
+
stats.column_distinct_count.push_back(DistinctCount({card, false}));
|
190
|
+
stats.column_names.push_back("dummy_scan_column");
|
191
|
+
}
|
192
|
+
stats.stats_initialized = true;
|
193
|
+
stats.table_name = "dummy scan";
|
194
|
+
return stats;
|
195
|
+
}
|
196
|
+
|
197
|
+
void RelationStatisticsHelper::CopyRelationStats(RelationStats &to, const RelationStats &from) {
|
198
|
+
to.column_distinct_count = from.column_distinct_count;
|
199
|
+
to.column_names = from.column_names;
|
200
|
+
to.cardinality = from.cardinality;
|
201
|
+
to.table_name = from.table_name;
|
202
|
+
to.stats_initialized = from.stats_initialized;
|
203
|
+
}
|
204
|
+
|
205
|
+
RelationStats RelationStatisticsHelper::CombineStatsOfReorderableOperator(vector<ColumnBinding> &bindings,
|
206
|
+
vector<RelationStats> relation_stats) {
|
207
|
+
RelationStats stats;
|
208
|
+
idx_t max_card = 0;
|
209
|
+
for (auto &child_stats : relation_stats) {
|
210
|
+
for (idx_t i = 0; i < child_stats.column_distinct_count.size(); i++) {
|
211
|
+
stats.column_distinct_count.push_back(child_stats.column_distinct_count.at(i));
|
212
|
+
stats.column_names.push_back(child_stats.column_names.at(i));
|
213
|
+
}
|
214
|
+
stats.table_name += "joined with " + child_stats.table_name;
|
215
|
+
max_card = MaxValue(max_card, child_stats.cardinality);
|
216
|
+
}
|
217
|
+
stats.stats_initialized = true;
|
218
|
+
stats.cardinality = max_card;
|
219
|
+
return stats;
|
220
|
+
}
|
221
|
+
|
222
|
+
RelationStats RelationStatisticsHelper::CombineStatsOfNonReorderableOperator(LogicalOperator &op,
|
223
|
+
vector<RelationStats> child_stats) {
|
224
|
+
D_ASSERT(child_stats.size() == 2);
|
225
|
+
RelationStats ret;
|
226
|
+
idx_t child_1_card = child_stats[0].stats_initialized ? child_stats[0].cardinality : 0;
|
227
|
+
idx_t child_2_card = child_stats[1].stats_initialized ? child_stats[1].cardinality : 0;
|
228
|
+
ret.cardinality = MaxValue(child_1_card, child_2_card);
|
229
|
+
ret.stats_initialized = true;
|
230
|
+
ret.filter_strength = 1;
|
231
|
+
ret.table_name = child_stats[0].table_name + " joined with " + child_stats[1].table_name;
|
232
|
+
for (auto &stats : child_stats) {
|
233
|
+
// MARK joins are nonreorderable. They won't return initialized stats
|
234
|
+
// continue in this case.
|
235
|
+
if (!stats.stats_initialized) {
|
236
|
+
continue;
|
237
|
+
}
|
238
|
+
for (auto &distinct_count : stats.column_distinct_count) {
|
239
|
+
ret.column_distinct_count.push_back(distinct_count);
|
240
|
+
}
|
241
|
+
for (auto &column_name : stats.column_names) {
|
242
|
+
ret.column_names.push_back(column_name);
|
243
|
+
}
|
244
|
+
}
|
245
|
+
return ret;
|
246
|
+
}
|
247
|
+
|
248
|
+
RelationStats RelationStatisticsHelper::ExtractExpressionGetStats(LogicalExpressionGet &expression_get,
|
249
|
+
ClientContext &context) {
|
250
|
+
auto stats = RelationStats();
|
251
|
+
idx_t card = expression_get.EstimateCardinality(context);
|
252
|
+
stats.cardinality = card;
|
253
|
+
for (idx_t i = 0; i < expression_get.GetColumnBindings().size(); i++) {
|
254
|
+
stats.column_distinct_count.push_back(DistinctCount({card, false}));
|
255
|
+
stats.column_names.push_back("expression_get_column");
|
256
|
+
}
|
257
|
+
stats.stats_initialized = true;
|
258
|
+
stats.table_name = "expression_get";
|
259
|
+
return stats;
|
260
|
+
}
|
261
|
+
|
262
|
+
RelationStats RelationStatisticsHelper::ExtractWindowStats(LogicalWindow &window, RelationStats &child_stats) {
|
263
|
+
RelationStats stats;
|
264
|
+
stats.cardinality = child_stats.cardinality;
|
265
|
+
stats.column_distinct_count = child_stats.column_distinct_count;
|
266
|
+
stats.column_names = child_stats.column_names;
|
267
|
+
stats.stats_initialized = true;
|
268
|
+
auto num_child_columns = window.GetColumnBindings().size();
|
269
|
+
|
270
|
+
for (idx_t column_index = child_stats.column_distinct_count.size(); column_index < num_child_columns;
|
271
|
+
column_index++) {
|
272
|
+
stats.column_distinct_count.push_back(DistinctCount({child_stats.cardinality, false}));
|
273
|
+
stats.column_names.push_back("window");
|
274
|
+
}
|
275
|
+
return stats;
|
276
|
+
}
|
277
|
+
|
278
|
+
RelationStats RelationStatisticsHelper::ExtractAggregationStats(LogicalAggregate &aggr, RelationStats &child_stats) {
|
279
|
+
RelationStats stats;
|
280
|
+
// TODO: look at child distinct count to better estimate cardinality.
|
281
|
+
stats.cardinality = child_stats.cardinality;
|
282
|
+
stats.column_distinct_count = child_stats.column_distinct_count;
|
283
|
+
stats.column_names = child_stats.column_names;
|
284
|
+
stats.stats_initialized = true;
|
285
|
+
auto num_child_columns = aggr.GetColumnBindings().size();
|
286
|
+
|
287
|
+
for (idx_t column_index = child_stats.column_distinct_count.size(); column_index < num_child_columns;
|
288
|
+
column_index++) {
|
289
|
+
stats.column_distinct_count.push_back(DistinctCount({child_stats.cardinality, false}));
|
290
|
+
stats.column_names.push_back("aggregate");
|
291
|
+
}
|
292
|
+
return stats;
|
293
|
+
}
|
294
|
+
|
295
|
+
idx_t RelationStatisticsHelper::InspectConjunctionAND(idx_t cardinality, idx_t column_index,
|
296
|
+
ConjunctionAndFilter &filter, BaseStatistics &base_stats) {
|
297
|
+
auto cardinality_after_filters = cardinality;
|
298
|
+
for (auto &child_filter : filter.child_filters) {
|
299
|
+
if (child_filter->filter_type != TableFilterType::CONSTANT_COMPARISON) {
|
300
|
+
continue;
|
301
|
+
}
|
302
|
+
auto &comparison_filter = child_filter->Cast<ConstantFilter>();
|
303
|
+
if (comparison_filter.comparison_type != ExpressionType::COMPARE_EQUAL) {
|
304
|
+
continue;
|
305
|
+
}
|
306
|
+
auto column_count = base_stats.GetDistinctCount();
|
307
|
+
auto filtered_card = cardinality;
|
308
|
+
// column_count = 0 when there is no column count (i.e parquet scans)
|
309
|
+
if (column_count > 0) {
|
310
|
+
// we want the ceil of cardinality/column_count. We also want to avoid compiler errors
|
311
|
+
filtered_card = (cardinality + column_count - 1) / column_count;
|
312
|
+
cardinality_after_filters = filtered_card;
|
313
|
+
}
|
314
|
+
}
|
315
|
+
return cardinality_after_filters;
|
316
|
+
}
|
317
|
+
|
318
|
+
// TODO: Currently only simple AND filters are pushed into table scans.
|
319
|
+
// When OR filters are pushed this function can be added
|
320
|
+
// idx_t RelationStatisticsHelper::InspectConjunctionOR(idx_t cardinality, idx_t column_index, ConjunctionOrFilter
|
321
|
+
// &filter,
|
322
|
+
// BaseStatistics &base_stats) {
|
323
|
+
// auto has_equality_filter = false;
|
324
|
+
// auto cardinality_after_filters = cardinality;
|
325
|
+
// for (auto &child_filter : filter.child_filters) {
|
326
|
+
// if (child_filter->filter_type != TableFilterType::CONSTANT_COMPARISON) {
|
327
|
+
// continue;
|
328
|
+
// }
|
329
|
+
// auto &comparison_filter = child_filter->Cast<ConstantFilter>();
|
330
|
+
// if (comparison_filter.comparison_type == ExpressionType::COMPARE_EQUAL) {
|
331
|
+
// auto column_count = base_stats.GetDistinctCount();
|
332
|
+
// auto increment = MaxValue<idx_t>(((cardinality + column_count - 1) / column_count), 1);
|
333
|
+
// if (has_equality_filter) {
|
334
|
+
// cardinality_after_filters += increment;
|
335
|
+
// } else {
|
336
|
+
// cardinality_after_filters = increment;
|
337
|
+
// }
|
338
|
+
// has_equality_filter = true;
|
339
|
+
// }
|
340
|
+
// if (child_filter->filter_type == TableFilterType::CONJUNCTION_AND) {
|
341
|
+
// auto &and_filter = child_filter->Cast<ConjunctionAndFilter>();
|
342
|
+
// cardinality_after_filters = RelationStatisticsHelper::InspectConjunctionAND(
|
343
|
+
// cardinality_after_filters, column_index, and_filter, base_stats);
|
344
|
+
// continue;
|
345
|
+
// }
|
346
|
+
// }
|
347
|
+
// D_ASSERT(cardinality_after_filters > 0);
|
348
|
+
// return cardinality_after_filters;
|
349
|
+
//}
|
350
|
+
|
351
|
+
} // namespace duckdb
|
@@ -458,6 +458,8 @@ bool Executor::ExecutionIsFinished() {
|
|
458
458
|
}
|
459
459
|
|
460
460
|
PendingExecutionResult Executor::ExecuteTask() {
|
461
|
+
// Only executor should return NO_TASKS_AVAILABLE
|
462
|
+
D_ASSERT(execution_result != PendingExecutionResult::NO_TASKS_AVAILABLE);
|
461
463
|
if (execution_result != PendingExecutionResult::RESULT_NOT_READY) {
|
462
464
|
return execution_result;
|
463
465
|
}
|
@@ -468,6 +470,10 @@ PendingExecutionResult Executor::ExecuteTask() {
|
|
468
470
|
if (!task) {
|
469
471
|
scheduler.GetTaskFromProducer(*producer, task);
|
470
472
|
}
|
473
|
+
if (!task && !HasError()) {
|
474
|
+
// there are no tasks to be scheduled and there are tasks blocked
|
475
|
+
return PendingExecutionResult::NO_TASKS_AVAILABLE;
|
476
|
+
}
|
471
477
|
if (task) {
|
472
478
|
// if we have a task, partially process it
|
473
479
|
auto result = task->Execute(TaskExecutionMode::PROCESS_PARTIAL);
|
@@ -9,6 +9,7 @@
|
|
9
9
|
#include "concurrentqueue.h"
|
10
10
|
#include "duckdb/common/thread.hpp"
|
11
11
|
#include "lightweightsemaphore.h"
|
12
|
+
#include <thread>
|
12
13
|
#else
|
13
14
|
#include <queue>
|
14
15
|
#endif
|
@@ -256,6 +257,12 @@ void TaskScheduler::Signal(idx_t n) {
|
|
256
257
|
#endif
|
257
258
|
}
|
258
259
|
|
260
|
+
void TaskScheduler::YieldThread() {
|
261
|
+
#ifndef DUCKDB_NO_THREADS
|
262
|
+
std::this_thread::yield();
|
263
|
+
#endif
|
264
|
+
}
|
265
|
+
|
259
266
|
void TaskScheduler::SetThreadsInternal(int32_t n) {
|
260
267
|
#ifndef DUCKDB_NO_THREADS
|
261
268
|
if (threads.size() == idx_t(n - 1)) {
|
@@ -46,7 +46,7 @@ BoundStatement Binder::Bind(ExecuteStatement &stmt) {
|
|
46
46
|
// catalog was modified or statement does not have clear types: rebind the statement before running the execute
|
47
47
|
Planner prepared_planner(context);
|
48
48
|
for (auto &pair : bind_values) {
|
49
|
-
prepared_planner.parameter_data.emplace(pair);
|
49
|
+
prepared_planner.parameter_data.emplace(std::make_pair(pair.first, BoundParameterData(pair.second)));
|
50
50
|
}
|
51
51
|
prepared = prepared_planner.PrepareSQLStatement(entry->second->unbound_statement->Copy());
|
52
52
|
rebound_plan = std::move(prepared_planner.plan);
|
@@ -109,6 +109,10 @@ void LogicalGet::ResolveTypes() {
|
|
109
109
|
}
|
110
110
|
|
111
111
|
idx_t LogicalGet::EstimateCardinality(ClientContext &context) {
|
112
|
+
// join order optimizer does better cardinality estimation.
|
113
|
+
if (has_estimated_cardinality) {
|
114
|
+
return estimated_cardinality;
|
115
|
+
}
|
112
116
|
if (function.cardinality) {
|
113
117
|
auto node_stats = function.cardinality(context, bind_data.get());
|
114
118
|
if (node_stats && node_stats->has_estimated_cardinality) {
|
@@ -10,3 +10,13 @@
|
|
10
10
|
|
11
11
|
#include "src/optimizer/join_order/cardinality_estimator.cpp"
|
12
12
|
|
13
|
+
#include "src/optimizer/join_order/cost_model.cpp"
|
14
|
+
|
15
|
+
#include "src/optimizer/join_order/plan_enumerator.cpp"
|
16
|
+
|
17
|
+
#include "src/optimizer/join_order/relation_manager.cpp"
|
18
|
+
|
19
|
+
#include "src/optimizer/join_order/query_graph_manager.cpp"
|
20
|
+
|
21
|
+
#include "src/optimizer/join_order/relation_statistics_helper.cpp"
|
22
|
+
|