diff --git a/src/java/com/cloudera/sqoop/orm/ClassWriter.java b/src/java/com/cloudera/sqoop/orm/ClassWriter.java index b5b8a12d..0080ef0e 100644 --- a/src/java/com/cloudera/sqoop/orm/ClassWriter.java +++ b/src/java/com/cloudera/sqoop/orm/ClassWriter.java @@ -42,6 +42,7 @@ import java.io.Writer; import java.util.HashSet; import java.util.Map; +import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -1057,11 +1058,18 @@ public void generate() throws IOException { // Translate all the column names into names that are safe to // use as identifiers. String [] cleanedColNames = cleanColNames(colNames); - + Set uniqColNames = new HashSet(); for (int i = 0; i < colNames.length; i++) { + // Guarantee uniq col identifier + String identifier = cleanedColNames[i]; + if (uniqColNames.contains(identifier)) { + throw new IllegalArgumentException("Duplicate Column identifier " + + "specified: '" + identifier + "'"); + } + uniqColNames.add(identifier); + // Make sure the col->type mapping holds for the // new identifier name, too. - String identifier = cleanedColNames[i]; String col = colNames[i]; columnTypes.put(identifier, columnTypes.get(col)); } diff --git a/src/test/com/cloudera/sqoop/mapreduce/TestImportJob.java b/src/test/com/cloudera/sqoop/mapreduce/TestImportJob.java index 3a0b9277..a3ee8120 100644 --- a/src/test/com/cloudera/sqoop/mapreduce/TestImportJob.java +++ b/src/test/com/cloudera/sqoop/mapreduce/TestImportJob.java @@ -59,7 +59,7 @@ public void testFailedImportDueToIOException() throws IOException { assertTrue(fs.exists(outputPath)); - String [] argv = getArgv(true, new String [] { "DATA_COL0" }, conf); + String[] argv = getArgv(true, new String[] { "DATA_COL0" }, conf); Sqoop importer = new Sqoop(new ImportTool()); try { @@ -72,11 +72,11 @@ public void testFailedImportDueToIOException() throws IOException { } /** A mapper that is guaranteed to cause the task to fail. */ - public static class NullDereferenceMapper - extends AutoProgressMapper { + public static class NullDereferenceMapper extends + AutoProgressMapper { - public void map(Object key, Object val, Context c) - throws IOException, InterruptedException { + public void map(Object key, Object val, Context c) throws IOException, + InterruptedException { String s = null; s.length(); // This will throw a NullPointerException. } @@ -122,19 +122,16 @@ public void testFailedImportDueToJobFail() throws IOException { // Use the dependency-injection manager. conf.setClass(ConnFactory.FACTORY_CLASS_NAMES_KEY, - InjectableManagerFactory.class, - ManagerFactory.class); + InjectableManagerFactory.class, ManagerFactory.class); - String [] argv = getArgv(true, new String [] { "DATA_COL0" }, conf); + String[] argv = getArgv(true, new String[] { "DATA_COL0" }, conf); // Use dependency injection to specify a mapper that we know // will fail. conf.setClass(InjectableConnManager.MAPPER_KEY, - NullDereferenceMapper.class, - Mapper.class); + NullDereferenceMapper.class, Mapper.class); - conf.setClass(InjectableConnManager.IMPORT_JOB_KEY, - DummyImportJob.class, + conf.setClass(InjectableConnManager.IMPORT_JOB_KEY, DummyImportJob.class, ImportJobBase.class); Sqoop importer = new Sqoop(new ImportTool(), conf); @@ -147,5 +144,32 @@ public void testFailedImportDueToJobFail() throws IOException { } } -} + public void testDuplicateColumns() throws IOException { + // Make sure that if a MapReduce job to do the import fails due + // to an IOException, we tell the user about it. + // Create a table to attempt to import. + createTableForColType("VARCHAR(32)", "'meep'"); + + Configuration conf = new Configuration(); + + // Make the output dir exist so we know the job will fail via IOException. + Path outputPath = new Path(new Path(getWarehouseDir()), getTableName()); + FileSystem fs = FileSystem.getLocal(conf); + fs.mkdirs(outputPath); + + assertTrue(fs.exists(outputPath)); + + String[] argv = getArgv(true, new String[] { "DATA_COL0,DATA_COL0" }, conf); + + Sqoop importer = new Sqoop(new ImportTool()); + try { + int ret = Sqoop.runSqoop(importer, argv); + assertTrue("Expected job to fail!", 1 == ret); + } catch (Exception e) { + // In debug mode, ImportException is wrapped in RuntimeException. + LOG.info("Got exceptional return (expected: ok). msg is: " + e); + } + } + +}