diff --git hcatalog/streaming/src/test/org/apache/hive/hcatalog/streaming/mutate/StreamingTestUtils.java hcatalog/streaming/src/test/org/apache/hive/hcatalog/streaming/mutate/StreamingTestUtils.java index e874877f..87a72b5 100644 --- hcatalog/streaming/src/test/org/apache/hive/hcatalog/streaming/mutate/StreamingTestUtils.java +++ hcatalog/streaming/src/test/org/apache/hive/hcatalog/streaming/mutate/StreamingTestUtils.java @@ -45,7 +45,7 @@ import org.apache.hadoop.hive.metastore.api.StorageDescriptor; import org.apache.hadoop.hive.metastore.api.Table; import org.apache.hadoop.hive.metastore.txn.TxnDbUtil; -import org.apache.hadoop.hive.ql.io.HiveInputFormat; +import org.apache.hadoop.hive.ql.io.orc.OrcInputFormat; import org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat; import org.apache.hadoop.hive.ql.io.orc.OrcSerde; import org.apache.hadoop.hive.serde.serdeConstants; @@ -183,7 +183,7 @@ public TableBuilder(Database database) { table.setParameters(tableParams); sd = new StorageDescriptor(); - sd.setInputFormat(HiveInputFormat.class.getName()); + sd.setInputFormat(OrcInputFormat.class.getName()); sd.setOutputFormat(OrcOutputFormat.class.getName()); sd.setNumBuckets(1); table.setSd(sd); @@ -207,6 +207,11 @@ public TableBuilder buckets(int buckets) { return this; } + public TableBuilder bucketCols(List columnNames) { + sd.setBucketCols(columnNames); + return this; + } + public TableBuilder addColumn(String columnName, String columnType) { columnNames.add(columnName); columnTypes.add(columnType); diff --git hcatalog/streaming/src/test/org/apache/hive/hcatalog/streaming/mutate/TestMutations.java hcatalog/streaming/src/test/org/apache/hive/hcatalog/streaming/mutate/TestMutations.java index 703cef6..f1de1df 100644 --- hcatalog/streaming/src/test/org/apache/hive/hcatalog/streaming/mutate/TestMutations.java +++ hcatalog/streaming/src/test/org/apache/hive/hcatalog/streaming/mutate/TestMutations.java @@ -92,12 +92,14 @@ public void setup() throws Exception { .name("partitioned") .addColumn("id", "int") .addColumn("msg", "string") - .partitionKeys("continent", "country"); + .partitionKeys("continent", "country") + .bucketCols(Collections.singletonList("string")); unpartitionedTableBuilder = tableBuilder(database) .name("unpartitioned") .addColumn("id", "int") - .addColumn("msg", "string"); + .addColumn("msg", "string") + .bucketCols(Collections.singletonList("string")); } @Test diff --git itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStore.java itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStore.java index 9e9753f..a55c186 100644 --- itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStore.java +++ itests/hive-unit/src/test/java/org/apache/hadoop/hive/metastore/TestHiveMetaStore.java @@ -23,6 +23,7 @@ import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; @@ -69,6 +70,7 @@ import org.apache.hadoop.hive.metastore.api.Table; import org.apache.hadoop.hive.metastore.api.Type; import org.apache.hadoop.hive.metastore.api.UnknownDBException; +import org.apache.hadoop.hive.metastore.api.hive_metastoreConstants; import org.apache.hadoop.hive.ql.exec.Utilities; import org.apache.hadoop.hive.ql.io.HiveInputFormat; import org.apache.hadoop.hive.ql.io.HiveOutputFormat; @@ -77,6 +79,7 @@ import org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe; import org.apache.hadoop.util.StringUtils; import org.apache.thrift.TException; +import org.junit.Assert; import org.junit.Test; import com.google.common.collect.Lists; @@ -2182,7 +2185,7 @@ public void testPartitionFilter() throws Exception { } assertNotNull(me); assertTrue("NoSuchObject exception", me.getMessage().contains( - "database/table does not exist")); + "invDBName.invTableName table not found")); client.dropTable(dbName, tblName); client.dropDatabase(dbName); @@ -2803,6 +2806,120 @@ private void createTable(String dbName, String tableName) createTable(dbName, tableName, null, null, null, sd, 0); } + @Test + public void testTransactionalValidation() throws Throwable { + String tblName = "acidTable"; + String owner = "acid"; + Map fields = new HashMap(); + fields.put("name", serdeConstants.STRING_TYPE_NAME); + fields.put("income", serdeConstants.INT_TYPE_NAME); + + Type type = createType("Person", fields); + + Map params = new HashMap(); + params.put("transactional", ""); + + Map serdParams = new HashMap(); + serdParams.put(serdeConstants.SERIALIZATION_FORMAT, "1"); + StorageDescriptor sd = createStorageDescriptor(tblName, type.getFields(), params, serdParams); + sd.setNumBuckets(0); + sd.unsetBucketCols(); + + /// CREATE TABLE scenarios + + // Fail - No "transactional" property is specified + try { + Table t = createTable(MetaStoreUtils.DEFAULT_DATABASE_NAME, tblName, owner, params, null, sd, 0); + Assert.assertTrue("Expected exception", false); + } catch (MetaException e) { + Assert.assertEquals("'transactional' property of TBLPROPERTIES may only have value 'true'", e.getMessage()); + } + + // Fail - "transactional" property is set to an invalid value + try { + params.clear(); + params.put("transactional", "foobar"); + Table t = createTable(MetaStoreUtils.DEFAULT_DATABASE_NAME, tblName, owner, params, null, sd, 0); + Assert.assertTrue("Expected exception", false); + } catch (MetaException e) { + Assert.assertEquals("'transactional' property of TBLPROPERTIES may only have value 'true'", e.getMessage()); + } + + // Fail - "transactional" is set to true, but the table is not bucketed + try { + params.clear(); + params.put("transactional", "true"); + Table t = createTable(MetaStoreUtils.DEFAULT_DATABASE_NAME, tblName, owner, params, null, sd, 0); + Assert.assertTrue("Expected exception", false); + } catch (MetaException e) { + Assert.assertEquals("The table must be bucketed and stored using an ACID compliant format (such as ORC)", e.getMessage()); + } + + // Fail - "transactional" is set to true, and the table is bucketed, but doesn't use ORC + try { + params.clear(); + params.put("transactional", "true"); + List bucketCols = new ArrayList(); + bucketCols.add("income"); + sd.setBucketCols(bucketCols); + Table t = createTable(MetaStoreUtils.DEFAULT_DATABASE_NAME, tblName, owner, params, null, sd, 0); + Assert.assertTrue("Expected exception", false); + } catch (MetaException e) { + Assert.assertEquals("The table must be bucketed and stored using an ACID compliant format (such as ORC)", e.getMessage()); + } + + // Succeed - "transactional" is set to true, and the table is bucketed, and uses ORC + params.clear(); + params.put("transactional", "true"); + List bucketCols = new ArrayList(); + bucketCols.add("income"); + sd.setBucketCols(bucketCols); + sd.setInputFormat("org.apache.hadoop.hive.ql.io.orc.OrcInputFormat"); + sd.setOutputFormat("org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat"); + Table t = createTable(MetaStoreUtils.DEFAULT_DATABASE_NAME, tblName, owner, params, null, sd, 0); + Assert.assertTrue("CREATE TABLE should succeed", "true".equals(t.getParameters().get(hive_metastoreConstants.TABLE_IS_TRANSACTIONAL))); + + /// ALTER TABLE scenarios + + // Fail - trying to set "transactional" to "false" is not allowed + try { + params.clear(); + params.put("transactional", "false"); + t = new Table(); + t.setParameters(params); + client.alter_table(MetaStoreUtils.DEFAULT_DATABASE_NAME, tblName, t); + Assert.assertTrue("Expected exception", false); + } catch (MetaException e) { + Assert.assertEquals("TBLPROPERTIES with 'transactional'='true' cannot be unset", e.getMessage()); + } + + // Fail - trying to set "transactional" to "true" but doesn't satisfy bucketing and Input/OutputFormat requirement + try { + tblName += "1"; + params.clear(); + sd.unsetBucketCols(); + t = createTable(MetaStoreUtils.DEFAULT_DATABASE_NAME, tblName, owner, params, null, sd, 0); + params.put("transactional", "true"); + t.setParameters(params); + client.alter_table(MetaStoreUtils.DEFAULT_DATABASE_NAME, tblName, t); + Assert.assertTrue("Expected exception", false); + } catch (MetaException e) { + Assert.assertEquals("The table must be bucketed and stored using an ACID compliant format (such as ORC)", e.getMessage()); + } + + // Succeed - trying to set "transactional" to "true", and satisfies bucketing and Input/OutputFormat requirement + tblName += "2"; + params.clear(); + sd.setNumBuckets(1); + sd.setBucketCols(bucketCols); + t = createTable(MetaStoreUtils.DEFAULT_DATABASE_NAME, tblName, owner, params, null, sd, 0); + params.put("transactional", "true"); + t.setParameters(params); + t.setPartitionKeys(Collections.EMPTY_LIST); + client.alter_table(MetaStoreUtils.DEFAULT_DATABASE_NAME, tblName, t); + Assert.assertTrue("ALTER TABLE should succeed", "true".equals(t.getParameters().get(hive_metastoreConstants.TABLE_IS_TRANSACTIONAL))); + } + private Table createTable(String dbName, String tblName, String owner, Map tableParams, Map partitionKeys, StorageDescriptor sd, int lastAccessTime) throws Exception { @@ -2829,6 +2946,15 @@ private Table createTable(String dbName, String tblName, String owner, tbl.setLastAccessTime(lastAccessTime); client.createTable(tbl); + + if (isThriftClient) { + // the createTable() above does not update the location in the 'tbl' + // object when the client is a thrift client and ALTER TABLE relies + // on the location being present in the 'tbl' object - so get the table + // from the metastore + tbl = client.getTable(dbName, tblName); + } + return tbl; } diff --git itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/txn/compactor/TestCompactor.java itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/txn/compactor/TestCompactor.java index 568f75a..ad32074 100644 --- itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/txn/compactor/TestCompactor.java +++ itests/hive-unit/src/test/java/org/apache/hadoop/hive/ql/txn/compactor/TestCompactor.java @@ -365,8 +365,7 @@ public void testStatsAfterCompactionPartTbl() throws Exception { executeStatementOnDriver("CREATE EXTERNAL TABLE " + tblNameStg + "(a INT, b STRING)" + " ROW FORMAT DELIMITED FIELDS TERMINATED BY '\\t' LINES TERMINATED BY '\\n'" + " STORED AS TEXTFILE" + - " LOCATION '" + stagingFolder.newFolder().toURI().getPath() + "'" + - " TBLPROPERTIES ('transactional'='true')", driver); + " LOCATION '" + stagingFolder.newFolder().toURI().getPath() + "'", driver); executeStatementOnDriver("load data local inpath '" + BASIC_FILE_NAME + "' overwrite into table " + tblNameStg, driver); diff --git metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java index 9eb15bd..557985e 100644 --- metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java +++ metastore/src/java/org/apache/hadoop/hive/metastore/HiveMetaStore.java @@ -431,6 +431,7 @@ public Object getValue() { preListeners = MetaStoreUtils.getMetaStoreListeners(MetaStorePreEventListener.class, hiveConf, hiveConf.getVar(HiveConf.ConfVars.METASTORE_PRE_EVENT_LISTENERS)); + preListeners.add(0, new TransactionalValidationListener(hiveConf)); listeners = MetaStoreUtils.getMetaStoreListeners(MetaStoreEventListener.class, hiveConf, hiveConf.getVar(HiveConf.ConfVars.METASTORE_EVENT_LISTENERS)); listeners.add(new SessionPropertiesListener(hiveConf)); diff --git metastore/src/java/org/apache/hadoop/hive/metastore/TransactionalValidationListener.java metastore/src/java/org/apache/hadoop/hive/metastore/TransactionalValidationListener.java new file mode 100644 index 0000000..96158f8 --- /dev/null +++ metastore/src/java/org/apache/hadoop/hive/metastore/TransactionalValidationListener.java @@ -0,0 +1,179 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hive.metastore; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hive.metastore.api.*; +import org.apache.hadoop.hive.metastore.events.PreAlterTableEvent; +import org.apache.hadoop.hive.metastore.events.PreCreateTableEvent; +import org.apache.hadoop.hive.metastore.events.PreEventContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +final class TransactionalValidationListener extends MetaStorePreEventListener { + public static final Logger LOG = LoggerFactory.getLogger(TransactionalValidationListener.class); + + TransactionalValidationListener(Configuration conf) { + super(conf); + } + + public void onEvent(PreEventContext context) throws MetaException, NoSuchObjectException, + InvalidOperationException { + switch (context.getEventType()) { + case CREATE_TABLE: + handle((PreCreateTableEvent) context); + break; + case ALTER_TABLE: + handle((PreAlterTableEvent) context); + break; + default: + //no validation required.. + } + } + + private void handle(PreAlterTableEvent context) throws MetaException { + handleAlterTableTransactionalProp(context); + } + + private void handle(PreCreateTableEvent context) throws MetaException { + handleCreateTableTransactionalProp(context); + } + + /** + * once a table is marked transactional, you cannot go back. Enforce this. + */ + private void handleAlterTableTransactionalProp(PreAlterTableEvent context) throws MetaException { + Table newTable = context.getNewTable(); + Map parameters = newTable.getParameters(); + if (parameters == null || parameters.isEmpty()) { + return; + } + Set keys = new HashSet<>(parameters.keySet()); + String transactionalValue = null; + boolean transactionalValuePresent = false; + for (String key : keys) { + if(hive_metastoreConstants.TABLE_IS_TRANSACTIONAL.equalsIgnoreCase(key)) { + transactionalValuePresent = true; + transactionalValue = parameters.get(key); + parameters.remove(key); + } + } + if (transactionalValuePresent) { + //normalize prop name + parameters.put(hive_metastoreConstants.TABLE_IS_TRANSACTIONAL, transactionalValue); + } + if ("true".equalsIgnoreCase(transactionalValue)) { + if (!conformToAcid(newTable)) { + throw new MetaException("The table must be bucketed and stored using an ACID compliant" + + " format (such as ORC)"); + } + return; + } + Table oldTable = context.getOldTable(); + String oldTransactionalValue = null; + for (String key : oldTable.getParameters().keySet()) { + if (hive_metastoreConstants.TABLE_IS_TRANSACTIONAL.equalsIgnoreCase(key)) { + oldTransactionalValue = oldTable.getParameters().get(key); + } + } + if (oldTransactionalValue == null ? transactionalValue == null + : oldTransactionalValue.equalsIgnoreCase(transactionalValue)) { + //this covers backward compat cases where this prop may have been set already + return; + } + // if here, there is attempt to set transactional to something other than 'true' + // and NOT the same value it was before + throw new MetaException("TBLPROPERTIES with 'transactional'='true' cannot be unset"); + } + + /** + * Normalize case and make sure: + * 1. 'true' is the only value to be set for 'transactional' (if set at all) + * 2. If set to 'true', we should also enforce bucketing and ORC format + */ + private void handleCreateTableTransactionalProp(PreCreateTableEvent context) throws MetaException { + Table newTable = context.getTable(); + Map parameters = newTable.getParameters(); + if (parameters == null || parameters.isEmpty()) { + return; + } + String transactionalValue = null; + boolean transactionalPropFound = false; + Set keys = new HashSet<>(parameters.keySet()); + for(String key : keys) { + if(hive_metastoreConstants.TABLE_IS_TRANSACTIONAL.equalsIgnoreCase(key)) { + transactionalPropFound = true; + transactionalValue = parameters.get(key); + parameters.remove(key); + } + } + + if (!transactionalPropFound) { + return; + } + + if ("false".equalsIgnoreCase(transactionalValue)) { + // just drop transactional=false. For backward compatibility in case someone has scripts + // with transactional=false + LOG.info("'transactional'='false' is no longer a valid property and will be ignored"); + return; + } + + if ("true".equalsIgnoreCase(transactionalValue)) { + if (!conformToAcid(newTable)) { + throw new MetaException("The table must be bucketed and stored using an ACID compliant" + + " format (such as ORC)"); + } + + // normalize prop name + parameters.put(hive_metastoreConstants.TABLE_IS_TRANSACTIONAL, Boolean.TRUE.toString()); + return; + } + + // transactional prop is found, but the value is not in expected range + throw new MetaException("'transactional' property of TBLPROPERTIES may only have value 'true'"); + } + + // Check if table is bucketed and InputFormatClass/OutputFormatClass should implement + // AcidInputFormat/AcidOutputFormat + private boolean conformToAcid(Table table) throws MetaException { + StorageDescriptor sd = table.getSd(); + if (sd.getBucketColsSize() < 1) { + return false; + } + + try { + Class inputFormatClass = Class.forName(sd.getInputFormat()); + Class outputFormatClass = Class.forName(sd.getOutputFormat()); + + if (inputFormatClass == null || outputFormatClass == null || + !Class.forName("org.apache.hadoop.hive.ql.io.AcidInputFormat").isAssignableFrom(inputFormatClass) || + !Class.forName("org.apache.hadoop.hive.ql.io.AcidOutputFormat").isAssignableFrom(outputFormatClass)) { + return false; + } + } catch (ClassNotFoundException e) { + throw new MetaException("Invalid input/output format for table"); + } + + return true; + } +} \ No newline at end of file diff --git ql/src/test/queries/clientnegative/create_not_acid.q ql/src/test/queries/clientnegative/create_not_acid.q new file mode 100644 index 0000000..8d6c9ac --- /dev/null +++ ql/src/test/queries/clientnegative/create_not_acid.q @@ -0,0 +1,6 @@ +set hive.support.concurrency=true; +set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager; + + +create table acid_notbucketed(a int, b varchar(128)) stored as orc TBLPROPERTIES ('transactional'='true'); + diff --git ql/src/test/queries/clientnegative/delete_not_bucketed.q ql/src/test/queries/clientnegative/delete_not_bucketed.q deleted file mode 100644 index d575a8f..0000000 --- ql/src/test/queries/clientnegative/delete_not_bucketed.q +++ /dev/null @@ -1,7 +0,0 @@ -set hive.support.concurrency=true; -set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager; - - -create table acid_notbucketed(a int, b varchar(128)) stored as orc TBLPROPERTIES ('transactional'='true'); - -delete from acid_notbucketed where a = 3; diff --git ql/src/test/queries/clientnegative/orc_change_fileformat_acid.q ql/src/test/queries/clientnegative/orc_change_fileformat_acid.q index 0fd287b..cc73616 100644 --- ql/src/test/queries/clientnegative/orc_change_fileformat_acid.q +++ ql/src/test/queries/clientnegative/orc_change_fileformat_acid.q @@ -1,3 +1,3 @@ SET hive.exec.schema.evolution=false; -create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true'); +create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true'); alter table src_orc set fileformat textfile; diff --git ql/src/test/queries/clientnegative/orc_change_serde_acid.q ql/src/test/queries/clientnegative/orc_change_serde_acid.q index d317a28..91a2be5 100644 --- ql/src/test/queries/clientnegative/orc_change_serde_acid.q +++ ql/src/test/queries/clientnegative/orc_change_serde_acid.q @@ -1,3 +1,3 @@ SET hive.exec.schema.evolution=false; -create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true'); +create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true'); alter table src_orc set serde 'org.apache.hadoop.hive.serde2.columnar.ColumnarSerDe'; diff --git ql/src/test/queries/clientnegative/orc_reorder_columns1_acid.q ql/src/test/queries/clientnegative/orc_reorder_columns1_acid.q index 2c6cc9f..234e74b 100644 --- ql/src/test/queries/clientnegative/orc_reorder_columns1_acid.q +++ ql/src/test/queries/clientnegative/orc_reorder_columns1_acid.q @@ -1,3 +1,3 @@ SET hive.exec.schema.evolution=false; -create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true'); +create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true'); alter table src_orc change key k tinyint first; diff --git ql/src/test/queries/clientnegative/orc_reorder_columns2_acid.q ql/src/test/queries/clientnegative/orc_reorder_columns2_acid.q index 938a0bc..57ab049 100644 --- ql/src/test/queries/clientnegative/orc_reorder_columns2_acid.q +++ ql/src/test/queries/clientnegative/orc_reorder_columns2_acid.q @@ -1,3 +1,3 @@ SET hive.exec.schema.evolution=false; -create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true'); +create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true'); alter table src_orc change key k tinyint after val; diff --git ql/src/test/queries/clientnegative/orc_replace_columns1_acid.q ql/src/test/queries/clientnegative/orc_replace_columns1_acid.q index 68a8127..9fe9209 100644 --- ql/src/test/queries/clientnegative/orc_replace_columns1_acid.q +++ ql/src/test/queries/clientnegative/orc_replace_columns1_acid.q @@ -1,3 +1,3 @@ SET hive.exec.schema.evolution=false; -create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true'); +create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true'); alter table src_orc replace columns (k int); diff --git ql/src/test/queries/clientnegative/orc_replace_columns2_acid.q ql/src/test/queries/clientnegative/orc_replace_columns2_acid.q index 417a5de..b1614e6 100644 --- ql/src/test/queries/clientnegative/orc_replace_columns2_acid.q +++ ql/src/test/queries/clientnegative/orc_replace_columns2_acid.q @@ -1,3 +1,3 @@ SET hive.exec.schema.evolution=false; -create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true'); +create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true'); alter table src_orc replace columns (k smallint, val string); diff --git ql/src/test/queries/clientnegative/orc_replace_columns3_acid.q ql/src/test/queries/clientnegative/orc_replace_columns3_acid.q index b09eb37..89c04e6 100644 --- ql/src/test/queries/clientnegative/orc_replace_columns3_acid.q +++ ql/src/test/queries/clientnegative/orc_replace_columns3_acid.q @@ -1,4 +1,4 @@ SET hive.exec.schema.evolution=false; -create table src_orc (key smallint, val string) stored as orc TBLPROPERTIES ('transactional'='true'); +create table src_orc (key smallint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true'); alter table src_orc replace columns (k int, val string, z smallint); alter table src_orc replace columns (k int, val string, z tinyint); diff --git ql/src/test/queries/clientnegative/orc_type_promotion1_acid.q ql/src/test/queries/clientnegative/orc_type_promotion1_acid.q index 26e67e5..b845bd6 100644 --- ql/src/test/queries/clientnegative/orc_type_promotion1_acid.q +++ ql/src/test/queries/clientnegative/orc_type_promotion1_acid.q @@ -1,3 +1,3 @@ SET hive.exec.schema.evolution=false; -create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true'); +create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true'); alter table src_orc change key key float; diff --git ql/src/test/queries/clientnegative/orc_type_promotion2_acid.q ql/src/test/queries/clientnegative/orc_type_promotion2_acid.q index e076d2b..5228cf8 100644 --- ql/src/test/queries/clientnegative/orc_type_promotion2_acid.q +++ ql/src/test/queries/clientnegative/orc_type_promotion2_acid.q @@ -1,5 +1,5 @@ SET hive.exec.schema.evolution=false; -create table src_orc (key smallint, val string) stored as orc TBLPROPERTIES ('transactional'='true'); +create table src_orc (key smallint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true'); desc src_orc; alter table src_orc change key key smallint; desc src_orc; diff --git ql/src/test/queries/clientnegative/orc_type_promotion3_acid.q ql/src/test/queries/clientnegative/orc_type_promotion3_acid.q index 3b7c28b..79e5c84 100644 --- ql/src/test/queries/clientnegative/orc_type_promotion3_acid.q +++ ql/src/test/queries/clientnegative/orc_type_promotion3_acid.q @@ -1,3 +1,3 @@ SET hive.exec.schema.evolution=false; -create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true'); +create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true'); alter table src_orc change key key smallint; diff --git ql/src/test/queries/clientnegative/update_not_bucketed.q ql/src/test/queries/clientnegative/update_not_bucketed.q deleted file mode 100644 index d7d0da4..0000000 --- ql/src/test/queries/clientnegative/update_not_bucketed.q +++ /dev/null @@ -1,7 +0,0 @@ -set hive.support.concurrency=true; -set hive.txn.manager=org.apache.hadoop.hive.ql.lockmgr.DbTxnManager; - - -create table acid_notbucketed(a int, b varchar(128)) partitioned by (ds string) stored as orc TBLPROPERTIES ('transactional'='true'); - -update acid_notbucketed set b = 'fred' where a = 3; diff --git ql/src/test/results/clientnegative/create_not_acid.q.out ql/src/test/results/clientnegative/create_not_acid.q.out new file mode 100644 index 0000000..bb8f6c9 --- /dev/null +++ ql/src/test/results/clientnegative/create_not_acid.q.out @@ -0,0 +1,5 @@ +PREHOOK: query: create table acid_notbucketed(a int, b varchar(128)) stored as orc TBLPROPERTIES ('transactional'='true') +PREHOOK: type: CREATETABLE +PREHOOK: Output: database:default +PREHOOK: Output: default@acid_notbucketed +FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. MetaException(message:The table must be bucketed and stored using an ACID compliant format (such as ORC)) diff --git ql/src/test/results/clientnegative/delete_not_bucketed.q.out ql/src/test/results/clientnegative/delete_not_bucketed.q.out deleted file mode 100644 index 8c4a40c..0000000 --- ql/src/test/results/clientnegative/delete_not_bucketed.q.out +++ /dev/null @@ -1,9 +0,0 @@ -PREHOOK: query: create table acid_notbucketed(a int, b varchar(128)) stored as orc TBLPROPERTIES ('transactional'='true') -PREHOOK: type: CREATETABLE -PREHOOK: Output: database:default -PREHOOK: Output: default@acid_notbucketed -POSTHOOK: query: create table acid_notbucketed(a int, b varchar(128)) stored as orc TBLPROPERTIES ('transactional'='true') -POSTHOOK: type: CREATETABLE -POSTHOOK: Output: database:default -POSTHOOK: Output: default@acid_notbucketed -FAILED: SemanticException [Error 10297]: Attempt to do update or delete on table default.acid_notbucketed that does not use an AcidOutputFormat or is not bucketed diff --git ql/src/test/results/clientnegative/orc_change_fileformat_acid.q.out ql/src/test/results/clientnegative/orc_change_fileformat_acid.q.out index c29fe79..cd3e168 100644 --- ql/src/test/results/clientnegative/orc_change_fileformat_acid.q.out +++ ql/src/test/results/clientnegative/orc_change_fileformat_acid.q.out @@ -1,8 +1,8 @@ -PREHOOK: query: create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +PREHOOK: query: create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') PREHOOK: type: CREATETABLE PREHOOK: Output: database:default PREHOOK: Output: default@src_orc -POSTHOOK: query: create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +POSTHOOK: query: create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') POSTHOOK: type: CREATETABLE POSTHOOK: Output: database:default POSTHOOK: Output: default@src_orc diff --git ql/src/test/results/clientnegative/orc_change_serde_acid.q.out ql/src/test/results/clientnegative/orc_change_serde_acid.q.out index 01fb870..612207b 100644 --- ql/src/test/results/clientnegative/orc_change_serde_acid.q.out +++ ql/src/test/results/clientnegative/orc_change_serde_acid.q.out @@ -1,8 +1,8 @@ -PREHOOK: query: create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +PREHOOK: query: create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') PREHOOK: type: CREATETABLE PREHOOK: Output: database:default PREHOOK: Output: default@src_orc -POSTHOOK: query: create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +POSTHOOK: query: create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') POSTHOOK: type: CREATETABLE POSTHOOK: Output: database:default POSTHOOK: Output: default@src_orc diff --git ql/src/test/results/clientnegative/orc_reorder_columns1_acid.q.out ql/src/test/results/clientnegative/orc_reorder_columns1_acid.q.out index 5186081..8f7255c 100644 --- ql/src/test/results/clientnegative/orc_reorder_columns1_acid.q.out +++ ql/src/test/results/clientnegative/orc_reorder_columns1_acid.q.out @@ -1,8 +1,8 @@ -PREHOOK: query: create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +PREHOOK: query: create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') PREHOOK: type: CREATETABLE PREHOOK: Output: database:default PREHOOK: Output: default@src_orc -POSTHOOK: query: create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +POSTHOOK: query: create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') POSTHOOK: type: CREATETABLE POSTHOOK: Output: database:default POSTHOOK: Output: default@src_orc diff --git ql/src/test/results/clientnegative/orc_reorder_columns2_acid.q.out ql/src/test/results/clientnegative/orc_reorder_columns2_acid.q.out index 7b65d7c..6cae15b 100644 --- ql/src/test/results/clientnegative/orc_reorder_columns2_acid.q.out +++ ql/src/test/results/clientnegative/orc_reorder_columns2_acid.q.out @@ -1,8 +1,8 @@ -PREHOOK: query: create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +PREHOOK: query: create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') PREHOOK: type: CREATETABLE PREHOOK: Output: database:default PREHOOK: Output: default@src_orc -POSTHOOK: query: create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +POSTHOOK: query: create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') POSTHOOK: type: CREATETABLE POSTHOOK: Output: database:default POSTHOOK: Output: default@src_orc diff --git ql/src/test/results/clientnegative/orc_replace_columns1_acid.q.out ql/src/test/results/clientnegative/orc_replace_columns1_acid.q.out index ec09d4b..46caec2 100644 --- ql/src/test/results/clientnegative/orc_replace_columns1_acid.q.out +++ ql/src/test/results/clientnegative/orc_replace_columns1_acid.q.out @@ -1,8 +1,8 @@ -PREHOOK: query: create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +PREHOOK: query: create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') PREHOOK: type: CREATETABLE PREHOOK: Output: database:default PREHOOK: Output: default@src_orc -POSTHOOK: query: create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +POSTHOOK: query: create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') POSTHOOK: type: CREATETABLE POSTHOOK: Output: database:default POSTHOOK: Output: default@src_orc diff --git ql/src/test/results/clientnegative/orc_replace_columns2_acid.q.out ql/src/test/results/clientnegative/orc_replace_columns2_acid.q.out index ae373d2..41df688 100644 --- ql/src/test/results/clientnegative/orc_replace_columns2_acid.q.out +++ ql/src/test/results/clientnegative/orc_replace_columns2_acid.q.out @@ -1,8 +1,8 @@ -PREHOOK: query: create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +PREHOOK: query: create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') PREHOOK: type: CREATETABLE PREHOOK: Output: database:default PREHOOK: Output: default@src_orc -POSTHOOK: query: create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +POSTHOOK: query: create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') POSTHOOK: type: CREATETABLE POSTHOOK: Output: database:default POSTHOOK: Output: default@src_orc diff --git ql/src/test/results/clientnegative/orc_replace_columns3_acid.q.out ql/src/test/results/clientnegative/orc_replace_columns3_acid.q.out index 90ab2fd..3fb1e32 100644 --- ql/src/test/results/clientnegative/orc_replace_columns3_acid.q.out +++ ql/src/test/results/clientnegative/orc_replace_columns3_acid.q.out @@ -1,8 +1,8 @@ -PREHOOK: query: create table src_orc (key smallint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +PREHOOK: query: create table src_orc (key smallint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') PREHOOK: type: CREATETABLE PREHOOK: Output: database:default PREHOOK: Output: default@src_orc -POSTHOOK: query: create table src_orc (key smallint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +POSTHOOK: query: create table src_orc (key smallint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') POSTHOOK: type: CREATETABLE POSTHOOK: Output: database:default POSTHOOK: Output: default@src_orc diff --git ql/src/test/results/clientnegative/orc_type_promotion1_acid.q.out ql/src/test/results/clientnegative/orc_type_promotion1_acid.q.out index 5357fd1..030ca35 100644 --- ql/src/test/results/clientnegative/orc_type_promotion1_acid.q.out +++ ql/src/test/results/clientnegative/orc_type_promotion1_acid.q.out @@ -1,8 +1,8 @@ -PREHOOK: query: create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +PREHOOK: query: create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') PREHOOK: type: CREATETABLE PREHOOK: Output: database:default PREHOOK: Output: default@src_orc -POSTHOOK: query: create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +POSTHOOK: query: create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') POSTHOOK: type: CREATETABLE POSTHOOK: Output: database:default POSTHOOK: Output: default@src_orc diff --git ql/src/test/results/clientnegative/orc_type_promotion2_acid.q.out ql/src/test/results/clientnegative/orc_type_promotion2_acid.q.out index 74e75cf..77e2e8d 100644 --- ql/src/test/results/clientnegative/orc_type_promotion2_acid.q.out +++ ql/src/test/results/clientnegative/orc_type_promotion2_acid.q.out @@ -1,8 +1,8 @@ -PREHOOK: query: create table src_orc (key smallint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +PREHOOK: query: create table src_orc (key smallint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') PREHOOK: type: CREATETABLE PREHOOK: Output: database:default PREHOOK: Output: default@src_orc -POSTHOOK: query: create table src_orc (key smallint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +POSTHOOK: query: create table src_orc (key smallint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') POSTHOOK: type: CREATETABLE POSTHOOK: Output: database:default POSTHOOK: Output: default@src_orc diff --git ql/src/test/results/clientnegative/orc_type_promotion3_acid.q.out ql/src/test/results/clientnegative/orc_type_promotion3_acid.q.out index 15e87fa..19400ce 100644 --- ql/src/test/results/clientnegative/orc_type_promotion3_acid.q.out +++ ql/src/test/results/clientnegative/orc_type_promotion3_acid.q.out @@ -1,8 +1,8 @@ -PREHOOK: query: create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +PREHOOK: query: create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') PREHOOK: type: CREATETABLE PREHOOK: Output: database:default PREHOOK: Output: default@src_orc -POSTHOOK: query: create table src_orc (key tinyint, val string) stored as orc TBLPROPERTIES ('transactional'='true') +POSTHOOK: query: create table src_orc (key tinyint, val string) clustered by (val) into 2 buckets stored as orc TBLPROPERTIES ('transactional'='true') POSTHOOK: type: CREATETABLE POSTHOOK: Output: database:default POSTHOOK: Output: default@src_orc diff --git ql/src/test/results/clientnegative/update_not_bucketed.q.out ql/src/test/results/clientnegative/update_not_bucketed.q.out deleted file mode 100644 index 42a48a0..0000000 --- ql/src/test/results/clientnegative/update_not_bucketed.q.out +++ /dev/null @@ -1,9 +0,0 @@ -PREHOOK: query: create table acid_notbucketed(a int, b varchar(128)) partitioned by (ds string) stored as orc TBLPROPERTIES ('transactional'='true') -PREHOOK: type: CREATETABLE -PREHOOK: Output: database:default -PREHOOK: Output: default@acid_notbucketed -POSTHOOK: query: create table acid_notbucketed(a int, b varchar(128)) partitioned by (ds string) stored as orc TBLPROPERTIES ('transactional'='true') -POSTHOOK: type: CREATETABLE -POSTHOOK: Output: database:default -POSTHOOK: Output: default@acid_notbucketed -FAILED: SemanticException [Error 10297]: Attempt to do update or delete on table default.acid_notbucketed that does not use an AcidOutputFormat or is not bucketed