1#include "duckdb/optimizer/filter_pushdown.hpp"
2#include "duckdb/planner/operator/logical_filter.hpp"
3#include "duckdb/planner/operator/logical_get.hpp"
4#include "duckdb/storage/data_table.hpp"
5using namespace duckdb;
6using namespace std;
7
8unique_ptr<LogicalOperator> FilterPushdown::PushdownGet(unique_ptr<LogicalOperator> op) {
9 assert(op->type == LogicalOperatorType::GET);
10 auto &get = (LogicalGet &)*op;
11 if (!get.tableFilters.empty()) {
12 if (!filters.empty()) {
13 //! We didn't managed to push down all filters to table scan
14 auto logicalFilter = make_unique<LogicalFilter>();
15 for (auto &f : filters) {
16 logicalFilter->expressions.push_back(move(f->filter));
17 }
18 logicalFilter->children.push_back(move(op));
19 return move(logicalFilter);
20 } else {
21 return op;
22 }
23 }
24 //! FIXME: We only need to skip if the index is in the column being filtered
25 if (!get.table || !get.table->storage->info->indexes.empty()) {
26 //! now push any existing filters
27 if (filters.empty()) {
28 //! no filters to push
29 return op;
30 }
31 auto filter = make_unique<LogicalFilter>();
32 for (auto &f : filters) {
33 filter->expressions.push_back(move(f->filter));
34 }
35 filter->children.push_back(move(op));
36 return move(filter);
37 }
38 PushFilters();
39
40 vector<unique_ptr<Filter>> filtersToPushDown;
41 get.tableFilters = combiner.GenerateTableScanFilters(
42 [&](unique_ptr<Expression> filter) {
43 auto f = make_unique<Filter>();
44 f->filter = move(filter);
45 f->ExtractBindings();
46 filtersToPushDown.push_back(move(f));
47 },
48 get.column_ids);
49 for (auto &f : get.tableFilters) {
50 f.column_index = get.column_ids[f.column_index];
51 }
52
53 GenerateFilters();
54 for (auto &f : filtersToPushDown) {
55 get.expressions.push_back(move(f->filter));
56 }
57
58 if (!filters.empty()) {
59 //! We didn't managed to push down all filters to table scan
60 auto logicalFilter = make_unique<LogicalFilter>();
61 for (auto &f : filters) {
62 logicalFilter->expressions.push_back(move(f->filter));
63 }
64 logicalFilter->children.push_back(move(op));
65 return move(logicalFilter);
66 }
67 return op;
68}
69