This is an automated email from the ASF dual-hosted git repository.
deniskuzZ pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git
The following commit(s) were added to refs/heads/master by this push:
new 1516fb91e8a HIVE-29604: DESCRIBE column fails with an execution error
for partition columns (#6472)
1516fb91e8a is described below
commit 1516fb91e8a622b4655b0e07a37fb449634c1637
Author: Tanishq Chugh <[email protected]>
AuthorDate: Fri May 15 12:27:05 2026 +0530
HIVE-29604: DESCRIBE column fails with an execution error for partition
columns (#6472)
---
.../ql/ddl/table/info/desc/DescTableOperation.java | 59 ++++++++----
.../test/queries/clientpositive/describe_syntax.q | 18 ++++
.../clientpositive/llap/desc_cols_formatted.q.out | 6 +-
.../clientpositive/llap/describe_syntax.q.out | 105 +++++++++++++++++++++
4 files changed, 165 insertions(+), 23 deletions(-)
diff --git
a/ql/src/java/org/apache/hadoop/hive/ql/ddl/table/info/desc/DescTableOperation.java
b/ql/src/java/org/apache/hadoop/hive/ql/ddl/table/info/desc/DescTableOperation.java
index b60126a8db1..9086ad90c67 100644
---
a/ql/src/java/org/apache/hadoop/hive/ql/ddl/table/info/desc/DescTableOperation.java
+++
b/ql/src/java/org/apache/hadoop/hive/ql/ddl/table/info/desc/DescTableOperation.java
@@ -21,6 +21,7 @@
import java.io.DataOutputStream;
import java.sql.SQLException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -88,11 +89,7 @@ public int execute() throws Exception {
if (desc.getColumnPath() == null) {
getColumnsNoColumnPath(table, part, cols);
} else {
- if (desc.isFormatted()) {
- getColumnDataColPathSpecified(table, part, cols, colStats,
deserializer);
- } else {
- cols.addAll(Hive.getFieldsFromDeserializer(desc.getColumnPath(),
deserializer, context.getConf()));
- }
+ getColumnDataColPathSpecified(table, part, cols, colStats,
deserializer);
}
fixDecimalColumnTypeName(cols);
@@ -191,28 +188,31 @@ private void getColumnDataColPathSpecified(Table table,
Partition part, List<Fie
throws HiveException, MetaException {
// when column name is specified in describe table DDL, colPath will be
db_name.table_name.column_name
String colName = desc.getColumnPath().split("\\.")[2];
+ FieldSchema partitionCol = resolveColumnSchema(table, deserializer,
colName, cols);
+
+ if (!desc.isFormatted()) {
+ return;
+ }
+
List<String> colNames = Lists.newArrayList(colName.toLowerCase());
if (part == null) {
if (table.isPartitioned() &&
StatsUtils.checkCanProvideColumnStats(table)) {
Map<String, String> tableProps = table.getParameters() == null ?
new HashMap<>() : table.getParameters();
- if (table.isPartitionKey(colNames.getFirst())) {
- getColumnDataForPartitionKeyColumn(table, cols, colStats, colNames,
tableProps);
+ if (partitionCol != null) {
+ addStatsForPartitionKeyColumn(table, colStats, colNames, tableProps,
partitionCol);
} else {
- getColumnsForNotPartitionKeyColumn(table, cols, colStats,
deserializer, colName,
- tableProps);
+ addStatsForRegularColumn(table, colStats, colName, tableProps);
}
table.setParameters(tableProps);
} else {
- cols.addAll(getFilteredFieldsFromDeserializer(table, deserializer,
colName));
colStats.addAll(context.getDb().getTableColumnStatistics(table,
colNames, false));
}
} else {
List<String> partitions = new ArrayList<>();
String partName = part.getName();
partitions.add(partName);
- cols.addAll(getFilteredFieldsFromDeserializer(table, deserializer,
colName));
Map<String, List<ColumnStatisticsObj>> partitionColumnStatistics =
context.getDb().getPartitionColumnStatistics(
table.getDbName(), table.getTableName(), partitions, colNames,
false);
List<ColumnStatisticsObj> partitionColStat =
partitionColumnStatistics.get(partName);
@@ -222,6 +222,31 @@ private void getColumnDataColPathSpecified(Table table,
Partition part, List<Fie
}
}
+ /**
+ * Adds the resolved FieldSchema(s) for {@code desc.getColumnPath()} to
{@code cols}:
+ * partition column, nested xpath traversal (e.g. {@code struct.field},
{@code array.$elem$},
+ * {@code map.$key$}/{@code $value$}), or top-level deserializer field.
+ *
+ * @return the partition FieldSchema if the path is a partition key,
otherwise null
+ */
+ private FieldSchema resolveColumnSchema(Table table, Deserializer
deserializer, String colName,
+ List<FieldSchema> cols) throws HiveException {
+ FieldSchema partitionCol = table.getPartColByName(colName.toLowerCase());
+ if (partitionCol != null) {
+ cols.add(partitionCol);
+ return partitionCol;
+ }
+ List<FieldSchema> resolved = (desc.getColumnPath().split("\\.").length ==
3)
+ ? getFilteredFieldsFromDeserializer(table, deserializer, colName)
+ : Collections.emptyList();
+ if (resolved.isEmpty()) {
+ // xpath path OR invalid top-level name — path-traversal handles both
+ resolved = Hive.getFieldsFromDeserializer(desc.getColumnPath(),
deserializer, context.getConf());
+ }
+ cols.addAll(resolved);
+ return null;
+ }
+
private List<FieldSchema> getFilteredFieldsFromDeserializer(Table table,
Deserializer deserializer,
String targetColName) throws HiveException {
List<FieldSchema> allFields =
Hive.getFieldsFromDeserializer(table.getTableName(), deserializer,
context.getConf());
@@ -239,11 +264,9 @@ private List<FieldSchema>
getFilteredFieldsFromDeserializer(Table table, Deseria
return filteredFields;
}
- private void getColumnDataForPartitionKeyColumn(Table table,
List<FieldSchema> cols,
- List<ColumnStatisticsObj> colStats, List<String> colNames, Map<String,
String> tableProps)
+ private void addStatsForPartitionKeyColumn(Table table,
List<ColumnStatisticsObj> colStats,
+ List<String> colNames, Map<String, String> tableProps, FieldSchema
partCol)
throws HiveException, MetaException {
- FieldSchema partCol = table.getPartColByName(colNames.getFirst());
- cols.add(partCol);
PartitionIterable parts = new PartitionIterable(context.getDb(), table,
null,
MetastoreConf.getIntVar(context.getConf(),
MetastoreConf.ConfVars.BATCH_RETRIEVE_MAX));
ColumnInfo ci = new ColumnInfo(partCol.getName(),
@@ -256,10 +279,8 @@ private void getColumnDataForPartitionKeyColumn(Table
table, List<FieldSchema> c
StatsSetupConst.setColumnStatsState(tableProps, colNames);
}
- private void getColumnsForNotPartitionKeyColumn(Table table,
List<FieldSchema> cols, List<ColumnStatisticsObj> colStats,
- Deserializer deserializer, String colName, Map<String, String>
tableProps)
- throws HiveException {
- cols.addAll(getFilteredFieldsFromDeserializer(table, deserializer,
colName));
+ private void addStatsForRegularColumn(Table table, List<ColumnStatisticsObj>
colStats,
+ String colName, Map<String, String> tableProps) throws HiveException {
List<String> parts = context.getDb().getPartitionNames(table, (short) -1);
AggrStats aggrStats = context.getDb().getAggrColStatsFor(table,
Lists.newArrayList(colName.toLowerCase()),
parts, false);
diff --git a/ql/src/test/queries/clientpositive/describe_syntax.q
b/ql/src/test/queries/clientpositive/describe_syntax.q
index 3f9db316b27..d5295412c81 100644
--- a/ql/src/test/queries/clientpositive/describe_syntax.q
+++ b/ql/src/test/queries/clientpositive/describe_syntax.q
@@ -34,6 +34,19 @@ DESCRIBE t1 key1;
DESCRIBE EXTENDED t1 key1;
DESCRIBE FORMATTED t1 key1;
+-- describe table partition column
+DESCRIBE t1 ds;
+DESCRIBE EXTENDED t1 ds;
+DESCRIBE FORMATTED t1 ds;
+
+-- describe database.table partition column
+DESCRIBE db1.t1 ds;
+DESCRIBE EXTENDED db1.t1 ds;
+DESCRIBE FORMATTED db1.t1 ds;
+
+-- describe table case-insensitive partition column
+DESCRIBE t1 PART;
+
-- describe table partition
DESCRIBE t1 PARTITION(ds='4', part='5');
DESCRIBE EXTENDED t1 PARTITION(ds='4', part='5');
@@ -43,3 +56,8 @@ DESCRIBE FORMATTED t1 PARTITION(ds='4', part='5');
DESCRIBE db1.t1 PARTITION(ds='4', part='5');
DESCRIBE EXTENDED db1.t1 PARTITION(ds='4', part='5');
DESCRIBE FORMATTED db1.t1 PARTITION(ds='4', part='5');
+
+-- describe table partition column with partition spec
+DESCRIBE t1 PARTITION(ds='3', part='3') ds;
+DESCRIBE EXTENDED t1 PARTITION(ds='4', part='5') part;
+DESCRIBE FORMATTED t1 PARTITION(ds='3', part='3') ds;
diff --git a/ql/src/test/results/clientpositive/llap/desc_cols_formatted.q.out
b/ql/src/test/results/clientpositive/llap/desc_cols_formatted.q.out
index 375576b1479..80c753707a2 100644
--- a/ql/src/test/results/clientpositive/llap/desc_cols_formatted.q.out
+++ b/ql/src/test/results/clientpositive/llap/desc_cols_formatted.q.out
@@ -93,8 +93,7 @@ PREHOOK: Input: default@tbl_t
POSTHOOK: query: DESCRIBE tbl_t Point
POSTHOOK: type: DESCTABLE
POSTHOOK: Input: default@tbl_t
-x int from deserializer
-y int from deserializer
+Point struct<x:int,y:int> from deserializer
COLUMN_STATS_ACCURATE
{\"BASIC_STATS\":\"true\",\"COLUMN_STATS\":{\"id\":\"true\",\"point\":\"true\"}}
PREHOOK: query: CREATE TABLE tbl_part(id int, Point STRUCT<x:INT, y:INT>)
PARTITIONED BY (name string)
PREHOOK: type: CREATETABLE
@@ -195,5 +194,4 @@ PREHOOK: Input: default@tbl_part
POSTHOOK: query: DESCRIBE tbl_part Point
POSTHOOK: type: DESCTABLE
POSTHOOK: Input: default@tbl_part
-x int from deserializer
-y int from deserializer
+Point struct<x:int,y:int> from deserializer
diff --git a/ql/src/test/results/clientpositive/llap/describe_syntax.q.out
b/ql/src/test/results/clientpositive/llap/describe_syntax.q.out
index e1c9dfb6318..f722036cc0e 100644
--- a/ql/src/test/results/clientpositive/llap/describe_syntax.q.out
+++ b/ql/src/test/results/clientpositive/llap/describe_syntax.q.out
@@ -284,6 +284,79 @@ num_falses
bit_vector
comment from deserializer
COLUMN_STATS_ACCURATE {}
+PREHOOK: query: DESCRIBE t1 ds
+PREHOOK: type: DESCTABLE
+PREHOOK: Input: db1@t1
+POSTHOOK: query: DESCRIBE t1 ds
+POSTHOOK: type: DESCTABLE
+POSTHOOK: Input: db1@t1
+ds string
+PREHOOK: query: DESCRIBE EXTENDED t1 ds
+PREHOOK: type: DESCTABLE
+PREHOOK: Input: db1@t1
+POSTHOOK: query: DESCRIBE EXTENDED t1 ds
+POSTHOOK: type: DESCTABLE
+POSTHOOK: Input: db1@t1
+ds string
+PREHOOK: query: DESCRIBE FORMATTED t1 ds
+PREHOOK: type: DESCTABLE
+PREHOOK: Input: db1@t1
+POSTHOOK: query: DESCRIBE FORMATTED t1 ds
+POSTHOOK: type: DESCTABLE
+POSTHOOK: Input: db1@t1
+col_name ds
+data_type string
+min
+max
+num_nulls 0
+distinct_count 2
+avg_col_len 100.0
+max_col_len 100
+num_trues
+num_falses
+bit_vector
+comment
+COLUMN_STATS_ACCURATE {\"COLUMN_STATS\":{\"ds\":\"true\"}}
+PREHOOK: query: DESCRIBE db1.t1 ds
+PREHOOK: type: DESCTABLE
+PREHOOK: Input: db1@t1
+POSTHOOK: query: DESCRIBE db1.t1 ds
+POSTHOOK: type: DESCTABLE
+POSTHOOK: Input: db1@t1
+ds string
+PREHOOK: query: DESCRIBE EXTENDED db1.t1 ds
+PREHOOK: type: DESCTABLE
+PREHOOK: Input: db1@t1
+POSTHOOK: query: DESCRIBE EXTENDED db1.t1 ds
+POSTHOOK: type: DESCTABLE
+POSTHOOK: Input: db1@t1
+ds string
+PREHOOK: query: DESCRIBE FORMATTED db1.t1 ds
+PREHOOK: type: DESCTABLE
+PREHOOK: Input: db1@t1
+POSTHOOK: query: DESCRIBE FORMATTED db1.t1 ds
+POSTHOOK: type: DESCTABLE
+POSTHOOK: Input: db1@t1
+col_name ds
+data_type string
+min
+max
+num_nulls 0
+distinct_count 2
+avg_col_len 100.0
+max_col_len 100
+num_trues
+num_falses
+bit_vector
+comment
+COLUMN_STATS_ACCURATE {\"COLUMN_STATS\":{\"ds\":\"true\"}}
+PREHOOK: query: DESCRIBE t1 PART
+PREHOOK: type: DESCTABLE
+PREHOOK: Input: db1@t1
+POSTHOOK: query: DESCRIBE t1 PART
+POSTHOOK: type: DESCTABLE
+POSTHOOK: Input: db1@t1
+part string
PREHOOK: query: DESCRIBE t1 PARTITION(ds='4', part='5')
PREHOOK: type: DESCTABLE
PREHOOK: Input: db1@t1
@@ -424,3 +497,35 @@ Bucket Columns: []
Sort Columns: []
Storage Desc Params:
serialization.format 1
+PREHOOK: query: DESCRIBE t1 PARTITION(ds='3', part='3') ds
+PREHOOK: type: DESCTABLE
+PREHOOK: Input: db1@t1
+POSTHOOK: query: DESCRIBE t1 PARTITION(ds='3', part='3') ds
+POSTHOOK: type: DESCTABLE
+POSTHOOK: Input: db1@t1
+ds string
+PREHOOK: query: DESCRIBE EXTENDED t1 PARTITION(ds='4', part='5') part
+PREHOOK: type: DESCTABLE
+PREHOOK: Input: db1@t1
+POSTHOOK: query: DESCRIBE EXTENDED t1 PARTITION(ds='4', part='5') part
+POSTHOOK: type: DESCTABLE
+POSTHOOK: Input: db1@t1
+part string
+PREHOOK: query: DESCRIBE FORMATTED t1 PARTITION(ds='3', part='3') ds
+PREHOOK: type: DESCTABLE
+PREHOOK: Input: db1@t1
+POSTHOOK: query: DESCRIBE FORMATTED t1 PARTITION(ds='3', part='3') ds
+POSTHOOK: type: DESCTABLE
+POSTHOOK: Input: db1@t1
+col_name ds
+data_type string
+min
+max
+num_nulls
+distinct_count
+avg_col_len
+max_col_len
+num_trues
+num_falses
+bit_vector
+comment