@@ -639,6 +639,30 @@ Result<std::vector<std::shared_ptr<FileScanTask>>> DataTableScan::PlanFiles() co
639639 return manifest_group->PlanFiles ();
640640}
641641
642+ // Friend function template for IncrementalScan that implements the shared PlanFiles
643+ // logic. It resolves the from/to snapshot range from the scan context and delegates
644+ // to the two-arg virtual PlanFiles() override in the concrete subclass.
645+ // Defined as a friend to access the protected two-arg PlanFiles().
646+ template <typename ScanTaskType>
647+ Result<std::vector<std::shared_ptr<ScanTaskType>>> ResolvePlanFiles (
648+ const IncrementalScan<ScanTaskType>& scan) {
649+ if (IsScanCurrentLineage (scan.context ())) {
650+ if (scan.metadata ()->current_snapshot_id == kInvalidSnapshotId ) {
651+ return std::vector<std::shared_ptr<ScanTaskType>>{};
652+ }
653+ }
654+
655+ ICEBERG_ASSIGN_OR_RAISE (
656+ int64_t to_snapshot_id_inclusive,
657+ internal::ToSnapshotIdInclusive (scan.context (), *scan.metadata ()));
658+ ICEBERG_ASSIGN_OR_RAISE (
659+ std::optional<int64_t > from_snapshot_id_exclusive,
660+ internal::FromSnapshotIdExclusive (scan.context (), *scan.metadata (),
661+ to_snapshot_id_inclusive));
662+
663+ return scan.PlanFiles (from_snapshot_id_exclusive, to_snapshot_id_inclusive);
664+ }
665+
642666// IncrementalAppendScan implementation
643667
644668Result<std::unique_ptr<IncrementalAppendScan>> IncrementalAppendScan::Make (
@@ -651,6 +675,11 @@ Result<std::unique_ptr<IncrementalAppendScan>> IncrementalAppendScan::Make(
651675 std::move (metadata), std::move (schema), std::move (io), std::move (context)));
652676}
653677
678+ Result<std::vector<std::shared_ptr<FileScanTask>>> IncrementalAppendScan::PlanFiles ()
679+ const {
680+ return ResolvePlanFiles<FileScanTask>(*this );
681+ }
682+
654683Result<std::vector<std::shared_ptr<FileScanTask>>> IncrementalAppendScan::PlanFiles (
655684 std::optional<int64_t > from_snapshot_id_exclusive,
656685 int64_t to_snapshot_id_inclusive) const {
@@ -725,35 +754,15 @@ Result<std::unique_ptr<IncrementalChangelogScan>> IncrementalChangelogScan::Make
725754 return NotImplemented (" IncrementalChangelogScan is not implemented" );
726755}
727756
757+ Result<std::vector<std::shared_ptr<ChangelogScanTask>>>
758+ IncrementalChangelogScan::PlanFiles () const {
759+ return ResolvePlanFiles<ChangelogScanTask>(*this );
760+ }
761+
728762Result<std::vector<std::shared_ptr<ChangelogScanTask>>>
729763IncrementalChangelogScan::PlanFiles (std::optional<int64_t > from_snapshot_id_exclusive,
730764 int64_t to_snapshot_id_inclusive) const {
731765 return NotImplemented (" IncrementalChangelogScan::PlanFiles is not implemented" );
732766}
733767
734- // Explicit template implementations for IncrementalScan
735- // This moves the template implementation from header to source file
736- template <typename ScanTaskType>
737- Result<std::vector<std::shared_ptr<ScanTaskType>>>
738- IncrementalScan<ScanTaskType>::PlanFiles() const {
739- if (IsScanCurrentLineage (context_)) {
740- ICEBERG_ASSIGN_OR_RAISE (auto current_snapshot, metadata_->Snapshot ());
741- if (current_snapshot == nullptr ) {
742- return std::vector<std::shared_ptr<ScanTaskType>>{};
743- }
744- }
745-
746- ICEBERG_ASSIGN_OR_RAISE (int64_t to_snapshot_id_inclusive,
747- internal::ToSnapshotIdInclusive (context_, *metadata_));
748- ICEBERG_ASSIGN_OR_RAISE (
749- std::optional<int64_t > from_snapshot_id_exclusive,
750- internal::FromSnapshotIdExclusive (context_, *metadata_, to_snapshot_id_inclusive));
751-
752- return PlanFiles (from_snapshot_id_exclusive, to_snapshot_id_inclusive);
753- }
754-
755- // Explicitly instantiate the templates
756- template class IncrementalScan <FileScanTask>;
757- template class IncrementalScan <ChangelogScanTask>;
758-
759768} // namespace iceberg
0 commit comments