Copilot commented on code in PR #873:
URL: https://github.com/apache/iceberg-cpp/pull/873#discussion_r3795548951


##########
src/iceberg/manifest/manifest_group.cc:
##########
@@ -132,6 +132,223 @@ ManifestGroup::~ManifestGroup() = default;
 ManifestGroup::ManifestGroup(ManifestGroup&&) noexcept = default;
 ManifestGroup& ManifestGroup::operator=(ManifestGroup&&) noexcept = default;
 
+class ManifestGroup::FilePlanningIterator final
+    : public Iterator<std::shared_ptr<FileScanTask>> {
+ public:
+  static Result<std::unique_ptr<Iterator<std::shared_ptr<FileScanTask>>>> Make(
+      std::unique_ptr<ManifestGroup> group) {
+    ICEBERG_RETURN_UNEXPECTED(group->CheckErrors());
+
+    group->delete_index_builder_.WithScanMetrics(group->scan_metrics_);
+    ICEBERG_ASSIGN_OR_RAISE(auto delete_index, 
group->delete_index_builder_.Build());
+
+    const bool drop_stats = ManifestReader::ShouldDropStats(group->columns_);
+    if (delete_index->has_equality_deletes()) {
+      group->columns_ = ManifestReader::WithStatsColumns(group->columns_);
+    }

Review Comment:
   `drop_stats` is computed before potentially mutating `group->columns_` for 
equality deletes. If `WithStatsColumns()` changes the outcome of 
`ShouldDropStats()`, the iterator may incorrectly drop stats even though 
equality-delete planning requires them. Compute `drop_stats` after the 
equality-delete column adjustment (or recompute it after mutation) so the 
drop/keep decision matches the final projected columns.



##########
src/iceberg/manifest/manifest_reader.cc:
##########
@@ -894,74 +1040,29 @@ Result<std::vector<ManifestEntry>> 
ManifestReaderImpl::ReadEntries(bool only_liv
   ICEBERG_RETURN_UNEXPECTED(OpenReader(std::move(projected_data_file_schema)));
   ICEBERG_DCHECK(file_reader_ != nullptr, "File reader should be initialized");
 
-  std::vector<ManifestEntry> manifest_entries;
   ICEBERG_ASSIGN_OR_RAISE(auto arrow_schema, file_reader_->Schema());
   internal::ArrowSchemaGuard schema_guard(&arrow_schema);
 
   // Get evaluators if needed
-  Evaluator* evaluator = nullptr;
-  InclusiveMetricsEvaluator* metrics_evaluator = nullptr;
+  std::unique_ptr<Evaluator> evaluator;
+  std::unique_ptr<InclusiveMetricsEvaluator> metrics_evaluator;
   if (HasPartitionFilter() || HasRowFilter()) {
-    ICEBERG_ASSIGN_OR_RAISE(evaluator, GetEvaluator());
+    ICEBERG_RETURN_UNEXPECTED(GetEvaluator());
+    evaluator = std::move(evaluator_);
   }
   if (HasRowFilter()) {
-    ICEBERG_ASSIGN_OR_RAISE(metrics_evaluator, GetMetricsEvaluator());
+    ICEBERG_RETURN_UNEXPECTED(GetMetricsEvaluator());
+    metrics_evaluator = std::move(metrics_evaluator_);
   }

Review Comment:
   The results of `GetEvaluator()` / `GetMetricsEvaluator()` are discarded, and 
the code instead moves `evaluator_` / `metrics_evaluator_` members. This is 
fragile and can be incorrect if those functions return the evaluator rather 
than populating members as a side effect. Prefer directly unwrapping into the 
local `std::unique_ptr` (e.g., via the existing `ICEBERG_ASSIGN_OR_RAISE`) or 
refactor the helpers to return the evaluator explicitly and use that return 
value here.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to