diff --git ql/src/java/org/apache/hadoop/hive/ql/ddl/table/drop/DropTableOperation.java ql/src/java/org/apache/hadoop/hive/ql/ddl/table/drop/DropTableOperation.java index f4d1a35d72..ef2cfc5229 100644 --- ql/src/java/org/apache/hadoop/hive/ql/ddl/table/drop/DropTableOperation.java +++ ql/src/java/org/apache/hadoop/hive/ql/ddl/table/drop/DropTableOperation.java @@ -24,6 +24,7 @@ import org.apache.hadoop.hive.ql.ddl.DDLOperation; import org.apache.hadoop.hive.ql.hooks.WriteEntity; import org.apache.hadoop.hive.ql.metadata.HiveException; +import org.apache.hadoop.hive.ql.metadata.HiveMaterializedViewsRegistry; import org.apache.hadoop.hive.ql.metadata.InvalidTableException; import org.apache.hadoop.hive.ql.metadata.Partition; import org.apache.hadoop.hive.ql.metadata.PartitionIterable; @@ -59,6 +60,12 @@ public int execute() throws HiveException { } } + HiveMaterializedViewsRegistry registry = HiveMaterializedViewsRegistry.get(); + if (registry.isTableUsed(table.getDbName(), table.getTableName())) { + throw new HiveException("Cannot drop table since it is used by at least one materialized view definition. \n" + + "Please drop any materialized view that uses the table before dropping it"); + } + ReplicationSpec replicationSpec = desc.getReplicationSpec(); if (replicationSpec.isInReplicationScope()) { /** diff --git ql/src/java/org/apache/hadoop/hive/ql/metadata/Hive.java ql/src/java/org/apache/hadoop/hive/ql/metadata/Hive.java index 1eb9c12cc8..60e1df4a4d 100644 --- ql/src/java/org/apache/hadoop/hive/ql/metadata/Hive.java +++ ql/src/java/org/apache/hadoop/hive/ql/metadata/Hive.java @@ -1235,13 +1235,6 @@ public void dropTable(String dbName, String tableName, boolean deleteData, if (!ignoreUnknownTab) { throw new HiveException(e); } - } catch (MetaException e) { - int idx = ExceptionUtils.indexOfType(e, SQLIntegrityConstraintViolationException.class); - if (idx != -1 && ExceptionUtils.getThrowables(e)[idx].getMessage().contains("MV_TABLES_USED")) { - throw new HiveException("Cannot drop table since it is used by at least one materialized view definition. " + - "Please drop any materialized view that uses the table before dropping it", e); - } - throw new HiveException(e); } catch (Exception e) { throw new HiveException(e); } diff --git ql/src/java/org/apache/hadoop/hive/ql/metadata/HiveMaterializedViewsRegistry.java ql/src/java/org/apache/hadoop/hive/ql/metadata/HiveMaterializedViewsRegistry.java index 4592f5ec34..b62d5a6475 100644 --- ql/src/java/org/apache/hadoop/hive/ql/metadata/HiveMaterializedViewsRegistry.java +++ ql/src/java/org/apache/hadoop/hive/ql/metadata/HiveMaterializedViewsRegistry.java @@ -538,4 +538,30 @@ private static Table extractTable(RelOptMaterialization materialization) { JDBC } + public boolean isTableUsed(String dbName, String tableName) { + for (ConcurrentMap dbMaterializedViews : materializedViews.values()) { + for (RelOptMaterialization materializedView : dbMaterializedViews.values()) { + if (usesTable(materializedView.queryRel, dbName, tableName)) { + return true; + } + } + } + + return false; + } + + private boolean usesTable(RelNode relNode, String dbName, String tableName) { + if (relNode instanceof HiveTableScan) { + List qualifiedName = ((HiveTableScan)relNode).getTable().getQualifiedName(); + return qualifiedName.get(0).equals(dbName) && qualifiedName.get(1).equals(tableName); + } else { + for (RelNode input : relNode.getInputs()) { + if (usesTable(input, dbName, tableName)) { + return true; + } + } + } + + return false; + } } diff --git ql/src/test/queries/clientnegative/drop_materialized_view_source.q ql/src/test/queries/clientnegative/drop_materialized_view_source.q new file mode 100644 index 0000000000..66184fad29 --- /dev/null +++ ql/src/test/queries/clientnegative/drop_materialized_view_source.q @@ -0,0 +1,7 @@ +set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager; + +create transactional table source_table (id int); +insert into source_table values (1), (2), (3); + +create materialized view mv_using_source as select count(*) from source_table; +drop table source_table; diff --git ql/src/test/queries/clientnegative/drop_materialized_view_source2.q ql/src/test/queries/clientnegative/drop_materialized_view_source2.q new file mode 100644 index 0000000000..bf531bab3d --- /dev/null +++ ql/src/test/queries/clientnegative/drop_materialized_view_source2.q @@ -0,0 +1,10 @@ +set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager; + +create transactional table source_table (id int); +insert into source_table values (1), (2), (3); +create view source_view as select * from source_table; + +create materialized view mv_using_source as select count(*) from source_view; +-- dropping the view is fine, as the MV uses not the view itself, but it's query for creating it's own during it's creation +drop view source_view; +drop table source_table; diff --git ql/src/test/results/clientnegative/drop_materialized_view_source.q.out ql/src/test/results/clientnegative/drop_materialized_view_source.q.out new file mode 100644 index 0000000000..668a14d889 --- /dev/null +++ ql/src/test/results/clientnegative/drop_materialized_view_source.q.out @@ -0,0 +1,33 @@ +PREHOOK: query: create transactional table source_table (id int) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@source_table +POSTHOOK: query: create transactional table source_table (id int) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@source_table +PREHOOK: query: insert into source_table values (1), (2), (3) +PREHOOK: type: QUERY +PREHOOK: Input: _dummy_database@_dummy_table +PREHOOK: Output: default@source_table +POSTHOOK: query: insert into source_table values (1), (2), (3) +POSTHOOK: type: QUERY +POSTHOOK: Input: _dummy_database@_dummy_table +POSTHOOK: Output: default@source_table +POSTHOOK: Lineage: source_table.id SCRIPT [] +PREHOOK: query: create materialized view mv_using_source as select count(*) from source_table +PREHOOK: type: CREATE_MATERIALIZED_VIEW +PREHOOK: Input: default@source_table +PREHOOK: Output: database:default +PREHOOK: Output: default@mv_using_source +POSTHOOK: query: create materialized view mv_using_source as select count(*) from source_table +POSTHOOK: type: CREATE_MATERIALIZED_VIEW +POSTHOOK: Input: default@source_table +POSTHOOK: Output: database:default +POSTHOOK: Output: default@mv_using_source +PREHOOK: query: drop table source_table +PREHOOK: type: DROPTABLE +PREHOOK: Input: default@source_table +PREHOOK: Output: default@source_table +FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.ddl.DDLTask. Cannot drop table since it is used by at least one materialized view definition. +Please drop any materialized view that uses the table before dropping it diff --git ql/src/test/results/clientnegative/drop_materialized_view_source2.q.out ql/src/test/results/clientnegative/drop_materialized_view_source2.q.out new file mode 100644 index 0000000000..08247ae335 --- /dev/null +++ ql/src/test/results/clientnegative/drop_materialized_view_source2.q.out @@ -0,0 +1,54 @@ +PREHOOK: query: create transactional table source_table (id int) +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@source_table +POSTHOOK: query: create transactional table source_table (id int) +POSTHOOK: type: CREATETABLE +POSTHOOK: Output: database:default +POSTHOOK: Output: default@source_table +PREHOOK: query: insert into source_table values (1), (2), (3) +PREHOOK: type: QUERY +PREHOOK: Input: _dummy_database@_dummy_table +PREHOOK: Output: default@source_table +POSTHOOK: query: insert into source_table values (1), (2), (3) +POSTHOOK: type: QUERY +POSTHOOK: Input: _dummy_database@_dummy_table +POSTHOOK: Output: default@source_table +POSTHOOK: Lineage: source_table.id SCRIPT [] +PREHOOK: query: create view source_view as select * from source_table +PREHOOK: type: CREATEVIEW +PREHOOK: Input: default@source_table +PREHOOK: Output: database:default +PREHOOK: Output: default@source_view +POSTHOOK: query: create view source_view as select * from source_table +POSTHOOK: type: CREATEVIEW +POSTHOOK: Input: default@source_table +POSTHOOK: Output: database:default +POSTHOOK: Output: default@source_view +POSTHOOK: Lineage: source_view.id SIMPLE [(source_table)source_table.FieldSchema(name:id, type:int, comment:null), ] +PREHOOK: query: create materialized view mv_using_source as select count(*) from source_view +PREHOOK: type: CREATE_MATERIALIZED_VIEW +PREHOOK: Input: default@source_table +PREHOOK: Input: default@source_view +PREHOOK: Output: database:default +PREHOOK: Output: default@mv_using_source +POSTHOOK: query: create materialized view mv_using_source as select count(*) from source_view +POSTHOOK: type: CREATE_MATERIALIZED_VIEW +POSTHOOK: Input: default@source_table +POSTHOOK: Input: default@source_view +POSTHOOK: Output: database:default +POSTHOOK: Output: default@mv_using_source +PREHOOK: query: drop view source_view +PREHOOK: type: DROPVIEW +PREHOOK: Input: default@source_view +PREHOOK: Output: default@source_view +POSTHOOK: query: drop view source_view +POSTHOOK: type: DROPVIEW +POSTHOOK: Input: default@source_view +POSTHOOK: Output: default@source_view +PREHOOK: query: drop table source_table +PREHOOK: type: DROPTABLE +PREHOOK: Input: default@source_table +PREHOOK: Output: default@source_table +FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.ddl.DDLTask. Cannot drop table since it is used by at least one materialized view definition. +Please drop any materialized view that uses the table before dropping it