diff --git metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java index e796048..47d3d31 100644 --- metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java +++ metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java @@ -55,6 +55,8 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.CommonConfigurationKeysPublic; +import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hive.common.FileUtils; import org.apache.hadoop.hive.common.LogUtils; @@ -198,6 +200,7 @@ import org.apache.hadoop.hive.metastore.txn.TxnHandler; import org.apache.hadoop.hive.serde2.Deserializer; import org.apache.hadoop.hive.serde2.SerDeException; +import org.apache.hadoop.hive.shims.HadoopShims; import org.apache.hadoop.hive.shims.ShimLoader; import org.apache.hadoop.hive.shims.Utils; import org.apache.hadoop.hive.thrift.HadoopThriftAuthBridge; @@ -1478,6 +1481,7 @@ private boolean drop_table_core(final RawStore ms, final String dbname, final St Path tblPath = null; List partPaths = null; Table tbl = null; + boolean ifPurge = false; try { ms.openTransaction(); // drop any partitions @@ -1489,6 +1493,17 @@ private boolean drop_table_core(final RawStore ms, final String dbname, final St throw new MetaException("Table metadata is corrupted"); } + /** + * Trash may be skipped iff: + * 1. deleteData == true, obviously. + * 2. tbl is external. + * 3. Either + * 3.1. User has specified PURGE from the commandline, and if not, + * 3.2. User has set the table to auto-purge. + */ + ifPurge = ((envContext != null) && Boolean.parseBoolean(envContext.getProperties().get("ifPurge"))) + || (tbl.isSetParameters() && "true".equalsIgnoreCase(tbl.getParameters().get("auto.purge"))); + firePreEvent(new PreDropTableEvent(tbl, deleteData, this)); boolean isIndexTable = isIndexTable(tbl); @@ -1521,6 +1536,19 @@ private boolean drop_table_core(final RawStore ms, final String dbname, final St } } + if(!ifPurge) { + String trashInterval = hiveConf.get(CommonConfigurationKeysPublic.FS_TRASH_INTERVAL_KEY); + boolean trashEnabled = trashInterval != null && trashInterval.length() > 0 + && Integer.parseInt(trashInterval) > 0; + if (trashEnabled) { + HadoopShims.HdfsEncryptionShim shim = + ShimLoader.getHadoopShims().createHdfsEncryptionShim(FileSystem.get(hiveConf), hiveConf); + if (shim.isPathEncrypted(tblPath)) { + throw new MetaException("Unable to drop table because it is in an encryption zone" + + " and trash is enabled. Use PURGE option to skip trash."); + } + } + } // Drop the partitions and get a list of locations which need to be deleted partPaths = dropPartitionsAndGetLocations(ms, dbname, name, tblPath, tbl.getPartitionKeys(), deleteData && !isExternal); @@ -1536,15 +1564,6 @@ private boolean drop_table_core(final RawStore ms, final String dbname, final St ms.rollbackTransaction(); } else if (deleteData && !isExternal) { // Data needs deletion. Check if trash may be skipped. - // Trash may be skipped iff: - // 1. deleteData == true, obviously. - // 2. tbl is external. - // 3. Either - // 3.1. User has specified PURGE from the commandline, and if not, - // 3.2. User has set the table to auto-purge. - boolean ifPurge = ((envContext != null) && Boolean.parseBoolean(envContext.getProperties().get("ifPurge"))) - || - (tbl.isSetParameters() && "true".equalsIgnoreCase(tbl.getParameters().get("auto.purge"))); // Delete the data in the partitions which have other locations deletePartitionData(partPaths, ifPurge); // Delete the data in the table diff --git ql/src/test/queries/clientpositive/encryption_drop_table.q ql/src/test/queries/clientpositive/encryption_drop_table.q new file mode 100644 index 0000000..3ae40dc --- /dev/null +++ ql/src/test/queries/clientpositive/encryption_drop_table.q @@ -0,0 +1,19 @@ +-- SORT_QUERY_RESULTS; + +-- we're setting this so that TestNegaiveCliDriver.vm doesn't stop processing after DROP TABLE fails; + +set hive.cli.errors.ignore=true; +set fs.trash.interval=50; + +DROP TABLE IF EXISTS encrypted_table; +CREATE TABLE encrypted_table (key INT, value STRING) LOCATION '${hiveconf:hive.metastore.warehouse.dir}/default/encrypted_table'; +CRYPTO CREATE_KEY --keyName key_128 --bitLength 128; +CRYPTO CREATE_ZONE --keyName key_128 --path ${hiveconf:hive.metastore.warehouse.dir}/default/encrypted_table; + +INSERT OVERWRITE TABLE encrypted_table SELECT * FROM src; +SHOW TABLES; +DROP TABLE default.encrypted_table; +SHOW TABLES; +DROP TABLE default.encrypted_table PURGE; +SHOW TABLES; +CRYPTO DELETE_KEY --keyName key_128; \ No newline at end of file diff --git ql/src/test/results/clientpositive/encrypted/encryption_drop_table.q.out ql/src/test/results/clientpositive/encrypted/encryption_drop_table.q.out new file mode 100644 index 0000000..b5e7726 --- /dev/null +++ ql/src/test/results/clientpositive/encrypted/encryption_drop_table.q.out @@ -0,0 +1,56 @@ +PREHOOK: query: DROP TABLE IF EXISTS encrypted_table +PREHOOK: type: DROPTABLE +POSTHOOK: query: DROP TABLE IF EXISTS encrypted_table +POSTHOOK: type: DROPTABLE +#### A masked pattern was here #### +PREHOOK: type: CREATETABLE +#### A masked pattern was here #### +PREHOOK: Output: database:default +PREHOOK: Output: default@encrypted_table +#### A masked pattern was here #### +POSTHOOK: type: CREATETABLE +#### A masked pattern was here #### +POSTHOOK: Output: database:default +POSTHOOK: Output: default@encrypted_table +Encryption key created: 'key_128' +Encryption zone created: '/build/ql/test/data/warehouse/default/encrypted_table' using key: 'key_128' +PREHOOK: query: INSERT OVERWRITE TABLE encrypted_table SELECT * FROM src +PREHOOK: type: QUERY +PREHOOK: Input: default@src +PREHOOK: Output: default@encrypted_table +POSTHOOK: query: INSERT OVERWRITE TABLE encrypted_table SELECT * FROM src +POSTHOOK: type: QUERY +POSTHOOK: Input: default@src +POSTHOOK: Output: default@encrypted_table +POSTHOOK: Lineage: encrypted_table.key EXPRESSION [(src)src.FieldSchema(name:key, type:string, comment:default), ] +POSTHOOK: Lineage: encrypted_table.value SIMPLE [(src)src.FieldSchema(name:value, type:string, comment:default), ] +PREHOOK: query: SHOW TABLES +PREHOOK: type: SHOWTABLES +POSTHOOK: query: SHOW TABLES +POSTHOOK: type: SHOWTABLES +encrypted_table +src +PREHOOK: query: DROP TABLE default.encrypted_table +PREHOOK: type: DROPTABLE +PREHOOK: Input: default@encrypted_table +PREHOOK: Output: default@encrypted_table +FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. MetaException(message:Unable to drop table because it is in an encryption zone and trash is enabled. Use PURGE option to skip trash.) +PREHOOK: query: SHOW TABLES +PREHOOK: type: SHOWTABLES +POSTHOOK: query: SHOW TABLES +POSTHOOK: type: SHOWTABLES +encrypted_table +src +PREHOOK: query: DROP TABLE default.encrypted_table PURGE +PREHOOK: type: DROPTABLE +PREHOOK: Input: default@encrypted_table +PREHOOK: Output: default@encrypted_table +POSTHOOK: query: DROP TABLE default.encrypted_table PURGE +POSTHOOK: type: DROPTABLE +POSTHOOK: Input: default@encrypted_table +POSTHOOK: Output: default@encrypted_table +PREHOOK: query: SHOW TABLES +PREHOOK: type: SHOWTABLES +POSTHOOK: query: SHOW TABLES +POSTHOOK: type: SHOWTABLES +src