You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by pv...@apache.org on 2018/01/27 19:17:29 UTC
[2/2] hive git commit: HIVE-18509: Create tests for table
manipulation related methods (create, alter, drop) (Peter Vary,
reviewed by Yongzhi Chen, Marta Kuczora and Adam Szita)
HIVE-18509: Create tests for table manipulation related methods (create, alter, drop) (Peter Vary, reviewed by Yongzhi Chen, Marta Kuczora and Adam Szita)
Project: http://git-wip-us.apache.org/repos/asf/hive/repo
Commit: http://git-wip-us.apache.org/repos/asf/hive/commit/1833ac9b
Tree: http://git-wip-us.apache.org/repos/asf/hive/tree/1833ac9b
Diff: http://git-wip-us.apache.org/repos/asf/hive/diff/1833ac9b
Branch: refs/heads/master
Commit: 1833ac9bd5fa5ab579e112b6cdd641c8ff69b770
Parents: fa0a8d2
Author: Peter Vary <pv...@cloudera.com>
Authored: Sat Jan 27 20:16:27 2018 +0100
Committer: Peter Vary <pv...@cloudera.com>
Committed: Sat Jan 27 20:16:27 2018 +0100
----------------------------------------------------------------------
.../TestTablesCreateDropAlterTruncate.java | 1129 ++++++++++++++++++
1 file changed, 1129 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/hive/blob/1833ac9b/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/client/TestTablesCreateDropAlterTruncate.java
----------------------------------------------------------------------
diff --git a/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/client/TestTablesCreateDropAlterTruncate.java b/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/client/TestTablesCreateDropAlterTruncate.java
new file mode 100644
index 0000000..abc400a
--- /dev/null
+++ b/standalone-metastore/src/test/java/org/apache/hadoop/hive/metastore/client/TestTablesCreateDropAlterTruncate.java
@@ -0,0 +1,1129 @@
+/*
+ * 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.client;
+
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hive.common.StatsSetupConst;
+import org.apache.hadoop.hive.metastore.IMetaStoreClient;
+import org.apache.hadoop.hive.metastore.api.AlreadyExistsException;
+import org.apache.hadoop.hive.metastore.api.EnvironmentContext;
+import org.apache.hadoop.hive.metastore.api.FieldSchema;
+import org.apache.hadoop.hive.metastore.api.InvalidObjectException;
+import org.apache.hadoop.hive.metastore.api.InvalidOperationException;
+import org.apache.hadoop.hive.metastore.api.MetaException;
+import org.apache.hadoop.hive.metastore.api.NoSuchObjectException;
+import org.apache.hadoop.hive.metastore.api.Partition;
+import org.apache.hadoop.hive.metastore.api.SerDeInfo;
+import org.apache.hadoop.hive.metastore.api.SkewedInfo;
+import org.apache.hadoop.hive.metastore.api.StorageDescriptor;
+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.PartitionBuilder;
+import org.apache.hadoop.hive.metastore.client.builder.TableBuilder;
+import org.apache.hadoop.hive.metastore.conf.MetastoreConf;
+import org.apache.hadoop.hive.metastore.minihms.AbstractMetaStoreService;
+import org.apache.thrift.protocol.TProtocolException;
+import org.apache.thrift.transport.TTransportException;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * Test class for IMetaStoreClient API. Testing the Table related functions for metadata
+ * manipulation, like creating, dropping and altering tables.
+ */
+@RunWith(Parameterized.class)
+public class TestTablesCreateDropAlterTruncate {
+ // Needed until there is no junit release with @BeforeParam, @AfterParam (junit 4.13)
+ // https://github.com/junit-team/junit4/commit/1bf8438b65858565dbb64736bfe13aae9cfc1b5a
+ // Then we should remove our own copy
+ private static Set<AbstractMetaStoreService> metaStoreServices = null;
+ private static final String DEFAULT_DATABASE = "default";
+ private static final String OTHER_DATABASE = "dummy";
+ private final AbstractMetaStoreService metaStore;
+ private IMetaStoreClient client;
+ private Table[] testTables = new Table[6];
+ private Table partitionedTable = null;
+ private Table externalTable = null;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static List<Object[]> getMetaStoreToTest() throws Exception {
+ List<Object[]> result = MetaStoreFactoryForTests.getMetaStores();
+ metaStoreServices = result.stream()
+ .map(test -> (AbstractMetaStoreService)test[1])
+ .collect(Collectors.toSet());
+ return result;
+ }
+
+ public TestTablesCreateDropAlterTruncate(String name, AbstractMetaStoreService metaStore) throws Exception {
+ this.metaStore = metaStore;
+ Map<MetastoreConf.ConfVars, String> msConf = new HashMap<MetastoreConf.ConfVars, String>();
+ // Enable trash, so it can be tested
+ Map<String, String> extraConf = new HashMap<String, String>();
+ extraConf.put("fs.trash.checkpoint.interval", "30"); // FS_TRASH_CHECKPOINT_INTERVAL_KEY
+ extraConf.put("fs.trash.interval", "30"); // FS_TRASH_INTERVAL_KEY (hadoop-2)
+
+ this.metaStore.start(msConf, extraConf);
+ }
+
+ // Needed until there is no junit release with @BeforeParam, @AfterParam (junit 4.13)
+ // https://github.com/junit-team/junit4/commit/1bf8438b65858565dbb64736bfe13aae9cfc1b5a
+ // Then we should move this to @AfterParam
+ @AfterClass
+ public static void stopMetaStores() throws Exception {
+ for(AbstractMetaStoreService metaStoreService : metaStoreServices) {
+ metaStoreService.stop();
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ // Get new client
+ client = metaStore.getClient();
+
+ // Clean up the database
+ client.dropDatabase(OTHER_DATABASE, true, true, true);
+ // Drop every table in the default database
+ for(String tableName : client.getAllTables(DEFAULT_DATABASE)) {
+ client.dropTable(DEFAULT_DATABASE, tableName, true, true, true);
+ }
+
+ // Clean up trash
+ metaStore.cleanWarehouseDirs();
+
+ testTables[0] =
+ new TableBuilder()
+ .setDbName(DEFAULT_DATABASE)
+ .setTableName("test_table")
+ .addCol("test_col", "int")
+ .build();
+
+ testTables[1] =
+ new TableBuilder()
+ .setDbName(DEFAULT_DATABASE)
+ .setTableName("test_view")
+ .addCol("test_col", "int")
+ .setType("VIRTUAL_VIEW")
+ .build();
+
+ testTables[2] =
+ new TableBuilder()
+ .setDbName(DEFAULT_DATABASE)
+ .setTableName("test_table_to_find_1")
+ .addCol("test_col", "int")
+ .build();
+
+ testTables[3] =
+ new TableBuilder()
+ .setDbName(DEFAULT_DATABASE)
+ .setTableName("test_partitioned_table")
+ .addCol("test_col1", "int")
+ .addCol("test_col2", "int")
+ .addPartCol("test_part_col", "int")
+ .build();
+
+ testTables[4] =
+ new TableBuilder()
+ .setDbName(DEFAULT_DATABASE)
+ .setTableName("external_table_for_test")
+ .addCol("test_col", "int")
+ .setLocation(metaStore.getWarehouseRoot() + "/external/table_dir")
+ .addTableParam("EXTERNAL", "TRUE")
+ .setType("EXTERNAL_TABLE")
+ .build();
+
+
+ client.createDatabase(new DatabaseBuilder().setName(OTHER_DATABASE).build());
+
+ testTables[5] =
+ new TableBuilder()
+ .setDbName(OTHER_DATABASE)
+ .setTableName("test_table")
+ .addCol("test_col", "int")
+ .build();
+
+ // Create the tables in the MetaStore
+ for(int i=0; i < testTables.length; i++) {
+ client.createTable(testTables[i]);
+ }
+
+ // Create partitions for the partitioned table
+ for(int i=0; i < 3; i++) {
+ Partition partition =
+ new PartitionBuilder()
+ .fromTable(testTables[3])
+ .addValue("a" + i)
+ .build();
+ client.add_partition(partition);
+ }
+ // Add data files to the partitioned table
+ List<Partition> partitions =
+ client.listPartitions(testTables[3].getDbName(), testTables[3].getTableName(), (short)-1);
+ for(Partition partition : partitions) {
+ Path dataFile = new Path(partition.getSd().getLocation().toString() + "/dataFile");
+ metaStore.createFile(dataFile, "100");
+ }
+
+ // Reload tables from the MetaStore, and create data files
+ for(int i=0; i < testTables.length; i++) {
+ testTables[i] = client.getTable(testTables[i].getDbName(), testTables[i].getTableName());
+ if (testTables[i].getPartitionKeys().isEmpty()) {
+ if (testTables[i].getSd().getLocation() != null) {
+ Path dataFile = new Path(testTables[i].getSd().getLocation().toString() + "/dataFile");
+ metaStore.createFile(dataFile, "100");
+ }
+ }
+ }
+ partitionedTable = testTables[3];
+ externalTable = testTables[4];
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ try {
+ if (client != null) {
+ client.close();
+ }
+ } finally {
+ client = null;
+ }
+ }
+
+ /**
+ * This test creates and queries a table and then drops it. Good for testing the happy path
+ * @throws Exception
+ */
+ @Test
+ public void testCreateGetDeleteTable() throws Exception {
+ // Try to create a table with all of the parameters set
+ Table table = getTableWithAllParametersSet();
+ client.createTable(table);
+ Table createdTable = client.getTable(table.getDbName(), table.getTableName());
+ // The createTime will be set on the server side, so the comparison should skip it
+ table.setCreateTime(createdTable.getCreateTime());
+ // The extra parameters will be added on server side, so check that the required ones are
+ // present
+ for(String key: table.getParameters().keySet()) {
+ Assert.assertEquals("parameters are the same",
+ table.getParameters().get(key), createdTable.getParameters().get(key));
+ }
+ // Reset the parameters, so we can compare
+ table.setParameters(createdTable.getParameters());
+ table.setCreationMetadata(createdTable.getCreationMetadata());
+ Assert.assertEquals("create/get table data", table, createdTable);
+
+ // Check that the directory is created
+ Assert.assertTrue("The directory should not be created",
+ metaStore.isPathExists(new Path(createdTable.getSd().getLocation())));
+
+ client.dropTable(table.getDbName(), table.getTableName(), true, false);
+ try {
+ client.getTable(table.getDbName(), table.getTableName());
+ Assert.fail("Expected a NoSuchObjectException to be thrown");
+ } catch (NoSuchObjectException exception) {
+ // Expected exception
+ }
+ }
+
+ @Test
+ public void testCreateTableDefaultValues() throws Exception {
+ Table table = new Table();
+ StorageDescriptor sd = new StorageDescriptor();
+ List<FieldSchema> cols = new ArrayList<FieldSchema>();
+
+ table.setDbName(DEFAULT_DATABASE);
+ table.setTableName("test_table_2");
+ cols.add(new FieldSchema("column_name", "int", null));
+ sd.setCols(cols);
+ sd.setSerdeInfo(new SerDeInfo());
+ table.setSd(sd);
+
+ client.createTable(table);
+ Table createdTable = client.getTable(table.getDbName(), table.getTableName());
+
+ Assert.assertNull("Comparing OwnerName", createdTable.getOwner());
+ Assert.assertNotEquals("Comparing CreateTime", 0, createdTable.getCreateTime());
+ Assert.assertEquals("Comparing LastAccessTime", 0, createdTable.getLastAccessTime());
+ Assert.assertEquals("Comparing Retention", 0, createdTable.getRetention());
+ Assert.assertEquals("Comparing PartitionKeys", 0, createdTable.getPartitionKeys().size());
+ // TODO: If this test method is the first to run, then the parameters does not contain totalSize
+ // and numFiles, if this runs after other tests (setUp/dropDatabase is successful), then the
+ // totalSize and the numFiles are set.
+ Assert.assertEquals("Comparing Parameters length", 1, createdTable.getParameters().size());
+ Assert.assertNotEquals("Comparing Parameters(transient_lastDdlTime)", "0",
+ createdTable.getParameters().get("transient_lastDdlTime"));
+// Assert.assertEquals("Comparing Parameters(totalSize)", "0",
+// createdTable.getParameters().get("totalSize"));
+// Assert.assertEquals("Comparing Parameters(numFiles)", "0",
+// createdTable.getParameters().get("numFiles"));
+ Assert.assertNull("Comparing ViewOriginalText", createdTable.getViewOriginalText());
+ Assert.assertNull("Comparing ViewExpandedText", createdTable.getViewExpandedText());
+ Assert.assertEquals("Comparing TableType", "MANAGED_TABLE", createdTable.getTableType());
+ Assert.assertTrue("Creation metadata should be empty", createdTable.getCreationMetadata().isEmpty());
+
+ // Storage Descriptor data
+ StorageDescriptor createdSd = createdTable.getSd();
+ Assert.assertEquals("Storage descriptor cols", 1, createdSd.getCols().size());
+ Assert.assertNull("Storage descriptor cols[0].comment",
+ createdSd.getCols().get(0).getComment());
+ Assert.assertEquals("Storage descriptor location", metaStore.getWarehouseRoot()
+ + "/" + table.getTableName(), createdSd.getLocation());
+ Assert.assertTrue("Table path should be created",
+ metaStore.isPathExists(new Path(createdSd.getLocation())));
+ // TODO: Embedded MetaStore changes the table object when client.createTable is called
+ //Assert.assertNull("Original table storage descriptor location should be null",
+ // table.getSd().getLocation());
+
+ Assert.assertNull("Storage descriptor input format", createdSd.getInputFormat());
+ Assert.assertNull("Storage descriptor output format", createdSd.getOutputFormat());
+ Assert.assertFalse("Storage descriptor compressed", createdSd.isCompressed());
+ Assert.assertEquals("Storage descriptor num buckets", 0, createdSd.getNumBuckets());
+ Assert.assertEquals("Storage descriptor bucket cols", 0, createdSd.getBucketCols().size());
+ Assert.assertEquals("Storage descriptor sort cols", 0, createdSd.getSortCols().size());
+ Assert.assertEquals("Storage descriptor parameters", 0, createdSd.getParameters().size());
+ Assert.assertFalse("Storage descriptor stored as subdir", createdSd.isStoredAsSubDirectories());
+
+ // Serde info
+ SerDeInfo serDeInfo = createdSd.getSerdeInfo();
+ Assert.assertNull("SerDeInfo name", serDeInfo.getName());
+ Assert.assertNull("SerDeInfo serialization lib", serDeInfo.getSerializationLib());
+ Assert.assertEquals("SerDeInfo parameters", 0, serDeInfo.getParameters().size());
+
+ // Skewed info
+ SkewedInfo skewedInfo = createdSd.getSkewedInfo();
+ Assert.assertEquals("Skewed info col names", 0, skewedInfo.getSkewedColNames().size());
+ Assert.assertEquals("Skewed info col values", 0, skewedInfo.getSkewedColValues().size());
+ Assert.assertEquals("Skewed info col value maps", 0,
+ skewedInfo.getSkewedColValueLocationMaps().size());
+ }
+
+ @Test
+ public void testCreateTableDefaultLocationInSpecificDatabase() throws Exception {
+ Table table = new Table();
+ StorageDescriptor sd = new StorageDescriptor();
+ List<FieldSchema> cols = new ArrayList<FieldSchema>();
+
+ table.setDbName(OTHER_DATABASE);
+ table.setTableName("test_table_2");
+ cols.add(new FieldSchema("column_name", "int", null));
+ sd.setCols(cols);
+ sd.setSerdeInfo(new SerDeInfo());
+ table.setSd(sd);
+
+ client.createTable(table);
+ Table createdTable = client.getTable(table.getDbName(), table.getTableName());
+ Assert.assertEquals("Storage descriptor location", metaStore.getWarehouseRoot()
+ + "/" + table.getDbName() + ".db/" + table.getTableName(),
+ createdTable.getSd().getLocation());
+ }
+
+ @Test
+ public void testCreateTableDefaultValuesView() throws Exception {
+ Table table = new Table();
+ StorageDescriptor sd = new StorageDescriptor();
+ List<FieldSchema> cols = new ArrayList<FieldSchema>();
+
+ table.setDbName(DEFAULT_DATABASE);
+ table.setTableName("test_table_2");
+ table.setTableType("VIRTUAL_VIEW");
+ cols.add(new FieldSchema("column_name", "int", null));
+ sd.setCols(cols);
+ sd.setSerdeInfo(new SerDeInfo());
+ table.setSd(sd);
+
+ client.createTable(table);
+ Table createdTable = client.getTable(table.getDbName(), table.getTableName());
+
+ // No location should be created for views
+ StorageDescriptor createdSd = createdTable.getSd();
+ Assert.assertNull("Storage descriptor location should be null",
+ createdTable.getSd().getLocation());
+ }
+
+ @Test(expected = MetaException.class)
+ public void testCreateTableNullDatabase() throws Exception {
+ Table table = testTables[0];
+ table.setDbName(null);
+
+ client.createTable(table);
+ }
+
+ @Test(expected = MetaException.class)
+ public void testCreateTableNullTableName() throws Exception {
+ Table table = testTables[0];
+ table.setTableName(null);
+
+ client.createTable(table);
+ }
+
+ @Test(expected = InvalidObjectException.class)
+ public void testCreateTableInvalidTableName() throws Exception {
+ Table table = testTables[0];
+ table.setTableName("test_table;");
+
+ client.createTable(table);
+ }
+
+ @Test(expected = InvalidObjectException.class)
+ public void testCreateTableEmptyName() throws Exception {
+ Table table = testTables[0];
+ table.setTableName("");
+
+ client.createTable(table);
+ }
+
+ @Test(expected = MetaException.class)
+ public void testCreateTableNullStorageDescriptor() throws Exception {
+ Table table = testTables[0];
+ table.setSd(null);
+
+ client.createTable(table);
+ }
+
+ private Table getNewTable() throws MetaException {
+ return new TableBuilder()
+ .setDbName(DEFAULT_DATABASE)
+ .setTableName("test_table_with_invalid_sd")
+ .addCol("test_col", "int")
+ .build();
+ }
+
+ @Test(expected = MetaException.class)
+ public void testCreateTableInvalidStorageDescriptorNullColumns() throws Exception {
+ Table table = getNewTable();
+ table.getSd().setCols(null);
+ client.createTable(table);
+ }
+
+ @Test(expected = MetaException.class)
+ public void testCreateTableInvalidStorageDescriptorNullSerdeInfo() throws Exception {
+ Table table = getNewTable();
+ table.getSd().setSerdeInfo(null);
+
+ client.createTable(table);
+ }
+
+ @Test(expected = MetaException.class)
+ public void testCreateTableInvalidStorageDescriptorNullColumnType() throws Exception {
+ Table table = getNewTable();
+ table.getSd().getCols().get(0).setType(null);
+
+ client.createTable(table);
+ }
+
+ @Test(expected = InvalidObjectException.class)
+ public void testCreateTableInvalidStorageDescriptorInvalidColumnType() throws Exception {
+ Table table = getNewTable();
+ table.getSd().getCols().get(0).setType("xyz");
+
+ client.createTable(table);
+ }
+
+ @Test(expected = InvalidObjectException.class)
+ public void testCreateTableNoSuchDatabase() throws Exception {
+ Table table = testTables[0];
+ table.setDbName("no_such_database");
+
+ client.createTable(table);
+ }
+
+ @Test(expected = AlreadyExistsException.class)
+ public void testCreateTableAlreadyExists() throws Exception {
+ Table table = testTables[0];
+
+ client.createTable(table);
+ }
+
+ @Test(expected = NoSuchObjectException.class)
+ public void testDropTableNoSuchDatabase() throws Exception {
+ Table table = testTables[2];
+
+ client.dropTable("no_such_database", table.getTableName(), true, false);
+ }
+
+ @Test(expected = NoSuchObjectException.class)
+ public void testDropTableNoSuchTable() throws Exception {
+ Table table = testTables[2];
+
+ client.dropTable(table.getDbName(), "no_such_table", true, false);
+ }
+
+ @Test(expected = NoSuchObjectException.class)
+ public void testDropTableNoSuchTableInTheDatabase() throws Exception {
+ Table table = testTables[2];
+
+ client.dropTable(OTHER_DATABASE, table.getTableName(), true, false);
+ }
+
+ @Test
+ public void testDropTableNullDatabase() throws Exception {
+ // Missing database in the query
+ try {
+ client.dropTable(null, OTHER_DATABASE, true, false);
+ // TODO: Should be checked on server side. On Embedded metastore it throws MetaException,
+ // on Remote metastore it throws TProtocolException
+ Assert.fail("Expected an MetaException or TProtocolException to be thrown");
+ } catch (MetaException exception) {
+ // Expected exception - Embedded MetaStore
+ } catch (TProtocolException exception) {
+ // Expected exception - Remote MetaStore
+ }
+ }
+
+ @Test
+ public void testDropTableNullTableName() throws Exception {
+ try {
+ client.dropTable(DEFAULT_DATABASE, null, true, false);
+ // TODO: Should be checked on server side. On Embedded metastore it throws MetaException,
+ // on Remote metastore it throws TProtocolException
+ Assert.fail("Expected an MetaException or TProtocolException to be thrown");
+ } catch (MetaException exception) {
+ // Expected exception - Embedded MetaStore
+ } catch (TProtocolException exception) {
+ // Expected exception - Remote MetaStore
+ }
+ }
+
+ @Test
+ public void testDropTableCaseInsensitive() throws Exception {
+ Table table = testTables[0];
+
+ // Test in upper case
+ client.dropTable(table.getDbName().toUpperCase(), table.getTableName().toUpperCase());
+ try {
+ client.getTable(table.getDbName(), table.getTableName());
+ Assert.fail("Expected a NoSuchObjectException to be thrown");
+ } catch (NoSuchObjectException exception) {
+ // Expected exception
+ }
+
+ // Test in mixed case
+ client.createTable(table);
+ client.dropTable("DeFaUlt", "TeST_tAbLE");
+ try {
+ client.getTable(table.getDbName(), table.getTableName());
+ Assert.fail("Expected a NoSuchObjectException to be thrown");
+ } catch (NoSuchObjectException exception) {
+ // Expected exception
+ }
+ }
+
+ @Test
+ public void testDropTableDeleteDir() throws Exception {
+ Table table = testTables[0];
+
+ client.dropTable(table.getDbName(), table.getTableName(), true, false);
+
+ Assert.assertFalse("Table path should be removed",
+ metaStore.isPathExists(new Path(table.getSd().getLocation())));
+
+ client.createTable(table);
+ client.dropTable(table.getDbName(), table.getTableName(), false, false);
+
+ Assert.assertTrue("Table path should be kept",
+ metaStore.isPathExists(new Path(table.getSd().getLocation())));
+
+ // Drop table with partitions
+ client.dropTable(partitionedTable.getDbName(), partitionedTable.getTableName(), true, false);
+
+ Assert.assertFalse("Table path should be removed",
+ metaStore.isPathExists(new Path(partitionedTable.getSd().getLocation())));
+ }
+
+ @Test
+ public void testDropTableIgnoreUnknown() throws Exception {
+ Table table = testTables[0];
+
+ // Check what happens, when we ignore these errors
+ client.dropTable("no_such_database", table.getTableName(), true, true);
+ client.dropTable(table.getDbName(), "no_such_table", false, true);
+ client.dropTable(OTHER_DATABASE, table.getTableName(), true, true);
+
+ // TODO: Strangely the default parametrization is to ignore missing tables
+ client.dropTable("no_such_database", table.getTableName());
+ client.dropTable(table.getDbName(), "no_such_table");
+ client.dropTable(OTHER_DATABASE, table.getTableName());
+ }
+
+ @Test
+ public void testDropTableWithPurge() throws Exception {
+ Table table = testTables[0];
+
+ client.dropTable(table.getDbName(), table.getTableName(), true, true, true);
+
+ Assert.assertFalse("Table path should be removed",
+ metaStore.isPathExists(new Path(table.getSd().getLocation())));
+ Assert.assertFalse("Table path should not be in trash",
+ metaStore.isPathExistsInTrash(new Path(table.getSd().getLocation())));
+ }
+
+ @Test
+ public void testDropTableWithoutPurge() throws Exception {
+ Table table = testTables[0];
+
+ client.dropTable(table.getDbName(), table.getTableName(), true, true, false);
+
+ Assert.assertFalse("Table path should be removed",
+ metaStore.isPathExists(new Path(table.getSd().getLocation())));
+ Assert.assertTrue("Table path should be in trash",
+ metaStore.isPathExistsInTrash(new Path(table.getSd().getLocation())));
+ }
+
+ @Test
+ public void testDropTableExternalWithPurge() throws Exception {
+ Table table = externalTable;
+
+ client.dropTable(table.getDbName(), table.getTableName(), true, true, true);
+
+ Assert.assertTrue("Table path should not be removed",
+ metaStore.isPathExists(new Path(table.getSd().getLocation())));
+ Assert.assertFalse("Table path should not be in trash",
+ metaStore.isPathExistsInTrash(new Path(table.getSd().getLocation())));
+ }
+
+ @Test
+ public void testDropTableExternalWithoutPurge() throws Exception {
+ Table table = externalTable;
+
+ client.dropTable(table.getDbName(), table.getTableName(), true, true, false);
+
+ Assert.assertTrue("Table path should not be removed",
+ metaStore.isPathExists(new Path(table.getSd().getLocation())));
+ Assert.assertFalse("Table path should be in trash",
+ metaStore.isPathExistsInTrash(new Path(table.getSd().getLocation())));
+ }
+
+ @Test
+ public void testTruncateTableUnpartitioned() throws Exception {
+ // Unpartitioned table
+ Path dataFile = new Path(testTables[0].getSd().getLocation().toString() + "/dataFile");
+ client.truncateTable(testTables[0].getDbName(), testTables[0].getTableName(), null);
+ Assert.assertTrue("Location should exist",
+ metaStore.isPathExists(new Path(testTables[0].getSd().getLocation())));
+ Assert.assertFalse("DataFile should be removed", metaStore.isPathExists(dataFile));
+
+ }
+
+ @Test
+ public void testTruncateTablePartitioned() throws Exception {
+ // Partitioned table - delete specific partitions a0, a2
+ List<String> partitionsToDelete = new ArrayList<String>();
+ partitionsToDelete.add("test_part_col=a0");
+ partitionsToDelete.add("test_part_col=a2");
+ client.truncateTable(partitionedTable.getDbName(), partitionedTable.getTableName(),
+ partitionsToDelete);
+ Assert.assertTrue("Location should exist",
+ metaStore.isPathExists(new Path(testTables[0].getSd().getLocation())));
+ List<Partition> partitions =
+ client.listPartitions(partitionedTable.getDbName(), partitionedTable.getTableName(),
+ (short)-1);
+ for(Partition partition : partitions) {
+ Path dataFile = new Path(partition.getSd().getLocation().toString() + "/dataFile");
+ if (partition.getValues().contains("a0") || partition.getValues().contains("a2")) {
+ // a0, a2 should be empty
+ Assert.assertFalse("DataFile should be removed", metaStore.isPathExists(dataFile));
+ } else {
+ // Others (a1) should be kept
+ Assert.assertTrue("DataFile should not be removed", metaStore.isPathExists(dataFile));
+ }
+ }
+
+ }
+
+ @Test
+ public void testTruncateTablePartitionedDeleteAll() throws Exception {
+ // Partitioned table - delete all
+ client.truncateTable(partitionedTable.getDbName(), partitionedTable.getTableName(), null);
+ Assert.assertTrue("Location should exist",
+ metaStore.isPathExists(new Path(testTables[0].getSd().getLocation())));
+ List<Partition> partitions =
+ client.listPartitions(partitionedTable.getDbName(), partitionedTable.getTableName(),
+ (short)-1);
+ for(Partition partition : partitions) {
+ Path dataFile = new Path(partition.getSd().getLocation().toString() + "/dataFile");
+ Assert.assertFalse("Every dataFile should be removed", metaStore.isPathExists(dataFile));
+ }
+ }
+
+ @Test
+ public void testAlterTable() throws Exception {
+ Table originalTable = testTables[2];
+ String originalTableName = originalTable.getTableName();
+ String originalDatabase = originalTable.getDbName();
+
+ Table newTable = getTableWithAllParametersSet();
+ newTable.setTableName(originalTableName);
+ newTable.setDbName(originalDatabase);
+ // Partition keys can not be set, but getTableWithAllParametersSet is added one, so remove for
+ // this test
+ newTable.setPartitionKeys(originalTable.getPartitionKeys());
+ client.alter_table(originalDatabase, originalTableName, newTable);
+ Table alteredTable = client.getTable(originalDatabase, originalTableName);
+
+ // The extra parameters will be added on server side, so check that the required ones are
+ // present
+ for(String key: newTable.getParameters().keySet()) {
+ Assert.assertEquals("parameters are present", newTable.getParameters().get(key),
+ alteredTable.getParameters().get(key));
+ }
+ // The parameters are checked manually, so do not check them
+ newTable.setParameters(alteredTable.getParameters());
+
+ // Some of the data is set on the server side, so reset those
+ newTable.setCreateTime(alteredTable.getCreateTime());
+ newTable.setCreationMetadata(alteredTable.getCreationMetadata());
+ Assert.assertEquals("The table data should be the same", newTable, alteredTable);
+ }
+
+ @Test
+ public void testAlterTableRename() throws Exception {
+ Table originalTable = testTables[2];
+ String originalTableName = originalTable.getTableName();
+ String originalDatabase = originalTable.getDbName();
+
+ Table newTable = originalTable.deepCopy();
+ // Do not change the location, so it is tested that the location will be changed even if the
+ // location is not set to null, just remain the same
+ newTable.setTableName("new_table");
+ client.alter_table(originalDatabase, originalTableName, newTable);
+ List<String> tableNames = client.getTables(originalDatabase, originalTableName);
+ Assert.assertEquals("Original table should be removed", 0, tableNames.size());
+ Assert.assertFalse("Original table directory should be removed",
+ metaStore.isPathExists(new Path(originalTable.getSd().getLocation())));
+ Table alteredTable = client.getTable(newTable.getDbName(), newTable.getTableName());
+ Assert.assertTrue("New table directory should exist",
+ metaStore.isPathExists(new Path(alteredTable.getSd().getLocation())));
+ Assert.assertEquals("New directory should be set", new Path(metaStore.getWarehouseRoot()
+ + "/" + alteredTable.getTableName()), new Path(alteredTable.getSd().getLocation()));
+
+ Path dataFile = new Path(alteredTable.getSd().getLocation().toString() + "/dataFile");
+ Assert.assertTrue("New directory should contain data", metaStore.isPathExists(dataFile));
+
+ // The following data should be changed
+ newTable.getSd().setLocation(alteredTable.getSd().getLocation());
+ Assert.assertEquals("The table data should be the same", newTable, alteredTable);
+ }
+
+ @Test
+ public void testAlterTableChangingDatabase() throws Exception {
+ Table originalTable = testTables[2];
+ String originalTableName = originalTable.getTableName();
+ String originalDatabase = originalTable.getDbName();
+
+ Table newTable = originalTable.deepCopy();
+ newTable.setDbName(OTHER_DATABASE);
+ client.alter_table(originalDatabase, originalTableName, newTable);
+ List<String> tableNames = client.getTables(originalDatabase, originalTableName);
+ Assert.assertEquals("Original table should be removed", 0, tableNames.size());
+ Assert.assertFalse("Original table directory should be removed",
+ metaStore.isPathExists(new Path(originalTable.getSd().getLocation())));
+ Table alteredTable = client.getTable(newTable.getDbName(), newTable.getTableName());
+ Assert.assertTrue("New table directory should exist",
+ metaStore.isPathExists(new Path(alteredTable.getSd().getLocation())));
+ Assert.assertEquals("New directory should be set", new Path(metaStore.getWarehouseRoot()
+ + "/" + alteredTable.getDbName() + ".db/" + alteredTable.getTableName()),
+ new Path(alteredTable.getSd().getLocation()));
+ Path dataFile = new Path(alteredTable.getSd().getLocation().toString() + "/dataFile");
+ Assert.assertTrue("New directory should contain data", metaStore.isPathExists(dataFile));
+
+ // The following data should be changed, other data should be the same
+ newTable.getSd().setLocation(alteredTable.getSd().getLocation());
+ Assert.assertEquals("The table data should be the same", newTable, alteredTable);
+ }
+
+ @Test
+ public void testAlterTableExternalTable() throws Exception {
+ Table originalTable = externalTable;
+ String originalTableName = originalTable.getTableName();
+ String originalDatabase = originalTable.getDbName();
+
+ Table newTable = originalTable.deepCopy();
+ newTable.setTableName("new_external_table_for_test");
+ client.alter_table(originalDatabase, originalTableName, newTable);
+ List<String> tableNames = client.getTables(originalDatabase, originalTableName);
+ Assert.assertEquals("Original table should be removed", 0, tableNames.size());
+ Assert.assertTrue("Original table directory should be kept",
+ metaStore.isPathExists(new Path(originalTable.getSd().getLocation())));
+ Table alteredTable = client.getTable(newTable.getDbName(), newTable.getTableName());
+ Assert.assertEquals("New location should be the same", originalTable.getSd().getLocation(),
+ alteredTable.getSd().getLocation());
+ Path dataFile = new Path(alteredTable.getSd().getLocation().toString() + "/dataFile");
+ Assert.assertTrue("The location should contain data", metaStore.isPathExists(dataFile));
+
+ // The extra parameters will be added on server side, so check that the required ones are
+ // present
+ for(String key: newTable.getParameters().keySet()) {
+ Assert.assertEquals("parameters are present", newTable.getParameters().get(key),
+ alteredTable.getParameters().get(key));
+ }
+ // The parameters are checked manually, so do not check them
+ newTable.setParameters(alteredTable.getParameters());
+ Assert.assertEquals("The table data should be the same", newTable, alteredTable);
+ }
+
+ @Test
+ public void testAlterTableExternalTableChangeLocation() throws Exception {
+ Table originalTable = externalTable;
+
+ // Change the location, and see the results
+ Table newTable = originalTable.deepCopy();
+ newTable.getSd().setLocation(newTable.getSd().getLocation() + "_modified");
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable);
+ Table alteredTable = client.getTable(newTable.getDbName(), newTable.getTableName());
+ Assert.assertTrue("Original table directory should be kept",
+ metaStore.isPathExists(new Path(originalTable.getSd().getLocation())));
+ Assert.assertEquals("New location should be the new one", newTable.getSd().getLocation(),
+ alteredTable.getSd().getLocation());
+ Path dataFile = new Path(alteredTable.getSd().getLocation().toString() + "/dataFile");
+ Assert.assertFalse("The location should not contain data", metaStore.isPathExists(dataFile));
+
+ // The extra parameters will be added on server side, so check that the required ones are
+ // present
+ for(String key: newTable.getParameters().keySet()) {
+ Assert.assertEquals("parameters are present", newTable.getParameters().get(key),
+ alteredTable.getParameters().get(key));
+ }
+ // The parameters are checked manually, so do not check them
+ newTable.setParameters(alteredTable.getParameters());
+
+ // The following data should be changed, other data should be the same
+ newTable.getSd().setLocation(alteredTable.getSd().getLocation());
+ Assert.assertEquals("The table data should be the same", newTable, alteredTable);
+ }
+
+ @Test
+ public void testAlterTableChangeCols() throws Exception {
+ Table originalTable = partitionedTable;
+
+ Table newTable = originalTable.deepCopy();
+
+ List<FieldSchema> cols = newTable.getSd().getCols();
+ // Change a column
+ cols.get(0).setName("modified_col");
+ // Remove a column
+ cols.remove(1);
+ // Add a new column
+ cols.add(new FieldSchema("new_col", "int", null));
+ // Store the changes
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable);
+ Table alteredTable = client.getTable(newTable.getDbName(), newTable.getTableName());
+ Assert.assertTrue("Original table directory should be kept",
+ metaStore.isPathExists(new Path(originalTable.getSd().getLocation())));
+
+ // The following data might be changed
+ alteredTable.setParameters(newTable.getParameters());
+ Assert.assertEquals("The table data should be the same", newTable, alteredTable);
+
+ // Modify partition column type, and comment
+ newTable.getPartitionKeys().get(0).setType("string");
+ newTable.getPartitionKeys().get(0).setComment("changed comment");
+
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable);
+ alteredTable = client.getTable(newTable.getDbName(), newTable.getTableName());
+ // The following data might be changed
+ alteredTable.setParameters(newTable.getParameters());
+ Assert.assertEquals("The table data should be the same", newTable, alteredTable);
+ }
+
+ @Test
+ public void testAlterTableCascade() throws Exception {
+ Table originalTable = partitionedTable;
+
+ Table newTable = originalTable.deepCopy();
+ List<FieldSchema> cols = newTable.getSd().getCols();
+ cols.add(new FieldSchema("new_col_1", "int", null));
+
+ // Run without cascade
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable, false);
+ Table alteredTable = client.getTable(newTable.getDbName(), newTable.getTableName());
+ Assert.assertEquals("The table data should be changed", newTable, alteredTable);
+
+ List<Partition> partitions =
+ client.listPartitions(originalTable.getDbName(), originalTable.getTableName(), (short)-1);
+ for(Partition partition : partitions) {
+ Assert.assertEquals("Partition columns should not be changed", 2,
+ partition.getSd().getCols().size());
+ }
+
+ // Run with cascade
+ cols.add(new FieldSchema("new_col_2", "int", null));
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable, true);
+ alteredTable = client.getTable(newTable.getDbName(), newTable.getTableName());
+ Assert.assertEquals("The table data should be changed", newTable, alteredTable);
+
+ partitions =
+ client.listPartitions(originalTable.getDbName(), originalTable.getTableName(), (short)-1);
+ for(Partition partition : partitions) {
+ Assert.assertEquals("Partition columns should be changed", 4,
+ partition.getSd().getCols().size());
+ }
+
+ // Run using environment context with cascade
+ cols.add(new FieldSchema("new_col_3", "int", null));
+ EnvironmentContext context = new EnvironmentContext();
+ context.putToProperties(StatsSetupConst.CASCADE, "true");
+ client.alter_table_with_environmentContext(originalTable.getDbName(),
+ originalTable.getTableName(), newTable, context);
+ alteredTable = client.getTable(newTable.getDbName(), newTable.getTableName());
+ Assert.assertEquals("The table data should be changed", newTable, alteredTable);
+
+ partitions =
+ client.listPartitions(originalTable.getDbName(), originalTable.getTableName(), (short)-1);
+ for(Partition partition : partitions) {
+ Assert.assertEquals("Partition columns should be changed", 5,
+ partition.getSd().getCols().size());
+ }
+ }
+
+ @Test(expected = MetaException.class)
+ public void testAlterTableNullDatabaseInNew() throws Exception {
+ Table originalTable = testTables[0];
+ Table newTable = originalTable.deepCopy();
+ newTable.setDbName(null);
+
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable);
+ }
+
+ @Test(expected = MetaException.class)
+ public void testAlterTableNullTableNameInNew() throws Exception {
+ Table originalTable = testTables[0];
+ Table newTable = originalTable.deepCopy();
+ newTable.setTableName(null);
+
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable);
+ }
+
+ @Test(expected = InvalidOperationException.class)
+ public void testAlterTableInvalidTableNameInNew() throws Exception {
+ Table originalTable = testTables[0];
+ Table newTable = originalTable.deepCopy();
+ newTable.setTableName("test_table;");
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable);
+ }
+
+ @Test(expected = InvalidOperationException.class)
+ public void testAlterTableEmptyTableNameInNew() throws Exception {
+ Table originalTable = testTables[0];
+ Table newTable = originalTable.deepCopy();
+ newTable.setTableName("");
+
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable);
+ }
+
+ @Test(expected = MetaException.class)
+ public void testAlterTableNullStorageDescriptorInNew() throws Exception {
+ Table originalTable = testTables[0];
+ Table newTable = originalTable.deepCopy();
+ newTable.setSd(null);
+
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable);
+ }
+
+ @Test(expected = MetaException.class)
+ public void testAlterTableNullDatabase() throws Exception {
+ Table originalTable = testTables[0];
+ Table newTable = originalTable.deepCopy();
+
+ client.alter_table(null, originalTable.getTableName(), newTable);
+ }
+
+ @Test(expected = MetaException.class)
+ public void testAlterTableNullTableName() throws Exception {
+ Table originalTable = testTables[0];
+ Table newTable = originalTable.deepCopy();
+
+ client.alter_table(originalTable.getDbName(), null, newTable);
+ }
+
+ @Test
+ public void testAlterTableNullNewTable() throws Exception {
+ Table originalTable = testTables[0];
+ try {
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), null);
+ // TODO: Should be checked on server side. On Embedded metastore it throws
+ // NullPointerException, on Remote metastore it throws TTransportException
+ Assert.fail("Expected a NullPointerException or TTransportException to be thrown");
+ } catch (NullPointerException exception) {
+ // Expected exception - Embedded MetaStore
+ } catch (TTransportException exception) {
+ // Expected exception - Remote MetaStore
+ }
+ }
+
+ @Test(expected = MetaException.class)
+ public void testAlterTableInvalidStorageDescriptorNullCols() throws Exception {
+ Table originalTable = testTables[0];
+ Table newTable = originalTable.deepCopy();
+ newTable.getSd().setCols(null);
+
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable);
+ }
+
+ @Test(expected = MetaException.class)
+ public void testAlterTableInvalidStorageDescriptorNullSerdeInfo() throws Exception {
+ Table originalTable = testTables[0];
+ Table newTable = originalTable.deepCopy();
+ newTable.getSd().setSerdeInfo(null);
+
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable);
+ }
+
+ @Test(expected = MetaException.class)
+ public void testAlterTableInvalidStorageDescriptorNullColumnType() throws Exception {
+ Table originalTable = testTables[0];
+ Table newTable = originalTable.deepCopy();
+ newTable.getSd().getCols().get(0).setType(null);
+
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable);
+ }
+
+ @Test(expected = MetaException.class)
+ public void testAlterTableInvalidStorageDescriptorNullLocation() throws Exception {
+ Table originalTable = testTables[0];
+ Table newTable = originalTable.deepCopy();
+ newTable.getSd().setLocation(null);
+
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable);
+ }
+
+ @Test(expected = InvalidOperationException.class)
+ public void testAlterTableInvalidStorageDescriptorInvalidColumnType() throws Exception {
+ Table originalTable = testTables[0];
+ Table newTable = originalTable.deepCopy();
+ newTable.getSd().getCols().get(0).setType("xyz");
+
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable);
+ }
+
+ @Test(expected = InvalidOperationException.class)
+ public void testAlterTableInvalidStorageDescriptorAddPartitionColumns() throws Exception {
+ Table originalTable = testTables[0];
+ Table newTable = originalTable.deepCopy();
+ newTable.addToPartitionKeys(new FieldSchema("new_part", "int", "comment"));
+
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable);
+ }
+
+ @Test(expected = InvalidOperationException.class)
+ public void testAlterTableInvalidStorageDescriptorAlterPartitionColumnName() throws Exception {
+ Table originalTable = partitionedTable;
+ Table newTable = originalTable.deepCopy();
+ newTable.getPartitionKeys().get(0).setName("altered_name");
+
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable);
+ }
+
+ @Test(expected = InvalidOperationException.class)
+ public void testAlterTableInvalidStorageDescriptorRemovePartitionColumn() throws Exception {
+ Table originalTable = partitionedTable;
+ Table newTable = originalTable.deepCopy();
+ newTable.getPartitionKeys().remove(0);
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable);
+ }
+
+ @Test(expected = InvalidOperationException.class)
+ public void testAlterTableNoSuchDatabase() throws Exception {
+ Table originalTable = testTables[2];
+ Table newTable = originalTable.deepCopy();
+
+ client.alter_table("no_such_database", originalTable.getTableName(), newTable);
+ }
+
+ @Test(expected = InvalidOperationException.class)
+ public void testAlterTableNoSuchTable() throws Exception {
+ Table originalTable = testTables[2];
+ Table newTable = originalTable.deepCopy();
+
+ client.alter_table(originalTable.getDbName(), "no_such_table_name", newTable);
+ }
+
+ @Test(expected = InvalidOperationException.class)
+ public void testAlterTableNoSuchTableInThisDatabase() throws Exception {
+ Table originalTable = testTables[2];
+ Table newTable = originalTable.deepCopy();
+
+ client.alter_table(OTHER_DATABASE, originalTable.getTableName(), newTable);
+ }
+
+ @Test
+ public void testAlterTableAlreadyExists() throws Exception {
+ Table originalTable = testTables[0];
+ Table newTable = originalTable.deepCopy();
+
+ newTable.setTableName(testTables[2].getTableName());
+ try {
+ // Already existing table
+ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable);
+ // TODO: Maybe throw AlreadyExistsException.
+ Assert.fail("Expected an InvalidOperationException to be thrown");
+ } catch (InvalidOperationException exception) {
+ // Expected exception
+ }
+ }
+
+ /**
+ * Creates a Table with all of the parameters set. The temporary table is available only on HS2
+ * server, so do not use it.
+ * @return The Table object
+ */
+ private Table getTableWithAllParametersSet() throws MetaException {
+ return new TableBuilder()
+ .setDbName(DEFAULT_DATABASE)
+ .setTableName("test_table_with_all_parameters_set")
+ .setCreateTime(100)
+ .setOwner("owner")
+ .setLastAccessTime(200)
+ .addPartCol("part_col", "int", "part col comment")
+ .addCol("test_col", "int", "test col comment")
+ .addCol("test_bucket_col", "int", "test bucket col comment")
+ .addCol("test_skewed_col", "int", "test skewed col comment")
+ .addCol("test_sort_col", "int", "test sort col comment")
+ .addBucketCol("test_bucket_col")
+ .addSkewedColName("test_skewed_col")
+ .addSortCol("test_sort_col", 1)
+ .setCompressed(true)
+ .setInputFormat("inputFormat")
+ .setInputFormat("outputFormat")
+ .setLocation(metaStore.getWarehouseRoot() + "/location")
+ .setNumBuckets(4)
+ .setRetention(30000)
+ .setRewriteEnabled(true)
+ .setType("VIEW")
+ .setViewExpandedText("viewExplainedText")
+ .setViewOriginalText("viewOriginalText")
+ .setSerdeLib("serdelib")
+ .setSerdeName("serdename")
+ .setStoredAsSubDirectories(true)
+ .addSerdeParam("serdeParam", "serdeParamValue")
+ .addTableParam("tableParam", "tableParamValue")
+ .addStorageDescriptorParam("sdParam", "sdParamValue")
+ .build();
+ }
+}