This is an automated email from the ASF dual-hosted git repository.
dengzh 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 709b9e221df HIVE-29484: HMS.getFields() fails with 'SchemaReader not
supported' for Avro and Hbase tables (#6350)
709b9e221df is described below
commit 709b9e221dfce3b1d5a69be1274f432dd778ee2d
Author: rtrivedi12 <[email protected]>
AuthorDate: Thu Apr 9 20:45:01 2026 -0500
HIVE-29484: HMS.getFields() fails with 'SchemaReader not supported' for
Avro and Hbase tables (#6350)
---
.../hive/metastore/TestStorageSchemaReader.java | 31 +++++-----
.../hadoop/hive/metastore/conf/MetastoreConf.java | 3 +-
.../apache/hadoop/hive/metastore/HMSHandler.java | 52 +++++++++++-----
.../hadoop/hive/metastore/TestHiveMetaStore.java | 70 +++++++++++++++++++++-
4 files changed, 126 insertions(+), 30 deletions(-)
diff --git
a/itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestStorageSchemaReader.java
b/itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestStorageSchemaReader.java
index fadd793bc23..5d3dcc30864 100644
---
a/itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestStorageSchemaReader.java
+++
b/itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestStorageSchemaReader.java
@@ -25,6 +25,7 @@
import org.apache.hadoop.hive.metastore.api.Table;
import org.apache.hadoop.hive.metastore.client.builder.DatabaseBuilder;
import org.apache.hadoop.hive.metastore.client.builder.TableBuilder;
+import org.apache.hadoop.hive.metastore.conf.MetastoreConf;
import org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat;
import org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat;
import org.apache.hadoop.hive.ql.io.orc.OrcInputFormat;
@@ -60,6 +61,8 @@ public class TestStorageSchemaReader {
@Before public void setUp() throws Exception {
dbName = "sampleDb";
hiveConf = new HiveConf(this.getClass());
+ // Unset the deprecated HiveConf value so MetastoreConf uses its own
default
+
hiveConf.unset(HiveConf.ConfVars.SERDES_USING_METASTORE_FOR_SCHEMA.varname);
new DatabaseBuilder().setName(dbName).create(new
HiveMetaStoreClient(hiveConf), hiveConf);
avroTableParams.put("avro.schema.literal",
"{\"name\":\"nullable\", \"type\":\"record\",
\"fields\":[{\"name\":\"id\", \"type\":\"int\"}, {\"name\":\"value\",
\"type\":\"int\"}]}");
@@ -111,15 +114,15 @@ private void checkFields(List<FieldSchema> fieldSchemas,
List<FieldSchema> field
}
@Test public void testAvroTableWithDefaultSSR() throws Exception {
- hiveConf.set("metastore.storage.schema.reader.impl",
"org.apache.hadoop.hive.metastore.DefaultStorageSchemaReader");
+ MetastoreConf.setVar(hiveConf,
MetastoreConf.ConfVars.STORAGE_SCHEMA_READER_IMPL,
"org.apache.hadoop.hive.metastore.DefaultStorageSchemaReader");
String tblName = "avroTable";
- createTable(tblName, AvroSerDe.class.getName(),
AvroContainerInputFormat.class.getName(),
+ Table tbl = createTable(tblName, AvroSerDe.class.getName(),
AvroContainerInputFormat.class.getName(),
AvroContainerOutputFormat.class.getName(), avroTableParams, new
HashMap<>());
- assertThrows("Storage schema reading not supported", MetaException.class,
() -> client.getSchema(dbName, tblName));
+ checkSchema(tblName, tbl);
}
@Test public void testAvroTableWithSerdeSSR() throws Exception {
- hiveConf.set("metastore.storage.schema.reader.impl",
"org.apache.hadoop.hive.metastore.SerDeStorageSchemaReader");
+ MetastoreConf.setVar(hiveConf,
MetastoreConf.ConfVars.STORAGE_SCHEMA_READER_IMPL,
"org.apache.hadoop.hive.metastore.SerDeStorageSchemaReader");
String tblName = "avroTable";
Table tbl = createTable(tblName, AvroSerDe.class.getName(),
AvroContainerInputFormat.class.getName(),
AvroContainerOutputFormat.class.getName(), avroTableParams, new
HashMap<>());
@@ -127,16 +130,16 @@ private void checkFields(List<FieldSchema> fieldSchemas,
List<FieldSchema> field
}
@Test public void testHbaseTableWithDefaultSSR() throws Exception {
- hiveConf.set("metastore.storage.schema.reader.impl",
"org.apache.hadoop.hive.metastore.DefaultStorageSchemaReader");
- String tblName = "jdbcTable";
+ MetastoreConf.setVar(hiveConf,
MetastoreConf.ConfVars.STORAGE_SCHEMA_READER_IMPL,
"org.apache.hadoop.hive.metastore.DefaultStorageSchemaReader");
+ String tblName = "hbaseTable";
- createTable(tblName, HBaseSerDe.class.getName(), null, null,
hbaseTableParams, hbaseSerdeParams);
- assertThrows("Storage schema reading not supported", MetaException.class,
() -> client.getSchema(dbName, tblName));
+ Table table = createTable(tblName, HBaseSerDe.class.getName(), null, null,
hbaseTableParams, hbaseSerdeParams);
+ checkSchema(tblName, table);
}
@Test public void testHbaseTableWithSerdeSSR() throws Exception {
- hiveConf.set("metastore.storage.schema.reader.impl",
"org.apache.hadoop.hive.metastore.SerDeStorageSchemaReader");
- String tblName = "jdbcTable";
+ MetastoreConf.setVar(hiveConf,
MetastoreConf.ConfVars.STORAGE_SCHEMA_READER_IMPL,
"org.apache.hadoop.hive.metastore.SerDeStorageSchemaReader");
+ String tblName = "hbaseTableSerde";
Table table =
createTable(tblName, "org.apache.hadoop.hive.hbase.HBaseSerDe", null,
null, hbaseTableParams, hbaseSerdeParams);
@@ -144,7 +147,7 @@ private void checkFields(List<FieldSchema> fieldSchemas,
List<FieldSchema> field
}
@Test public void testJdbcTableWithDefaultSSR() throws Exception {
- hiveConf.set("metastore.storage.schema.reader.impl",
"org.apache.hadoop.hive.metastore.DefaultStorageSchemaReader");
+ MetastoreConf.setVar(hiveConf,
MetastoreConf.ConfVars.STORAGE_SCHEMA_READER_IMPL,
"org.apache.hadoop.hive.metastore.DefaultStorageSchemaReader");
String tblName = "jdbcTable";
createTable(tblName, JdbcSerDe.class.getName(), null, null,
jdbcTableParams, jdbcSerdeParams);
@@ -152,7 +155,7 @@ private void checkFields(List<FieldSchema> fieldSchemas,
List<FieldSchema> field
}
@Test public void testJdbcTableWithSerdeSSR() throws Exception {
- hiveConf.set("metastore.storage.schema.reader.impl",
"org.apache.hadoop.hive.metastore.SerDeStorageSchemaReader");
+ MetastoreConf.setVar(hiveConf,
MetastoreConf.ConfVars.STORAGE_SCHEMA_READER_IMPL,
"org.apache.hadoop.hive.metastore.SerDeStorageSchemaReader");
String tblName = "jdbcTable";
Table table = createTable(tblName, JdbcSerDe.class.getName(), null, null,
jdbcTableParams, jdbcSerdeParams);
@@ -160,7 +163,7 @@ private void checkFields(List<FieldSchema> fieldSchemas,
List<FieldSchema> field
}
@Test public void testOrcTableWithDefaultSSR() throws Exception {
- hiveConf.set("metastore.storage.schema.reader.impl",
"org.apache.hadoop.hive.metastore.DefaultStorageSchemaReader");
+ MetastoreConf.setVar(hiveConf,
MetastoreConf.ConfVars.STORAGE_SCHEMA_READER_IMPL,
"org.apache.hadoop.hive.metastore.DefaultStorageSchemaReader");
String tblName = "orcTable2";
Table tbl =
createTable(tblName, OrcSerde.class.getName(),
OrcInputFormat.class.getName(), OrcOutputFormat.class.getName(),
@@ -169,7 +172,7 @@ private void checkFields(List<FieldSchema> fieldSchemas,
List<FieldSchema> field
}
@Test public void testOrcTableWithSerdeSSR() throws Exception {
- hiveConf.set("metastore.storage.schema.reader.impl",
"org.apache.hadoop.hive.metastore.SerDeStorageSchemaReader");
+ MetastoreConf.setVar(hiveConf,
MetastoreConf.ConfVars.STORAGE_SCHEMA_READER_IMPL,
"org.apache.hadoop.hive.metastore.SerDeStorageSchemaReader");
String tblName = "orcTable";
Table tbl =
createTable(tblName, OrcSerde.class.getName(),
OrcInputFormat.class.getName(), OrcOutputFormat.class.getName(),
diff --git
a/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/conf/MetastoreConf.java
b/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/conf/MetastoreConf.java
index 16ccf508a43..10015f74837 100644
---
a/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/conf/MetastoreConf.java
+++
b/standalone-metastore/metastore-common/src/main/java/org/apache/hadoop/hive/metastore/conf/MetastoreConf.java
@@ -1441,7 +1441,8 @@ public enum ConfVars {
"org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe," +
"org.apache.hadoop.hive.serde2.lazybinary.LazyBinarySerDe," +
"org.apache.hadoop.hive.serde2.OpenCSVSerde," +
- "org.apache.iceberg.mr.hive.HiveIcebergSerDe",
+ "org.apache.iceberg.mr.hive.HiveIcebergSerDe," +
+ "org.apache.hadoop.hive.hbase.HBaseSerDe",
"SerDes retrieving schema from metastore. This is an internal
parameter."),
SERDES_WITHOUT_FROM_DESERIALIZER("metastore.serdes.without.from.deserializer",
"hive.metastore.serdes.without.from.deserializer",
diff --git
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
index 9838d9d2573..522a62f90ef 100644
---
a/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
+++
b/standalone-metastore/metastore-server/src/main/java/org/apache/hadoop/hive/metastore/HMSHandler.java
@@ -126,6 +126,8 @@ public class HMSHandler extends FacebookBase implements
IHMSHandler {
static final int LOG_SAMPLE_PARTITIONS_HALF_SIZE = 2;
static final String LOG_SAMPLE_PARTITIONS_SEPARATOR = ",";
+
+ private static final String AVRO_SERDE_CLASS =
"org.apache.hadoop.hive.serde2.avro.AvroSerDe";
private Warehouse wh; // hdfs warehouse
private static Striped<Lock> tablelocks;
@@ -3969,26 +3971,17 @@ private List<FieldSchema>
get_fields_with_environment_context_core(String db, St
String base_table_name = names[0];
String[] parsedDbName = parseDbName(db, conf);
- Table tbl;
List<FieldSchema> ret = null;
Exception ex = null;
try {
- try {
- GetTableRequest getTableRequest = new
GetTableRequest(parsedDbName[DB_NAME], base_table_name);
- getTableRequest.setCatName(parsedDbName[CAT_NAME]);
- tbl = get_table_core(getTableRequest);
- firePreEvent(new PreReadTableEvent(tbl, this));
- } catch (NoSuchObjectException e) {
- throw new UnknownTableException(e.getMessage());
- }
- if (null == tbl.getSd().getSerdeInfo().getSerializationLib() ||
+ Table tbl = getTableForGetFields(parsedDbName, base_table_name);
+ String serdeLib = tbl.getSd().getSerdeInfo().getSerializationLib();
+ if (serdeLib == null ||
MetastoreConf.getStringCollection(conf,
- ConfVars.SERDES_USING_METASTORE_FOR_SCHEMA).contains(
- tbl.getSd().getSerdeInfo().getSerializationLib())) {
+
ConfVars.SERDES_USING_METASTORE_FOR_SCHEMA).contains(serdeLib)) {
ret = tbl.getSd().getCols();
} else {
- StorageSchemaReader schemaReader = getStorageSchemaReader();
- ret = schemaReader.readSchema(tbl, envContext, getConf());
+ ret = getFieldsUsingSchemaReader(tbl, db, tableName, serdeLib,
envContext);
}
} catch (Exception e) {
ex = e;
@@ -3999,6 +3992,37 @@ private List<FieldSchema>
get_fields_with_environment_context_core(String db, St
return ret;
}
+ private Table getTableForGetFields(String[] parsedDbName, String
baseTableName)
+ throws UnknownTableException, MetaException {
+ try {
+ GetTableRequest getTableRequest = new
GetTableRequest(parsedDbName[DB_NAME], baseTableName);
+ getTableRequest.setCatName(parsedDbName[CAT_NAME]);
+ Table tbl = get_table_core(getTableRequest);
+ firePreEvent(new PreReadTableEvent(tbl, this));
+ return tbl;
+ } catch (NoSuchObjectException e) {
+ throw new UnknownTableException(e.getMessage());
+ }
+ }
+
+ private List<FieldSchema> getFieldsUsingSchemaReader(Table tbl, String db,
String tableName, String serdeLib,
+ EnvironmentContext envContext) throws MetaException {
+ try {
+ StorageSchemaReader schemaReader = getStorageSchemaReader();
+ return schemaReader.readSchema(tbl, envContext, getConf());
+ } catch (UnsupportedOperationException e) {
+ // Fallback to metastore for Avro Schema
+ if (AVRO_SERDE_CLASS.equals(serdeLib)) {
+ LOG.warn(
+ "Unable to read schema from storage for AvroSerDe table '{}.{}'.
Returning metastore SD columns " +
+ "as fallback; schema may be stale.",
+ db, tableName, e);
+ return tbl.getSd().getCols();
+ }
+ throw e;
+ }
+ }
+
@Override
public GetFieldsResponse get_fields_req(GetFieldsRequest req)
throws MetaException, UnknownTableException, UnknownDBException {
diff --git
a/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStore.java
b/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStore.java
index 8f1ba073f1b..8ebc1a7ccf9 100644
---
a/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStore.java
+++
b/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStore.java
@@ -154,7 +154,7 @@ public void setUp() throws Exception {
MetaStoreTestUtils.setConfForStandloneMode(conf);
MetastoreConf.setLongVar(conf, ConfVars.BATCH_RETRIEVE_MAX, 2);
MetastoreConf.setLongVar(conf, ConfVars.LIMIT_PARTITION_REQUEST,
DEFAULT_LIMIT_PARTITION_REQUEST);
- MetastoreConf.setVar(conf, ConfVars.STORAGE_SCHEMA_READER_IMPL,
"no.such.class");
+ MetastoreConf.setVar(conf, ConfVars.STORAGE_SCHEMA_READER_IMPL,
"org.apache.hadoop.hive.metastore.DefaultStorageSchemaReader");
MetastoreConf.setBoolVar(conf, ConfVars.INTEGER_JDO_PUSHDOWN, true);
}
@@ -3973,4 +3973,72 @@ public void testDropDataConnectorIfNotExistsTrue()
throws Exception {
// No such data connector, ignore NoSuchObjectException
client.dropDataConnector("no_such_data_connector", true, false);
}
+
+ @Test
+ public void testGetFieldsForAvroSerDe() throws Exception {
+ String dbName = "test_avro_serde_db";
+ String avroTbl = "avro_tbl";
+
+ client.dropTable(dbName, avroTbl, true, true);
+ silentDropDatabase(dbName);
+
+ new DatabaseBuilder()
+ .setName(dbName)
+ .create(client, conf);
+
+ new TableBuilder()
+ .setDbName(dbName)
+ .setTableName(avroTbl)
+ .setSerdeLib("org.apache.hadoop.hive.serde2.avro.AvroSerDe")
+
.setInputFormat("org.apache.hadoop.hive.ql.io.avro.AvroContainerInputFormat")
+
.setOutputFormat("org.apache.hadoop.hive.ql.io.avro.AvroContainerOutputFormat")
+ .addCol("foo", "int", "")
+ .addCol("bar", "string", "")
+ .addCol("baz", "bigint", "")
+ .create(client, conf);
+
+ List<FieldSchema> fields = client.getFields(dbName, avroTbl);
+ assertEquals("AvroSerDe table should return 3 fields from metastore", 3,
fields.size());
+ assertEquals("foo", fields.get(0).getName());
+ assertEquals("bar", fields.get(1).getName());
+ assertEquals("baz", fields.get(2).getName());
+
+ List<FieldSchema> schema = client.getSchema(dbName, avroTbl);
+ assertEquals("AvroSerDe getSchema should return 3 columns", 3,
schema.size());
+
+ client.dropTable(dbName, avroTbl, true, true);
+ client.dropDatabase(dbName);
+ }
+
+ @Test
+ public void testGetFieldsForHBaseSerDe() throws Exception {
+ String dbName = "test_hbase_serde_db";
+ String hbaseTbl = "hbase_tbl";
+
+ client.dropTable(dbName, hbaseTbl, true, true);
+ silentDropDatabase(dbName);
+
+ new DatabaseBuilder()
+ .setName(dbName)
+ .create(client, conf);
+
+ new TableBuilder()
+ .setDbName(dbName)
+ .setTableName(hbaseTbl)
+ .setSerdeLib("org.apache.hadoop.hive.hbase.HBaseSerDe")
+ .addCol("key", "string", "")
+ .addCol("value", "string", "")
+ .create(client, conf);
+
+ List<FieldSchema> fields = client.getFields(dbName, hbaseTbl);
+ assertEquals("HBaseSerDe table should return 2 fields from metastore", 2,
fields.size());
+ assertEquals("key", fields.get(0).getName());
+ assertEquals("value", fields.get(1).getName());
+
+ List<FieldSchema> schema = client.getSchema(dbName, hbaseTbl);
+ assertEquals("HBaseSerDe getSchema should return 2 columns", 2,
schema.size());
+
+ client.dropTable(dbName, hbaseTbl, true, true);
+ client.dropDatabase(dbName);
+ }
}