diff --git a/ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java b/ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java index 39b287a2e55d76d5c9f6fdc2b8be75d790ade644..fd746b78b3d00bbec9746c3a77901eec7c9c77fb 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/ErrorMsg.java @@ -431,6 +431,7 @@ DROP_NATIVE_FUNCTION(10301, "Cannot drop native function"), UPDATE_CANNOT_UPDATE_BUCKET_VALUE(10302, "Updating values of bucketing columns is not supported. Column {0}.", true), IMPORT_INTO_STRICT_REPL_TABLE(10303,"Non-repl import disallowed against table that is a destination of replication."), + CTAS_LOCATION_NONEMPTY(10304, "CREATE-TABLE-AS-SELECT cannot create table with location to a non-empty directory."), //========================== 20000 range starts here ========================// SCRIPT_INIT_ERROR(20000, "Unable to initialize custom script."), diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java index f05407d38393cb5aa582ad3df16f06856f93869b..0a780af1cb41e787710f159aaa30e50095a81dba 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java @@ -20,6 +20,7 @@ import static org.apache.hadoop.hive.conf.HiveConf.ConfVars.HIVESTATSDBCLASS; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.Serializable; import java.security.AccessControlException; @@ -10960,6 +10961,31 @@ ASTNode analyzeCreateTable( throw new SemanticException(e); } + if(location != null && location.length() != 0) { + Path locPath = new Path(location); + FileSystem curFs = null; + FileStatus locStats = null; + try { + curFs = locPath.getFileSystem(conf); + if(curFs != null) { + locStats = curFs.getFileStatus(locPath); + } + if(locStats != null && locStats.isDir()) { + FileStatus[] lStats = curFs.listStatus(locPath); + if(lStats != null && lStats.length != 0) { + throw new SemanticException(ErrorMsg.CTAS_LOCATION_NONEMPTY.getMsg(location)); + } + } + } catch (FileNotFoundException nfe) { + //we will create the folder if it does not exist. + } catch (IOException ioE) { + if (LOG.isDebugEnabled()) { + LOG.debug("Exception when validate folder ",ioE); + } + + } + } + tblProps = addDefaultProperties(tblProps); tableDesc = new CreateTableDesc(qualifiedTabName[0], dbDotTab, isExt, isTemporary, cols, diff --git a/ql/src/test/queries/clientnegative/ctas_noemptyfolder.q b/ql/src/test/queries/clientnegative/ctas_noemptyfolder.q new file mode 100644 index 0000000000000000000000000000000000000000..18c9086af3166ee2eaf3d0870e31a0525a9d4735 --- /dev/null +++ b/ql/src/test/queries/clientnegative/ctas_noemptyfolder.q @@ -0,0 +1,10 @@ +create table ctas1 +location 'file:${system:test.tmp.dir}/ctastmpfolder' +as +select * from src limit 3; + +create table ctas2 +location 'file:${system:test.tmp.dir}/ctastmpfolder' +as +select * from src limit 2; + diff --git a/ql/src/test/results/clientnegative/ctas_noemptyfolder.q.out b/ql/src/test/results/clientnegative/ctas_noemptyfolder.q.out new file mode 100644 index 0000000000000000000000000000000000000000..76d7b867f4fe9555ee420186c2d2e99abd8bb1ac --- /dev/null +++ b/ql/src/test/results/clientnegative/ctas_noemptyfolder.q.out @@ -0,0 +1,19 @@ +PREHOOK: query: create table ctas1 +#### A masked pattern was here #### +as +select * from src limit 3 +PREHOOK: type: CREATETABLE_AS_SELECT +PREHOOK: Input: default@src +#### A masked pattern was here #### +PREHOOK: Output: database:default +PREHOOK: Output: default@ctas1 +POSTHOOK: query: create table ctas1 +#### A masked pattern was here #### +as +select * from src limit 3 +POSTHOOK: type: CREATETABLE_AS_SELECT +POSTHOOK: Input: default@src +#### A masked pattern was here #### +POSTHOOK: Output: database:default +POSTHOOK: Output: default@ctas1 +#### A masked pattern was here ####