iceberg-cpp
Loading...
Searching...
No Matches
table_scan.h
Go to the documentation of this file.
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20#pragma once
21
24
25#include <cstdint>
26#include <functional>
27#include <memory>
28#include <optional>
29#include <string>
30#include <unordered_map>
31#include <unordered_set>
32#include <vector>
33
35#include "iceberg/result.h"
37#include "iceberg/type_fwd.h"
40#include "iceberg/util/stream.h"
41
42namespace iceberg {
43
45class ICEBERG_EXPORT ScanTask {
46 public:
47 enum class Kind : uint8_t {
48 kFileScanTask,
49 kChangelogScanTask,
50 };
51
53 virtual Kind kind() const = 0;
54
56 virtual int64_t size_bytes() const = 0;
57
59 virtual int32_t files_count() const = 0;
60
62 virtual int64_t estimated_row_count() const = 0;
63
64 virtual ~ScanTask();
65};
66
68class ICEBERG_EXPORT FileScanTask : public ScanTask {
69 public:
77 explicit FileScanTask(std::shared_ptr<DataFile> data_file,
78 std::vector<std::shared_ptr<DataFile>> delete_files = {},
79 std::shared_ptr<Expression> filter = nullptr);
80
88 std::shared_ptr<DataFile> data_file, int64_t start, int64_t length,
89 std::vector<std::shared_ptr<DataFile>> delete_files = {},
90 std::shared_ptr<Expression> filter = nullptr);
91
93 int64_t start() const { return range_ ? range_->start : 0; }
94
96 int64_t length() const;
97
99 bool is_split() const { return range_.has_value(); }
100
102 const std::shared_ptr<DataFile>& data_file() const { return data_file_; }
103
105 const std::vector<std::shared_ptr<DataFile>>& delete_files() const {
106 return delete_files_;
107 }
108
110 const std::shared_ptr<Expression>& residual_filter() const { return residual_filter_; }
111
112 Kind kind() const override { return Kind::kFileScanTask; }
113 int64_t size_bytes() const override;
114 int32_t files_count() const override;
115
119 int64_t estimated_row_count() const override;
120
121 private:
122 // Only set for a partial file; whole-file tasks leave range_ empty.
123 struct Range {
124 int64_t start;
125 int64_t length;
126 };
127
128 FileScanTask(std::shared_ptr<DataFile> data_file,
129 std::vector<std::shared_ptr<DataFile>> delete_files,
130 std::shared_ptr<Expression> filter, Range range);
131
132 std::shared_ptr<DataFile> data_file_;
133 std::vector<std::shared_ptr<DataFile>> delete_files_;
134 std::shared_ptr<Expression> residual_filter_;
135 std::optional<Range> range_;
136};
137
140
142using FileScanTaskStreamPtr = std::unique_ptr<FileScanTaskStream>;
143
144enum class ChangelogOperation : uint8_t {
145 kInsert,
146 kDelete,
147 kUpdateBefore,
148 kUpdateAfter,
149};
150
152class ICEBERG_EXPORT ChangelogScanTask : public ScanTask {
153 public:
161 ChangelogScanTask(int32_t change_ordinal, int64_t commit_snapshot_id,
162 std::shared_ptr<DataFile> data_file,
163 std::vector<std::shared_ptr<DataFile>> delete_files = {},
164 std::shared_ptr<Expression> residual_filter = nullptr);
165
166 Kind kind() const override { return Kind::kChangelogScanTask; }
167
168 int64_t size_bytes() const override;
169 int32_t files_count() const override;
170 int64_t estimated_row_count() const override;
171
172 virtual ChangelogOperation operation() const = 0;
173
175 int32_t change_ordinal() const { return change_ordinal_; }
176
178 int64_t commit_snapshot_id() const { return commit_snapshot_id_; }
179
181 const std::shared_ptr<Expression>& residual_filter() const { return residual_filter_; }
182
183 protected:
184 int32_t change_ordinal_;
185 int64_t commit_snapshot_id_;
186 std::shared_ptr<DataFile> data_file_;
187 std::vector<std::shared_ptr<DataFile>> delete_files_;
188 std::shared_ptr<Expression> residual_filter_;
189};
190
209class ICEBERG_EXPORT AddedRowsScanTask : public ChangelogScanTask {
210 public:
211 using ChangelogScanTask::ChangelogScanTask;
212
213 ChangelogOperation operation() const override { return ChangelogOperation::kInsert; }
214
216 const std::shared_ptr<DataFile>& data_file() const { return data_file_; }
217
221 const std::vector<std::shared_ptr<DataFile>>& delete_files() const {
222 return delete_files_;
223 }
224};
225
239class ICEBERG_EXPORT DeletedDataFileScanTask : public ChangelogScanTask {
240 public:
241 using ChangelogScanTask::ChangelogScanTask;
242
243 ChangelogOperation operation() const override { return ChangelogOperation::kDelete; }
244
246 const std::shared_ptr<DataFile>& data_file() const { return data_file_; }
247
252 const std::vector<std::shared_ptr<DataFile>>& existing_deletes() const {
253 return delete_files_;
254 }
255};
256
257namespace internal {
258
259// Internal table scan context used by different scan implementations.
260struct ICEBERG_EXPORT TableScanContext {
261 std::optional<int64_t> snapshot_id;
262 std::shared_ptr<Expression> filter;
263 bool ignore_residuals{false};
264 bool case_sensitive{true};
265 bool return_column_stats{false};
266 std::unordered_set<int32_t> columns_to_keep_stats;
267 std::optional<std::vector<std::string>> selected_columns;
268 std::shared_ptr<Schema> projected_schema;
269 std::unordered_map<std::string, std::string> options;
270 bool from_snapshot_id_inclusive{false};
271 std::optional<int64_t> from_snapshot_id;
272 std::optional<int64_t> to_snapshot_id;
273 std::string branch{};
274 std::optional<int64_t> min_rows_requested;
275 bool use_snapshot_schema{false};
276 OptionalExecutor plan_executor;
277 std::string table_name;
278 std::shared_ptr<MetricsReporter> metrics_reporter;
279
280 // Validate the context parameters to see if they have conflicts.
281 [[nodiscard]] Status Validate() const;
282};
283
284} // namespace internal
285
286// Concept to check if a type is an incremental scan
287template <typename T>
288concept IsIncrementalScan = std::is_base_of_v<IncrementalScan<FileScanTask>, T> ||
289 std::is_base_of_v<IncrementalScan<ChangelogScanTask>, T>;
290
292template <typename ScanType = DataTableScan>
293class ICEBERG_TEMPLATE_CLASS_EXPORT TableScanBuilder : public ErrorCollector {
294 public:
298
303 TableScanBuilder& Option(std::string key, std::string value);
304
307 TableScanBuilder& Project(std::shared_ptr<Schema> schema);
308
312 TableScanBuilder& CaseSensitive(bool case_sensitive);
313
318
325 TableScanBuilder& IncludeColumnStats(const std::vector<std::string>& requested_columns);
326
336 TableScanBuilder& Select(const std::vector<std::string>& column_names);
337
340 TableScanBuilder& Filter(std::shared_ptr<Expression> filter);
341
344
353
362
366 TableScanBuilder& UseSnapshot(int64_t snapshot_id);
367
372 TableScanBuilder& UseRef(const std::string& ref);
373
379 TableScanBuilder& AsOfTime(int64_t timestamp_millis);
380
391 TableScanBuilder& FromSnapshot(int64_t from_snapshot_id, bool inclusive = false)
392 requires IsIncrementalScan<ScanType>;
393
404 TableScanBuilder& FromSnapshot(const std::string& ref, bool inclusive = false)
405 requires IsIncrementalScan<ScanType>;
406
415 TableScanBuilder& ToSnapshot(int64_t to_snapshot_id)
416 requires IsIncrementalScan<ScanType>;
417
426 TableScanBuilder& ToSnapshot(const std::string& ref)
427 requires IsIncrementalScan<ScanType>;
428
433 TableScanBuilder& UseBranch(const std::string& branch)
434 requires IsIncrementalScan<ScanType>;
435
440 TableScanBuilder& ReportWith(std::shared_ptr<MetricsReporter> reporter);
441
444 virtual Result<std::unique_ptr<ScanType>> Build();
445
446 protected:
447 TableScanBuilder(std::shared_ptr<TableMetadata> metadata, std::shared_ptr<FileIO> io,
448 std::string table_name,
449 std::shared_ptr<MetricsReporter> metrics_reporter);
450
452 TableScanBuilder& operator=(TableScanBuilder&&) = default;
453
454 // Return the snapshot schema for tags and time travel, else the table schema.
455 Result<std::reference_wrapper<const std::shared_ptr<Schema>>> ResolveSnapshotSchema();
456 Status ResolveColumnStatsSelection();
457
458 std::shared_ptr<TableMetadata> metadata_;
459 std::shared_ptr<FileIO> io_;
460 internal::TableScanContext context_;
461 std::shared_ptr<Schema> snapshot_schema_;
462 std::optional<std::vector<std::string>> requested_column_stats_;
463};
464
466class ICEBERG_EXPORT TableScan {
467 public:
468 virtual ~TableScan();
469
471 const std::shared_ptr<TableMetadata>& metadata() const;
472
475
478
481
483 virtual const std::shared_ptr<FileIO>& io() const;
484
486 const std::shared_ptr<Expression>& filter() const;
487
489 bool is_case_sensitive() const;
490
491 protected:
492 TableScan(std::shared_ptr<TableMetadata> metadata, std::shared_ptr<Schema> schema,
493 std::shared_ptr<FileIO> io, internal::TableScanContext context);
494
496 const;
497
498 virtual const std::vector<std::string>& ScanColumns() const;
499
500 const std::shared_ptr<TableMetadata> metadata_;
501 const std::shared_ptr<Schema> schema_;
502 const std::shared_ptr<FileIO> io_;
503 const internal::TableScanContext context_;
504 mutable std::shared_ptr<Schema> projected_schema_;
505};
506
509template <typename ScanTaskType>
511 public:
512 ~IncrementalScan() override = default;
513
514 virtual Result<std::vector<std::shared_ptr<ScanTaskType>>> PlanFiles() const = 0;
515
516 protected:
518 std::optional<int64_t> from_snapshot_id_exclusive,
519 int64_t to_snapshot_id_inclusive) const = 0;
520
521 using TableScan::TableScan;
522
523 // Allow the free function ResolvePlanFiles to access protected members.
524 template <typename T>
525 friend Result<std::vector<std::shared_ptr<T>>> ResolvePlanFiles(
526 const IncrementalScan<T>& scan);
527};
528
529} // namespace iceberg
A scan task for inserts generated by adding a data file to the table.
Definition table_scan.h:209
const std::shared_ptr< DataFile > & data_file() const
The data file containing the added rows.
Definition table_scan.h:216
const std::vector< std::shared_ptr< DataFile > > & delete_files() const
A list of delete files to apply when reading the data file in this task.
Definition table_scan.h:221
A scan task for reading changelog entries between snapshots.
Definition table_scan.h:152
int64_t size_bytes() const override
The number of bytes that should be read by this scan task.
int32_t change_ordinal() const
The position of this change in the changelog order (0-based).
Definition table_scan.h:175
int64_t commit_snapshot_id() const
The snapshot ID that committed this change.
Definition table_scan.h:178
int64_t estimated_row_count() const override
The number of rows that should be read by this scan task.
ChangelogScanTask(int32_t change_ordinal, int64_t commit_snapshot_id, std::shared_ptr< DataFile > data_file, std::vector< std::shared_ptr< DataFile > > delete_files={}, std::shared_ptr< Expression > residual_filter=nullptr)
Construct an AddedRowsScanTask.
Kind kind() const override
The kind of scan task.
Definition table_scan.h:166
const std::shared_ptr< Expression > & residual_filter() const
Residual filter to apply after reading.
Definition table_scan.h:181
int32_t files_count() const override
The number of files that should be read by this scan task.
A scan task for deletes generated by removing a data file from the table.
Definition table_scan.h:239
const std::vector< std::shared_ptr< DataFile > > & existing_deletes() const
A list of previously added delete files to apply when reading the data file in this task.
Definition table_scan.h:252
const std::shared_ptr< DataFile > & data_file() const
The data file that was deleted.
Definition table_scan.h:246
Base class for collecting errors in the builder pattern.
Definition error_collector.h:99
Schedules iceberg-cpp tasks.
Definition executor.h:46
Pluggable module for reading, writing, and deleting files.
Definition file_io.h:130
Task representing a data file and its corresponding delete files.
Definition table_scan.h:68
bool is_split() const
Whether this task reads a proper subset of its data file.
Definition table_scan.h:99
static Result< std::shared_ptr< FileScanTask > > MakeSplit(std::shared_ptr< DataFile > data_file, int64_t start, int64_t length, std::vector< std::shared_ptr< DataFile > > delete_files={}, std::shared_ptr< Expression > filter=nullptr)
Make a task for a validated half-open byte range [start, start + length).
int64_t estimated_row_count() const override
The estimated number of rows in this task, prorated by byte range. For valid, non-overlapping splits ...
int32_t files_count() const override
The number of files that should be read by this scan task.
int64_t start() const
The inclusive byte offset where this task starts, or zero for a whole file.
Definition table_scan.h:93
Kind kind() const override
The kind of scan task.
Definition table_scan.h:112
const std::shared_ptr< DataFile > & data_file() const
The data file that should be read by this scan task.
Definition table_scan.h:102
const std::shared_ptr< Expression > & residual_filter() const
Residual filter to apply after reading.
Definition table_scan.h:110
int64_t length() const
The byte length of this task, or the size of a whole file.
int64_t size_bytes() const override
The number of bytes that should be read by this scan task.
FileScanTask(std::shared_ptr< DataFile > data_file, std::vector< std::shared_ptr< DataFile > > delete_files={}, std::shared_ptr< Expression > filter=nullptr)
Construct with data file, delete files, and residual filter.
const std::vector< std::shared_ptr< DataFile > > & delete_files() const
Delete files that apply to this data file.
Definition table_scan.h:105
A base template class for incremental scans that read changes between snapshots, and return scan task...
Definition table_scan.h:510
Interface for reporting metrics from Iceberg operations.
Definition metrics_reporter.h:86
An abstract scan task.
Definition table_scan.h:45
virtual int32_t files_count() const =0
The number of files that should be read by this scan task.
virtual int64_t estimated_row_count() const =0
The number of rows that should be read by this scan task.
virtual int64_t size_bytes() const =0
The number of bytes that should be read by this scan task.
virtual Kind kind() const =0
The kind of scan task.
A schema for a Table.
Definition schema.h:51
A pull-based stream whose reads may fail.
Definition stream.h:47
Builder class for creating TableScan instances.
Definition table_scan.h:293
TableScanBuilder & Option(std::string key, std::string value)
Update property that will override the table's behavior based on the incoming pair....
TableScanBuilder & UseRef(const std::string &ref)
Request this scan to use the given reference.
static Result< std::unique_ptr< TableScanBuilder< ScanType > > > Make(const Table &table)
Constructs a TableScanBuilder for the given table.
TableScanBuilder & IgnoreResiduals()
Request data filtering to files but not to rows in those files.
TableScanBuilder & Select(const std::vector< std::string > &column_names)
Request this scan to read the given data columns.
TableScanBuilder & Filter(std::shared_ptr< Expression > filter)
Set the expression to filter data.
TableScanBuilder & CaseSensitive(bool case_sensitive)
If data columns are selected via Select(), controls whether the match to the schema will be done with...
TableScanBuilder & IncludeColumnStats()
Request this scan to load the column stats with each data file.
TableScanBuilder & IncludeColumnStats(const std::vector< std::string > &requested_columns)
Request this scan to load the column stats for the specific columns with each data file.
TableScanBuilder & AsOfTime(int64_t timestamp_millis)
Request this scan to use the most recent snapshot as of the given time in milliseconds on the branch ...
TableScanBuilder & UseSnapshot(int64_t snapshot_id)
Request this scan to use the given snapshot by ID.
TableScanBuilder & Project(std::shared_ptr< Schema > schema)
Set the projected schema.
TableScanBuilder & FromSnapshot(int64_t from_snapshot_id, bool inclusive=false)
Instructs this scan to look for changes starting from a particular snapshot.
TableScanBuilder & PlanWith(Executor &executor)
Configure an executor for manifest planning.
TableScanBuilder & MinRowsRequested(int64_t num_rows)
Request this scan to return at least the given number of rows.
Represents a configured scan operation on a table.
Definition table_scan.h:466
Result< std::shared_ptr< Schema > > schema() const
Returns the projected schema for the scan.
Result< std::shared_ptr< Snapshot > > snapshot() const
Returns the snapshot to scan. If there is no snapshot, returns nullptr.
const std::shared_ptr< TableMetadata > & metadata() const
Returns the table metadata being scanned.
virtual const std::shared_ptr< FileIO > & io() const
Returns the file I/O instance used for reading files.
const internal::TableScanContext & context() const
Returns the scan context.
bool is_case_sensitive() const
Returns whether this scan is case-sensitive.
const std::shared_ptr< Expression > & filter() const
Returns this scan's filter expression.
Represents an Iceberg table.
Definition table.h:45
Definition expected.h:1199
Definition table_scan.h:288
Define task executor interfaces.
Define symbol visibility macros for core Iceberg APIs.
Core Apache Iceberg C++ APIs.
Definition arrow_io_util.h:34
std::unique_ptr< FileScanTaskStream > FileScanTaskStreamPtr
Owning pointer to a file scan task stream.
Definition table_scan.h:142
STL namespace.
Define Result, Status, and error helpers.
Pull-based stream interface for fallible, lazily produced values.
Represents the metadata for an Iceberg table.
Definition table_metadata.h:73
Definition table_scan.h:260