diff --git a/itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/parse/TestReplicationScenariosAcrossInstances.java b/itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/parse/TestReplicationScenariosAcrossInstances.java index 6c45641..35ad982 100644 --- a/itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/parse/TestReplicationScenariosAcrossInstances.java +++ b/itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/parse/TestReplicationScenariosAcrossInstances.java @@ -1400,4 +1400,25 @@ public void testDumpExternalTableSetTrue() throws Throwable { .run("select id from t4") .verifyResult(null); // Returns null as create table event doesn't list files } + + @Test + public void testDumpExternalTableWithAddPartitionEvent() throws Throwable { + WarehouseInstance.Tuple tuple = primary.dump("repl dump " + primaryDbName); + + replica.load(replicatedDbName, tuple.dumpLocation); + + tuple = primary.run("use " + primaryDbName) + .run("create external table t1 (place string) partitioned by (country string)") + .run("alter table t1 add partition(country='india')") + .run("alter table t1 add partition(country='us')") + .dump("repl dump " + primaryDbName + " from " + tuple.lastReplicationId + + " with ('hive.repl.include.external.tables'='true')"); + + replica.load(replicatedDbName, tuple.dumpLocation) + .run("use " + replicatedDbName) + .run("show tables like 't1'") + .verifyResult("t1") + .run("show partitions t1") + .verifyResults(new String[] { "country=india", "country=us" }); + } } diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/repl/dump/events/AddPartitionHandler.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/repl/dump/events/AddPartitionHandler.java index cf15905..973a65b 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/parse/repl/dump/events/AddPartitionHandler.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/repl/dump/events/AddPartitionHandler.java @@ -85,14 +85,19 @@ public void handle(Context withinContext) throws Exception { withinContext.hiveConf); Iterator partitionFilesIter = apm.getPartitionFilesIter().iterator(); - for (Partition qlPtn : qlPtns) { - Iterable files = partitionFilesIter.next().getFiles(); - if (files != null) { - // encoded filename/checksum of files, write into _files - try (BufferedWriter fileListWriter = writer(withinContext, qlPtn)) { - for (String file : files) { - fileListWriter.write(file); - fileListWriter.newLine(); + + // We expect one to one mapping between partitions and file iterators. For external table, this + // list would be empty. So, it is enough to check hasNext outside the loop. + if (partitionFilesIter.hasNext()) { + for (Partition qlPtn : qlPtns) { + Iterable files = partitionFilesIter.next().getFiles(); + if (files != null) { + // encoded filename/checksum of files, write into _files + try (BufferedWriter fileListWriter = writer(withinContext, qlPtn)) { + for (String file : files) { + fileListWriter.write(file); + fileListWriter.newLine(); + } } } }