diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/BaseSemanticAnalyzer.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/BaseSemanticAnalyzer.java index 8a1bfd21b4..d18dba554e 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/parse/BaseSemanticAnalyzer.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/BaseSemanticAnalyzer.java @@ -906,6 +906,17 @@ protected static void processForeignKeys(String databaseName, String tableName, } } + protected boolean hasEnabledOrValidatedConstraints(List notNullConstraints){ + if(notNullConstraints != null) { + for (SQLNotNullConstraint nnC : notNullConstraints) { + if (nnC.isEnable_cstr() || nnC.isValidate_cstr()) { + return true; + } + } + } + return false; + } + private static void checkColumnName(String columnName) throws SemanticException { if (VirtualColumn.VIRTUAL_COLUMN_NAMES.contains(columnName.toUpperCase())) { throw new SemanticException(ErrorMsg.INVALID_COLUMN_NAME.getMsg(columnName)); diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java index b766791ebc..834cb0c605 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/DDLSemanticAnalyzer.java @@ -96,6 +96,7 @@ import org.apache.hadoop.hive.ql.metadata.HiveException; import org.apache.hadoop.hive.ql.metadata.HiveUtils; import org.apache.hadoop.hive.ql.metadata.InvalidTableException; +import org.apache.hadoop.hive.ql.metadata.NotNullConstraint; import org.apache.hadoop.hive.ql.metadata.Partition; import org.apache.hadoop.hive.ql.metadata.Table; import org.apache.hadoop.hive.ql.parse.authorization.AuthorizationParseUtils; @@ -1895,6 +1896,26 @@ private void validateAlterTableType(Table tbl, AlterTableTypes op, boolean expec } } + private boolean hasConstraintsEnabled(final String tblName) throws SemanticException{ + + NotNullConstraint nnc = null; + try { + // retrieve enabled NOT NULL constraint from metastore + nnc = Hive.get().getEnabledNotNullConstraints( + db.getDatabaseCurrent().getName(), tblName); + } catch (Exception e) { + if (e instanceof SemanticException) { + throw (SemanticException) e; + } else { + throw (new RuntimeException(e)); + } + } + if(nnc != null && !nnc.getNotNullConstraints().isEmpty()) { + return true; + } + return false; + } + private void analyzeAlterTableProps(String[] qualified, HashMap partSpec, ASTNode ast, boolean expectView, boolean isUnset) throws SemanticException { @@ -1919,7 +1940,17 @@ private void analyzeAlterTableProps(String[] qualified, HashMap throw new SemanticException("AlterTable " + entry.getKey() + " failed with value " + entry.getValue()); } - } else { + } + // if table is being modified to be external we need to make sure existing table + // doesn't have enabled constraint since constraints are disallowed with such tables + else if(entry.getKey().equals("external") && entry.getValue().equals("true")){ + if(hasConstraintsEnabled(qualified[1])){ + throw new SemanticException( + ErrorMsg.INVALID_CSTR_SYNTAX.getMsg("Table: " + tableName + " has constraints enabled." + + "Please remove those constraints to change this property.")); + } + } + else { if (queryState.getCommandType() .equals(HiveOperation.ALTERTABLE_UPDATETABLESTATS.getOperationName()) || queryState.getCommandType() @@ -3354,6 +3385,13 @@ private void analyzeAlterTableRenameCol(String[] qualified, ASTNode ast, /* Validate the operation of renaming a column name. */ Table tab = getTable(qualified); + if(tab.getTableType() == TableType.EXTERNAL_TABLE + && hasEnabledOrValidatedConstraints(notNullConstraints)){ + throw new SemanticException( + ErrorMsg.INVALID_CSTR_SYNTAX.getMsg("Constraints are disallowed with External tables. " + + "Only RELY is allowed.")); + } + SkewedInfo skewInfo = tab.getTTable().getSd().getSkewedInfo(); if ((null != skewInfo) && (null != skewInfo.getSkewedColNames()) 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 8e587f1cf6..38f209a382 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 @@ -12548,6 +12548,13 @@ ASTNode analyzeCreateTable( throw new SemanticException("Unrecognized command."); } + if(isExt && hasEnabledOrValidatedConstraints(notNullConstraints)){ + throw new SemanticException( + ErrorMsg.INVALID_CSTR_SYNTAX.getMsg("Constraints are disallowed with External tables. " + + "Only RELY is allowed.")); + } + + storageFormat.fillDefaultStorageFormat(isExt, false); // check for existence of table diff --git a/ql/src/test/queries/clientnegative/alter_external_with_constraint.q b/ql/src/test/queries/clientnegative/alter_external_with_constraint.q new file mode 100644 index 0000000000..041585e4dc --- /dev/null +++ b/ql/src/test/queries/clientnegative/alter_external_with_constraint.q @@ -0,0 +1,3 @@ +CREATE external TABLE table1 (a STRING, b STRING); +Alter table table1 change b b STRING NOT NULL enable; + diff --git a/ql/src/test/queries/clientnegative/alter_tableprops_external_with_constraint.q b/ql/src/test/queries/clientnegative/alter_tableprops_external_with_constraint.q new file mode 100644 index 0000000000..9deefb138b --- /dev/null +++ b/ql/src/test/queries/clientnegative/alter_tableprops_external_with_constraint.q @@ -0,0 +1,3 @@ +CREATE TABLE table1 (a STRING NOT NULL enforced, b STRING); +Alter table table1 set TBLPROPERTIES('external'='true'); + diff --git a/ql/src/test/queries/clientnegative/create_external_with_constraint.q b/ql/src/test/queries/clientnegative/create_external_with_constraint.q new file mode 100644 index 0000000000..5b126627d7 --- /dev/null +++ b/ql/src/test/queries/clientnegative/create_external_with_constraint.q @@ -0,0 +1 @@ +CREATE external TABLE table1 (a STRING not null enforced, b STRING); diff --git a/ql/src/test/results/clientnegative/alter_external_with_constraint.q.out b/ql/src/test/results/clientnegative/alter_external_with_constraint.q.out new file mode 100644 index 0000000000..a6001a40bf --- /dev/null +++ b/ql/src/test/results/clientnegative/alter_external_with_constraint.q.out @@ -0,0 +1,9 @@ +PREHOOK: query: CREATE external TABLE table1 (a STRING, b STRING) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@table1 +POSTHOOK: query: CREATE external TABLE table1 (a STRING, b STRING) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@table1 +FAILED: SemanticException [Error 10326]: Invalid Constraint syntax Constraints are disallowed with External tables. Only RELY is allowed. diff --git a/ql/src/test/results/clientnegative/alter_tableprops_external_with_constraint.q.out b/ql/src/test/results/clientnegative/alter_tableprops_external_with_constraint.q.out new file mode 100644 index 0000000000..6cfc93261f --- /dev/null +++ b/ql/src/test/results/clientnegative/alter_tableprops_external_with_constraint.q.out @@ -0,0 +1,9 @@ +PREHOOK: query: CREATE TABLE table1 (a STRING NOT NULL enforced, b STRING) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@table1 +POSTHOOK: query: CREATE TABLE table1 (a STRING NOT NULL enforced, b STRING) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@table1 +FAILED: SemanticException [Error 10326]: Invalid Constraint syntax Table: default.table1 has constraints enabled.Please remove those constraints to change this property. diff --git a/ql/src/test/results/clientnegative/create_external_with_constraint.q.out b/ql/src/test/results/clientnegative/create_external_with_constraint.q.out new file mode 100644 index 0000000000..e69566d503 --- /dev/null +++ b/ql/src/test/results/clientnegative/create_external_with_constraint.q.out @@ -0,0 +1 @@ +FAILED: SemanticException [Error 10326]: Invalid Constraint syntax Constraints are disallowed with External tables. Only RELY is allowed.