diff --git ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java index 141d9ff..9d98839 100644 --- ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java +++ ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java @@ -418,9 +418,22 @@ public class DDLSemanticAnalyzer extends BaseSemanticAnalyzer { rootTasks.add(createIndex); } - private void analyzeDropIndex(ASTNode ast) { + private void analyzeDropIndex(ASTNode ast) throws SemanticException { String indexName = unescapeIdentifier(ast.getChild(0).getText()); String tableName = unescapeIdentifier(ast.getChild(1).getText()); + boolean ifExists = (ast.getFirstChildWithType(TOK_IFEXISTS) != null); + // we want to signal an error if the index doesn't exist and we're + // configured not to ignore this + boolean throwException = + !ifExists && !HiveConf.getBoolVar(conf, ConfVars.DROPIGNORESNONEXISTENT); + if (throwException) { + try { + Index idx = db.getIndex(tableName, indexName); + } catch (HiveException e) { + throw new SemanticException(ErrorMsg.INVALID_INDEX.getMsg(indexName)); + } + } + DropIndexDesc dropIdxDesc = new DropIndexDesc(indexName, tableName); rootTasks.add(TaskFactory.get(new DDLWork(getInputs(), getOutputs(), dropIdxDesc), conf)); @@ -1223,7 +1236,12 @@ public class DDLSemanticAnalyzer extends BaseSemanticAnalyzer { } if (partSpecs != null) { - addTablePartsOutputs(tblName, partSpecs); + boolean ifExists = (ast.getFirstChildWithType(TOK_IFEXISTS) != null); + // we want to signal an error if the partition doesn't exist and we're + // configured not to fail silently + boolean throwException = + !ifExists && !HiveConf.getBoolVar(conf, ConfVars.DROPIGNORESNONEXISTENT); + addTablePartsOutputs(tblName, partSpecs, throwException, ast); } rootTasks.add(TaskFactory.get(new DDLWork(getInputs(), getOutputs(), @@ -1470,6 +1488,17 @@ public class DDLSemanticAnalyzer extends BaseSemanticAnalyzer { */ private void addTablePartsOutputs(String tblName, List> partSpecs) throws SemanticException { + addTablePartsOutputs(tblName, partSpecs, false, null); + } + + /** + * Add the table partitions to be modified in the output, so that it is available for the + * pre-execution hook. If the partition does not exist, throw an error if + * throwIfNonExistent is true, otherwise ignore it. + */ + private void addTablePartsOutputs(String tblName, List> partSpecs, + boolean throwIfNonExistent, ASTNode ast) + throws SemanticException { Table tab; try { tab = db.getTable(tblName); @@ -1477,7 +1506,10 @@ public class DDLSemanticAnalyzer extends BaseSemanticAnalyzer { throw new SemanticException(ErrorMsg.INVALID_TABLE.getMsg(tblName)); } - for (Map partSpec : partSpecs) { + Iterator> i; + int index; + for (i = partSpecs.iterator(), index = 1; i.hasNext(); ++index) { + Map partSpec = i.next(); try { Partition part = db.getPartition(tab, partSpec, false); if (part == null) { @@ -1486,7 +1518,11 @@ public class DDLSemanticAnalyzer extends BaseSemanticAnalyzer { outputs.add(new WriteEntity(part)); } catch (HiveException e) { // Ignore the error if the partition does not exist + if (throwIfNonExistent) { + throw new SemanticException(ErrorMsg.INVALID_PARTITION.getMsg(ast.getChild(index))); + } } } } + } diff --git ql/src/java/org/apache/hadoop/hive/ql/parse/ErrorMsg.java ql/src/java/org/apache/hadoop/hive/ql/parse/ErrorMsg.java index a02e6b4..01eef69 100644 --- ql/src/java/org/apache/hadoop/hive/ql/parse/ErrorMsg.java +++ ql/src/java/org/apache/hadoop/hive/ql/parse/ErrorMsg.java @@ -41,6 +41,7 @@ public enum ErrorMsg { GENERIC_ERROR("Exception while processing"), INVALID_TABLE("Table not found", "42S02"), INVALID_COLUMN("Invalid Column Reference"), + INVALID_INDEX("Invalid Index"), INVALID_TABLE_OR_COLUMN("Invalid Table Alias or Column Reference"), AMBIGUOUS_TABLE_OR_COLUMN("Ambiguous Table Alias or Column Reference"), INVALID_PARTITION("Partition not found"), diff --git ql/src/java/org/apache/hadoop/hive/ql/parse/FunctionSemanticAnalyzer.java ql/src/java/org/apache/hadoop/hive/ql/parse/FunctionSemanticAnalyzer.java index 54323d2..e90da62 100644 --- ql/src/java/org/apache/hadoop/hive/ql/parse/FunctionSemanticAnalyzer.java +++ ql/src/java/org/apache/hadoop/hive/ql/parse/FunctionSemanticAnalyzer.java @@ -18,9 +18,13 @@ package org.apache.hadoop.hive.ql.parse; +import static org.apache.hadoop.hive.ql.parse.HiveParser.TOK_IFEXISTS; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.hive.conf.HiveConf; +import org.apache.hadoop.hive.conf.HiveConf.ConfVars; +import org.apache.hadoop.hive.ql.exec.FunctionRegistry; import org.apache.hadoop.hive.ql.exec.TaskFactory; import org.apache.hadoop.hive.ql.plan.CreateFunctionDesc; import org.apache.hadoop.hive.ql.plan.DropFunctionDesc; @@ -59,6 +63,15 @@ public class FunctionSemanticAnalyzer extends BaseSemanticAnalyzer { private void analyzeDropFunction(ASTNode ast) throws SemanticException { String functionName = ast.getChild(0).getText(); + boolean ifExists = (ast.getFirstChildWithType(TOK_IFEXISTS) != null); + // we want to signal an error if the function doesn't exist and we're + // configured not to ignore this + boolean throwException = + !ifExists && !HiveConf.getBoolVar(conf, ConfVars.DROPIGNORESNONEXISTENT); + if (throwException && FunctionRegistry.getFunctionInfo(functionName) == null) { + throw new SemanticException(ErrorMsg.INVALID_FUNCTION.getMsg(functionName)); + } + DropFunctionDesc desc = new DropFunctionDesc(functionName); rootTasks.add(TaskFactory.get(new FunctionWork(desc), conf)); } diff --git ql/src/java/org/apache/hadoop/hive/ql/parse/Hive.g ql/src/java/org/apache/hadoop/hive/ql/parse/Hive.g index 2551261..10ba08d 100644 --- ql/src/java/org/apache/hadoop/hive/ql/parse/Hive.g +++ ql/src/java/org/apache/hadoop/hive/ql/parse/Hive.g @@ -427,8 +427,8 @@ indexPropertiesList dropIndexStatement @init { msgs.push("drop index statement");} @after {msgs.pop();} - : KW_DROP KW_INDEX indexName=Identifier KW_ON tab=Identifier - ->^(TOK_DROPINDEX $indexName $tab) + : KW_DROP KW_INDEX ifExists? indexName=Identifier KW_ON tab=Identifier + ->^(TOK_DROPINDEX $indexName $tab ifExists?) ; dropTableStatement @@ -555,8 +555,8 @@ partitionLocation alterStatementSuffixDropPartitions @init { msgs.push("drop partition statement"); } @after { msgs.pop(); } - : Identifier KW_DROP partitionSpec (COMMA partitionSpec)* - -> ^(TOK_ALTERTABLE_DROPPARTS Identifier partitionSpec+) + : Identifier KW_DROP ifExists? partitionSpec (COMMA partitionSpec)* + -> ^(TOK_ALTERTABLE_DROPPARTS Identifier partitionSpec+ ifExists?) ; alterStatementSuffixProperties @@ -738,8 +738,8 @@ createFunctionStatement dropFunctionStatement @init { msgs.push("drop temporary function statement"); } @after { msgs.pop(); } - : KW_DROP KW_TEMPORARY KW_FUNCTION Identifier - -> ^(TOK_DROPFUNCTION Identifier) + : KW_DROP KW_TEMPORARY KW_FUNCTION ifExists? Identifier + -> ^(TOK_DROPFUNCTION Identifier ifExists?) ; createViewStatement diff --git ql/src/test/queries/clientnegative/drop_function_failure.q ql/src/test/queries/clientnegative/drop_function_failure.q new file mode 100644 index 0000000..51dc5e9 --- /dev/null +++ ql/src/test/queries/clientnegative/drop_function_failure.q @@ -0,0 +1,3 @@ +set hive.exec.drop.ignorenonexistent=false; +-- Can't use DROP TEMPORARY FUNCTION if the function doesn't exist and IF EXISTS isn't specified +DROP TEMPORARY FUNCTION UnknownFunction; diff --git ql/src/test/queries/clientnegative/drop_index_failure.q ql/src/test/queries/clientnegative/drop_index_failure.q new file mode 100644 index 0000000..6e907df --- /dev/null +++ ql/src/test/queries/clientnegative/drop_index_failure.q @@ -0,0 +1,3 @@ +set hive.exec.drop.ignorenonexistent=false; +-- Can't use DROP INDEX if the index doesn't exist and IF EXISTS isn't specified +DROP INDEX UnknownIndex ON src; diff --git ql/src/test/queries/clientnegative/drop_partition_failure.q ql/src/test/queries/clientnegative/drop_partition_failure.q new file mode 100644 index 0000000..c2074f6 --- /dev/null +++ ql/src/test/queries/clientnegative/drop_partition_failure.q @@ -0,0 +1,11 @@ +create table mp (a string) partitioned by (b string, c string); + +alter table mp add partition (b='1', c='1'); +alter table mp add partition (b='1', c='2'); +alter table mp add partition (b='2', c='2'); + +show partitions mp; + +set hive.exec.drop.ignorenonexistent=false; +-- Can't use DROP PARTITION if the partition doesn't exist and IF EXISTS isn't specified +alter table mp drop partition (b='3'); diff --git ql/src/test/queries/clientpositive/drop_function.q ql/src/test/queries/clientpositive/drop_function.q new file mode 100644 index 0000000..18c428c --- /dev/null +++ ql/src/test/queries/clientpositive/drop_function.q @@ -0,0 +1,2 @@ +SET hive.exec.drop.ignorenonexistent=false; +DROP TEMPORARY FUNCTION IF EXISTS UnknownFunction; diff --git ql/src/test/queries/clientpositive/drop_index.q ql/src/test/queries/clientpositive/drop_index.q new file mode 100644 index 0000000..df23f8d --- /dev/null +++ ql/src/test/queries/clientpositive/drop_index.q @@ -0,0 +1,2 @@ +SET hive.exec.drop.ignorenonexistent=false; +DROP INDEX IF EXISTS UnknownIndex ON src; diff --git ql/src/test/queries/clientpositive/drop_multi_partitions.q ql/src/test/queries/clientpositive/drop_multi_partitions.q index d13e9b6..14e2356 100644 --- ql/src/test/queries/clientpositive/drop_multi_partitions.q +++ ql/src/test/queries/clientpositive/drop_multi_partitions.q @@ -11,5 +11,7 @@ alter table mp drop partition (b='1'); show partitions mp; +set hive.exec.drop.ignorenonexistent=false; +alter table mp drop if exists partition (b='3'); - +show partitions mp; diff --git ql/src/test/queries/clientpositive/drop_table.q ql/src/test/queries/clientpositive/drop_table.q index 2eba403..6d189fc 100644 --- ql/src/test/queries/clientpositive/drop_table.q +++ ql/src/test/queries/clientpositive/drop_table.q @@ -1,2 +1,2 @@ -SET hive.exec.dropfailssilently=false; +SET hive.exec.drop.ignorenonexistent=false; DROP TABLE IF EXISTS UnknownTable; diff --git ql/src/test/queries/clientpositive/drop_view.q ql/src/test/queries/clientpositive/drop_view.q index 12337df..4ff0975 100644 --- ql/src/test/queries/clientpositive/drop_view.q +++ ql/src/test/queries/clientpositive/drop_view.q @@ -1,2 +1,2 @@ -SET hive.exec.dropfailssilently=false; +SET hive.exec.drop.ignorenonexistent=false; DROP VIEW IF EXISTS UnknownView; diff --git ql/src/test/results/clientnegative/drop_function_failure.q.out ql/src/test/results/clientnegative/drop_function_failure.q.out new file mode 100644 index 0000000..0629c37 --- /dev/null +++ ql/src/test/results/clientnegative/drop_function_failure.q.out @@ -0,0 +1 @@ +FAILED: Error in semantic analysis: Invalid Function UnknownFunction diff --git ql/src/test/results/clientnegative/drop_index_failure.q.out ql/src/test/results/clientnegative/drop_index_failure.q.out new file mode 100644 index 0000000..c91afac --- /dev/null +++ ql/src/test/results/clientnegative/drop_index_failure.q.out @@ -0,0 +1 @@ +FAILED: Error in semantic analysis: Invalid Index UnknownIndex diff --git ql/src/test/results/clientnegative/drop_partition_failure.q.out ql/src/test/results/clientnegative/drop_partition_failure.q.out new file mode 100644 index 0000000..97b4839 --- /dev/null +++ ql/src/test/results/clientnegative/drop_partition_failure.q.out @@ -0,0 +1,34 @@ +PREHOOK: query: create table mp (a string) partitioned by (b string, c string) +PREHOOK: type: CREATETABLE +POSTHOOK: query: create table mp (a string) partitioned by (b string, c string) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: default@mp +PREHOOK: query: alter table mp add partition (b='1', c='1') +PREHOOK: type: ALTERTABLE_ADDPARTS +PREHOOK: Input: default@mp +POSTHOOK: query: alter table mp add partition (b='1', c='1') +POSTHOOK: type: ALTERTABLE_ADDPARTS +POSTHOOK: Input: default@mp +POSTHOOK: Output: default@mp@b=1/c=1 +PREHOOK: query: alter table mp add partition (b='1', c='2') +PREHOOK: type: ALTERTABLE_ADDPARTS +PREHOOK: Input: default@mp +POSTHOOK: query: alter table mp add partition (b='1', c='2') +POSTHOOK: type: ALTERTABLE_ADDPARTS +POSTHOOK: Input: default@mp +POSTHOOK: Output: default@mp@b=1/c=2 +PREHOOK: query: alter table mp add partition (b='2', c='2') +PREHOOK: type: ALTERTABLE_ADDPARTS +PREHOOK: Input: default@mp +POSTHOOK: query: alter table mp add partition (b='2', c='2') +POSTHOOK: type: ALTERTABLE_ADDPARTS +POSTHOOK: Input: default@mp +POSTHOOK: Output: default@mp@b=2/c=2 +PREHOOK: query: show partitions mp +PREHOOK: type: SHOWPARTITIONS +POSTHOOK: query: show partitions mp +POSTHOOK: type: SHOWPARTITIONS +b=1/c=1 +b=1/c=2 +b=2/c=2 +FAILED: Error in semantic analysis: line 3:31 Partition not found '3' diff --git ql/src/test/results/clientpositive/drop_function.q.out ql/src/test/results/clientpositive/drop_function.q.out new file mode 100644 index 0000000..cace484 --- /dev/null +++ ql/src/test/results/clientpositive/drop_function.q.out @@ -0,0 +1,4 @@ +PREHOOK: query: DROP TEMPORARY FUNCTION IF EXISTS UnknownFunction +PREHOOK: type: DROPFUNCTION +POSTHOOK: query: DROP TEMPORARY FUNCTION IF EXISTS UnknownFunction +POSTHOOK: type: DROPFUNCTION diff --git ql/src/test/results/clientpositive/drop_index.q.out ql/src/test/results/clientpositive/drop_index.q.out new file mode 100644 index 0000000..c7c4a78 --- /dev/null +++ ql/src/test/results/clientpositive/drop_index.q.out @@ -0,0 +1,4 @@ +PREHOOK: query: DROP INDEX IF EXISTS UnknownIndex ON src +PREHOOK: type: DROPINDEX +POSTHOOK: query: DROP INDEX IF EXISTS UnknownIndex ON src +POSTHOOK: type: DROPINDEX diff --git ql/src/test/results/clientpositive/drop_multi_partitions.q.out ql/src/test/results/clientpositive/drop_multi_partitions.q.out index 0ba2d72..037b949 100644 --- ql/src/test/results/clientpositive/drop_multi_partitions.q.out +++ ql/src/test/results/clientpositive/drop_multi_partitions.q.out @@ -61,3 +61,14 @@ PREHOOK: type: SHOWPARTITIONS POSTHOOK: query: show partitions mp POSTHOOK: type: SHOWPARTITIONS b=2/c=2 +PREHOOK: query: alter table mp drop if exists partition (b='3') +PREHOOK: type: ALTERTABLE_DROPPARTS +PREHOOK: Input: default@mp +POSTHOOK: query: alter table mp drop if exists partition (b='3') +POSTHOOK: type: ALTERTABLE_DROPPARTS +POSTHOOK: Input: default@mp +PREHOOK: query: show partitions mp +PREHOOK: type: SHOWPARTITIONS +POSTHOOK: query: show partitions mp +POSTHOOK: type: SHOWPARTITIONS +b=2/c=2