1#include "duckdb/storage/table/scan_state.hpp"
2#include "duckdb/storage/table/row_group.hpp"
3#include "duckdb/storage/table/column_segment.hpp"
4#include "duckdb/transaction/duck_transaction.hpp"
5#include "duckdb/storage/table/column_data.hpp"
6#include "duckdb/storage/table/row_group_collection.hpp"
7#include "duckdb/storage/table/row_group_segment_tree.hpp"
8
9namespace duckdb {
10
11void TableScanState::Initialize(vector<column_t> column_ids, TableFilterSet *table_filters) {
12 this->column_ids = std::move(column_ids);
13 this->table_filters = table_filters;
14 if (table_filters) {
15 D_ASSERT(table_filters->filters.size() > 0);
16 this->adaptive_filter = make_uniq<AdaptiveFilter>(args&: table_filters);
17 }
18}
19
20const vector<column_t> &TableScanState::GetColumnIds() {
21 D_ASSERT(!column_ids.empty());
22 return column_ids;
23}
24
25TableFilterSet *TableScanState::GetFilters() {
26 D_ASSERT(!table_filters || adaptive_filter.get());
27 return table_filters;
28}
29
30AdaptiveFilter *TableScanState::GetAdaptiveFilter() {
31 return adaptive_filter.get();
32}
33
34void ColumnScanState::NextInternal(idx_t count) {
35 if (!current) {
36 //! There is no column segment
37 return;
38 }
39 row_index += count;
40 while (row_index >= current->start + current->count) {
41 current = segment_tree->GetNextSegment(segment: current);
42 initialized = false;
43 segment_checked = false;
44 if (!current) {
45 break;
46 }
47 }
48 D_ASSERT(!current || (row_index >= current->start && row_index < current->start + current->count));
49}
50
51void ColumnScanState::Next(idx_t count) {
52 NextInternal(count);
53 for (auto &child_state : child_states) {
54 child_state.Next(count);
55 }
56}
57
58const vector<storage_t> &CollectionScanState::GetColumnIds() {
59 return parent.GetColumnIds();
60}
61
62TableFilterSet *CollectionScanState::GetFilters() {
63 return parent.GetFilters();
64}
65
66AdaptiveFilter *CollectionScanState::GetAdaptiveFilter() {
67 return parent.GetAdaptiveFilter();
68}
69
70ParallelCollectionScanState::ParallelCollectionScanState()
71 : collection(nullptr), current_row_group(nullptr), processed_rows(0) {
72}
73
74CollectionScanState::CollectionScanState(TableScanState &parent_p)
75 : row_group(nullptr), vector_index(0), max_row_group_row(0), row_groups(nullptr), max_row(0), batch_index(0),
76 parent(parent_p) {
77}
78
79bool CollectionScanState::Scan(DuckTransaction &transaction, DataChunk &result) {
80 while (row_group) {
81 row_group->Scan(transaction, state&: *this, result);
82 if (result.size() > 0) {
83 return true;
84 } else if (max_row <= row_group->start + row_group->count) {
85 row_group = nullptr;
86 return false;
87 } else {
88 do {
89 row_group = row_groups->GetNextSegment(segment: row_group);
90 if (row_group) {
91 if (row_group->start >= max_row) {
92 row_group = nullptr;
93 break;
94 }
95 bool scan_row_group = row_group->InitializeScan(state&: *this);
96 if (scan_row_group) {
97 // scan this row group
98 break;
99 }
100 }
101 } while (row_group);
102 }
103 }
104 return false;
105}
106
107bool CollectionScanState::ScanCommitted(DataChunk &result, SegmentLock &l, TableScanType type) {
108 while (row_group) {
109 row_group->ScanCommitted(state&: *this, result, type);
110 if (result.size() > 0) {
111 return true;
112 } else {
113 row_group = row_groups->GetNextSegment(l, segment: row_group);
114 if (row_group) {
115 row_group->InitializeScan(state&: *this);
116 }
117 }
118 }
119 return false;
120}
121
122bool CollectionScanState::ScanCommitted(DataChunk &result, TableScanType type) {
123 while (row_group) {
124 row_group->ScanCommitted(state&: *this, result, type);
125 if (result.size() > 0) {
126 return true;
127 } else {
128 row_group = row_groups->GetNextSegment(segment: row_group);
129 if (row_group) {
130 row_group->InitializeScan(state&: *this);
131 }
132 }
133 }
134 return false;
135}
136
137} // namespace duckdb
138