Code review comment: So currently only support MOR from the last snapshots. Can we reserve interfaces to support `Time Travel Query` and `Incremental query`.

Code under review:
public List<Split> getSplits() throws UserException {
        
        

        
        
        
        
        
        

        HMSExternalTable targetTable = (HMSExternalTable) source.getTargetTable();
        HoodieTableMetaClient hudiClient = HiveMetaStoreClientHelper.getHudiClient(targetTable);

        hudiClient.reloadActiveTimeline();

        String partitionName = getHudiPartitionName(targetTable, hudiClient);

        List<Split> splits = new ArrayList<>();

        String basePath = targetTable.getRemoteTable().getSd().getLocation();
        String inputFormat = targetTable.getRemoteTable().getSd().getInputFormat();
        String serdeLib = targetTable.getRemoteTable().getSd().getSerdeInfo().getSerializationLib();

        TableSchemaResolver schemaUtil = new TableSchemaResolver(hudiClient);
        Schema hudiSchema;
        try {
            hudiSchema = HoodieAvroUtils.createHoodieWriteSchema(schemaUtil.getTableAvroSchema());
        } catch (Exception e) {
            throw new RuntimeException("Cannot get hudi table schema.");
        }

        List<String> columnNames = new ArrayList<>();
        List<String> columnTypes = new ArrayList<>();
        List<FieldSchema> allFields = targetTable.getRemoteTable().getSd().getCols();
        allFields.addAll(targetTable.getRemoteTable().getPartitionKeys());

        for (Schema.Field hudiField : hudiSchema.getFields()) {

            String columnName = hudiField.name().toLowerCase(Locale.ROOT);
            Optional<FieldSchema> field = allFields.stream()
                    .filter(f -> f.getName().equals(columnName)).findFirst();
            if (!field.isPresent()) {
                String errorMsg = String.format("Hudi column %s not exists in hive metastore.", hudiField.name());
                throw new IllegalArgumentException(errorMsg);
            }
            columnNames.add(columnName);
            String columnType = HudiExternalTable.fromAvroHudiTypeToHiveTypeString(hudiField.schema());
            columnTypes.add(columnType);
        }

        try {
            String globPath = String.format("%s/%s/*", hudiClient.getBasePath(), partitionName);
            List<FileStatus> statuses = FSUtils.getGlobStatusExcludingMetaFolder(hudiClient.getRawFs(),
                    new Path(globPath));

            HoodieTimeline timeline = hudiClient.getCommitsAndCompactionTimeline().filterCompletedInstants();
            Option<HoodieInstant> latestInstant = timeline.lastInstant();
            if (!latestInstant.isPresent()) {
                return new ArrayList<>();
            }
            String queryInstant = latestInstant.get().getTimestamp();
            HoodieTableFileSystemView fileSystemView = new HoodieTableFileSystemView(hudiClient,
                    timeline, statuses.toArray(new FileStatus[0]));

            Iterator<FileSlice> hoodieFileSliceIterator = fileSystemView
                    .getLatestMergedFileSlicesBeforeOrOn(partitionName, queryInstant).iterator();

            while (hoodieFileSliceIterator.hasNext()) {
                FileSlice fileSlice = hoodieFileSliceIterator.next();
                Optional<HoodieBaseFile> baseFile = fileSlice.getBaseFile().toJavaOptional();
                String filePath = baseFile.map(BaseFile::getPath).orElse("");
                long fileSize = baseFile.map(BaseFile::getFileSize).orElse(0L);

                List<String> logs = fileSlice.getLogFiles().map(HoodieLogFile::getFileName)
                        .collect(Collectors.toList());

                HudiSplit split = new HudiSplit(new Path(filePath), 0, fileSize, fileSize, new String[0]);
                split.setTableFormatType(TableFormatType.HUDI);
                split.setHudiDeltaLogs(logs);
                split.setInputFormat(inputFormat);
                split.setSerde(serdeLib);
                split.setBasePath(basePath);
                split.setHudiColumnNames(columnNames);
                split.setHudiColumnTypes(columnTypes);
                split.setInstantTime(queryInstant);
                splits.add(split);
            }
        } catch (Exception e) {
            LOG.error("Failed to get hudi file on path: {}", e);
            throw new UserException("Failed to get hudi remote file's metadata on path: %s. msg: %s");
        }
        return splits;
    }

Line commented on: HoodieTimeline timeline = hudiClient.getCommitsAndCompactionTimeline().filterCompletedInstants();

Revised code:
public List<Split> getSplits() throws UserException {
        
        

        
        
        
        
        
        

        HMSExternalTable targetTable = (HMSExternalTable) source.getTargetTable();
        HoodieTableMetaClient hudiClient = HiveMetaStoreClientHelper.getHudiClient(targetTable);

        hudiClient.reloadActiveTimeline();

        String partitionName = getHudiPartitionName(targetTable, hudiClient);

        String basePath = targetTable.getRemoteTable().getSd().getLocation();
        String inputFormat = targetTable.getRemoteTable().getSd().getInputFormat();
        String serdeLib = targetTable.getRemoteTable().getSd().getSerdeInfo().getSerializationLib();

        TableSchemaResolver schemaUtil = new TableSchemaResolver(hudiClient);
        Schema hudiSchema;
        try {
            hudiSchema = HoodieAvroUtils.createHoodieWriteSchema(schemaUtil.getTableAvroSchema());
        } catch (Exception e) {
            throw new RuntimeException("Cannot get hudi table schema.");
        }

        List<String> columnNames = new ArrayList<>();
        List<String> columnTypes = new ArrayList<>();
        List<FieldSchema> allFields = targetTable.getRemoteTable().getSd().getCols();
        allFields.addAll(targetTable.getRemoteTable().getPartitionKeys());

        List<Split> splits = new ArrayList<>();
        for (Schema.Field hudiField : hudiSchema.getFields()) {

            String columnName = hudiField.name().toLowerCase(Locale.ROOT);
            
            Optional<FieldSchema> field = allFields.stream().filter(f -> f.getName().equals(columnName)).findFirst();
            if (!field.isPresent()) {
                String errorMsg = String.format("Hudi column %s not exists in hive metastore.", hudiField.name());
                throw new IllegalArgumentException(errorMsg);
            }
            columnNames.add(columnName);
            String columnType = HudiExternalTable.fromAvroHudiTypeToHiveTypeString(hudiField.schema());
            columnTypes.add(columnType);
        }

        try {
            String globPath = String.format("%s/%s/*", hudiClient.getBasePathV2().toString(), partitionName);
            List<FileStatus> statuses = FSUtils.getGlobStatusExcludingMetaFolder(hudiClient.getRawFs(),
                    new Path(globPath));

            HoodieTimeline timeline = hudiClient.getCommitsAndCompactionTimeline().filterCompletedInstants();
            Option<HoodieInstant> latestInstant = timeline.lastInstant();
            if (!latestInstant.isPresent()) {
                return new ArrayList<>();
            }
            String queryInstant = latestInstant.get().getTimestamp();
            HoodieTableFileSystemView fileSystemView = new HoodieTableFileSystemView(hudiClient,
                    timeline, statuses.toArray(new FileStatus[0]));

            Iterator<FileSlice> hoodieFileSliceIterator = fileSystemView
                    .getLatestMergedFileSlicesBeforeOrOn(partitionName, queryInstant).iterator();

            while (hoodieFileSliceIterator.hasNext()) {
                FileSlice fileSlice = hoodieFileSliceIterator.next();
                Optional<HoodieBaseFile> baseFile = fileSlice.getBaseFile().toJavaOptional();
                String filePath = baseFile.map(BaseFile::getPath).orElse("");
                long fileSize = baseFile.map(BaseFile::getFileSize).orElse(0L);

                List<String> logs = fileSlice.getLogFiles().map(HoodieLogFile::getFileName)
                        .collect(Collectors.toList());

                HudiSplit split = new HudiSplit(new Path(filePath), 0, fileSize, fileSize, new String[0]);
                split.setTableFormatType(TableFormatType.HUDI);
                split.setHudiDeltaLogs(logs);
                split.setInputFormat(inputFormat);
                split.setSerde(serdeLib);
                split.setBasePath(basePath);
                split.setHudiColumnNames(columnNames);
                split.setHudiColumnTypes(columnTypes);
                split.setInstantTime(queryInstant);
                splits.add(split);
            }
        } catch (Exception e) {
            String errorMsg = String.format("Failed to get hudi info on basePath: %s", basePath);
            LOG.error(errorMsg, e);
            throw new IllegalArgumentException(errorMsg, e);
        }
        return splits;
    }