1 | #include "duckdb/execution/operator/scan/physical_table_scan.hpp" |
2 | |
3 | #include <utility> |
4 | |
5 | #include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp" |
6 | #include "duckdb/transaction/transaction.hpp" |
7 | #include "duckdb/planner/expression/bound_conjunction_expression.hpp" |
8 | |
9 | using namespace duckdb; |
10 | using namespace std; |
11 | |
12 | class PhysicalTableScanOperatorState : public PhysicalOperatorState { |
13 | public: |
14 | PhysicalTableScanOperatorState(Expression &expr) |
15 | : PhysicalOperatorState(nullptr), initialized(false), executor(expr) { |
16 | } |
17 | PhysicalTableScanOperatorState() : PhysicalOperatorState(nullptr), initialized(false) { |
18 | } |
19 | //! Whether or not the scan has been initialized |
20 | bool initialized; |
21 | //! The current position in the scan |
22 | TableScanState scan_offset; |
23 | //! Execute filters inside the table |
24 | ExpressionExecutor executor; |
25 | }; |
26 | |
27 | PhysicalTableScan::PhysicalTableScan(LogicalOperator &op, TableCatalogEntry &tableref, DataTable &table, |
28 | vector<column_t> column_ids, vector<unique_ptr<Expression>> filter, |
29 | unordered_map<idx_t, vector<TableFilter>> table_filters) |
30 | : PhysicalOperator(PhysicalOperatorType::SEQ_SCAN, op.types), tableref(tableref), table(table), |
31 | column_ids(move(column_ids)), table_filters(move(table_filters)) { |
32 | if (filter.size() > 1) { |
33 | //! create a big AND out of the expressions |
34 | auto conjunction = make_unique<BoundConjunctionExpression>(ExpressionType::CONJUNCTION_AND); |
35 | for (auto &expr : filter) { |
36 | conjunction->children.push_back(move(expr)); |
37 | } |
38 | expression = move(conjunction); |
39 | } else if (filter.size() == 1) { |
40 | expression = move(filter[0]); |
41 | } |
42 | } |
43 | void PhysicalTableScan::GetChunkInternal(ClientContext &context, DataChunk &chunk, PhysicalOperatorState *state_) { |
44 | auto state = reinterpret_cast<PhysicalTableScanOperatorState *>(state_); |
45 | if (column_ids.empty()) { |
46 | return; |
47 | } |
48 | auto &transaction = Transaction::GetTransaction(context); |
49 | if (!state->initialized) { |
50 | table.InitializeScan(transaction, state->scan_offset, column_ids, &table_filters); |
51 | state->initialized = true; |
52 | } |
53 | table.Scan(transaction, chunk, state->scan_offset, table_filters); |
54 | } |
55 | |
56 | string PhysicalTableScan::() const { |
57 | if (expression) { |
58 | return tableref.name + " " + expression->ToString(); |
59 | } else { |
60 | return tableref.name; |
61 | } |
62 | } |
63 | |
64 | unique_ptr<PhysicalOperatorState> PhysicalTableScan::GetOperatorState() { |
65 | if (expression) { |
66 | return make_unique<PhysicalTableScanOperatorState>(*expression); |
67 | } else { |
68 | return make_unique<PhysicalTableScanOperatorState>(); |
69 | } |
70 | } |
71 | |