iceberg-cpp
Loading...
Searching...
No Matches
table_scan.h
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
22#include <functional>
23#include <memory>
24#include <optional>
25#include <string>
26#include <unordered_map>
27#include <unordered_set>
28#include <vector>
29
30#include "iceberg/iceberg_export.h"
31#include "iceberg/result.h"
33#include "iceberg/type_fwd.h"
35#include "iceberg/util/executor.h"
36
37namespace iceberg {
38
40class ICEBERG_EXPORT ScanTask {
41 public:
42 enum class Kind : uint8_t {
43 kFileScanTask,
44 kChangelogScanTask,
45 };
46
48 virtual Kind kind() const = 0;
49
51 virtual int64_t size_bytes() const = 0;
52
54 virtual int32_t files_count() const = 0;
55
57 virtual int64_t estimated_row_count() const = 0;
58
59 virtual ~ScanTask();
60};
61
63class ICEBERG_EXPORT FileScanTask : public ScanTask {
64 public:
70 explicit FileScanTask(std::shared_ptr<DataFile> data_file,
71 std::vector<std::shared_ptr<DataFile>> delete_files = {},
72 std::shared_ptr<Expression> filter = nullptr);
73
75 const std::shared_ptr<DataFile>& data_file() const { return data_file_; }
76
78 const std::vector<std::shared_ptr<DataFile>>& delete_files() const {
79 return delete_files_;
80 }
81
83 const std::shared_ptr<Expression>& residual_filter() const { return residual_filter_; }
84
85 Kind kind() const override { return Kind::kFileScanTask; }
86 int64_t size_bytes() const override;
87 int32_t files_count() const override;
88 int64_t estimated_row_count() const override;
89
90 private:
91 std::shared_ptr<DataFile> data_file_;
92 std::vector<std::shared_ptr<DataFile>> delete_files_;
93 std::shared_ptr<Expression> residual_filter_;
94};
95
96enum class ChangelogOperation : uint8_t {
97 kInsert,
98 kDelete,
99 kUpdateBefore,
100 kUpdateAfter,
101};
102
104class ICEBERG_EXPORT ChangelogScanTask : public ScanTask {
105 public:
113 ChangelogScanTask(int32_t change_ordinal, int64_t commit_snapshot_id,
114 std::shared_ptr<DataFile> data_file,
115 std::vector<std::shared_ptr<DataFile>> delete_files = {},
116 std::shared_ptr<Expression> residual_filter = nullptr)
117 : change_ordinal_(change_ordinal),
118 commit_snapshot_id_(commit_snapshot_id),
119 data_file_(std::move(data_file)),
120 delete_files_(std::move(delete_files)),
121 residual_filter_(std::move(residual_filter)) {}
122
123 Kind kind() const override { return Kind::kChangelogScanTask; }
124
125 int64_t size_bytes() const override;
126 int32_t files_count() const override;
127 int64_t estimated_row_count() const override;
128
129 virtual ChangelogOperation operation() const = 0;
130
132 int32_t change_ordinal() const { return change_ordinal_; }
133
135 int64_t commit_snapshot_id() const { return commit_snapshot_id_; }
136
138 const std::shared_ptr<Expression>& residual_filter() const { return residual_filter_; }
139
140 protected:
141 int32_t change_ordinal_;
142 int64_t commit_snapshot_id_;
143 std::shared_ptr<DataFile> data_file_;
144 std::vector<std::shared_ptr<DataFile>> delete_files_;
145 std::shared_ptr<Expression> residual_filter_;
146};
147
166class ICEBERG_EXPORT AddedRowsScanTask : public ChangelogScanTask {
167 public:
168 using ChangelogScanTask::ChangelogScanTask;
169
170 ChangelogOperation operation() const override { return ChangelogOperation::kInsert; }
171
173 const std::shared_ptr<DataFile>& data_file() const { return data_file_; }
174
178 const std::vector<std::shared_ptr<DataFile>>& delete_files() const {
179 return delete_files_;
180 }
181};
182
196class ICEBERG_EXPORT DeletedDataFileScanTask : public ChangelogScanTask {
197 public:
198 using ChangelogScanTask::ChangelogScanTask;
199
200 ChangelogOperation operation() const override { return ChangelogOperation::kDelete; }
201
203 const std::shared_ptr<DataFile>& data_file() const { return data_file_; }
204
209 const std::vector<std::shared_ptr<DataFile>>& existing_deletes() const {
210 return delete_files_;
211 }
212};
213
214namespace internal {
215
216// Internal table scan context used by different scan implementations.
218 std::optional<int64_t> snapshot_id;
219 std::shared_ptr<Expression> filter;
220 bool ignore_residuals{false};
221 bool case_sensitive{true};
222 bool return_column_stats{false};
223 std::unordered_set<int32_t> columns_to_keep_stats;
224 std::vector<std::string> selected_columns;
225 std::shared_ptr<Schema> projected_schema;
226 std::unordered_map<std::string, std::string> options;
227 bool from_snapshot_id_inclusive{false};
228 std::optional<int64_t> from_snapshot_id;
229 std::optional<int64_t> to_snapshot_id;
230 std::string branch{};
231 std::optional<int64_t> min_rows_requested;
232 OptionalExecutor plan_executor;
233
234 // Validate the context parameters to see if they have conflicts.
235 [[nodiscard]] Status Validate() const;
236};
237
238} // namespace internal
239
240// Concept to check if a type is an incremental scan
241template <typename T>
242concept IsIncrementalScan = std::is_base_of_v<IncrementalScan<FileScanTask>, T> ||
243 std::is_base_of_v<IncrementalScan<ChangelogScanTask>, T>;
244
246template <typename ScanType = DataTableScan>
247class ICEBERG_TEMPLATE_CLASS_EXPORT TableScanBuilder : public ErrorCollector {
248 public:
252 static Result<std::unique_ptr<TableScanBuilder<ScanType>>> Make(
253 std::shared_ptr<TableMetadata> metadata, std::shared_ptr<FileIO> io);
254
259 TableScanBuilder& Option(std::string key, std::string value);
260
263 TableScanBuilder& Project(std::shared_ptr<Schema> schema);
264
268 TableScanBuilder& CaseSensitive(bool case_sensitive);
269
273 TableScanBuilder& IncludeColumnStats();
274
281 TableScanBuilder& IncludeColumnStats(const std::vector<std::string>& requested_columns);
282
289 TableScanBuilder& Select(const std::vector<std::string>& column_names);
290
293 TableScanBuilder& Filter(std::shared_ptr<Expression> filter);
294
296 TableScanBuilder& IgnoreResiduals();
297
305 TableScanBuilder& MinRowsRequested(int64_t num_rows);
306
311 TableScanBuilder& PlanWith(Executor& executor);
312
316 TableScanBuilder& UseSnapshot(int64_t snapshot_id);
317
322 TableScanBuilder& UseRef(const std::string& ref);
323
329 TableScanBuilder& AsOfTime(int64_t timestamp_millis);
330
341 TableScanBuilder& FromSnapshot(int64_t from_snapshot_id, bool inclusive = false)
343
354 TableScanBuilder& FromSnapshot(const std::string& ref, bool inclusive = false)
356
365 TableScanBuilder& ToSnapshot(int64_t to_snapshot_id)
367
376 TableScanBuilder& ToSnapshot(const std::string& ref)
378
383 TableScanBuilder& UseBranch(const std::string& branch)
385
388 Result<std::unique_ptr<ScanType>> Build();
389
390 protected:
391 TableScanBuilder(std::shared_ptr<TableMetadata> metadata, std::shared_ptr<FileIO> io);
392
393 // Return the schema bound to the specified snapshot.
394 Result<std::reference_wrapper<const std::shared_ptr<Schema>>> ResolveSnapshotSchema();
395 Status ResolveColumnStatsSelection();
396
397 std::shared_ptr<TableMetadata> metadata_;
398 std::shared_ptr<FileIO> io_;
400 std::shared_ptr<Schema> snapshot_schema_;
401 std::optional<std::vector<std::string>> requested_column_stats_;
402};
403
405class ICEBERG_EXPORT TableScan {
406 public:
407 virtual ~TableScan();
408
410 const std::shared_ptr<TableMetadata>& metadata() const;
411
413 Result<std::shared_ptr<Snapshot>> snapshot() const;
414
416 Result<std::shared_ptr<Schema>> schema() const;
417
419 const internal::TableScanContext& context() const;
420
422 const std::shared_ptr<FileIO>& io() const;
423
425 const std::shared_ptr<Expression>& filter() const;
426
428 bool is_case_sensitive() const;
429
430 protected:
431 TableScan(std::shared_ptr<TableMetadata> metadata, std::shared_ptr<Schema> schema,
432 std::shared_ptr<FileIO> io, internal::TableScanContext context);
433
434 Result<std::reference_wrapper<const std::shared_ptr<Schema>>> ResolveProjectedSchema()
435 const;
436
437 virtual const std::vector<std::string>& ScanColumns() const;
438
439 const std::shared_ptr<TableMetadata> metadata_;
440 const std::shared_ptr<Schema> schema_;
441 const std::shared_ptr<FileIO> io_;
442 const internal::TableScanContext context_;
443 mutable std::shared_ptr<Schema> projected_schema_;
444};
445
447class ICEBERG_EXPORT DataTableScan : public TableScan {
448 public:
449 ~DataTableScan() override = default;
450
452 static Result<std::unique_ptr<DataTableScan>> Make(
453 std::shared_ptr<TableMetadata> metadata, std::shared_ptr<Schema> schema,
454 std::shared_ptr<FileIO> io, internal::TableScanContext context);
455
458 Result<std::vector<std::shared_ptr<FileScanTask>>> PlanFiles() const;
459
460 protected:
461 using TableScan::TableScan;
462};
463
466template <typename ScanTaskType>
468 public:
469 ~IncrementalScan() override = default;
470
471 virtual Result<std::vector<std::shared_ptr<ScanTaskType>>> PlanFiles() const = 0;
472
473 protected:
474 virtual Result<std::vector<std::shared_ptr<ScanTaskType>>> PlanFiles(
475 std::optional<int64_t> from_snapshot_id_exclusive,
476 int64_t to_snapshot_id_inclusive) const = 0;
477
478 using TableScan::TableScan;
479
480 // Allow the free function ResolvePlanFiles to access protected members.
481 template <typename T>
482 friend Result<std::vector<std::shared_ptr<T>>> ResolvePlanFiles(
483 const IncrementalScan<T>& scan);
484};
485
487class ICEBERG_EXPORT IncrementalAppendScan : public IncrementalScan<FileScanTask> {
488 public:
490 static Result<std::unique_ptr<IncrementalAppendScan>> Make(
491 std::shared_ptr<TableMetadata> metadata, std::shared_ptr<Schema> schema,
492 std::shared_ptr<FileIO> io, internal::TableScanContext context);
493
494 ~IncrementalAppendScan() override = default;
495
496 Result<std::vector<std::shared_ptr<FileScanTask>>> PlanFiles() const override;
497
498 protected:
499 Result<std::vector<std::shared_ptr<FileScanTask>>> PlanFiles(
500 std::optional<int64_t> from_snapshot_id_exclusive,
501 int64_t to_snapshot_id_inclusive) const override;
502
503 using IncrementalScan::IncrementalScan;
504};
505
507class ICEBERG_EXPORT IncrementalChangelogScan
508 : public IncrementalScan<ChangelogScanTask> {
509 public:
511 static Result<std::unique_ptr<IncrementalChangelogScan>> Make(
512 std::shared_ptr<TableMetadata> metadata, std::shared_ptr<Schema> schema,
513 std::shared_ptr<FileIO> io, internal::TableScanContext context);
514
515 ~IncrementalChangelogScan() override = default;
516
517 Result<std::vector<std::shared_ptr<ChangelogScanTask>>> PlanFiles() const override;
518
519 protected:
520 Result<std::vector<std::shared_ptr<ChangelogScanTask>>> PlanFiles(
521 std::optional<int64_t> from_snapshot_id_exclusive,
522 int64_t to_snapshot_id_inclusive) const override;
523
524 using IncrementalScan::IncrementalScan;
525};
526
527extern template class ICEBERG_EXTERN_TEMPLATE_CLASS_EXPORT
528 TableScanBuilder<DataTableScan>;
529extern template class ICEBERG_EXTERN_TEMPLATE_CLASS_EXPORT
530 TableScanBuilder<IncrementalAppendScan>;
531extern template class ICEBERG_EXTERN_TEMPLATE_CLASS_EXPORT
532 TableScanBuilder<IncrementalChangelogScan>;
533
534} // namespace iceberg
A scan task for inserts generated by adding a data file to the table.
Definition table_scan.h:166
const std::shared_ptr< DataFile > & data_file() const
The data file containing the added rows.
Definition table_scan.h:173
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:178
A scan task for reading changelog entries between snapshots.
Definition table_scan.h:104
int32_t change_ordinal() const
The position of this change in the changelog order (0-based).
Definition table_scan.h:132
int64_t commit_snapshot_id() const
The snapshot ID that committed this change.
Definition table_scan.h:135
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.
Definition table_scan.h:113
Kind kind() const override
The kind of scan task.
Definition table_scan.h:123
const std::shared_ptr< Expression > & residual_filter() const
Residual filter to apply after reading.
Definition table_scan.h:138
A scan that reads data files and applies delete files to filter rows.
Definition table_scan.h:447
A scan task for deletes generated by removing a data file from the table.
Definition table_scan.h:196
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:209
const std::shared_ptr< DataFile > & data_file() const
The data file that was deleted.
Definition table_scan.h:203
Base class for collecting errors in the builder pattern.
Definition error_collector.h:93
Schedules iceberg-cpp internal planning tasks.
Definition executor.h:43
Task representing a data file and its corresponding delete files.
Definition table_scan.h:63
Kind kind() const override
The kind of scan task.
Definition table_scan.h:85
const std::shared_ptr< DataFile > & data_file() const
The data file that should be read by this scan task.
Definition table_scan.h:75
const std::shared_ptr< Expression > & residual_filter() const
Residual filter to apply after reading.
Definition table_scan.h:83
const std::vector< std::shared_ptr< DataFile > > & delete_files() const
Delete files that apply to this data file.
Definition table_scan.h:78
A scan that reads data files added between snapshots (incremental appends).
Definition table_scan.h:487
A scan that reads changelog entries between snapshots.
Definition table_scan.h:508
A base template class for incremental scans that read changes between snapshots, and return scan task...
Definition table_scan.h:467
An abstract scan task.
Definition table_scan.h:40
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.
Builder class for creating TableScan instances.
Definition table_scan.h:247
Represents a configured scan operation on a table.
Definition table_scan.h:405
Definition table_scan.h:242
STL namespace.
Definition table_scan.h:217