diff --git ql/src/java/org/apache/hadoop/hive/ql/exec/DDLTask.java ql/src/java/org/apache/hadoop/hive/ql/exec/DDLTask.java index cb7fdf73b5..7b6113de1e 100644 --- ql/src/java/org/apache/hadoop/hive/ql/exec/DDLTask.java +++ ql/src/java/org/apache/hadoop/hive/ql/exec/DDLTask.java @@ -115,6 +115,12 @@ import org.apache.hadoop.hive.metastore.api.WMResourcePlanStatus; import org.apache.hadoop.hive.metastore.api.WMTrigger; import org.apache.hadoop.hive.metastore.api.WMValidateResourcePlanResponse; +import org.apache.hadoop.hive.metastore.api.PrimaryKeysRequest; +import org.apache.hadoop.hive.metastore.api.UniqueConstraintsRequest; +import org.apache.hadoop.hive.metastore.api.NotNullConstraintsRequest; +import org.apache.hadoop.hive.metastore.api.DefaultConstraintsRequest; +import org.apache.hadoop.hive.metastore.api.CheckConstraintsRequest; +import org.apache.hadoop.hive.metastore.api.ForeignKeysRequest; import org.apache.hadoop.hive.metastore.conf.MetastoreConf; import org.apache.hadoop.hive.metastore.txn.TxnStore; import org.apache.hadoop.hive.metastore.utils.MetaStoreUtils; @@ -2334,14 +2340,138 @@ private int showCreateTable(Hive db, DataOutputStream outStream, String tableNam String tbl_columns = ""; List cols = tbl.getCols(); List columns = new ArrayList(); + + //Constraints + List primaryKeys = new ArrayList<>(); + List foreignKeys = new ArrayList<>(); + List uniqueConstraints = new ArrayList<>(); + List notNullConstraints = new ArrayList<>(); + List defaultConstraints = new ArrayList<>(); + List checkConstraints = new ArrayList<>(); + try { + primaryKeys = db.getMSC().getPrimaryKeys(new PrimaryKeysRequest(tbl.getDbName(), tbl.getTableName())); + foreignKeys = db.getMSC().getForeignKeys(new ForeignKeysRequest(null, null, + tbl.getDbName(), tbl.getTableName())); + uniqueConstraints = db.getMSC().getUniqueConstraints(new UniqueConstraintsRequest( + MetaStoreUtils.getDefaultCatalog(conf), tbl.getDbName(), tbl.getTableName())); + notNullConstraints = db.getMSC().getNotNullConstraints(new NotNullConstraintsRequest( + MetaStoreUtils.getDefaultCatalog(conf), tbl.getDbName(), tbl.getTableName())); + defaultConstraints = db.getMSC().getDefaultConstraints(new DefaultConstraintsRequest( + MetaStoreUtils.getDefaultCatalog(conf), tbl.getDbName(), tbl.getTableName())); + checkConstraints = db.getMSC().getCheckConstraints(new CheckConstraintsRequest( + MetaStoreUtils.getDefaultCatalog(conf), tbl.getDbName(), tbl.getTableName())); + } catch (Exception e) { + throw new HiveException(e); + } + + + //Convert constraints lists to map, where column name is the key + Map primaryKeysByColName = new HashMap<>(); + Map uniqueConstraintsByColName = new HashMap<>(); + Map notNullConstraintsByColName = new HashMap<>(); + Map defaultConstraintsByColName = new HashMap<>(); + Map checkConstraintsByColName = new HashMap<>(); + primaryKeys.forEach(pk -> primaryKeysByColName.put(pk.getColumn_name(), pk)); + uniqueConstraints.forEach(u -> uniqueConstraintsByColName.put(u.getColumn_name(), u)); + notNullConstraints.forEach(nn -> notNullConstraintsByColName.put(nn.getColumn_name(), nn)); + defaultConstraints.forEach(d -> defaultConstraintsByColName.put(d.getColumn_name(), d)); + checkConstraints.forEach(c -> checkConstraintsByColName.put(c.getColumn_name(), c)); + + //Convert foreign keys list to a map, where constraint name is the key + Map> foreignKeysByColName = new HashMap<>(); + foreignKeys.forEach(x -> { + List foreignKeyList = foreignKeysByColName.get(x.getFk_name()); + if (foreignKeyList != null) { + foreignKeysByColName.get(x.getFk_name()).add(x); + } else { + List list = new ArrayList<>(); + list.add(x); + foreignKeysByColName.put(x.getFk_name(), list); + } + }); + for (FieldSchema col : cols) { String columnDesc = " `" + col.getName() + "` " + col.getType(); + if(defaultConstraintsByColName.containsKey(col.getName())) { + SQLDefaultConstraint defaultConstraint = defaultConstraintsByColName.get(col.getName()); + //DEFAULT only support ENABLE and DISABLE keywords + columnDesc += " DEFAULT " + defaultConstraint.getDefault_value() + + (defaultConstraint.isEnable_cstr() ? " ENABLE" : " DISABLE"); + } + if(uniqueConstraintsByColName.containsKey(col.getName())) { + SQLUniqueConstraint uniqueConstraint = uniqueConstraintsByColName.get(col.getName()); + columnDesc += " UNIQUE" + (uniqueConstraint.isEnable_cstr() ? " ENABLE" : " DISABLE") + + (uniqueConstraint.isValidate_cstr() ? " VALIDATE" : " NOVALIDATE") + + (uniqueConstraint.isRely_cstr() ? " RELY" : " NORELY"); + } + if(notNullConstraintsByColName.containsKey(col.getName())) { + SQLNotNullConstraint notNullConstraint = notNullConstraintsByColName.get(col.getName()); + columnDesc += " NOT NULL" + (notNullConstraint.isEnable_cstr() ? " ENABLE" : " DISABLE") + + (notNullConstraint.isValidate_cstr() ? " VALIDATE" : " NOVALIDATE") + + (notNullConstraint.isRely_cstr() ? " RELY" : " NORELY"); + } + if(checkConstraintsByColName.containsKey(col.getName())) { + SQLCheckConstraint checkConstraint = checkConstraintsByColName.get(col.getName()); + columnDesc += " CHECK " + checkConstraint.getCheck_expression() + + (checkConstraint.isEnable_cstr() ? " ENABLE" : " DISABLE") + + (checkConstraint.isValidate_cstr() ? " VALIDATE" : " NOVALIDATE") + + (checkConstraint.isRely_cstr() ? " RELY" : " NORELY"); + } if (col.getComment() != null) { columnDesc = columnDesc + " COMMENT '" + HiveStringUtils.escapeHiveCommand(col.getComment()) + "'"; } columns.add(columnDesc); } + + StringBuilder constaintsStr = new StringBuilder(); + //If the table has primary and foreign keys as well, comma is needed to separate them + boolean needComma = false; + + if(!primaryKeysByColName.isEmpty()) { + constaintsStr.append(" PRIMARY KEY ("); + for (Map.Entry pk : primaryKeysByColName.entrySet()) { + constaintsStr.append(pk.getKey() + ", "); + } + constaintsStr.setLength(constaintsStr.length()-2); + SQLPrimaryKey pk = (SQLPrimaryKey)primaryKeysByColName.values().toArray()[0]; + constaintsStr.append(")"); + constaintsStr.append((pk.isEnable_cstr() ? " ENABLE" : " DISABLE") + + (pk.isValidate_cstr() ? " VALIDATE" : " NOVALIDATE") + + (pk.isRely_cstr() ? " RELY" : " NORELY")); + + //If the table has other constraints, comma is needed + needComma = true; + } + + //Getting all the foreign key constraints to iterate through it + if(!foreignKeysByColName.isEmpty()) { + if(needComma) { + constaintsStr.append(", \n"); + } + for(Map.Entry> e : foreignKeysByColName.entrySet()) { + StringBuilder childCols = new StringBuilder(); + StringBuilder parentCols = new StringBuilder(); + String parentDb = "", parentTable = ""; + for (SQLForeignKey foreignKey : e.getValue()) { + childCols.append(foreignKey.getFkcolumn_name() + ", "); + parentCols.append(foreignKey.getPkcolumn_name() + ", "); + parentDb = foreignKey.getPktable_db(); + parentTable = foreignKey.getPktable_name(); + } + childCols.setLength(childCols.length()-2); + parentCols.setLength(parentCols.length()-2); + SQLForeignKey fk = e.getValue().get(0); + constaintsStr.append(" FOREIGN KEY (" + childCols.toString() + ") REFERENCES " + + parentDb + "." + parentTable + "(" + parentCols.toString() + ")"); + constaintsStr.append((fk.isEnable_cstr() ? " ENABLE" : " DISABLE") + + (fk.isValidate_cstr() ? " VALIDATE" : " NOVALIDATE") + + (fk.isRely_cstr() ? " RELY" : " NORELY")); + } + } + if (!constaintsStr.toString().equals("")) { + columns.add(constaintsStr.toString()); + } tbl_columns = StringUtils.join(columns, ", \n"); // Table comment