| 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 | |