http://git-wip-us.apache.org/repos/asf/hive/blob/651e7950/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/client/TestTablesCreateDropAlterTruncate.java ---------------------------------------------------------------------- diff --cc standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/client/TestTablesCreateDropAlterTruncate.java index 0000000,816a735..bf302ed mode 000000,100644..100644 --- a/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/client/TestTablesCreateDropAlterTruncate.java +++ b/standalone-metastore/metastore-server/src/test/java/org/apache/hadoop/hive/metastore/client/TestTablesCreateDropAlterTruncate.java @@@ -1,0 -1,1385 +1,1400 @@@ + /* + * 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.ColumnType; + import org.apache.hadoop.hive.metastore.IMetaStoreClient; + import org.apache.hadoop.hive.metastore.MetaStoreTestUtils; + import org.apache.hadoop.hive.metastore.TableType; + import org.apache.hadoop.hive.metastore.annotation.MetastoreCheckinTest; + import org.apache.hadoop.hive.metastore.api.AlreadyExistsException; + import org.apache.hadoop.hive.metastore.api.Catalog; + import org.apache.hadoop.hive.metastore.api.CreationMetadata; + import org.apache.hadoop.hive.metastore.api.Database; + 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.PrincipalType; + 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.api.UnknownDBException; + import org.apache.hadoop.hive.metastore.client.builder.CatalogBuilder; + 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.TApplicationException; + import org.apache.thrift.TException; + import org.apache.thrift.protocol.TProtocolException; + import org.apache.thrift.transport.TTransportException; + import org.junit.After; + import org.junit.Assert; + import org.junit.Before; + import org.junit.BeforeClass; + import org.junit.Test; + import org.junit.experimental.categories.Category; + import org.junit.runner.RunWith; + import org.junit.runners.Parameterized; + + import java.io.File; + import java.net.URI; + import java.net.URISyntaxException; + import java.util.ArrayList; + import java.util.Arrays; + import java.util.Collections; + import java.util.HashMap; + import java.util.HashSet; + import java.util.List; + import java.util.Map; + import java.util.Set; + + import static org.apache.hadoop.hive.metastore.Warehouse.DEFAULT_CATALOG_NAME; + import static org.apache.hadoop.hive.metastore.Warehouse.DEFAULT_DATABASE_NAME; + + /** + * Test class for IMetaStoreClient API. Testing the Table related functions for metadata + * manipulation, like creating, dropping and altering tables. + */ + @RunWith(Parameterized.class) + @Category(MetastoreCheckinTest.class) + public class TestTablesCreateDropAlterTruncate extends MetaStoreClientTest { + 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; + + public TestTablesCreateDropAlterTruncate(String name, AbstractMetaStoreService metaStore) { + this.metaStore = metaStore; + } + + @BeforeClass + public static void startMetaStores() { + Map<MetastoreConf.ConfVars, String> msConf = new HashMap<MetastoreConf.ConfVars, String>(); + // Enable trash, so it can be tested + Map<String, String> extraConf = new HashMap<>(); + extraConf.put("fs.trash.checkpoint.interval", "30"); // FS_TRASH_CHECKPOINT_INTERVAL_KEY + extraConf.put("fs.trash.interval", "30"); // FS_TRASH_INTERVAL_KEY (hadoop-2) + startMetaStores(msConf, extraConf); + } + + @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() + .setTableName("test_table") + .addCol("test_col", "int") + .create(client, metaStore.getConf()); + + testTables[1] = + new TableBuilder() + .setTableName("test_view") + .addCol("test_col", "int") + .setType("VIRTUAL_VIEW") + .create(client, metaStore.getConf()); + + testTables[2] = + new TableBuilder() + .setTableName("test_table_to_find_1") + .addCol("test_col", "int") + .create(client, metaStore.getConf()); + + testTables[3] = + new TableBuilder() + .setTableName("test_partitioned_table") + .addCol("test_col1", "int") + .addCol("test_col2", "int") + .addPartCol("test_part_col", "int") + .create(client, metaStore.getConf()); + + testTables[4] = + new TableBuilder() + .setTableName("external_table_for_test") + .addCol("test_col", "int") + .setLocation(metaStore.getWarehouseRoot() + "/external/table_dir") + .addTableParam("EXTERNAL", "TRUE") + .setType("EXTERNAL_TABLE") + .create(client, metaStore.getConf()); + + + new DatabaseBuilder().setName(OTHER_DATABASE).create(client, metaStore.getConf()); + + testTables[5] = + new TableBuilder() + .setDbName(OTHER_DATABASE) + .setTableName("test_table") + .addCol("test_col", "int") + .create(client, metaStore.getConf()); + + // Create partitions for the partitioned table + for(int i=0; i < 2; i++) { + new PartitionBuilder() + .inTable(testTables[3]) + .addValue("a" + i) + .addToTable(client, metaStore.getConf()); + } + // Add an external partition too + new PartitionBuilder() + .inTable(testTables[3]) + .addValue("a2") + .setLocation(metaStore.getWarehouseRoot() + "/external/a2") + .addToTable(client, metaStore.getConf()); + + // 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() + "/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() + "/dataFile"); + metaStore.createFile(dataFile, "100"); + } + } + } + partitionedTable = testTables[3]; + externalTable = testTables[4]; + } + + @After + public void tearDown() throws Exception { + try { + if (client != null) { + try { + client.close(); + } catch (Exception e) { + // HIVE-19729: Shallow the exceptions based on the discussion in the Jira + } + } + } finally { + client = null; + } + } + + /** + * This test creates and queries a table and then drops it. Good for testing the happy path + */ + @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()); ++ table.setWriteId(createdTable.getWriteId()); + 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<>(); + + 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.assertEquals("Comparing OwnerType", PrincipalType.USER, createdTable.getOwnerType()); + 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() == null); + + // 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<>(); + + 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<>(); + + 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 + 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() + .setTableName("test_table_with_invalid_sd") + .addCol("test_col", "int") + .build(metaStore.getConf()); + } + + @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]; + Partition externalPartition = client.getPartition(partitionedTable.getDbName(), + partitionedTable.getTableName(), "test_part_col=a2"); + + 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()))); + + Assert.assertFalse("Extra partition path should be removed", + metaStore.isPathExists(new Path(externalPartition.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() + "/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<>(); + 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() + "/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() + "/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()); ++ newTable.setWriteId(alteredTable.getWriteId()); + 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() + "/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() + "/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() + "/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() + "/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); + } + + @SuppressWarnings("deprecation") + @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) ++ @Test + public void testAlterTableNullTableNameInNew() throws Exception { + Table originalTable = testTables[0]; + Table newTable = originalTable.deepCopy(); + newTable.setTableName(null); + - client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable); ++ try { ++ client.alter_table(originalTable.getDbName(), originalTable.getTableName(), newTable); ++ Assert.fail("Expected exception"); ++ } catch (MetaException | TProtocolException ex) { ++ // Expected. ++ } + } + + @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) ++ @Test + public void testAlterTableNullDatabase() throws Exception { + Table originalTable = testTables[0]; + Table newTable = originalTable.deepCopy(); - - client.alter_table(null, originalTable.getTableName(), newTable); ++ try { ++ client.alter_table(null, originalTable.getTableName(), newTable); ++ Assert.fail("Expected exception"); ++ } catch (MetaException | TProtocolException ex) { ++ } + } + - @Test(expected = MetaException.class) ++ @Test + public void testAlterTableNullTableName() throws Exception { + Table originalTable = testTables[0]; + Table newTable = originalTable.deepCopy(); + - client.alter_table(originalTable.getDbName(), null, newTable); ++ try { ++ client.alter_table(originalTable.getDbName(), null, newTable); ++ Assert.fail("Expected exception"); ++ } catch (MetaException | TProtocolException ex) { ++ // Expected. ++ } + } + + @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) { ++ } catch (TProtocolException 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 + } + } + + @Test + public void tablesInOtherCatalogs() throws TException, URISyntaxException { + String catName = "create_etc_tables_in_other_catalogs"; + Catalog cat = new CatalogBuilder() + .setName(catName) + .setLocation(MetaStoreTestUtils.getTestWarehouseDir(catName)) + .build(); + client.createCatalog(cat); + + String dbName = "db_in_other_catalog"; + // For this one don't specify a location to make sure it gets put in the catalog directory + Database db = new DatabaseBuilder() + .setName(dbName) + .setCatalogName(catName) + .create(client, metaStore.getConf()); + + String[] tableNames = new String[4]; + for (int i = 0; i < tableNames.length; i++) { + tableNames[i] = "table_in_other_catalog_" + i; + TableBuilder builder = new TableBuilder() + .inDb(db) + .setTableName(tableNames[i]) + .addCol("col1_" + i, ColumnType.STRING_TYPE_NAME) + .addCol("col2_" + i, ColumnType.INT_TYPE_NAME); + // Make one have a non-standard location + if (i == 0) builder.setLocation(MetaStoreTestUtils.getTestWarehouseDir(tableNames[i])); + // Make one partitioned + if (i == 2) builder.addPartCol("pcol1", ColumnType.STRING_TYPE_NAME); + // Make one a materialized view + if (i == 3) { + builder.setType(TableType.MATERIALIZED_VIEW.name()) + .setRewriteEnabled(true) + .addMaterializedViewReferencedTable(dbName + "." + tableNames[0]); + } + client.createTable(builder.build(metaStore.getConf())); + } + + // Add partitions for the partitioned table + String[] partVals = new String[3]; + Table partitionedTable = client.getTable(catName, dbName, tableNames[2]); + for (int i = 0; i < partVals.length; i++) { + partVals[i] = "part" + i; + new PartitionBuilder() + .inTable(partitionedTable) + .addValue(partVals[i]) + .addToTable(client, metaStore.getConf()); + } + + // Get tables, make sure the locations are correct + for (int i = 0; i < tableNames.length; i++) { + Table t = client.getTable(catName, dbName, tableNames[i]); + Assert.assertEquals(catName, t.getCatName()); + String expectedLocation = (i < 1) ? + new File(MetaStoreTestUtils.getTestWarehouseDir(tableNames[i])).toURI().toString() + : + new File(cat.getLocationUri() + File.separatorChar + dbName + ".db", + tableNames[i]).toURI().toString(); + + Assert.assertEquals(expectedLocation, t.getSd().getLocation() + "/"); + File dir = new File(new URI(t.getSd().getLocation()).getPath()); + Assert.assertTrue(dir.exists() && dir.isDirectory()); + + } + + // Make sure getting table in the wrong catalog does not work + try { + Table t = client.getTable(DEFAULT_DATABASE_NAME, tableNames[0]); + Assert.fail(); + } catch (NoSuchObjectException e) { + // NOP + } + + // test getAllTables + Set<String> fetchedNames = new HashSet<>(client.getAllTables(catName, dbName)); + Assert.assertEquals(tableNames.length, fetchedNames.size()); + for (String tableName : tableNames) Assert.assertTrue(fetchedNames.contains(tableName)); + + fetchedNames = new HashSet<>(client.getAllTables(DEFAULT_DATABASE_NAME)); + for (String tableName : tableNames) Assert.assertFalse(fetchedNames.contains(tableName)); + + // test getMaterializedViewsForRewriting + List<String> materializedViews = client.getMaterializedViewsForRewriting(catName, dbName); + Assert.assertEquals(1, materializedViews.size()); + Assert.assertEquals(tableNames[3], materializedViews.get(0)); + + fetchedNames = new HashSet<>(client.getMaterializedViewsForRewriting(DEFAULT_DATABASE_NAME)); + Assert.assertFalse(fetchedNames.contains(tableNames[3])); + + // test getTableObjectsByName + List<Table> fetchedTables = client.getTableObjectsByName(catName, dbName, + Arrays.asList(tableNames[0], tableNames[1])); + Assert.assertEquals(2, fetchedTables.size()); + Collections.sort(fetchedTables); + Assert.assertEquals(tableNames[0], fetchedTables.get(0).getTableName()); + Assert.assertEquals(tableNames[1], fetchedTables.get(1).getTableName()); + + fetchedTables = client.getTableObjectsByName(DEFAULT_DATABASE_NAME, + Arrays.asList(tableNames[0], tableNames[1])); + Assert.assertEquals(0, fetchedTables.size()); + + // Test altering the table + Table t = client.getTable(catName, dbName, tableNames[0]).deepCopy(); + t.getParameters().put("test", "test"); + client.alter_table(catName, dbName, tableNames[0], t); + t = client.getTable(catName, dbName, tableNames[0]).deepCopy(); + Assert.assertEquals("test", t.getParameters().get("test")); + + // Alter a table in the wrong catalog + try { + client.alter_table(DEFAULT_DATABASE_NAME, tableNames[0], t); + Assert.fail(); + } catch (InvalidOperationException e) { + // NOP + } + + // Update the metadata for the materialized view + CreationMetadata cm = client.getTable(catName, dbName, tableNames[3]).getCreationMetadata(); + cm.addToTablesUsed(dbName + "." + tableNames[1]); + cm.unsetMaterializationTime(); + client.updateCreationMetadata(catName, dbName, tableNames[3], cm); + + List<String> partNames = new ArrayList<>(); + for (String partVal : partVals) partNames.add("pcol1=" + partVal); + // Truncate a table + client.truncateTable(catName, dbName, tableNames[0], partNames); + + // Truncate a table in the wrong catalog + try { + client.truncateTable(DEFAULT_DATABASE_NAME, tableNames[0], partNames); + Assert.fail(); + } catch (NoSuchObjectException|TApplicationException e) { + // NOP + } + + // Drop a table from the wrong catalog + try { + client.dropTable(DEFAULT_DATABASE_NAME, tableNames[0], true, false); + Assert.fail(); + } catch (NoSuchObjectException|TApplicationException e) { + // NOP + } + + // Should ignore the failure + client.dropTable(DEFAULT_DATABASE_NAME, tableNames[0], false, true); + + // Have to do this in reverse order so that we drop the materialized view first. + for (int i = tableNames.length - 1; i >= 0; i--) { + t = client.getTable(catName, dbName, tableNames[i]); + File tableDir = new File(new URI(t.getSd().getLocation()).getPath()); + Assert.assertTrue(tableDir.exists() && tableDir.isDirectory()); + + if (tableNames[i].equalsIgnoreCase(tableNames[0])) { + client.dropTable(catName, dbName, tableNames[i], false, false); + Assert.assertTrue(tableDir.exists() && tableDir.isDirectory()); + } else { + client.dropTable(catName, dbName, tableNames[i]); + Assert.assertFalse(tableDir.exists()); + } + } + Assert.assertEquals(0, client.getAllTables(catName, dbName).size()); + } + + @Test(expected = InvalidObjectException.class) + public void createTableInBogusCatalog() throws TException { + new TableBuilder() + .setCatName("nosuch") + .setTableName("doomed") + .addCol("col1", ColumnType.STRING_TYPE_NAME) + .addCol("col2", ColumnType.INT_TYPE_NAME) + .create(client, metaStore.getConf()); + } + + @Test(expected = NoSuchObjectException.class) + public void getTableInBogusCatalog() throws TException { + client.getTable("nosuch", testTables[0].getDbName(), testTables[0].getTableName()); + } + + @Test + public void getAllTablesInBogusCatalog() throws TException { + List<String> names = client.getAllTables("nosuch", testTables[0].getDbName()); + Assert.assertTrue(names.isEmpty()); + } + + @Test(expected = UnknownDBException.class) + public void getTableObjectsByNameBogusCatalog() throws TException { + client.getTableObjectsByName("nosuch", testTables[0].getDbName(), + Arrays.asList(testTables[0].getTableName(), testTables[1].getTableName())); + } + + @Test + public void getMaterializedViewsInBogusCatalog() throws TException { + List<String> names = client.getMaterializedViewsForRewriting("nosuch", DEFAULT_DATABASE_NAME); + Assert.assertTrue(names.isEmpty()); + } + + @Test(expected = InvalidOperationException.class) + public void alterTableBogusCatalog() throws TException { + Table t = testTables[0].deepCopy(); + t.getParameters().put("a", "b"); + client.alter_table("nosuch", t.getDbName(), t.getTableName(), t); + } + + @Test(expected = InvalidOperationException.class) + public void moveTablesBetweenCatalogsOnAlter() throws TException { + String catName = "move_table_between_catalogs_on_alter"; + Catalog cat = new CatalogBuilder() + .setName(catName) + .setLocation(MetaStoreTestUtils.getTestWarehouseDir(catName)) + .build(); + client.createCatalog(cat); + + String dbName = "a_db"; + // For this one don't specify a location to make sure it gets put in the catalog directory + Database db = new DatabaseBuilder() + .setName(dbName) + .setCatalogName(catName) + .create(client, metaStore.getConf()); + + String tableName = "non_movable_table"; + Table before = new TableBuilder() + .inDb(db) + .setTableName(tableName) + .addCol("col1", ColumnType.STRING_TYPE_NAME) + .addCol("col2", ColumnType.INT_TYPE_NAME) + .create(client, metaStore.getConf()); + Table after = before.deepCopy(); + after.setCatName(DEFAULT_CATALOG_NAME); + client.alter_table(catName, dbName, tableName, after); + + } + + @Test + public void truncateTableBogusCatalog() throws TException { + try { + List<String> partNames = client.listPartitionNames(partitionedTable.getDbName(), + partitionedTable.getTableName(), (short) -1); + client.truncateTable("nosuch", partitionedTable.getDbName(), partitionedTable.getTableName(), + partNames); + Assert.fail(); // For reasons I don't understand and am too lazy to debug at the moment the + // NoSuchObjectException gets swallowed by a TApplicationException in remote mode. + } catch (TApplicationException|NoSuchObjectException e) { + //NOP + } + } + + @Test(expected = NoSuchObjectException.class) + public void dropTableBogusCatalog() throws TException { + client.dropTable("nosuch", testTables[0].getDbName(), testTables[0].getTableName(), true, false); + } + + /** + * 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) + .setOwnerType(PrincipalType.ROLE) + .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(metaStore.getConf()); + } + }
http://git-wip-us.apache.org/repos/asf/hive/blob/651e7950/standalone-metastore/pom.xml ----------------------------------------------------------------------
