@Test public void testShowRollback() throws IOException { HoodieActiveTimeline activeTimeline = new RollbacksCommand.RollbackTimeline(HoodieCLI.getTableMetaClient()); Stream<HoodieInstant> rollback = activeTimeline.getRollbackTimeline().filterCompletedInstants().getInstants(); HoodieInstant instant = rollback.findFirst().orElse(null); assertNotNull(instant, "The instant can not be null."); CommandResult cr = getShell().executeCommand("show rollback --instant " + instant.getTimestamp()); assertTrue(cr.isSuccess()); List<Comparable[]> rows = new ArrayList<>(); HoodieRollbackMetadata metadata = TimelineMetadataUtils.deserializeAvroMetadata( activeTimeline.getInstantDetails(instant).get(), HoodieRollbackMetadata.class); metadata.getPartitionMetadata().forEach((key, value) -> Stream .concat(value.getSuccessDeleteFiles().stream().map(f -> Pair.of(f, true)), value.getFailedDeleteFiles().stream().map(f -> Pair.of(f, false))) .forEach(fileWithDeleteStatus -> { Comparable[] row = new Comparable[5]; row[0] = metadata.getStartRollbackTime(); row[1] = metadata.getCommitsRollback().toString(); row[2] = key; row[3] = fileWithDeleteStatus.getLeft(); row[4] = fileWithDeleteStatus.getRight(); rows.add(row); })); TableHeader header = new TableHeader().addTableHeaderField(HoodieTableHeaderFields.HEADER_INSTANT) .addTableHeaderField(HoodieTableHeaderFields.HEADER_ROLLBACK_INSTANT) .addTableHeaderField(HoodieTableHeaderFields.HEADER_PARTITION) .addTableHeaderField(HoodieTableHeaderFields.HEADER_DELETED_FILE) .addTableHeaderField(HoodieTableHeaderFields.HEADER_SUCCEEDED); String expected = HoodiePrintHelper.print(header, new HashMap<>(), "", false, -1, false, rows); expected = removeNonWordAndStripSpace(expected); String got = removeNonWordAndStripSpace(cr.getResult().toString()); assertEquals(expected, got); }
@CliCommand(value = "show rollback", help = "Show details of a rollback instant") public String showRollback( @CliOption(key = {"instant"}, help = "Rollback instant", mandatory = true) String rollbackInstant, @CliOption(key = {"limit"}, help = "Limit #rows to be displayed", unspecifiedDefaultValue = "10") Integer limit, @CliOption(key = {"sortBy"}, help = "Sorting Field", unspecifiedDefaultValue = "") final String sortByField, @CliOption(key = {"desc"}, help = "Ordering", unspecifiedDefaultValue = "false") final boolean descending, @CliOption(key = {"headeronly"}, help = "Print Header Only", unspecifiedDefaultValue = "false") final boolean headerOnly) throws IOException { HoodieActiveTimeline activeTimeline = new RollbackTimeline(HoodieCLI.getTableMetaClient()); final List<Comparable[]> rows = new ArrayList<>(); HoodieRollbackMetadata metadata = TimelineMetadataUtils.deserializeAvroMetadata( activeTimeline.getInstantDetails(new HoodieInstant(State.COMPLETED, ROLLBACK_ACTION, rollbackInstant)).get(), HoodieRollbackMetadata.class); metadata.getPartitionMetadata().forEach((key, value) -> Stream .concat(value.getSuccessDeleteFiles().stream().map(f -> Pair.of(f, true)), value.getFailedDeleteFiles().stream().map(f -> Pair.of(f, false))) .forEach(fileWithDeleteStatus -> { Comparable[] row = new Comparable[5]; row[0] = metadata.getStartRollbackTime(); row[1] = metadata.getCommitsRollback().toString(); row[2] = key; row[3] = fileWithDeleteStatus.getLeft(); row[4] = fileWithDeleteStatus.getRight(); rows.add(row); })); TableHeader header = new TableHeader().addTableHeaderField(HoodieTableHeaderFields.HEADER_INSTANT) .addTableHeaderField(HoodieTableHeaderFields.HEADER_ROLLBACK_INSTANT) .addTableHeaderField(HoodieTableHeaderFields.HEADER_PARTITION) .addTableHeaderField(HoodieTableHeaderFields.HEADER_DELETED_FILE) .addTableHeaderField(HoodieTableHeaderFields.HEADER_SUCCEEDED); return HoodiePrintHelper.print(header, new HashMap<>(), sortByField, descending, limit, headerOnly, rows); }
RollbacksCommand implements CommandMarker { @CliCommand(value = "show rollback", help = "Show details of a rollback instant") public String showRollback( @CliOption(key = {"instant"}, help = "Rollback instant", mandatory = true) String rollbackInstant, @CliOption(key = {"limit"}, help = "Limit #rows to be displayed", unspecifiedDefaultValue = "10") Integer limit, @CliOption(key = {"sortBy"}, help = "Sorting Field", unspecifiedDefaultValue = "") final String sortByField, @CliOption(key = {"desc"}, help = "Ordering", unspecifiedDefaultValue = "false") final boolean descending, @CliOption(key = {"headeronly"}, help = "Print Header Only", unspecifiedDefaultValue = "false") final boolean headerOnly) throws IOException { HoodieActiveTimeline activeTimeline = new RollbackTimeline(HoodieCLI.getTableMetaClient()); final List<Comparable[]> rows = new ArrayList<>(); HoodieRollbackMetadata metadata = TimelineMetadataUtils.deserializeAvroMetadata( activeTimeline.getInstantDetails(new HoodieInstant(State.COMPLETED, ROLLBACK_ACTION, rollbackInstant)).get(), HoodieRollbackMetadata.class); metadata.getPartitionMetadata().forEach((key, value) -> Stream .concat(value.getSuccessDeleteFiles().stream().map(f -> Pair.of(f, true)), value.getFailedDeleteFiles().stream().map(f -> Pair.of(f, false))) .forEach(fileWithDeleteStatus -> { Comparable[] row = new Comparable[5]; row[0] = metadata.getStartRollbackTime(); row[1] = metadata.getCommitsRollback().toString(); row[2] = key; row[3] = fileWithDeleteStatus.getLeft(); row[4] = fileWithDeleteStatus.getRight(); rows.add(row); })); TableHeader header = new TableHeader().addTableHeaderField(HoodieTableHeaderFields.HEADER_INSTANT) .addTableHeaderField(HoodieTableHeaderFields.HEADER_ROLLBACK_INSTANT) .addTableHeaderField(HoodieTableHeaderFields.HEADER_PARTITION) .addTableHeaderField(HoodieTableHeaderFields.HEADER_DELETED_FILE) .addTableHeaderField(HoodieTableHeaderFields.HEADER_SUCCEEDED); return HoodiePrintHelper.print(header, new HashMap<>(), sortByField, descending, limit, headerOnly, rows); } }
RollbacksCommand implements CommandMarker { @CliCommand(value = "show rollback", help = "Show details of a rollback instant") public String showRollback( @CliOption(key = {"instant"}, help = "Rollback instant", mandatory = true) String rollbackInstant, @CliOption(key = {"limit"}, help = "Limit #rows to be displayed", unspecifiedDefaultValue = "10") Integer limit, @CliOption(key = {"sortBy"}, help = "Sorting Field", unspecifiedDefaultValue = "") final String sortByField, @CliOption(key = {"desc"}, help = "Ordering", unspecifiedDefaultValue = "false") final boolean descending, @CliOption(key = {"headeronly"}, help = "Print Header Only", unspecifiedDefaultValue = "false") final boolean headerOnly) throws IOException { HoodieActiveTimeline activeTimeline = new RollbackTimeline(HoodieCLI.getTableMetaClient()); final List<Comparable[]> rows = new ArrayList<>(); HoodieRollbackMetadata metadata = TimelineMetadataUtils.deserializeAvroMetadata( activeTimeline.getInstantDetails(new HoodieInstant(State.COMPLETED, ROLLBACK_ACTION, rollbackInstant)).get(), HoodieRollbackMetadata.class); metadata.getPartitionMetadata().forEach((key, value) -> Stream .concat(value.getSuccessDeleteFiles().stream().map(f -> Pair.of(f, true)), value.getFailedDeleteFiles().stream().map(f -> Pair.of(f, false))) .forEach(fileWithDeleteStatus -> { Comparable[] row = new Comparable[5]; row[0] = metadata.getStartRollbackTime(); row[1] = metadata.getCommitsRollback().toString(); row[2] = key; row[3] = fileWithDeleteStatus.getLeft(); row[4] = fileWithDeleteStatus.getRight(); rows.add(row); })); TableHeader header = new TableHeader().addTableHeaderField(HoodieTableHeaderFields.HEADER_INSTANT) .addTableHeaderField(HoodieTableHeaderFields.HEADER_ROLLBACK_INSTANT) .addTableHeaderField(HoodieTableHeaderFields.HEADER_PARTITION) .addTableHeaderField(HoodieTableHeaderFields.HEADER_DELETED_FILE) .addTableHeaderField(HoodieTableHeaderFields.HEADER_SUCCEEDED); return HoodiePrintHelper.print(header, new HashMap<>(), sortByField, descending, limit, headerOnly, rows); }  }
RollbacksCommand implements CommandMarker { @CliCommand(value = "show rollback", help = "Show details of a rollback instant") public String showRollback( @CliOption(key = {"instant"}, help = "Rollback instant", mandatory = true) String rollbackInstant, @CliOption(key = {"limit"}, help = "Limit #rows to be displayed", unspecifiedDefaultValue = "10") Integer limit, @CliOption(key = {"sortBy"}, help = "Sorting Field", unspecifiedDefaultValue = "") final String sortByField, @CliOption(key = {"desc"}, help = "Ordering", unspecifiedDefaultValue = "false") final boolean descending, @CliOption(key = {"headeronly"}, help = "Print Header Only", unspecifiedDefaultValue = "false") final boolean headerOnly) throws IOException { HoodieActiveTimeline activeTimeline = new RollbackTimeline(HoodieCLI.getTableMetaClient()); final List<Comparable[]> rows = new ArrayList<>(); HoodieRollbackMetadata metadata = TimelineMetadataUtils.deserializeAvroMetadata( activeTimeline.getInstantDetails(new HoodieInstant(State.COMPLETED, ROLLBACK_ACTION, rollbackInstant)).get(), HoodieRollbackMetadata.class); metadata.getPartitionMetadata().forEach((key, value) -> Stream .concat(value.getSuccessDeleteFiles().stream().map(f -> Pair.of(f, true)), value.getFailedDeleteFiles().stream().map(f -> Pair.of(f, false))) .forEach(fileWithDeleteStatus -> { Comparable[] row = new Comparable[5]; row[0] = metadata.getStartRollbackTime(); row[1] = metadata.getCommitsRollback().toString(); row[2] = key; row[3] = fileWithDeleteStatus.getLeft(); row[4] = fileWithDeleteStatus.getRight(); rows.add(row); })); TableHeader header = new TableHeader().addTableHeaderField(HoodieTableHeaderFields.HEADER_INSTANT) .addTableHeaderField(HoodieTableHeaderFields.HEADER_ROLLBACK_INSTANT) .addTableHeaderField(HoodieTableHeaderFields.HEADER_PARTITION) .addTableHeaderField(HoodieTableHeaderFields.HEADER_DELETED_FILE) .addTableHeaderField(HoodieTableHeaderFields.HEADER_SUCCEEDED); return HoodiePrintHelper.print(header, new HashMap<>(), sortByField, descending, limit, headerOnly, rows); }  @CliCommand(value = "show rollbacks", help = "List all rollback instants") String showRollbacks(
      @CliOption(key = {"limit"}, help = "Limit #rows to be displayed", unspecifiedDefaultValue = "10") Integer limit,
      @CliOption(key = {"sortBy"}, help = "Sorting Field", unspecifiedDefaultValue = "") final String sortByField,
      @CliOption(key = {"desc"}, help = "Ordering", unspecifiedDefaultValue = "false") final boolean descending,
      @CliOption(key = {"headeronly"}, help = "Print Header Only",
          unspecifiedDefaultValue = "false") final boolean headerOnly); @CliCommand(value = "show rollback", help = "Show details of a rollback instant") String showRollback(
      @CliOption(key = {"instant"}, help = "Rollback instant", mandatory = true) String rollbackInstant,
      @CliOption(key = {"limit"}, help = "Limit  #rows to be displayed", unspecifiedDefaultValue = "10") Integer limit,
      @CliOption(key = {"sortBy"}, help = "Sorting Field", unspecifiedDefaultValue = "") final String sortByField,
      @CliOption(key = {"desc"}, help = "Ordering", unspecifiedDefaultValue = "false") final boolean descending,
      @CliOption(key = {"headeronly"}, help = "Print Header Only",
          unspecifiedDefaultValue = "false") final boolean headerOnly); }
RollbacksCommand implements CommandMarker { @CliCommand(value = "show rollback", help = "Show details of a rollback instant") public String showRollback( @CliOption(key = {"instant"}, help = "Rollback instant", mandatory = true) String rollbackInstant, @CliOption(key = {"limit"}, help = "Limit #rows to be displayed", unspecifiedDefaultValue = "10") Integer limit, @CliOption(key = {"sortBy"}, help = "Sorting Field", unspecifiedDefaultValue = "") final String sortByField, @CliOption(key = {"desc"}, help = "Ordering", unspecifiedDefaultValue = "false") final boolean descending, @CliOption(key = {"headeronly"}, help = "Print Header Only", unspecifiedDefaultValue = "false") final boolean headerOnly) throws IOException { HoodieActiveTimeline activeTimeline = new RollbackTimeline(HoodieCLI.getTableMetaClient()); final List<Comparable[]> rows = new ArrayList<>(); HoodieRollbackMetadata metadata = TimelineMetadataUtils.deserializeAvroMetadata( activeTimeline.getInstantDetails(new HoodieInstant(State.COMPLETED, ROLLBACK_ACTION, rollbackInstant)).get(), HoodieRollbackMetadata.class); metadata.getPartitionMetadata().forEach((key, value) -> Stream .concat(value.getSuccessDeleteFiles().stream().map(f -> Pair.of(f, true)), value.getFailedDeleteFiles().stream().map(f -> Pair.of(f, false))) .forEach(fileWithDeleteStatus -> { Comparable[] row = new Comparable[5]; row[0] = metadata.getStartRollbackTime(); row[1] = metadata.getCommitsRollback().toString(); row[2] = key; row[3] = fileWithDeleteStatus.getLeft(); row[4] = fileWithDeleteStatus.getRight(); rows.add(row); })); TableHeader header = new TableHeader().addTableHeaderField(HoodieTableHeaderFields.HEADER_INSTANT) .addTableHeaderField(HoodieTableHeaderFields.HEADER_ROLLBACK_INSTANT) .addTableHeaderField(HoodieTableHeaderFields.HEADER_PARTITION) .addTableHeaderField(HoodieTableHeaderFields.HEADER_DELETED_FILE) .addTableHeaderField(HoodieTableHeaderFields.HEADER_SUCCEEDED); return HoodiePrintHelper.print(header, new HashMap<>(), sortByField, descending, limit, headerOnly, rows); }  @CliCommand(value = "show rollbacks", help = "List all rollback instants") String showRollbacks(
      @CliOption(key = {"limit"}, help = "Limit #rows to be displayed", unspecifiedDefaultValue = "10") Integer limit,
      @CliOption(key = {"sortBy"}, help = "Sorting Field", unspecifiedDefaultValue = "") final String sortByField,
      @CliOption(key = {"desc"}, help = "Ordering", unspecifiedDefaultValue = "false") final boolean descending,
      @CliOption(key = {"headeronly"}, help = "Print Header Only",
          unspecifiedDefaultValue = "false") final boolean headerOnly); @CliCommand(value = "show rollback", help = "Show details of a rollback instant") String showRollback(
      @CliOption(key = {"instant"}, help = "Rollback instant", mandatory = true) String rollbackInstant,
      @CliOption(key = {"limit"}, help = "Limit  #rows to be displayed", unspecifiedDefaultValue = "10") Integer limit,
      @CliOption(key = {"sortBy"}, help = "Sorting Field", unspecifiedDefaultValue = "") final String sortByField,
      @CliOption(key = {"desc"}, help = "Ordering", unspecifiedDefaultValue = "false") final boolean descending,
      @CliOption(key = {"headeronly"}, help = "Print Header Only",
          unspecifiedDefaultValue = "false") final boolean headerOnly);  }