diff --git ql/src/java/org/apache/hadoop/hive/ql/ddl/table/create/show/ShowCreateTableOperation.java ql/src/java/org/apache/hadoop/hive/ql/ddl/table/create/show/ShowCreateTableOperation.java index affed03fbb..d8873cce58 100644 --- ql/src/java/org/apache/hadoop/hive/ql/ddl/table/create/show/ShowCreateTableOperation.java +++ ql/src/java/org/apache/hadoop/hive/ql/ddl/table/create/show/ShowCreateTableOperation.java @@ -51,6 +51,12 @@ import org.apache.hadoop.hive.ql.metadata.Table; import org.apache.hadoop.hive.ql.util.DirectionUtils; import org.apache.hadoop.hive.serde.serdeConstants; +import org.apache.hadoop.hive.serde2.typeinfo.ListTypeInfo; +import org.apache.hadoop.hive.serde2.typeinfo.MapTypeInfo; +import org.apache.hadoop.hive.serde2.typeinfo.StructTypeInfo; +import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo; +import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoUtils; +import org.apache.hadoop.hive.serde2.typeinfo.UnionTypeInfo; import org.apache.hive.common.util.HiveStringUtils; import org.stringtemplate.v4.ST; @@ -143,7 +149,7 @@ private String getExternal(Table table) { private String getColumns(Table table) { List columnDescs = new ArrayList(); for (FieldSchema col : table.getCols()) { - String columnDesc = " `" + col.getName() + "` " + col.getType(); + String columnDesc = " `" + col.getName() + "` " + formatType(TypeInfoUtils.getTypeInfoFromTypeString(col.getType())); if (col.getComment() != null) { columnDesc += " COMMENT '" + HiveStringUtils.escapeHiveCommand(col.getComment()) + "'"; } @@ -152,6 +158,53 @@ private String getColumns(Table table) { return StringUtils.join(columnDescs, ", \n"); } + /** Struct fields are identifiers, need to be put between ``. */ + private String formatType(TypeInfo typeInfo) { + switch (typeInfo.getCategory()) { + case PRIMITIVE: + return typeInfo.getTypeName(); + case STRUCT: + StringBuilder structFormattedType = new StringBuilder(); + + StructTypeInfo structTypeInfo = (StructTypeInfo)typeInfo; + for (int i = 0; i < structTypeInfo.getAllStructFieldNames().size(); i++) { + if (structFormattedType.length() != 0) { + structFormattedType.append(", "); + } + + String structElementName = structTypeInfo.getAllStructFieldNames().get(i); + String structElementType = formatType(structTypeInfo.getAllStructFieldTypeInfos().get(i)); + + structFormattedType.append("`" + structElementName + "`:" + structElementType); + } + return "struct<" + structFormattedType.toString() + ">"; + case LIST: + ListTypeInfo listTypeInfo = (ListTypeInfo)typeInfo; + String elementType = formatType(listTypeInfo.getListElementTypeInfo()); + return "array<" + elementType + ">"; + case MAP: + MapTypeInfo mapTypeInfo = (MapTypeInfo)typeInfo; + String keyTypeInfo = mapTypeInfo.getMapKeyTypeInfo().getTypeName(); + String valueTypeInfo = formatType(mapTypeInfo.getMapValueTypeInfo()); + return "map<" + keyTypeInfo + "," + valueTypeInfo + ">"; + case UNION: + StringBuilder unionFormattedType = new StringBuilder(); + + UnionTypeInfo unionTypeInfo = (UnionTypeInfo)typeInfo; + for (TypeInfo unionElementTypeInfo : unionTypeInfo.getAllUnionObjectTypeInfos()) { + if (unionFormattedType.length() != 0) { + unionFormattedType.append(", "); + } + + String unionElementType = formatType(unionElementTypeInfo); + unionFormattedType.append(unionElementType); + } + return "uniontype<" + unionFormattedType.toString() + ">"; + default: + throw new RuntimeException("Unknown type: " + typeInfo.getCategory()); + } + } + private String getComment(Table table) { String comment = table.getProperty("comment"); return (comment != null) ? "COMMENT '" + HiveStringUtils.escapeHiveCommand(comment) + "'" : ""; diff --git ql/src/test/queries/clientpositive/show_create_table_db_table.q ql/src/test/queries/clientpositive/show_create_table_db_table.q index 35ac5bf73e..ffe36180ca 100644 --- ql/src/test/queries/clientpositive/show_create_table_db_table.q +++ ql/src/test/queries/clientpositive/show_create_table_db_table.q @@ -5,12 +5,15 @@ SHOW DATABASES; CREATE TABLE tmp_feng.tmp_showcrt1(key string, value int); CREATE TABLE tmp_feng.tmp_showcrt2(key string, value int) skewed by (key) on ('1','2'); CREATE TABLE tmp_feng.tmp_showcrt3(key string, value int) skewed by (key) on ('1','2') stored as directories; +CREATE TABLE tmp_feng.tmp_showcrt4(s1 struct, s2 struct, array>>>>>); USE default; SHOW CREATE TABLE tmp_feng.tmp_showcrt1; SHOW CREATE TABLE tmp_feng.tmp_showcrt2; SHOW CREATE TABLE tmp_feng.tmp_showcrt3; +SHOW CREATE TABLE tmp_feng.tmp_showcrt4; DROP TABLE tmp_feng.tmp_showcrt1; DROP TABLE tmp_feng.tmp_showcrt2; DROP TABLE tmp_feng.tmp_showcrt3; +DROP TABLE tmp_feng.tmp_showcrt4; DROP DATABASE tmp_feng; diff --git ql/src/test/results/clientpositive/show_create_table_db_table.q.out ql/src/test/results/clientpositive/show_create_table_db_table.q.out index 33410c8582..27e68b8ecc 100644 --- ql/src/test/results/clientpositive/show_create_table_db_table.q.out +++ ql/src/test/results/clientpositive/show_create_table_db_table.q.out @@ -34,6 +34,14 @@ POSTHOOK: query: CREATE TABLE tmp_feng.tmp_showcrt3(key string, value int) skewe POSTHOOK: type: CREATETABLE POSTHOOK: Output: database:tmp_feng POSTHOOK: Output: tmp_feng@tmp_showcrt3 +PREHOOK: query: CREATE TABLE tmp_feng.tmp_showcrt4(s1 struct, s2 struct, array>>>>>) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:tmp_feng +PREHOOK: Output: tmp_feng@tmp_showcrt4 +POSTHOOK: query: CREATE TABLE tmp_feng.tmp_showcrt4(s1 struct, s2 struct, array>>>>>) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:tmp_feng +POSTHOOK: Output: tmp_feng@tmp_showcrt4 PREHOOK: query: USE default PREHOOK: type: SWITCHDATABASE PREHOOK: Input: database:default @@ -105,6 +113,26 @@ LOCATION TBLPROPERTIES ( 'bucketing_version'='2', #### A masked pattern was here #### +PREHOOK: query: SHOW CREATE TABLE tmp_feng.tmp_showcrt4 +PREHOOK: type: SHOW_CREATETABLE +PREHOOK: Input: tmp_feng@tmp_showcrt4 +POSTHOOK: query: SHOW CREATE TABLE tmp_feng.tmp_showcrt4 +POSTHOOK: type: SHOW_CREATETABLE +POSTHOOK: Input: tmp_feng@tmp_showcrt4 +CREATE TABLE `tmp_feng.tmp_showcrt4`( + `s1` struct<`p1`:string>, + `s2` struct<`p2`:array, array>>>>>) +ROW FORMAT SERDE + 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe' +STORED AS INPUTFORMAT + 'org.apache.hadoop.mapred.TextInputFormat' +OUTPUTFORMAT + 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' +LOCATION +#### A masked pattern was here #### +TBLPROPERTIES ( + 'bucketing_version'='2', +#### A masked pattern was here #### PREHOOK: query: DROP TABLE tmp_feng.tmp_showcrt1 PREHOOK: type: DROPTABLE PREHOOK: Input: tmp_feng@tmp_showcrt1 @@ -129,6 +157,14 @@ POSTHOOK: query: DROP TABLE tmp_feng.tmp_showcrt3 POSTHOOK: type: DROPTABLE POSTHOOK: Input: tmp_feng@tmp_showcrt3 POSTHOOK: Output: tmp_feng@tmp_showcrt3 +PREHOOK: query: DROP TABLE tmp_feng.tmp_showcrt4 +PREHOOK: type: DROPTABLE +PREHOOK: Input: tmp_feng@tmp_showcrt4 +PREHOOK: Output: tmp_feng@tmp_showcrt4 +POSTHOOK: query: DROP TABLE tmp_feng.tmp_showcrt4 +POSTHOOK: type: DROPTABLE +POSTHOOK: Input: tmp_feng@tmp_showcrt4 +POSTHOOK: Output: tmp_feng@tmp_showcrt4 PREHOOK: query: DROP DATABASE tmp_feng PREHOOK: type: DROPDATABASE PREHOOK: Input: database:tmp_feng